@unifold/ui-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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/deposits/DepositModal.tsx
2
- import { useState as useState25, useEffect as useEffect18 } from "react";
2
+ import { useState as useState24, useEffect as useEffect18 } from "react";
3
3
  import { ChevronRight as ChevronRight9, MapPinOff, AlertTriangle } from "lucide-react";
4
4
 
5
5
  // src/components/shared/dialog.tsx
@@ -14,6 +14,26 @@ function cn(...inputs) {
14
14
  return twMerge(clsx(inputs));
15
15
  }
16
16
  var WALLET_CHAIN_TYPE_STORAGE_KEY = "unifold_last_wallet_type";
17
+ var WALLET_USER_DISCONNECTED_KEY = "unifold_wallet_user_disconnected";
18
+ function getUserDisconnectedWallet() {
19
+ if (typeof window === "undefined") return false;
20
+ try {
21
+ return localStorage.getItem(WALLET_USER_DISCONNECTED_KEY) === "true";
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function setUserDisconnectedWallet(disconnected) {
27
+ if (typeof window === "undefined") return;
28
+ try {
29
+ if (disconnected) {
30
+ localStorage.setItem(WALLET_USER_DISCONNECTED_KEY, "true");
31
+ } else {
32
+ localStorage.removeItem(WALLET_USER_DISCONNECTED_KEY);
33
+ }
34
+ } catch {
35
+ }
36
+ }
17
37
  function getStoredWalletChainType() {
18
38
  if (typeof window === "undefined") return void 0;
19
39
  try {
@@ -591,11 +611,127 @@ import { useState as useState4 } from "react";
591
611
 
592
612
  // src/components/deposits/DepositHeader.tsx
593
613
  import { ArrowLeft, X as X2 } from "lucide-react";
594
- import { useEffect as useEffect2, useState as useState2 } from "react";
614
+ import { useEffect as useEffect2, useLayoutEffect, useState as useState2 } from "react";
595
615
  import { getAddressBalance } from "@unifold/core";
616
+
617
+ // src/components/deposits/browser-wallets/utils.ts
618
+ import { IneligibilityReason } from "@unifold/core";
619
+ function getIconUrl(iconUrl, assetCdnUrl) {
620
+ if (!iconUrl) return void 0;
621
+ if (iconUrl.startsWith("http://") || iconUrl.startsWith("https://")) {
622
+ return iconUrl;
623
+ }
624
+ if (assetCdnUrl) {
625
+ return `${assetCdnUrl}${iconUrl.startsWith("/") ? "" : "/"}${iconUrl}`;
626
+ }
627
+ return iconUrl;
628
+ }
629
+ function getTokenFromBalance(balance) {
630
+ if (balance.token) {
631
+ return balance.token;
632
+ }
633
+ const legacyBalance = balance;
634
+ if (legacyBalance.symbol && legacyBalance.decimals !== void 0) {
635
+ return {
636
+ symbol: legacyBalance.symbol,
637
+ name: legacyBalance.name,
638
+ icon_url: legacyBalance.icon_url,
639
+ icon_urls: [],
640
+ token_address: legacyBalance.token_address,
641
+ chain_id: legacyBalance.chain_id,
642
+ chain_name: legacyBalance.chain_name,
643
+ chain_type: legacyBalance.chain_type,
644
+ decimals: legacyBalance.decimals,
645
+ chain_icon_url: legacyBalance.chain_icon_url,
646
+ chain_icon_urls: [],
647
+ minimum_deposit_amount_usd: 0
648
+ };
649
+ }
650
+ return null;
651
+ }
652
+ function isBalanceEligible(balance) {
653
+ if (balance.is_eligible !== void 0) {
654
+ return balance.is_eligible;
655
+ }
656
+ const legacyBalance = balance;
657
+ if (legacyBalance.is_eligible !== void 0) {
658
+ return legacyBalance.is_eligible;
659
+ }
660
+ return true;
661
+ }
662
+ function getIneligibilityMessage(balance) {
663
+ if (isBalanceEligible(balance)) {
664
+ return null;
665
+ }
666
+ switch (balance.ineligibility_reason) {
667
+ case IneligibilityReason.MINIMUM_NOT_MET:
668
+ return "Low balance";
669
+ case IneligibilityReason.NOT_SUPPORTED_DEPOSIT_FROM:
670
+ return "Not supported";
671
+ default:
672
+ return "Not eligible";
673
+ }
674
+ }
675
+ function formatTokenAmount(amount, decimals, symbol) {
676
+ const value = Number(amount) / 10 ** decimals;
677
+ const upperSymbol = symbol.toUpperCase();
678
+ let maxDecimals = 4;
679
+ if (upperSymbol === "BTC" || upperSymbol === "WBTC") {
680
+ maxDecimals = 8;
681
+ } else if (upperSymbol === "ETH" || upperSymbol === "WETH" || upperSymbol === "SOL") {
682
+ maxDecimals = 6;
683
+ }
684
+ if (value >= 1) {
685
+ return value.toLocaleString(void 0, {
686
+ minimumFractionDigits: 2,
687
+ maximumFractionDigits: maxDecimals
688
+ });
689
+ } else if (value > 0) {
690
+ return value.toLocaleString(void 0, {
691
+ minimumFractionDigits: 2,
692
+ maximumFractionDigits: maxDecimals,
693
+ minimumSignificantDigits: 2,
694
+ maximumSignificantDigits: 6
695
+ });
696
+ }
697
+ return "0.00";
698
+ }
699
+ function formatUsdAmount(amountUsd) {
700
+ if (!amountUsd) return null;
701
+ const value = parseFloat(amountUsd);
702
+ if (value <= 0) return null;
703
+ return value.toLocaleString(void 0, {
704
+ minimumFractionDigits: 2,
705
+ maximumFractionDigits: 2
706
+ });
707
+ }
708
+ function truncateAddress2(address) {
709
+ if (address.length <= 13) return address;
710
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
711
+ }
712
+ function formatBalanceDisplay(balance, projectName) {
713
+ return projectName ? `${projectName} Balance: ${balance}` : `Balance: ${balance}`;
714
+ }
715
+ function formatProcessingTime(seconds) {
716
+ if (seconds === null || seconds === 0) {
717
+ return "< 1 min";
718
+ }
719
+ const minutes = Math.floor(seconds / 60);
720
+ const remainingSeconds = seconds % 60;
721
+ if (minutes === 0) {
722
+ return `< ${remainingSeconds} sec`;
723
+ } else if (remainingSeconds === 0) {
724
+ return `< ${minutes} min`;
725
+ } else {
726
+ return `< ${minutes} min ${remainingSeconds} sec`;
727
+ }
728
+ }
729
+
730
+ // src/components/deposits/DepositHeader.tsx
596
731
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
597
732
  function DepositHeader({
598
733
  title,
734
+ subtitle,
599
735
  showBack = false,
600
736
  showClose = true,
601
737
  onBack,
@@ -606,19 +742,41 @@ function DepositHeader({
606
742
  balanceChainType,
607
743
  balanceChainId,
608
744
  balanceTokenAddress,
745
+ projectName,
609
746
  publishableKey
610
747
  }) {
611
748
  const { colors: colors2, fonts, components } = useTheme();
612
749
  const [balance, setBalance] = useState2(null);
613
750
  const [isLoadingBalance, setIsLoadingBalance] = useState2(false);
751
+ const [showBalanceSkeleton, setShowBalanceSkeleton] = useState2(false);
752
+ const showBalanceBlock = showBalance === true;
753
+ useLayoutEffect(() => {
754
+ if (!showBalanceBlock) {
755
+ setBalance(null);
756
+ setIsLoadingBalance(false);
757
+ setShowBalanceSkeleton(false);
758
+ }
759
+ }, [showBalanceBlock]);
614
760
  useEffect2(() => {
615
761
  if (!showBalance || !balanceAddress || !balanceChainType || !balanceChainId || !balanceTokenAddress || !publishableKey) {
616
762
  setBalance(null);
617
763
  setIsLoadingBalance(false);
764
+ setShowBalanceSkeleton(false);
765
+ return;
766
+ }
767
+ const supportedChainTypes = ["ethereum", "solana", "bitcoin"];
768
+ if (!supportedChainTypes.includes(balanceChainType)) {
769
+ setBalance(null);
770
+ setIsLoadingBalance(false);
771
+ setShowBalanceSkeleton(false);
618
772
  return;
619
773
  }
620
774
  let cancelled = false;
621
775
  setIsLoadingBalance(true);
776
+ setShowBalanceSkeleton(false);
777
+ const skeletonTimer = window.setTimeout(() => {
778
+ if (!cancelled) setShowBalanceSkeleton(true);
779
+ }, 150);
622
780
  getAddressBalance(
623
781
  balanceAddress,
624
782
  balanceChainType,
@@ -627,7 +785,7 @@ function DepositHeader({
627
785
  publishableKey
628
786
  ).then((response) => {
629
787
  if (cancelled) return;
630
- if (response.balance && response.balance.amount !== "0") {
788
+ if (response.balance) {
631
789
  const token = response.balance.token;
632
790
  if (!token) {
633
791
  setBalance(null);
@@ -655,12 +813,12 @@ function DepositHeader({
655
813
  maximumSignificantDigits: 6
656
814
  });
657
815
  } else {
658
- formatted = value.toExponential(2);
816
+ formatted = value === 0 ? "0.00" : value.toExponential(2);
659
817
  }
660
- const balanceText = response.balance.amount_usd ? `Balance: $${response.balance.amount_usd} (${formatted} ${response.balance.token.symbol})` : `Balance: ${formatted} ${response.balance.token.symbol}`;
661
- setBalance(balanceText);
818
+ 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}`;
819
+ setBalance(amountPart);
662
820
  } else {
663
- setBalance(null);
821
+ setBalance("$0.00");
664
822
  }
665
823
  }).catch((error) => {
666
824
  if (cancelled) return;
@@ -669,9 +827,11 @@ function DepositHeader({
669
827
  }).finally(() => {
670
828
  if (cancelled) return;
671
829
  setIsLoadingBalance(false);
830
+ setShowBalanceSkeleton(false);
672
831
  });
673
832
  return () => {
674
833
  cancelled = true;
834
+ window.clearTimeout(skeletonTimer);
675
835
  };
676
836
  }, [
677
837
  showBalance,
@@ -727,18 +887,27 @@ function DepositHeader({
727
887
  children: title
728
888
  }
729
889
  ),
730
- showBalance && (isLoadingBalance ? /* @__PURE__ */ jsx3("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-2" }) : balance ? /* @__PURE__ */ jsx3(
890
+ subtitle ? /* @__PURE__ */ jsx3(
731
891
  "div",
732
892
  {
733
- className: "uf-text-xs uf-mt-2",
893
+ className: "uf-text-xs uf-mt-1",
734
894
  style: {
735
- color: colors2.foreground,
736
- fontFamily: fonts.regular,
737
- opacity: 0.7
895
+ color: colors2.foregroundMuted,
896
+ fontFamily: fonts.regular
897
+ },
898
+ children: subtitle
899
+ }
900
+ ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ jsx3("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ jsx3(
901
+ "div",
902
+ {
903
+ className: "uf-text-xs uf-mt-1",
904
+ style: {
905
+ color: colors2.foregroundMuted,
906
+ fontFamily: fonts.regular
738
907
  },
739
- children: balance
908
+ children: formatBalanceDisplay(balance, projectName)
740
909
  }
741
- ) : null)
910
+ ) : null : null
742
911
  ] }),
743
912
  showClose ? /* @__PURE__ */ jsx3(
744
913
  "button",
@@ -1099,34 +1268,65 @@ function interpolate(template, params) {
1099
1268
  import { useState as useState5, useEffect as useEffect3, useRef } from "react";
1100
1269
  import {
1101
1270
  queryExecutions,
1271
+ pollDirectExecutions,
1102
1272
  ExecutionStatus
1103
1273
  } from "@unifold/core";
1274
+ var DEPOSIT_CONFIRM_DELAY_MS = 1e4;
1275
+ var POLL_INTERVAL_MS = 2500;
1276
+ var POLL_ENDPOINT_INTERVAL_MS = 3e3;
1277
+ var CUTOFF_BUFFER_MS = 6e4;
1104
1278
  function useDepositPolling({
1105
1279
  userId,
1106
1280
  publishableKey,
1281
+ depositConfirmationMode = "auto_ui",
1282
+ depositWalletId,
1107
1283
  enabled = true,
1108
1284
  onDepositSuccess,
1109
1285
  onDepositError
1110
1286
  }) {
1111
1287
  const [executions, setExecutions] = useState5([]);
1112
1288
  const [isPolling, setIsPolling] = useState5(false);
1113
- const pollingIntervalRef = useRef(
1114
- null
1115
- );
1116
- const [modalOpenedAt] = useState5(/* @__PURE__ */ new Date());
1117
- const [trackedExecutions, setTrackedExecutions] = useState5(/* @__PURE__ */ new Map());
1289
+ const [pollingEnabled, setPollingEnabled] = useState5(false);
1290
+ const [showWaitingUi, setShowWaitingUi] = useState5(false);
1291
+ const modalOpenedAtRef = useRef(/* @__PURE__ */ new Date());
1292
+ const trackedExecutionsRef = useRef(/* @__PURE__ */ new Map());
1293
+ const onDepositSuccessRef = useRef(onDepositSuccess);
1294
+ const onDepositErrorRef = useRef(onDepositError);
1295
+ useEffect3(() => {
1296
+ onDepositSuccessRef.current = onDepositSuccess;
1297
+ }, [onDepositSuccess]);
1118
1298
  useEffect3(() => {
1119
- if (!userId || !modalOpenedAt || !enabled) return;
1120
- const pollInterval = setInterval(async () => {
1299
+ onDepositErrorRef.current = onDepositError;
1300
+ }, [onDepositError]);
1301
+ useEffect3(() => {
1302
+ if (depositConfirmationMode === "manual" || !enabled) return;
1303
+ const timeout = setTimeout(() => {
1304
+ setPollingEnabled(true);
1305
+ if (depositConfirmationMode === "auto_ui") {
1306
+ setShowWaitingUi(true);
1307
+ }
1308
+ }, DEPOSIT_CONFIRM_DELAY_MS);
1309
+ return () => clearTimeout(timeout);
1310
+ }, [depositConfirmationMode, enabled]);
1311
+ useEffect3(() => {
1312
+ if (!userId || !enabled) return;
1313
+ const modalOpenedAt = modalOpenedAtRef.current;
1314
+ const poll = async () => {
1121
1315
  try {
1122
1316
  const response = await queryExecutions(userId, publishableKey);
1317
+ const cutoff = new Date(modalOpenedAt.getTime() - CUTOFF_BUFFER_MS);
1318
+ const sortedExecutions = [...response.data].sort((a, b) => {
1319
+ const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
1320
+ const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
1321
+ return timeB - timeA;
1322
+ });
1123
1323
  let executionToShow = null;
1124
- for (const execution of response.data) {
1324
+ for (const execution of sortedExecutions) {
1125
1325
  const executionTime = execution.created_at ? new Date(execution.created_at) : null;
1126
- if (!executionTime || executionTime <= modalOpenedAt) {
1326
+ if (!executionTime || executionTime < cutoff) {
1127
1327
  continue;
1128
1328
  }
1129
- const trackedStatus = trackedExecutions.get(execution.id);
1329
+ const trackedStatus = trackedExecutionsRef.current.get(execution.id);
1130
1330
  if (!trackedStatus) {
1131
1331
  executionToShow = execution;
1132
1332
  break;
@@ -1147,35 +1347,30 @@ function useDepositPolling({
1147
1347
  }
1148
1348
  if (executionToShow) {
1149
1349
  const execution = executionToShow;
1350
+ const previousStatus = trackedExecutionsRef.current.get(execution.id);
1351
+ trackedExecutionsRef.current.set(execution.id, execution.status);
1150
1352
  setExecutions((prev) => {
1151
1353
  const existingIndex = prev.findIndex((e) => e.id === execution.id);
1152
1354
  if (existingIndex >= 0) {
1153
1355
  const updated = [...prev];
1154
1356
  updated[existingIndex] = execution;
1155
1357
  return updated;
1156
- } else {
1157
- return [...prev, execution];
1158
1358
  }
1159
- });
1160
- const previousStatus = trackedExecutions.get(execution.id);
1161
- setTrackedExecutions((prev) => {
1162
- const updated = new Map(prev);
1163
- updated.set(execution.id, execution.status);
1164
- return updated;
1359
+ return [...prev, execution];
1165
1360
  });
1166
1361
  const inProgressStatuses = [
1167
1362
  ExecutionStatus.PENDING,
1168
1363
  ExecutionStatus.WAITING,
1169
1364
  ExecutionStatus.DELAYED
1170
1365
  ];
1171
- if (execution.status === ExecutionStatus.SUCCEEDED && onDepositSuccess && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
1172
- onDepositSuccess({
1366
+ if (execution.status === ExecutionStatus.SUCCEEDED && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
1367
+ onDepositSuccessRef.current?.({
1173
1368
  message: "Deposit completed successfully",
1174
1369
  executionId: execution.id,
1175
1370
  transaction: execution
1176
1371
  });
1177
- } else if (execution.status === ExecutionStatus.FAILED && onDepositError && previousStatus !== ExecutionStatus.FAILED) {
1178
- onDepositError({
1372
+ } else if (execution.status === ExecutionStatus.FAILED && previousStatus !== ExecutionStatus.FAILED) {
1373
+ onDepositErrorRef.current?.({
1179
1374
  message: "Deposit failed",
1180
1375
  code: "DEPOSIT_FAILED",
1181
1376
  error: execution
@@ -1184,36 +1379,45 @@ function useDepositPolling({
1184
1379
  }
1185
1380
  } catch (error) {
1186
1381
  console.error("Failed to fetch executions:", error);
1187
- if (onDepositError) {
1188
- onDepositError({
1189
- message: "Failed to fetch deposit status",
1190
- code: "POLLING_ERROR",
1191
- error
1192
- });
1193
- }
1382
+ onDepositErrorRef.current?.({
1383
+ message: "Failed to fetch deposit status",
1384
+ code: "POLLING_ERROR",
1385
+ error
1386
+ });
1194
1387
  }
1195
- }, 3e3);
1388
+ };
1389
+ const pollInterval = setInterval(poll, POLL_INTERVAL_MS);
1196
1390
  setIsPolling(true);
1197
- pollingIntervalRef.current = pollInterval;
1198
1391
  return () => {
1199
- if (pollingIntervalRef.current) {
1200
- clearInterval(pollingIntervalRef.current);
1201
- pollingIntervalRef.current = null;
1202
- }
1392
+ clearInterval(pollInterval);
1203
1393
  setIsPolling(false);
1204
1394
  };
1205
- }, [
1206
- userId,
1207
- publishableKey,
1208
- modalOpenedAt,
1209
- trackedExecutions,
1210
- enabled,
1211
- onDepositSuccess,
1212
- onDepositError
1213
- ]);
1395
+ }, [userId, publishableKey, enabled]);
1396
+ useEffect3(() => {
1397
+ if (!pollingEnabled || !depositWalletId) return;
1398
+ const triggerPoll = async () => {
1399
+ try {
1400
+ await pollDirectExecutions(
1401
+ { deposit_wallet_id: depositWalletId },
1402
+ publishableKey
1403
+ );
1404
+ } catch {
1405
+ }
1406
+ };
1407
+ triggerPoll();
1408
+ const interval = setInterval(triggerPoll, POLL_ENDPOINT_INTERVAL_MS);
1409
+ return () => clearInterval(interval);
1410
+ }, [pollingEnabled, depositWalletId, publishableKey]);
1411
+ const handleIveDeposited = () => {
1412
+ setPollingEnabled(true);
1413
+ setShowWaitingUi(true);
1414
+ };
1214
1415
  return {
1215
1416
  executions,
1216
- isPolling
1417
+ isPolling,
1418
+ pollingEnabled,
1419
+ showWaitingUi,
1420
+ handleIveDeposited
1217
1421
  };
1218
1422
  }
1219
1423
 
@@ -1225,7 +1429,7 @@ import { useState as useState7 } from "react";
1225
1429
  import { X as X3 } from "lucide-react";
1226
1430
  import {
1227
1431
  ExecutionStatus as ExecutionStatus3,
1228
- getIconUrl as getIconUrl2
1432
+ getIconUrl as getIconUrl3
1229
1433
  } from "@unifold/core";
1230
1434
 
1231
1435
  // src/components/deposits/DepositDetailContent.tsx
@@ -1233,7 +1437,7 @@ import { useEffect as useEffect4, useState as useState6 } from "react";
1233
1437
  import { ExternalLink, ChevronDown, ChevronUp } from "lucide-react";
1234
1438
  import {
1235
1439
  ExecutionStatus as ExecutionStatus2,
1236
- getIconUrl,
1440
+ getIconUrl as getIconUrl2,
1237
1441
  getTokenChains,
1238
1442
  getChainName
1239
1443
  } from "@unifold/core";
@@ -1338,7 +1542,7 @@ function DepositDetailContent({ execution }) {
1338
1542
  /* @__PURE__ */ jsx7(
1339
1543
  "img",
1340
1544
  {
1341
- src: execution.destination_token_metadata?.icon_url || getIconUrl("/icons/tokens/svg/usdc.svg"),
1545
+ src: execution.destination_token_metadata?.icon_url || getIconUrl2("/icons/tokens/svg/usdc.svg"),
1342
1546
  alt: "Token",
1343
1547
  width: 64,
1344
1548
  height: 64,
@@ -1845,7 +2049,7 @@ function DepositSuccessToast({
1845
2049
  /* @__PURE__ */ jsx8(
1846
2050
  "img",
1847
2051
  {
1848
- src: tokenIconUrl || getIconUrl2("/icons/tokens/svg/usdc.svg"),
2052
+ src: tokenIconUrl || getIconUrl3("/icons/tokens/svg/usdc.svg"),
1849
2053
  alt: "Token",
1850
2054
  width: 36,
1851
2055
  height: 36,
@@ -2923,7 +3127,7 @@ import { useEffect as useEffect6, useState as useState10 } from "react";
2923
3127
  import { ChevronRight as ChevronRight2 } from "lucide-react";
2924
3128
  import {
2925
3129
  ExecutionStatus as ExecutionStatus4,
2926
- getIconUrl as getIconUrl3
3130
+ getIconUrl as getIconUrl4
2927
3131
  } from "@unifold/core";
2928
3132
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2929
3133
  function DepositExecutionItem({
@@ -2974,7 +3178,7 @@ function DepositExecutionItem({
2974
3178
  /* @__PURE__ */ jsx11(
2975
3179
  "img",
2976
3180
  {
2977
- src: execution.destination_token_metadata?.icon_url || getIconUrl3("/icons/tokens/svg/usdc.svg"),
3181
+ src: execution.destination_token_metadata?.icon_url || getIconUrl4("/icons/tokens/svg/usdc.svg"),
2978
3182
  alt: "Token",
2979
3183
  width: 36,
2980
3184
  height: 36,
@@ -5085,10 +5289,48 @@ var WALLET_ICON_COMPONENTS = {
5085
5289
  backpack: BackpackIcon,
5086
5290
  glow: GlowIcon
5087
5291
  };
5088
- function truncateAddress2(address) {
5292
+ function truncateAddress3(address) {
5089
5293
  if (address.length <= 10) return address;
5090
5294
  return `${address.slice(0, 4)}...${address.slice(-4)}`;
5091
5295
  }
5296
+ function identifyEthWallet(provider, _win, hint) {
5297
+ switch (hint) {
5298
+ case "metamask":
5299
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
5300
+ case "phantom":
5301
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
5302
+ case "coinbase":
5303
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
5304
+ case "okx":
5305
+ return { type: "okx", name: "OKX Wallet", icon: "okx" };
5306
+ case "rabby":
5307
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
5308
+ case "trust":
5309
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
5310
+ case "rainbow":
5311
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
5312
+ }
5313
+ const anyProvider = provider;
5314
+ if (provider.isPhantom) {
5315
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
5316
+ }
5317
+ if (anyProvider.isCoinbaseWallet) {
5318
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
5319
+ }
5320
+ if (anyProvider.isRabby) {
5321
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
5322
+ }
5323
+ if (anyProvider.isTrust) {
5324
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
5325
+ }
5326
+ if (anyProvider.isRainbow) {
5327
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
5328
+ }
5329
+ if (provider.isMetaMask && !provider.isPhantom) {
5330
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
5331
+ }
5332
+ return { type: "metamask", name: "Wallet", icon: "metamask" };
5333
+ }
5092
5334
  function BrowserWalletButton({
5093
5335
  onClick,
5094
5336
  onConnectClick,
@@ -5105,9 +5347,35 @@ function BrowserWalletButton({
5105
5347
  const [balanceText, setBalanceText] = React20.useState(null);
5106
5348
  const [isLoadingBalance, setIsLoadingBalance] = React20.useState(false);
5107
5349
  const iconVariant = mode === "dark" ? "light" : "dark";
5350
+ const onDisconnectRef = React20.useRef(onDisconnect);
5351
+ onDisconnectRef.current = onDisconnect;
5108
5352
  React20.useEffect(() => {
5109
5353
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
5110
5354
  }, []);
5355
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React20.useState(0);
5356
+ React20.useEffect(() => {
5357
+ if (typeof window === "undefined") return;
5358
+ const anyWin = window;
5359
+ if (!anyWin.__eip6963Providers) {
5360
+ anyWin.__eip6963Providers = [];
5361
+ }
5362
+ const handleAnnouncement = (event) => {
5363
+ const { detail } = event;
5364
+ if (!detail?.info || !detail?.provider) return;
5365
+ const exists = anyWin.__eip6963Providers.some(
5366
+ (p) => p.info.uuid === detail.info.uuid
5367
+ );
5368
+ if (!exists) {
5369
+ anyWin.__eip6963Providers.push(detail);
5370
+ setEip6963ProviderCount(anyWin.__eip6963Providers.length);
5371
+ }
5372
+ };
5373
+ window.addEventListener("eip6963:announceProvider", handleAnnouncement);
5374
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
5375
+ return () => {
5376
+ window.removeEventListener("eip6963:announceProvider", handleAnnouncement);
5377
+ };
5378
+ }, []);
5111
5379
  React20.useEffect(() => {
5112
5380
  if (!wallet || !publishableKey) {
5113
5381
  setBalanceText(null);
@@ -5157,166 +5425,85 @@ function BrowserWalletButton({
5157
5425
  try {
5158
5426
  const win = typeof window !== "undefined" ? window : null;
5159
5427
  if (!win) return;
5428
+ if (getUserDisconnectedWallet()) {
5429
+ if (mounted) {
5430
+ setWallet(null);
5431
+ setIsLoading(false);
5432
+ }
5433
+ return;
5434
+ }
5160
5435
  if (!chainType || chainType === "solana") {
5161
- const phantomSolana = win.phantom?.solana;
5162
- if (phantomSolana?.isPhantom) {
5163
- if (phantomSolana.isConnected && phantomSolana.publicKey) {
5436
+ const anyWin2 = win;
5437
+ const trySilentSolana = async (provider, type, name, icon) => {
5438
+ if (!provider) return false;
5439
+ if (provider.isConnected && provider.publicKey) {
5164
5440
  if (mounted) {
5165
- setWallet({
5166
- type: "phantom-solana",
5167
- name: "Phantom",
5168
- address: phantomSolana.publicKey.toString(),
5169
- icon: "phantom"
5170
- });
5441
+ setWallet({ type, name, address: provider.publicKey.toString(), icon });
5171
5442
  setIsLoading(false);
5172
5443
  }
5173
- return;
5444
+ return true;
5174
5445
  }
5175
- }
5176
- const solflare = win.solflare;
5177
- if (solflare?.isConnected && solflare?.publicKey) {
5178
- if (mounted) {
5179
- setWallet({
5180
- type: "solflare",
5181
- name: "Solflare",
5182
- address: solflare.publicKey.toString(),
5183
- icon: "solflare"
5184
- });
5185
- setIsLoading(false);
5446
+ try {
5447
+ const resp = await provider.connect({ onlyIfTrusted: true });
5448
+ if (mounted && resp.publicKey) {
5449
+ setWallet({ type, name, address: resp.publicKey.toString(), icon });
5450
+ setIsLoading(false);
5451
+ return true;
5452
+ }
5453
+ } catch {
5186
5454
  }
5187
- return;
5455
+ return false;
5456
+ };
5457
+ if (await trySilentSolana(win.phantom?.solana, "phantom-solana", "Phantom", "phantom")) return;
5458
+ if (await trySilentSolana(anyWin2.solflare, "solflare", "Solflare", "solflare")) return;
5459
+ if (await trySilentSolana(anyWin2.backpack, "backpack", "Backpack", "backpack")) return;
5460
+ if (await trySilentSolana(anyWin2.glow, "glow", "Glow", "glow")) return;
5461
+ }
5462
+ if (!chainType || chainType === "ethereum") {
5463
+ const anyWin2 = win;
5464
+ const allProviders = [];
5465
+ const eip6963Providers = anyWin2.__eip6963Providers || [];
5466
+ for (const { info, provider } of eip6963Providers) {
5467
+ let walletId = "default";
5468
+ if (info.rdns.includes("metamask")) walletId = "metamask";
5469
+ else if (info.rdns.includes("phantom")) walletId = "phantom";
5470
+ else if (info.rdns.includes("coinbase")) walletId = "coinbase";
5471
+ else if (info.rdns.includes("okx")) walletId = "okx";
5472
+ else if (info.rdns.includes("rabby")) walletId = "rabby";
5473
+ else if (info.rdns.includes("trust")) walletId = "trust";
5474
+ else if (info.rdns.includes("rainbow")) walletId = "rainbow";
5475
+ allProviders.push({ provider, walletId });
5188
5476
  }
5189
- const backpack = win.backpack;
5190
- if (backpack?.isConnected && backpack?.publicKey) {
5191
- if (mounted) {
5192
- setWallet({
5193
- type: "backpack",
5194
- name: "Backpack",
5195
- address: backpack.publicKey.toString(),
5196
- icon: "backpack"
5197
- });
5198
- setIsLoading(false);
5477
+ if (allProviders.length === 0) {
5478
+ if (win.phantom?.ethereum) {
5479
+ allProviders.push({ provider: win.phantom.ethereum, walletId: "phantom" });
5199
5480
  }
5200
- return;
5201
- }
5202
- const glow = win.glow;
5203
- if (glow?.isConnected && glow?.publicKey) {
5204
- if (mounted) {
5205
- setWallet({
5206
- type: "glow",
5207
- name: "Glow",
5208
- address: glow.publicKey.toString(),
5209
- icon: "glow"
5210
- });
5211
- setIsLoading(false);
5481
+ if (anyWin2.okxwallet) {
5482
+ allProviders.push({ provider: anyWin2.okxwallet, walletId: "okx" });
5483
+ }
5484
+ if (anyWin2.coinbaseWalletExtension) {
5485
+ allProviders.push({ provider: anyWin2.coinbaseWalletExtension, walletId: "coinbase" });
5486
+ }
5487
+ if (win.ethereum) {
5488
+ const isDuplicate = allProviders.some((p) => p.provider === win.ethereum);
5489
+ if (!isDuplicate) {
5490
+ allProviders.push({ provider: win.ethereum, walletId: "default" });
5491
+ }
5212
5492
  }
5213
- return;
5214
5493
  }
5215
- }
5216
- if (!chainType || chainType === "ethereum") {
5217
- const ethProvider2 = win.ethereum;
5218
- if (ethProvider2) {
5494
+ for (const { provider, walletId } of allProviders) {
5495
+ if (!provider) continue;
5219
5496
  try {
5220
- const accounts = await ethProvider2.request({ method: "eth_accounts" });
5221
- if (accounts && accounts.length > 0) {
5222
- const address = accounts[0];
5223
- if (ethProvider2.isMetaMask && !ethProvider2.isPhantom) {
5224
- const providers = ethProvider2.providers;
5225
- if (win.okxwallet) {
5226
- if (mounted) {
5227
- setWallet({
5228
- type: "okx",
5229
- name: "OKX Wallet",
5230
- address,
5231
- icon: "okx"
5232
- });
5233
- setIsLoading(false);
5234
- }
5235
- return;
5236
- }
5237
- if (ethProvider2.isRabby) {
5238
- if (mounted) {
5239
- setWallet({
5240
- type: "rabby",
5241
- name: "Rabby",
5242
- address,
5243
- icon: "rabby"
5244
- });
5245
- setIsLoading(false);
5246
- }
5247
- return;
5248
- }
5249
- if (ethProvider2.isTrust || win.trustwallet) {
5250
- if (mounted) {
5251
- setWallet({
5252
- type: "trust",
5253
- name: "Trust Wallet",
5254
- address,
5255
- icon: "trust"
5256
- });
5257
- setIsLoading(false);
5258
- }
5259
- return;
5260
- }
5261
- if (ethProvider2.isRainbow) {
5262
- if (mounted) {
5263
- setWallet({
5264
- type: "rainbow",
5265
- name: "Rainbow",
5266
- address,
5267
- icon: "rainbow"
5268
- });
5269
- setIsLoading(false);
5270
- }
5271
- return;
5272
- }
5273
- if (mounted) {
5274
- setWallet({
5275
- type: "metamask",
5276
- name: "MetaMask",
5277
- address,
5278
- icon: "metamask"
5279
- });
5280
- setIsLoading(false);
5281
- }
5282
- return;
5283
- }
5284
- if (ethProvider2.isPhantom) {
5285
- if (mounted) {
5286
- setWallet({
5287
- type: "phantom-ethereum",
5288
- name: "Phantom",
5289
- address,
5290
- icon: "phantom"
5291
- });
5292
- setIsLoading(false);
5293
- }
5294
- return;
5295
- }
5296
- if (ethProvider2.isCoinbaseWallet) {
5297
- if (mounted) {
5298
- setWallet({
5299
- type: "coinbase",
5300
- name: "Coinbase Wallet",
5301
- address,
5302
- icon: "coinbase"
5303
- });
5304
- setIsLoading(false);
5305
- }
5306
- return;
5307
- }
5308
- if (mounted) {
5309
- setWallet({
5310
- type: "metamask",
5311
- name: "Wallet",
5312
- address,
5313
- icon: "metamask"
5314
- });
5315
- setIsLoading(false);
5316
- }
5317
- return;
5497
+ const accounts = await provider.request({ method: "eth_accounts" });
5498
+ if (!accounts || accounts.length === 0) continue;
5499
+ const address = accounts[0];
5500
+ const resolved = identifyEthWallet(provider, anyWin2, walletId);
5501
+ if (mounted) {
5502
+ setWallet({ ...resolved, address });
5503
+ setIsLoading(false);
5318
5504
  }
5319
- } catch (ethError) {
5505
+ return;
5506
+ } catch {
5320
5507
  }
5321
5508
  }
5322
5509
  }
@@ -5337,12 +5524,12 @@ function BrowserWalletButton({
5337
5524
  detectWallet();
5338
5525
  };
5339
5526
  const handleDisconnect = () => {
5340
- onDisconnect?.();
5527
+ onDisconnectRef.current?.();
5341
5528
  detectWallet();
5342
5529
  };
5343
5530
  const handleEthAccountsChanged = (accounts) => {
5344
5531
  if (Array.isArray(accounts) && accounts.length === 0) {
5345
- onDisconnect?.();
5532
+ onDisconnectRef.current?.();
5346
5533
  }
5347
5534
  detectWallet();
5348
5535
  };
@@ -5352,10 +5539,24 @@ function BrowserWalletButton({
5352
5539
  solanaProvider.on("disconnect", handleDisconnect);
5353
5540
  solanaProvider.on("accountChanged", handleAccountsChanged);
5354
5541
  }
5355
- const ethProvider = window.phantom?.ethereum || window.ethereum;
5356
- if (ethProvider) {
5357
- ethProvider.on("accountsChanged", handleEthAccountsChanged);
5358
- ethProvider.on("chainChanged", handleAccountsChanged);
5542
+ const anyWin = window;
5543
+ const ethProviders = [];
5544
+ if (anyWin.__eip6963Providers) {
5545
+ for (const { provider } of anyWin.__eip6963Providers) {
5546
+ if (provider && !ethProviders.includes(provider)) {
5547
+ ethProviders.push(provider);
5548
+ }
5549
+ }
5550
+ }
5551
+ if (window.ethereum && !ethProviders.includes(window.ethereum)) {
5552
+ ethProviders.push(window.ethereum);
5553
+ }
5554
+ if (window.phantom?.ethereum && !ethProviders.includes(window.phantom.ethereum)) {
5555
+ ethProviders.push(window.phantom.ethereum);
5556
+ }
5557
+ for (const provider of ethProviders) {
5558
+ provider.on("accountsChanged", handleEthAccountsChanged);
5559
+ provider.on("chainChanged", handleAccountsChanged);
5359
5560
  }
5360
5561
  return () => {
5361
5562
  mounted = false;
@@ -5364,12 +5565,12 @@ function BrowserWalletButton({
5364
5565
  solanaProvider.off("disconnect", handleDisconnect);
5365
5566
  solanaProvider.off("accountChanged", handleAccountsChanged);
5366
5567
  }
5367
- if (ethProvider) {
5368
- ethProvider.removeListener("accountsChanged", handleEthAccountsChanged);
5369
- ethProvider.removeListener("chainChanged", handleAccountsChanged);
5568
+ for (const provider of ethProviders) {
5569
+ provider.removeListener("accountsChanged", handleEthAccountsChanged);
5570
+ provider.removeListener("chainChanged", handleAccountsChanged);
5370
5571
  }
5371
5572
  };
5372
- }, [chainType]);
5573
+ }, [chainType, eip6963ProviderCount]);
5373
5574
  const handleConnect = async () => {
5374
5575
  if (wallet) {
5375
5576
  onClick(wallet);
@@ -5385,6 +5586,7 @@ function BrowserWalletButton({
5385
5586
  const solanaProvider = window.phantom?.solana || window.solana;
5386
5587
  if (solanaProvider?.isPhantom) {
5387
5588
  const { publicKey } = await solanaProvider.connect();
5589
+ setUserDisconnectedWallet(false);
5388
5590
  setWallet({
5389
5591
  type: "phantom-solana",
5390
5592
  name: "Phantom",
@@ -5402,6 +5604,7 @@ function BrowserWalletButton({
5402
5604
  method: "eth_requestAccounts"
5403
5605
  });
5404
5606
  if (accounts && accounts.length > 0) {
5607
+ setUserDisconnectedWallet(false);
5405
5608
  const isPhantom = ethProvider.isPhantom;
5406
5609
  setWallet({
5407
5610
  type: isPhantom ? "phantom-ethereum" : "metamask",
@@ -5413,7 +5616,10 @@ function BrowserWalletButton({
5413
5616
  }
5414
5617
  }
5415
5618
  } catch (error) {
5416
- console.error("Error connecting wallet:", error);
5619
+ if (error && typeof error === "object" && "code" in error && error.code === 4001) {
5620
+ } else {
5621
+ console.error("Error connecting wallet:", error);
5622
+ }
5417
5623
  } finally {
5418
5624
  setIsConnecting(false);
5419
5625
  }
@@ -5459,7 +5665,7 @@ function BrowserWalletButton({
5459
5665
  color: components.card.titleColor,
5460
5666
  fontFamily: fonts.regular
5461
5667
  },
5462
- children: wallet ? `${wallet.name} (${truncateAddress2(wallet.address)})` : "Connect Wallet"
5668
+ children: wallet ? `${wallet.name} (${truncateAddress3(wallet.address)})` : "Connect Wallet"
5463
5669
  }
5464
5670
  ),
5465
5671
  isLoadingBalance ? /* @__PURE__ */ jsx30("div", { className: "uf-h-3 uf-w-24 uf-bg-muted uf-rounded uf-animate-pulse" }) : /* @__PURE__ */ jsx30(
@@ -5660,7 +5866,7 @@ function useSupportedDepositTokens(publishableKey, options) {
5660
5866
  }
5661
5867
 
5662
5868
  // src/components/deposits/TransferCryptoSingleInput.tsx
5663
- import { useState as useState20, useEffect as useEffect14, useRef as useRef4, useMemo as useMemo4 } from "react";
5869
+ import { useState as useState19, useEffect as useEffect14, useMemo as useMemo4 } from "react";
5664
5870
  import {
5665
5871
  ChevronDown as ChevronDown3,
5666
5872
  ChevronUp as ChevronUp2,
@@ -5675,14 +5881,9 @@ import {
5675
5881
  } from "lucide-react";
5676
5882
 
5677
5883
  // src/components/deposits/StyledQRCode.tsx
5678
- import { useEffect as useEffect12, useRef as useRef3, useState as useState16, useCallback } from "react";
5884
+ import { useEffect as useEffect12, useRef as useRef4 } from "react";
5679
5885
  import QRCodeStyling from "qr-code-styling";
5680
- import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
5681
- var qrCache = /* @__PURE__ */ new Map();
5682
- var imageCache = /* @__PURE__ */ new Map();
5683
- function getCacheKey(value, size, imageUrl, darkMode) {
5684
- return `${value}|${size}|${imageUrl || ""}|${darkMode}`;
5685
- }
5886
+ import { jsx as jsx31 } from "react/jsx-runtime";
5686
5887
  function createQRConfig(value, size, imageUrl, imageSize, darkMode) {
5687
5888
  return {
5688
5889
  type: "svg",
@@ -5719,79 +5920,6 @@ function createQRConfig(value, size, imageUrl, imageSize, darkMode) {
5719
5920
  }
5720
5921
  };
5721
5922
  }
5722
- async function preloadImageAsync(url) {
5723
- if (!url || imageCache.has(url)) return;
5724
- return new Promise((resolve) => {
5725
- const img = new Image();
5726
- img.crossOrigin = "anonymous";
5727
- img.onload = () => {
5728
- imageCache.set(url, true);
5729
- resolve();
5730
- };
5731
- img.onerror = () => {
5732
- imageCache.set(url, false);
5733
- resolve();
5734
- };
5735
- img.src = url;
5736
- });
5737
- }
5738
- function waitForStyledQR(container, maxAttempts = 20) {
5739
- return new Promise((resolve) => {
5740
- let attempts = 0;
5741
- const check = () => {
5742
- const svg = container.querySelector("svg");
5743
- if (!svg) {
5744
- if (attempts++ < maxAttempts) {
5745
- requestAnimationFrame(check);
5746
- } else {
5747
- resolve(null);
5748
- }
5749
- return;
5750
- }
5751
- const hasCircles = svg.querySelectorAll("circle").length > 0;
5752
- const hasPaths = svg.querySelectorAll("path").length > 0;
5753
- if (hasCircles || hasPaths) {
5754
- resolve(svg.outerHTML);
5755
- } else if (attempts++ < maxAttempts) {
5756
- requestAnimationFrame(check);
5757
- } else {
5758
- resolve(svg.outerHTML);
5759
- }
5760
- };
5761
- requestAnimationFrame(check);
5762
- });
5763
- }
5764
- async function preloadQRCode(value, size = 180, imageUrl, imageSize = 45, darkMode = false) {
5765
- if (!value) return;
5766
- const cacheKey = getCacheKey(value, size, imageUrl, darkMode);
5767
- if (qrCache.has(cacheKey)) return;
5768
- if (imageUrl) {
5769
- await preloadImageAsync(imageUrl);
5770
- }
5771
- const tempContainer = document.createElement("div");
5772
- tempContainer.style.position = "absolute";
5773
- tempContainer.style.left = "-9999px";
5774
- tempContainer.style.top = "-9999px";
5775
- document.body.appendChild(tempContainer);
5776
- try {
5777
- const config = createQRConfig(value, size, imageUrl, imageSize, darkMode);
5778
- const qrInstance = new QRCodeStyling(config);
5779
- qrInstance.append(tempContainer);
5780
- const svgString = await waitForStyledQR(tempContainer);
5781
- if (svgString) {
5782
- qrCache.set(cacheKey, { svgString });
5783
- }
5784
- } finally {
5785
- document.body.removeChild(tempContainer);
5786
- }
5787
- }
5788
- function isQRCodeCached(value, size = 180, imageUrl, darkMode = false) {
5789
- const cacheKey = getCacheKey(value, size, imageUrl, darkMode);
5790
- return qrCache.has(cacheKey);
5791
- }
5792
- function clearQRCodeCache() {
5793
- qrCache.clear();
5794
- }
5795
5923
  function StyledQRCode({
5796
5924
  value,
5797
5925
  size = 180,
@@ -5799,116 +5927,37 @@ function StyledQRCode({
5799
5927
  imageSize = 45,
5800
5928
  darkMode = false
5801
5929
  }) {
5802
- const containerRef = useRef3(null);
5803
- const [isReady, setIsReady] = useState16(false);
5804
- const currentKeyRef = useRef3("");
5805
- const cacheKey = getCacheKey(value, size, imageUrl, darkMode);
5806
- const cachedEntry = qrCache.get(cacheKey);
5807
- const renderQR = useCallback(async () => {
5930
+ const containerRef = useRef4(null);
5931
+ const qrRef = useRef4(null);
5932
+ useEffect12(() => {
5808
5933
  if (!containerRef.current || !value) return;
5809
- const key = getCacheKey(value, size, imageUrl, darkMode);
5810
- if (currentKeyRef.current === key) {
5811
- setIsReady(true);
5812
- return;
5813
- }
5814
- currentKeyRef.current = key;
5815
- containerRef.current.innerHTML = "";
5816
- const cached = qrCache.get(key);
5817
- if (cached?.svgString) {
5818
- containerRef.current.innerHTML = cached.svgString;
5819
- setIsReady(true);
5820
- return;
5821
- }
5822
- if (imageUrl) {
5823
- await preloadImageAsync(imageUrl);
5824
- }
5825
5934
  const config = createQRConfig(value, size, imageUrl, imageSize, darkMode);
5826
- const qrInstance = new QRCodeStyling(config);
5827
- qrInstance.append(containerRef.current);
5828
- const svgString = await waitForStyledQR(containerRef.current);
5829
- if (svgString) {
5830
- qrCache.set(key, { svgString });
5935
+ if (!qrRef.current) {
5936
+ qrRef.current = new QRCodeStyling(config);
5937
+ qrRef.current.append(containerRef.current);
5938
+ } else {
5939
+ qrRef.current.update(config);
5831
5940
  }
5832
- setIsReady(true);
5833
5941
  }, [value, size, imageUrl, imageSize, darkMode]);
5834
- useEffect12(() => {
5835
- let mounted = true;
5836
- const init = async () => {
5837
- if (!mounted) return;
5838
- await renderQR();
5839
- };
5840
- setIsReady(false);
5841
- init();
5842
- return () => {
5843
- mounted = false;
5844
- };
5845
- }, [renderQR]);
5846
- const showSkeleton = !isReady && !cachedEntry?.svgString;
5847
- return /* @__PURE__ */ jsxs28(
5942
+ return /* @__PURE__ */ jsx31(
5848
5943
  "div",
5849
5944
  {
5945
+ ref: containerRef,
5850
5946
  style: {
5851
5947
  width: size,
5852
5948
  height: size,
5853
5949
  display: "flex",
5854
5950
  alignItems: "center",
5855
- justifyContent: "center",
5856
- position: "relative"
5857
- },
5858
- children: [
5859
- showSkeleton && /* @__PURE__ */ jsx31(
5860
- "div",
5861
- {
5862
- style: {
5863
- position: "absolute",
5864
- inset: 0,
5865
- display: "flex",
5866
- alignItems: "center",
5867
- justifyContent: "center",
5868
- background: darkMode ? "linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)" : "linear-gradient(135deg, #f0f0f0 0%, #e0e0e0 100%)",
5869
- borderRadius: 8,
5870
- animation: "uf-qr-pulse 1.5s ease-in-out infinite"
5871
- },
5872
- children: /* @__PURE__ */ jsx31(
5873
- "div",
5874
- {
5875
- style: {
5876
- width: size * 0.6,
5877
- height: size * 0.6,
5878
- background: darkMode ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.05)",
5879
- borderRadius: 4
5880
- }
5881
- }
5882
- )
5883
- }
5884
- ),
5885
- /* @__PURE__ */ jsx31(
5886
- "div",
5887
- {
5888
- ref: containerRef,
5889
- style: {
5890
- width: size,
5891
- height: size,
5892
- opacity: isReady ? 1 : 0,
5893
- transition: "opacity 0.15s ease-out"
5894
- }
5895
- }
5896
- ),
5897
- /* @__PURE__ */ jsx31("style", { children: `
5898
- @keyframes uf-qr-pulse {
5899
- 0%, 100% { opacity: 1; }
5900
- 50% { opacity: 0.6; }
5901
- }
5902
- ` })
5903
- ]
5951
+ justifyContent: "center"
5952
+ }
5904
5953
  }
5905
5954
  );
5906
5955
  }
5907
5956
 
5908
5957
  // src/components/deposits/TokenSelectorSheet.tsx
5909
- import { useState as useState17, useMemo as useMemo3, useEffect as useEffect13 } from "react";
5958
+ import { useState as useState16, useMemo as useMemo3, useEffect as useEffect13 } from "react";
5910
5959
  import { ArrowLeft as ArrowLeft2, X as X4 } from "lucide-react";
5911
- import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
5960
+ import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
5912
5961
  var STORAGE_KEY = "unifold_recent_tokens";
5913
5962
  var MAX_RECENT_TOKENS = 5;
5914
5963
  var COMMON_TOKENS = [
@@ -5917,7 +5966,8 @@ var COMMON_TOKENS = [
5917
5966
  { symbol: "USDC", chainType: "solana", chainId: "mainnet" },
5918
5967
  { symbol: "POL", chainType: "ethereum", chainId: "137" },
5919
5968
  { symbol: "BNB", chainType: "ethereum", chainId: "56" },
5920
- { symbol: "BTC", chainType: "bitcoin", chainId: "mainnet" }
5969
+ { symbol: "BTC", chainType: "bitcoin", chainId: "mainnet" },
5970
+ { symbol: "XRP", chainType: "xrpl", chainId: "mainnet" }
5921
5971
  ];
5922
5972
  function getRecentTokens() {
5923
5973
  if (typeof window === "undefined") return [];
@@ -5964,9 +6014,9 @@ function TokenSelectorSheet({
5964
6014
  }) {
5965
6015
  const { themeClass, colors: colors2, fonts, components } = useTheme();
5966
6016
  const isDarkMode = themeClass.includes("uf-dark");
5967
- const [searchQuery, setSearchQuery] = useState17("");
5968
- const [recentTokens, setRecentTokens] = useState17([]);
5969
- const [hoveredTokenKey, setHoveredTokenKey] = useState17(null);
6017
+ const [searchQuery, setSearchQuery] = useState16("");
6018
+ const [recentTokens, setRecentTokens] = useState16([]);
6019
+ const [hoveredTokenKey, setHoveredTokenKey] = useState16(null);
5970
6020
  useEffect13(() => {
5971
6021
  setRecentTokens(getRecentTokens());
5972
6022
  }, []);
@@ -6038,7 +6088,7 @@ function TokenSelectorSheet({
6038
6088
  onOpenChange(false);
6039
6089
  };
6040
6090
  if (!open) return null;
6041
- return /* @__PURE__ */ jsxs29(
6091
+ return /* @__PURE__ */ jsxs28(
6042
6092
  "div",
6043
6093
  {
6044
6094
  className: `${themeClass} uf-px-6`,
@@ -6053,7 +6103,7 @@ function TokenSelectorSheet({
6053
6103
  backgroundColor: colors2.background
6054
6104
  },
6055
6105
  children: [
6056
- /* @__PURE__ */ jsxs29("div", { className: "uf-flex uf-items-center uf-justify-between uf-py-3", children: [
6106
+ /* @__PURE__ */ jsxs28("div", { className: "uf-flex uf-items-center uf-justify-between uf-py-3", children: [
6057
6107
  /* @__PURE__ */ jsx32(
6058
6108
  "button",
6059
6109
  {
@@ -6092,7 +6142,7 @@ function TokenSelectorSheet({
6092
6142
  }
6093
6143
  }
6094
6144
  ) }) }),
6095
- quickSelectOptions.length > 0 && !searchQuery && /* @__PURE__ */ jsxs29("div", { className: "uf-pb-3 uf--mx-6", children: [
6145
+ quickSelectOptions.length > 0 && !searchQuery && /* @__PURE__ */ jsxs28("div", { className: "uf-pb-3 uf--mx-6", children: [
6096
6146
  /* @__PURE__ */ jsx32(
6097
6147
  "div",
6098
6148
  {
@@ -6112,7 +6162,7 @@ function TokenSelectorSheet({
6112
6162
  children: quickSelectOptions.map(({ token, chain, isRecent }) => {
6113
6163
  const chainKey = `${chain.chain_type}:${chain.chain_id}`;
6114
6164
  const isSelected = token.symbol === selectedToken && chainKey === selectedChainKey;
6115
- return /* @__PURE__ */ jsxs29(
6165
+ return /* @__PURE__ */ jsxs28(
6116
6166
  "div",
6117
6167
  {
6118
6168
  style: { position: "relative", flexShrink: 0 },
@@ -6140,7 +6190,7 @@ function TokenSelectorSheet({
6140
6190
  children: /* @__PURE__ */ jsx32(X4, { style: { width: 12, height: 12 } })
6141
6191
  }
6142
6192
  ),
6143
- /* @__PURE__ */ jsxs29(
6193
+ /* @__PURE__ */ jsxs28(
6144
6194
  "button",
6145
6195
  {
6146
6196
  type: "button",
@@ -6159,7 +6209,7 @@ function TokenSelectorSheet({
6159
6209
  backgroundColor: isSelected ? components.card.backgroundColor : hoveredTokenKey === `${token.symbol}-${chainKey}` ? colors2.cardHover : "transparent"
6160
6210
  },
6161
6211
  children: [
6162
- /* @__PURE__ */ jsxs29("div", { style: { position: "relative", flexShrink: 0 }, children: [
6212
+ /* @__PURE__ */ jsxs28("div", { style: { position: "relative", flexShrink: 0 }, children: [
6163
6213
  /* @__PURE__ */ jsx32(
6164
6214
  "img",
6165
6215
  {
@@ -6193,7 +6243,7 @@ function TokenSelectorSheet({
6193
6243
  }
6194
6244
  )
6195
6245
  ] }),
6196
- /* @__PURE__ */ jsxs29("div", { style: { textAlign: "left" }, children: [
6246
+ /* @__PURE__ */ jsxs28("div", { style: { textAlign: "left" }, children: [
6197
6247
  /* @__PURE__ */ jsx32(
6198
6248
  "div",
6199
6249
  {
@@ -6257,7 +6307,7 @@ function TokenSelectorSheet({
6257
6307
  ) : /* @__PURE__ */ jsx32("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: filteredOptions.map(({ token, chain }) => {
6258
6308
  const chainKey = `${chain.chain_type}:${chain.chain_id}`;
6259
6309
  const isSelected = token.symbol === selectedToken && chainKey === selectedChainKey;
6260
- return /* @__PURE__ */ jsxs29(
6310
+ return /* @__PURE__ */ jsxs28(
6261
6311
  "button",
6262
6312
  {
6263
6313
  type: "button",
@@ -6278,7 +6328,7 @@ function TokenSelectorSheet({
6278
6328
  backgroundColor: isSelected ? components.card.backgroundColor : hoveredTokenKey === `${token.symbol}-${chainKey}` ? colors2.cardHover : "transparent"
6279
6329
  },
6280
6330
  children: [
6281
- /* @__PURE__ */ jsxs29("div", { style: { position: "relative", flexShrink: 0 }, children: [
6331
+ /* @__PURE__ */ jsxs28("div", { style: { position: "relative", flexShrink: 0 }, children: [
6282
6332
  /* @__PURE__ */ jsx32(
6283
6333
  "img",
6284
6334
  {
@@ -6312,7 +6362,7 @@ function TokenSelectorSheet({
6312
6362
  }
6313
6363
  )
6314
6364
  ] }),
6315
- /* @__PURE__ */ jsxs29("div", { style: { flex: 1, minWidth: 0 }, children: [
6365
+ /* @__PURE__ */ jsxs28("div", { style: { flex: 1, minWidth: 0 }, children: [
6316
6366
  /* @__PURE__ */ jsx32(
6317
6367
  "div",
6318
6368
  {
@@ -6337,7 +6387,7 @@ function TokenSelectorSheet({
6337
6387
  }
6338
6388
  )
6339
6389
  ] }),
6340
- /* @__PURE__ */ jsxs29(
6390
+ /* @__PURE__ */ jsxs28(
6341
6391
  "div",
6342
6392
  {
6343
6393
  style: {
@@ -6349,7 +6399,7 @@ function TokenSelectorSheet({
6349
6399
  children: [
6350
6400
  "Minimum:",
6351
6401
  " ",
6352
- /* @__PURE__ */ jsxs29("span", { style: { color: isDarkMode ? "#fbbf24" : "#d97706" }, children: [
6402
+ /* @__PURE__ */ jsxs28("span", { style: { color: isDarkMode ? "#fbbf24" : "#d97706" }, children: [
6353
6403
  "$",
6354
6404
  chain.minimum_deposit_amount_usd
6355
6405
  ] })
@@ -6366,50 +6416,34 @@ function TokenSelectorSheet({
6366
6416
  );
6367
6417
  }
6368
6418
 
6369
- // src/components/deposits/shared/PollCooldownButton.tsx
6370
- import { pollDirectExecutions } from "@unifold/core";
6371
- import { jsx as jsx33 } from "react/jsx-runtime";
6372
- function PollCooldownButton({
6373
- currentWalletId,
6374
- pollCooldown,
6375
- publishableKey,
6376
- onCooldownChange,
6377
- cooldownRef,
6378
- buttonText = "Check again"
6419
+ // src/components/deposits/DepositPollingUi.tsx
6420
+ import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
6421
+ function DepositPollingUi({
6422
+ depositConfirmationMode,
6423
+ showWaitingUi,
6424
+ hasExecution,
6425
+ onIveDeposited
6379
6426
  }) {
6380
- const handleClick = async () => {
6381
- if (!currentWalletId || pollCooldown > 0) return;
6382
- try {
6383
- await pollDirectExecutions(
6384
- { deposit_wallet_id: currentWalletId },
6385
- publishableKey
6386
- );
6387
- const cooldownSeconds = 5;
6388
- onCooldownChange(cooldownSeconds);
6389
- if (cooldownRef.current) clearInterval(cooldownRef.current);
6390
- cooldownRef.current = setInterval(() => {
6391
- onCooldownChange((prev) => {
6392
- if (prev <= 1) {
6393
- if (cooldownRef.current) clearInterval(cooldownRef.current);
6394
- cooldownRef.current = null;
6395
- return 0;
6396
- }
6397
- return prev - 1;
6398
- });
6399
- }, 1e3);
6400
- } catch (error) {
6401
- console.error("Failed to start poll workflow:", error);
6402
- }
6403
- };
6404
- return /* @__PURE__ */ jsx33("div", { children: /* @__PURE__ */ jsx33(
6405
- "button",
6406
- {
6407
- onClick: handleClick,
6408
- disabled: !currentWalletId || pollCooldown > 0,
6409
- 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",
6410
- children: pollCooldown > 0 ? `${buttonText} in ${pollCooldown}s` : "I've made the deposit"
6411
- }
6412
- ) });
6427
+ if (depositConfirmationMode === "manual" && !showWaitingUi) {
6428
+ return /* @__PURE__ */ jsx33(
6429
+ "button",
6430
+ {
6431
+ onClick: onIveDeposited,
6432
+ 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",
6433
+ children: "I've made the deposit"
6434
+ }
6435
+ );
6436
+ }
6437
+ if (showWaitingUi && !hasExecution) {
6438
+ return /* @__PURE__ */ jsxs29("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: [
6439
+ /* @__PURE__ */ jsx33("div", { className: "uf-flex-shrink-0", children: /* @__PURE__ */ jsx33("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" }) }),
6440
+ /* @__PURE__ */ jsxs29("div", { children: [
6441
+ /* @__PURE__ */ jsx33("div", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: "Processing deposit transactions" }),
6442
+ /* @__PURE__ */ jsx33("div", { className: "uf-text-xs uf-text-muted-foreground", children: "We're checking if your deposit has landed." })
6443
+ ] })
6444
+ ] });
6445
+ }
6446
+ return null;
6413
6447
  }
6414
6448
 
6415
6449
  // src/components/deposits/shared/DepositFooterLinks.tsx
@@ -6516,9 +6550,9 @@ function GlossaryModal({
6516
6550
  }
6517
6551
 
6518
6552
  // src/components/deposits/shared/useCopyAddress.ts
6519
- import { useState as useState18 } from "react";
6553
+ import { useState as useState17 } from "react";
6520
6554
  function useCopyAddress() {
6521
- const [copied, setCopied] = useState18(false);
6555
+ const [copied, setCopied] = useState17(false);
6522
6556
  const handleCopy = (address) => {
6523
6557
  if (!address) return;
6524
6558
  navigator.clipboard.writeText(address);
@@ -6607,6 +6641,7 @@ function TransferCryptoSingleInput({
6607
6641
  destinationChainType,
6608
6642
  destinationChainId,
6609
6643
  destinationTokenAddress,
6644
+ depositConfirmationMode = "auto_ui",
6610
6645
  onExecutionsChange,
6611
6646
  onDepositSuccess,
6612
6647
  onDepositError,
@@ -6614,25 +6649,15 @@ function TransferCryptoSingleInput({
6614
6649
  }) {
6615
6650
  const { themeClass, colors: colors2, fonts, components } = useTheme();
6616
6651
  const isDarkMode = themeClass.includes("uf-dark");
6617
- const [token, setToken] = useState20("USDC");
6618
- const [chain, setChain] = useState20("solana:mainnet");
6619
- const [copied, setCopied] = useState20(false);
6652
+ const [token, setToken] = useState19("USDC");
6653
+ const [chain, setChain] = useState19("solana:mainnet");
6654
+ const [copied, setCopied] = useState19(false);
6620
6655
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
6621
- const [glossaryOpen, setGlossaryOpen] = useState20(false);
6622
- const [pollCooldown, setPollCooldown] = useState20(0);
6623
- const cooldownRef = useRef4(null);
6624
- const [detailsExpanded, setDetailsExpanded] = useState20(false);
6625
- const [depositsModalOpen, setDepositsModalOpen] = useState20(false);
6626
- const [tokenSelectorOpen, setTokenSelectorOpen] = useState20(false);
6627
- const [initialSelectionDone, setInitialSelectionDone] = useState20(false);
6628
- useEffect14(() => {
6629
- return () => {
6630
- if (cooldownRef.current) {
6631
- clearInterval(cooldownRef.current);
6632
- cooldownRef.current = null;
6633
- }
6634
- };
6635
- }, []);
6656
+ const [glossaryOpen, setGlossaryOpen] = useState19(false);
6657
+ const [detailsExpanded, setDetailsExpanded] = useState19(false);
6658
+ const [depositsModalOpen, setDepositsModalOpen] = useState19(false);
6659
+ const [tokenSelectorOpen, setTokenSelectorOpen] = useState19(false);
6660
+ const [initialSelectionDone, setInitialSelectionDone] = useState19(false);
6636
6661
  const {
6637
6662
  data: tokensResponse,
6638
6663
  isLoading: tokensLoading
@@ -6659,13 +6684,6 @@ function TransferCryptoSingleInput({
6659
6684
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
6660
6685
  const loading = externalWallets?.length ? false : walletsLoading;
6661
6686
  const error = walletsError?.message ?? null;
6662
- const { executions: depositExecutions, isPolling } = useDepositPolling({
6663
- userId,
6664
- publishableKey,
6665
- enabled: true,
6666
- onDepositSuccess,
6667
- onDepositError
6668
- });
6669
6687
  const allAvailableChains = useMemo4(() => {
6670
6688
  const chainsMap = /* @__PURE__ */ new Map();
6671
6689
  supportedTokens.forEach((t6) => {
@@ -6685,6 +6703,15 @@ function TransferCryptoSingleInput({
6685
6703
  const currentChainType = currentChainData?.chain_type || "ethereum";
6686
6704
  const currentWallet = getWalletByChainType2(wallets, currentChainType);
6687
6705
  const depositAddress = currentWallet?.address || "";
6706
+ const { executions: depositExecutions, isPolling, showWaitingUi, handleIveDeposited } = useDepositPolling({
6707
+ userId,
6708
+ publishableKey,
6709
+ depositConfirmationMode,
6710
+ depositWalletId: currentWallet?.id,
6711
+ enabled: true,
6712
+ onDepositSuccess,
6713
+ onDepositError
6714
+ });
6688
6715
  useEffect14(() => {
6689
6716
  if (!supportedTokens.length || initialSelectionDone) return;
6690
6717
  let selectedTokenData;
@@ -6734,28 +6761,6 @@ function TransferCryptoSingleInput({
6734
6761
  onExecutionsChange(depositExecutions);
6735
6762
  }
6736
6763
  }, [depositExecutions, onExecutionsChange]);
6737
- useEffect14(() => {
6738
- if (!wallets.length || !allAvailableChains.length) return;
6739
- const preloadAllQRCodes = async () => {
6740
- for (const wallet of wallets) {
6741
- if (!wallet.address) continue;
6742
- const chainData = allAvailableChains.find(
6743
- (c) => c.chain_type === wallet.chain_type
6744
- );
6745
- const chainIconUrl = chainData?.icon_url;
6746
- await preloadQRCode(
6747
- wallet.address,
6748
- 180,
6749
- // size
6750
- chainIconUrl,
6751
- 45,
6752
- // imageSize
6753
- isDarkMode
6754
- );
6755
- }
6756
- };
6757
- preloadAllQRCodes();
6758
- }, [wallets, allAvailableChains, isDarkMode]);
6759
6764
  useEffect14(() => {
6760
6765
  if (!supportedTokens.length) return;
6761
6766
  const currentToken = supportedTokens.find((t6) => t6.symbol === token);
@@ -7028,14 +7033,12 @@ function TransferCryptoSingleInput({
7028
7033
  ] })
7029
7034
  ] }),
7030
7035
  /* @__PURE__ */ jsx37(
7031
- PollCooldownButton,
7036
+ DepositPollingUi,
7032
7037
  {
7033
- currentWalletId: currentWallet?.id,
7034
- pollCooldown,
7035
- publishableKey,
7036
- onCooldownChange: setPollCooldown,
7037
- cooldownRef,
7038
- buttonText: "Try again"
7038
+ depositConfirmationMode,
7039
+ showWaitingUi,
7040
+ hasExecution: depositExecutions.length > 0,
7041
+ onIveDeposited: handleIveDeposited
7039
7042
  }
7040
7043
  ),
7041
7044
  /* @__PURE__ */ jsx37(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) }),
@@ -7086,7 +7089,7 @@ function TransferCryptoSingleInput({
7086
7089
  }
7087
7090
 
7088
7091
  // src/components/deposits/TransferCryptoDoubleInput.tsx
7089
- import { useState as useState21, useEffect as useEffect15, useRef as useRef5, useMemo as useMemo5 } from "react";
7092
+ import { useState as useState20, useEffect as useEffect15, useMemo as useMemo5 } from "react";
7090
7093
  import {
7091
7094
  ChevronDown as ChevronDown5,
7092
7095
  ChevronUp as ChevronUp4,
@@ -7241,6 +7244,7 @@ function TransferCryptoDoubleInput({
7241
7244
  destinationChainType,
7242
7245
  destinationChainId,
7243
7246
  destinationTokenAddress,
7247
+ depositConfirmationMode = "auto_ui",
7244
7248
  onExecutionsChange,
7245
7249
  onDepositSuccess,
7246
7250
  onDepositError,
@@ -7248,24 +7252,14 @@ function TransferCryptoDoubleInput({
7248
7252
  }) {
7249
7253
  const { themeClass, colors: colors2, fonts, components } = useTheme();
7250
7254
  const isDarkMode = themeClass.includes("uf-dark");
7251
- const [token, setToken] = useState21("USDC");
7252
- const [chain, setChain] = useState21("solana:mainnet");
7253
- const [copied, setCopied] = useState21(false);
7255
+ const [token, setToken] = useState20("USDC");
7256
+ const [chain, setChain] = useState20("solana:mainnet");
7257
+ const [copied, setCopied] = useState20(false);
7254
7258
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
7255
- const [glossaryOpen, setGlossaryOpen] = useState21(false);
7256
- const [pollCooldown, setPollCooldown] = useState21(0);
7257
- const cooldownRef = useRef5(null);
7258
- const [detailsExpanded, setDetailsExpanded] = useState21(false);
7259
- const [depositsModalOpen, setDepositsModalOpen] = useState21(false);
7260
- const [initialSelectionDone, setInitialSelectionDone] = useState21(false);
7261
- useEffect15(() => {
7262
- return () => {
7263
- if (cooldownRef.current) {
7264
- clearInterval(cooldownRef.current);
7265
- cooldownRef.current = null;
7266
- }
7267
- };
7268
- }, []);
7259
+ const [glossaryOpen, setGlossaryOpen] = useState20(false);
7260
+ const [detailsExpanded, setDetailsExpanded] = useState20(false);
7261
+ const [depositsModalOpen, setDepositsModalOpen] = useState20(false);
7262
+ const [initialSelectionDone, setInitialSelectionDone] = useState20(false);
7269
7263
  const {
7270
7264
  data: tokensResponse,
7271
7265
  isLoading: tokensLoading
@@ -7292,13 +7286,6 @@ function TransferCryptoDoubleInput({
7292
7286
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
7293
7287
  const loading = externalWallets?.length ? false : walletsLoading;
7294
7288
  const error = walletsError?.message ?? null;
7295
- const { executions: depositExecutions, isPolling } = useDepositPolling({
7296
- userId,
7297
- publishableKey,
7298
- enabled: true,
7299
- onDepositSuccess,
7300
- onDepositError
7301
- });
7302
7289
  const allAvailableChains = useMemo5(() => {
7303
7290
  const chainsMap = /* @__PURE__ */ new Map();
7304
7291
  supportedTokens.forEach((t6) => {
@@ -7318,6 +7305,15 @@ function TransferCryptoDoubleInput({
7318
7305
  const currentChainType = currentChainData?.chain_type || "ethereum";
7319
7306
  const currentWallet = getWalletByChainType3(wallets, currentChainType);
7320
7307
  const depositAddress = currentWallet?.address || "";
7308
+ const { executions: depositExecutions, isPolling, showWaitingUi, handleIveDeposited } = useDepositPolling({
7309
+ userId,
7310
+ publishableKey,
7311
+ depositConfirmationMode,
7312
+ depositWalletId: currentWallet?.id,
7313
+ enabled: true,
7314
+ onDepositSuccess,
7315
+ onDepositError
7316
+ });
7321
7317
  useEffect15(() => {
7322
7318
  if (!supportedTokens.length || initialSelectionDone) return;
7323
7319
  const allChains = /* @__PURE__ */ new Set();
@@ -7340,28 +7336,6 @@ function TransferCryptoDoubleInput({
7340
7336
  onExecutionsChange(depositExecutions);
7341
7337
  }
7342
7338
  }, [depositExecutions, onExecutionsChange]);
7343
- useEffect15(() => {
7344
- if (!wallets.length || !allAvailableChains.length) return;
7345
- const preloadAllQRCodes = async () => {
7346
- for (const wallet of wallets) {
7347
- if (!wallet.address) continue;
7348
- const chainData = allAvailableChains.find(
7349
- (c) => c.chain_type === wallet.chain_type
7350
- );
7351
- const chainIconUrl = chainData?.icon_url;
7352
- await preloadQRCode(
7353
- wallet.address,
7354
- 180,
7355
- // size
7356
- chainIconUrl,
7357
- 45,
7358
- // imageSize
7359
- isDarkMode
7360
- );
7361
- }
7362
- };
7363
- preloadAllQRCodes();
7364
- }, [wallets, allAvailableChains, isDarkMode]);
7365
7339
  useEffect15(() => {
7366
7340
  if (!supportedTokens.length) return;
7367
7341
  const currentToken = supportedTokens.find((t6) => t6.symbol === token);
@@ -7668,14 +7642,12 @@ function TransferCryptoDoubleInput({
7668
7642
  ] })
7669
7643
  ] }),
7670
7644
  /* @__PURE__ */ jsx39(
7671
- PollCooldownButton,
7645
+ DepositPollingUi,
7672
7646
  {
7673
- currentWalletId: currentWallet?.id,
7674
- pollCooldown,
7675
- publishableKey,
7676
- onCooldownChange: setPollCooldown,
7677
- cooldownRef,
7678
- buttonText: "Check again"
7647
+ depositConfirmationMode,
7648
+ showWaitingUi,
7649
+ hasExecution: depositExecutions.length > 0,
7650
+ onIveDeposited: handleIveDeposited
7679
7651
  }
7680
7652
  ),
7681
7653
  /* @__PURE__ */ jsx39(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) }),
@@ -7729,110 +7701,10 @@ function TransferCryptoDoubleInput({
7729
7701
  import * as React24 from "react";
7730
7702
  import { getAddressBalances as getAddressBalances2, getSupportedDepositTokens as getSupportedDepositTokens2, buildSolanaTransaction, sendSolanaTransaction as sendSolanaTransactionToBackend } from "@unifold/core";
7731
7703
 
7732
- // src/components/deposits/browser-wallets/utils.ts
7733
- function getIconUrl4(iconUrl, assetCdnUrl) {
7734
- if (!iconUrl) return void 0;
7735
- if (iconUrl.startsWith("http://") || iconUrl.startsWith("https://")) {
7736
- return iconUrl;
7737
- }
7738
- if (assetCdnUrl) {
7739
- return `${assetCdnUrl}${iconUrl.startsWith("/") ? "" : "/"}${iconUrl}`;
7740
- }
7741
- return iconUrl;
7742
- }
7743
- function getTokenFromBalance(balance) {
7744
- if (balance.token) {
7745
- return balance.token;
7746
- }
7747
- const legacyBalance = balance;
7748
- if (legacyBalance.symbol && legacyBalance.decimals !== void 0) {
7749
- return {
7750
- symbol: legacyBalance.symbol,
7751
- name: legacyBalance.name,
7752
- icon_url: legacyBalance.icon_url,
7753
- icon_urls: [],
7754
- token_address: legacyBalance.token_address,
7755
- chain_id: legacyBalance.chain_id,
7756
- chain_name: legacyBalance.chain_name,
7757
- chain_type: legacyBalance.chain_type,
7758
- decimals: legacyBalance.decimals,
7759
- chain_icon_url: legacyBalance.chain_icon_url,
7760
- chain_icon_urls: [],
7761
- minimum_deposit_amount_usd: 0
7762
- };
7763
- }
7764
- return null;
7765
- }
7766
- function isBalanceEligible(balance) {
7767
- if (balance.is_eligible !== void 0) {
7768
- return balance.is_eligible;
7769
- }
7770
- const legacyBalance = balance;
7771
- if (legacyBalance.is_eligible !== void 0) {
7772
- return legacyBalance.is_eligible;
7773
- }
7774
- return true;
7775
- }
7776
- function formatTokenAmount(amount, decimals, symbol) {
7777
- const value = Number(amount) / 10 ** decimals;
7778
- const upperSymbol = symbol.toUpperCase();
7779
- let maxDecimals = 4;
7780
- if (upperSymbol === "BTC" || upperSymbol === "WBTC") {
7781
- maxDecimals = 8;
7782
- } else if (upperSymbol === "ETH" || upperSymbol === "WETH" || upperSymbol === "SOL") {
7783
- maxDecimals = 6;
7784
- }
7785
- if (value >= 1) {
7786
- return value.toLocaleString(void 0, {
7787
- minimumFractionDigits: 2,
7788
- maximumFractionDigits: maxDecimals
7789
- });
7790
- } else if (value > 0) {
7791
- return value.toLocaleString(void 0, {
7792
- minimumFractionDigits: 2,
7793
- maximumFractionDigits: maxDecimals,
7794
- minimumSignificantDigits: 2,
7795
- maximumSignificantDigits: 6
7796
- });
7797
- }
7798
- return "0.00";
7799
- }
7800
- function formatUsdAmount(amountUsd) {
7801
- if (!amountUsd) return null;
7802
- const value = parseFloat(amountUsd);
7803
- if (value <= 0) return null;
7804
- return value.toLocaleString(void 0, {
7805
- minimumFractionDigits: 2,
7806
- maximumFractionDigits: 2
7807
- });
7808
- }
7809
- function truncateAddress3(address) {
7810
- if (address.length <= 13) return address;
7811
- return `${address.slice(0, 6)}...${address.slice(-4)}`;
7812
- }
7813
- function formatBalanceDisplay(balance, projectName) {
7814
- return projectName ? `${projectName} Balance: ${balance}` : `Balance: ${balance}`;
7815
- }
7816
- function formatProcessingTime(seconds) {
7817
- if (seconds === null || seconds === 0) {
7818
- return "< 1 min";
7819
- }
7820
- const minutes = Math.floor(seconds / 60);
7821
- const remainingSeconds = seconds % 60;
7822
- if (minutes === 0) {
7823
- return `< ${remainingSeconds} sec`;
7824
- } else if (remainingSeconds === 0) {
7825
- return `< ${minutes} min`;
7826
- } else {
7827
- return `< ${minutes} min ${remainingSeconds} sec`;
7828
- }
7829
- }
7830
-
7831
7704
  // src/components/deposits/browser-wallets/SelectTokenView.tsx
7832
7705
  import { Loader2 as Loader22 } from "lucide-react";
7833
7706
  import { Fragment as Fragment5, jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
7834
7707
  function SelectTokenView({
7835
- walletInfo,
7836
7708
  projectName,
7837
7709
  assetCdnUrl,
7838
7710
  balances,
@@ -7851,27 +7723,12 @@ function SelectTokenView({
7851
7723
  DepositHeader,
7852
7724
  {
7853
7725
  title: "Select Token",
7726
+ subtitle: formatBalanceDisplay(`$${totalBalanceUsd || "0.00"}`, projectName),
7854
7727
  showBack: true,
7855
7728
  onBack,
7856
7729
  onClose
7857
7730
  }
7858
7731
  ),
7859
- /* @__PURE__ */ jsxs35(
7860
- "div",
7861
- {
7862
- className: "uf-flex uf-flex-col uf-w-full uf-items-center uf-pb-3",
7863
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
7864
- children: [
7865
- /* @__PURE__ */ jsxs35("div", { className: "uf-text-xs", children: [
7866
- walletInfo.name,
7867
- " (",
7868
- truncateAddress3(walletInfo.address),
7869
- ")"
7870
- ] }),
7871
- /* @__PURE__ */ jsx40("div", { className: "uf-text-xs", children: formatBalanceDisplay(`$${totalBalanceUsd || "0.00"}`, projectName) })
7872
- ]
7873
- }
7874
- ),
7875
7732
  /* @__PURE__ */ jsx40("div", { className: "uf-h-[300px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ jsx40("div", { className: "uf-space-y-2", children: isLoading ? /* @__PURE__ */ jsx40("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-12", children: /* @__PURE__ */ jsx40(
7876
7733
  Loader22,
7877
7734
  {
@@ -7882,6 +7739,7 @@ function SelectTokenView({
7882
7739
  const token = getTokenFromBalance(balance);
7883
7740
  if (!token) return null;
7884
7741
  const isEligible = isBalanceEligible(balance);
7742
+ const ineligibilityMessage = getIneligibilityMessage(balance);
7885
7743
  const isSelected = selectedBalance && getTokenFromBalance(selectedBalance)?.token_address === token.token_address && getTokenFromBalance(selectedBalance)?.chain_id === token.chain_id;
7886
7744
  const formattedAmount = formatTokenAmount(balance.amount, token.decimals, token.symbol);
7887
7745
  const formattedUsd = formatUsdAmount(balance.amount_usd);
@@ -7899,10 +7757,10 @@ function SelectTokenView({
7899
7757
  children: [
7900
7758
  /* @__PURE__ */ jsxs35("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
7901
7759
  /* @__PURE__ */ jsxs35("div", { className: "uf-relative uf-w-9 uf-h-9", children: [
7902
- getIconUrl4(token.icon_url, assetCdnUrl) ? /* @__PURE__ */ jsx40(
7760
+ getIconUrl(token.icon_url, assetCdnUrl) ? /* @__PURE__ */ jsx40(
7903
7761
  "img",
7904
7762
  {
7905
- src: getIconUrl4(token.icon_url, assetCdnUrl),
7763
+ src: getIconUrl(token.icon_url, assetCdnUrl),
7906
7764
  alt: token.symbol,
7907
7765
  width: 36,
7908
7766
  height: 36,
@@ -7917,10 +7775,10 @@ function SelectTokenView({
7917
7775
  children: /* @__PURE__ */ jsx40("span", { className: "uf-text-xs uf-font-medium", style: { color: colors2.foreground }, children: token.symbol.slice(0, 2) })
7918
7776
  }
7919
7777
  ),
7920
- getIconUrl4(token.chain_icon_url, assetCdnUrl) && /* @__PURE__ */ jsx40(
7778
+ getIconUrl(token.chain_icon_url, assetCdnUrl) && /* @__PURE__ */ jsx40(
7921
7779
  "img",
7922
7780
  {
7923
- src: getIconUrl4(token.chain_icon_url, assetCdnUrl),
7781
+ src: getIconUrl(token.chain_icon_url, assetCdnUrl),
7924
7782
  alt: token.chain_name,
7925
7783
  width: 16,
7926
7784
  height: 16,
@@ -7951,7 +7809,7 @@ function SelectTokenView({
7951
7809
  style: { color: components.card.subtitleColor, fontFamily: fonts.regular },
7952
7810
  children: [
7953
7811
  token.chain_name,
7954
- !isEligible && " \u2022 Minimum not met"
7812
+ ineligibilityMessage && ` \u2022 ${ineligibilityMessage}`
7955
7813
  ]
7956
7814
  }
7957
7815
  )
@@ -8010,8 +7868,6 @@ function SelectTokenView({
8010
7868
  // src/components/deposits/browser-wallets/EnterAmountView.tsx
8011
7869
  import { Fragment as Fragment6, jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
8012
7870
  function EnterAmountView({
8013
- walletInfo,
8014
- projectName,
8015
7871
  selectedBalance,
8016
7872
  selectedToken,
8017
7873
  amountUsd,
@@ -8028,54 +7884,20 @@ function EnterAmountView({
8028
7884
  onClose
8029
7885
  }) {
8030
7886
  const { colors: colors2, fonts, components } = useTheme();
8031
- return /* @__PURE__ */ jsxs36("div", { className: "uf-flex uf-flex-col uf-h-[420px]", children: [
7887
+ 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}`;
7888
+ return /* @__PURE__ */ jsxs36(Fragment6, { children: [
8032
7889
  /* @__PURE__ */ jsx41(
8033
7890
  DepositHeader,
8034
7891
  {
8035
7892
  title: "Enter Amount",
7893
+ subtitle: balanceSubtitle,
8036
7894
  showBack: true,
8037
7895
  onBack,
8038
7896
  onClose
8039
7897
  }
8040
7898
  ),
8041
- /* @__PURE__ */ jsxs36("div", { className: "uf-text-center uf-pb-2", children: [
8042
- /* @__PURE__ */ jsxs36(
8043
- "div",
8044
- {
8045
- className: "uf-text-xs",
8046
- style: { color: colors2.foreground, fontFamily: fonts.regular },
8047
- children: [
8048
- walletInfo.name,
8049
- " (",
8050
- truncateAddress3(walletInfo.address),
8051
- ")"
8052
- ]
8053
- }
8054
- ),
8055
- /* @__PURE__ */ jsx41(
8056
- "div",
8057
- {
8058
- className: "uf-text-sm uf-mt-1",
8059
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
8060
- children: selectedBalance?.amount_usd ? /* @__PURE__ */ jsxs36(Fragment6, { children: [
8061
- "Balance: $",
8062
- parseFloat(selectedBalance.amount_usd).toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
8063
- " (",
8064
- formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol),
8065
- " ",
8066
- selectedToken.symbol,
8067
- ")"
8068
- ] }) : /* @__PURE__ */ jsxs36(Fragment6, { children: [
8069
- "Balance: ",
8070
- formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol),
8071
- " ",
8072
- selectedToken.symbol
8073
- ] })
8074
- }
8075
- )
8076
- ] }),
8077
- /* @__PURE__ */ jsxs36("div", { className: "uf-flex-1 uf-overflow-y-auto", children: [
8078
- /* @__PURE__ */ jsx41("div", { className: "uf-text-center uf-h-[100px] uf-flex uf-flex-col uf-justify-center", children: /* @__PURE__ */ jsxs36("div", { className: "uf-flex uf-items-center uf-justify-center", children: [
7899
+ /* @__PURE__ */ jsxs36("div", { className: "uf-text-center uf-py-6", children: [
7900
+ /* @__PURE__ */ jsxs36("div", { className: "uf-flex uf-items-center uf-justify-center", children: [
8079
7901
  /* @__PURE__ */ jsx41(
8080
7902
  "span",
8081
7903
  {
@@ -8111,60 +7933,57 @@ function EnterAmountView({
8111
7933
  }
8112
7934
  }
8113
7935
  )
8114
- ] }) }),
8115
- formattedTokenAmount && /* @__PURE__ */ jsxs36("div", { className: "uf-text-sm uf-text-center", style: { color: colors2.foregroundMuted }, children: [
7936
+ ] }),
7937
+ formattedTokenAmount && /* @__PURE__ */ jsxs36("div", { className: "uf-text-sm uf-mt-2", style: { color: colors2.foregroundMuted }, children: [
8116
7938
  "\u2248 ",
8117
7939
  formattedTokenAmount
8118
- ] }),
8119
- /* @__PURE__ */ jsxs36("div", { className: "uf-flex uf-gap-2 uf-mt-4 uf-mb-4", children: [
8120
- [25, 50, 100, 500].map((quickAmount) => /* @__PURE__ */ jsxs36(
8121
- "button",
8122
- {
8123
- onClick: () => onAmountChange(quickAmount.toString()),
8124
- className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
8125
- style: {
8126
- backgroundColor: components.card.backgroundColor,
8127
- color: colors2.foreground,
8128
- fontFamily: fonts.medium
8129
- },
8130
- children: [
8131
- "$",
8132
- quickAmount
8133
- ]
8134
- },
8135
- quickAmount
8136
- )),
8137
- /* @__PURE__ */ jsx41(
8138
- "button",
8139
- {
8140
- onClick: onMaxClick,
8141
- className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
8142
- style: {
8143
- backgroundColor: colors2.primary + "20",
8144
- color: colors2.primary,
8145
- fontFamily: fonts.medium
8146
- },
8147
- children: "MAX"
8148
- }
8149
- )
8150
- ] }),
8151
- tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && /* @__PURE__ */ jsxs36(
8152
- "div",
7940
+ ] })
7941
+ ] }),
7942
+ /* @__PURE__ */ jsxs36("div", { className: "uf-flex uf-gap-2 uf-mb-4", children: [
7943
+ [25, 50, 100, 500].map((quickAmount) => /* @__PURE__ */ jsxs36(
7944
+ "button",
8153
7945
  {
8154
- className: "uf-text-center uf-text-xs uf-mb-2",
7946
+ onClick: () => onAmountChange(quickAmount.toString()),
7947
+ className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
8155
7948
  style: {
8156
- color: colors2.warning,
8157
- fontFamily: fonts.regular
7949
+ backgroundColor: components.card.backgroundColor,
7950
+ color: colors2.foreground,
7951
+ fontFamily: fonts.medium
8158
7952
  },
8159
7953
  children: [
8160
- "Minimum deposit: $",
8161
- tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
7954
+ "$",
7955
+ quickAmount
8162
7956
  ]
7957
+ },
7958
+ quickAmount
7959
+ )),
7960
+ /* @__PURE__ */ jsx41(
7961
+ "button",
7962
+ {
7963
+ onClick: onMaxClick,
7964
+ className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
7965
+ style: {
7966
+ backgroundColor: colors2.primary + "20",
7967
+ color: colors2.primary,
7968
+ fontFamily: fonts.medium
7969
+ },
7970
+ children: "MAX"
8163
7971
  }
8164
- ),
8165
- inputUsdNum > 0 && /* @__PURE__ */ jsx41(Fragment6, { children: inputUsdNum > maxUsdAmount ? /* @__PURE__ */ jsx41("div", { className: "uf-text-center uf-text-sm uf-mb-2", style: { color: colors2.error }, children: "Insufficient balance" }) : error && /* @__PURE__ */ jsx41("div", { className: "uf-text-center uf-text-sm uf-mb-2 uf-px-2", style: { color: colors2.error }, children: error }) })
7972
+ )
8166
7973
  ] }),
8167
- /* @__PURE__ */ jsx41("div", { className: "uf-pt-4", children: /* @__PURE__ */ jsx41(
7974
+ tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && /* @__PURE__ */ jsxs36(
7975
+ "div",
7976
+ {
7977
+ className: "uf-text-center uf-text-xs uf-mb-3",
7978
+ style: { color: colors2.warning, fontFamily: fonts.regular },
7979
+ children: [
7980
+ "Minimum deposit: $",
7981
+ tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
7982
+ ]
7983
+ }
7984
+ ),
7985
+ inputUsdNum > 0 && /* @__PURE__ */ jsx41(Fragment6, { children: inputUsdNum > maxUsdAmount ? /* @__PURE__ */ jsx41("div", { className: "uf-text-center uf-text-sm uf-mb-3", style: { color: colors2.error }, children: "Insufficient balance" }) : error && /* @__PURE__ */ jsx41("div", { className: "uf-text-center uf-text-sm uf-mb-3 uf-px-2", style: { color: colors2.error }, children: error }) }),
7986
+ /* @__PURE__ */ jsx41(
8168
7987
  "button",
8169
7988
  {
8170
7989
  onClick: onReview,
@@ -8177,7 +7996,7 @@ function EnterAmountView({
8177
7996
  },
8178
7997
  children: "Review"
8179
7998
  }
8180
- ) })
7999
+ )
8181
8000
  ] });
8182
8001
  }
8183
8002
 
@@ -8245,10 +8064,10 @@ function ReviewView({
8245
8064
  }
8246
8065
  ),
8247
8066
  /* @__PURE__ */ jsxs37("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
8248
- getIconUrl4(selectedToken.icon_url, assetCdnUrl) && /* @__PURE__ */ jsx42(
8067
+ getIconUrl(selectedToken.icon_url, assetCdnUrl) && /* @__PURE__ */ jsx42(
8249
8068
  "img",
8250
8069
  {
8251
- src: getIconUrl4(selectedToken.icon_url, assetCdnUrl),
8070
+ src: getIconUrl(selectedToken.icon_url, assetCdnUrl),
8252
8071
  alt: selectedToken.symbol,
8253
8072
  className: "uf-w-5 uf-h-5 uf-rounded-full"
8254
8073
  }
@@ -8261,7 +8080,7 @@ function ReviewView({
8261
8080
  children: [
8262
8081
  walletInfo.name,
8263
8082
  " (",
8264
- truncateAddress3(walletInfo.address),
8083
+ truncateAddress2(walletInfo.address),
8265
8084
  ")"
8266
8085
  ]
8267
8086
  }
@@ -8282,7 +8101,7 @@ function ReviewView({
8282
8101
  {
8283
8102
  className: "uf-text-sm uf-font-medium",
8284
8103
  style: { color: colors2.foreground, fontFamily: fonts.medium },
8285
- children: truncateAddress3(recipientAddress)
8104
+ children: truncateAddress2(recipientAddress)
8286
8105
  }
8287
8106
  )
8288
8107
  ] }),
@@ -8486,7 +8305,7 @@ function BrowserWalletModal({
8486
8305
  const themeClass = theme === "dark" ? "uf-dark" : "";
8487
8306
  const chainType = depositWallet.chain_type;
8488
8307
  const recipientAddress = depositWallet.address;
8489
- const supportedChainType = chainType === "algorand" ? "ethereum" : chainType;
8308
+ const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
8490
8309
  const { executions: depositExecutions, isPolling } = useDepositPolling({
8491
8310
  userId,
8492
8311
  publishableKey,
@@ -8897,20 +8716,6 @@ function BrowserWalletModal({
8897
8716
  if (tokenAmount === 0 || !selectedToken) return null;
8898
8717
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(/\.?0+$/, "");
8899
8718
  }, [tokenAmount, selectedToken]);
8900
- const getTitle = () => {
8901
- switch (step) {
8902
- case "select-token":
8903
- return "Select Token";
8904
- case "input-amount":
8905
- return "Enter Amount";
8906
- case "review":
8907
- return "Review";
8908
- case "confirming":
8909
- return "Confirming...";
8910
- default:
8911
- return "Browser Wallet";
8912
- }
8913
- };
8914
8719
  return /* @__PURE__ */ jsx44(Fragment9, { children: /* @__PURE__ */ jsx44(
8915
8720
  Dialog,
8916
8721
  {
@@ -8932,7 +8737,6 @@ function BrowserWalletModal({
8932
8737
  step === "select-token" && /* @__PURE__ */ jsx44(
8933
8738
  SelectTokenView,
8934
8739
  {
8935
- walletInfo,
8936
8740
  projectName,
8937
8741
  assetCdnUrl,
8938
8742
  balances,
@@ -8949,8 +8753,6 @@ function BrowserWalletModal({
8949
8753
  step === "input-amount" && selectedToken && selectedBalance && /* @__PURE__ */ jsx44(
8950
8754
  EnterAmountView,
8951
8755
  {
8952
- walletInfo,
8953
- projectName,
8954
8756
  selectedBalance,
8955
8757
  selectedToken,
8956
8758
  amountUsd,
@@ -9302,6 +9104,7 @@ function WalletSelectionModal({
9302
9104
  if (!accounts || accounts.length === 0) {
9303
9105
  throw new Error("No accounts returned from wallet");
9304
9106
  }
9107
+ setUserDisconnectedWallet(false);
9305
9108
  const address = accounts[0];
9306
9109
  const walletType = wallet.id === "phantom" ? "phantom-ethereum" : wallet.id === "coinbase" ? "coinbase" : "metamask";
9307
9110
  onWalletConnected({
@@ -9341,6 +9144,7 @@ function WalletSelectionModal({
9341
9144
  }
9342
9145
  const response = await provider.connect();
9343
9146
  const address = response.publicKey.toString();
9147
+ setUserDisconnectedWallet(false);
9344
9148
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
9345
9149
  onWalletConnected({
9346
9150
  type: walletType,
@@ -9648,24 +9452,25 @@ function DepositModal({
9648
9452
  hideDepositTracker = false,
9649
9453
  showBalanceHeader = false,
9650
9454
  transferInputVariant = "double_input",
9455
+ depositConfirmationMode = "auto_ui",
9651
9456
  enableConnectWallet = false,
9652
9457
  onDepositSuccess,
9653
9458
  onDepositError,
9654
9459
  theme = "dark"
9655
9460
  }) {
9656
9461
  const { colors: colors2, fonts } = useTheme();
9657
- const [view, setView] = useState25("main");
9658
- const [cardView, setCardView] = useState25(
9462
+ const [view, setView] = useState24("main");
9463
+ const [cardView, setCardView] = useState24(
9659
9464
  "amount"
9660
9465
  );
9661
- const [browserWalletModalOpen, setBrowserWalletModalOpen] = useState25(false);
9662
- const [browserWalletInfo, setBrowserWalletInfo] = useState25(null);
9663
- const [walletSelectionModalOpen, setWalletSelectionModalOpen] = useState25(false);
9664
- const [browserWalletChainType, setBrowserWalletChainType] = useState25(() => getStoredWalletChainType());
9665
- const [quotesCount, setQuotesCount] = useState25(0);
9666
- const [depositsModalOpen, setDepositsModalOpen] = useState25(false);
9667
- const [depositExecutions, setDepositExecutions] = useState25([]);
9668
- const [projectConfig, setProjectConfig] = useState25(null);
9466
+ const [browserWalletModalOpen, setBrowserWalletModalOpen] = useState24(false);
9467
+ const [browserWalletInfo, setBrowserWalletInfo] = useState24(null);
9468
+ const [walletSelectionModalOpen, setWalletSelectionModalOpen] = useState24(false);
9469
+ const [browserWalletChainType, setBrowserWalletChainType] = useState24(() => getStoredWalletChainType());
9470
+ const [quotesCount, setQuotesCount] = useState24(0);
9471
+ const [depositsModalOpen, setDepositsModalOpen] = useState24(false);
9472
+ const [depositExecutions, setDepositExecutions] = useState24([]);
9473
+ const [projectConfig, setProjectConfig] = useState24(null);
9669
9474
  const isMobileView = useIsMobileViewport();
9670
9475
  useEffect18(() => {
9671
9476
  setProjectConfig(null);
@@ -9684,7 +9489,7 @@ function DepositModal({
9684
9489
  // Only fetch when modal is open
9685
9490
  });
9686
9491
  const wallets = depositAddressResponse?.data ?? [];
9687
- const [resolvedTheme, setResolvedTheme] = useState25(
9492
+ const [resolvedTheme, setResolvedTheme] = useState24(
9688
9493
  theme === "auto" ? "dark" : theme
9689
9494
  );
9690
9495
  useEffect18(() => {
@@ -9739,6 +9544,7 @@ function DepositModal({
9739
9544
  };
9740
9545
  const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
9741
9546
  const handleWalletDisconnect = () => {
9547
+ setUserDisconnectedWallet(true);
9742
9548
  clearStoredWalletChainType();
9743
9549
  setBrowserWalletChainType(void 0);
9744
9550
  setBrowserWalletInfo(null);
@@ -9830,6 +9636,7 @@ function DepositModal({
9830
9636
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
9831
9637
  balanceChainId: destinationChainId,
9832
9638
  balanceTokenAddress: destinationTokenAddress,
9639
+ projectName: projectConfig?.project_name,
9833
9640
  publishableKey
9834
9641
  }
9835
9642
  ),
@@ -9910,7 +9717,14 @@ function DepositModal({
9910
9717
  title: t5.transferCrypto.title,
9911
9718
  showBack: true,
9912
9719
  onBack: handleBack,
9913
- onClose: handleClose
9720
+ onClose: handleClose,
9721
+ showBalance: showBalanceHeader,
9722
+ balanceAddress: recipientAddress,
9723
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
9724
+ balanceChainId: destinationChainId,
9725
+ balanceTokenAddress: destinationTokenAddress,
9726
+ projectName: projectConfig?.project_name,
9727
+ publishableKey
9914
9728
  }
9915
9729
  ),
9916
9730
  transferInputVariant === "single_input" ? /* @__PURE__ */ jsx46(
@@ -9922,6 +9736,7 @@ function DepositModal({
9922
9736
  destinationChainType,
9923
9737
  destinationChainId,
9924
9738
  destinationTokenAddress,
9739
+ depositConfirmationMode,
9925
9740
  onExecutionsChange: setDepositExecutions,
9926
9741
  onDepositSuccess,
9927
9742
  onDepositError,
@@ -9936,6 +9751,7 @@ function DepositModal({
9936
9751
  destinationChainType,
9937
9752
  destinationChainId,
9938
9753
  destinationTokenAddress,
9754
+ depositConfirmationMode,
9939
9755
  onExecutionsChange: setDepositExecutions,
9940
9756
  onDepositSuccess,
9941
9757
  onDepositError,
@@ -9950,7 +9766,14 @@ function DepositModal({
9950
9766
  showBack: true,
9951
9767
  onBack: handleBack,
9952
9768
  onClose: handleClose,
9953
- badge: cardView === "quotes" ? { count: quotesCount } : void 0
9769
+ badge: cardView === "quotes" ? { count: quotesCount } : void 0,
9770
+ showBalance: showBalanceHeader,
9771
+ balanceAddress: recipientAddress,
9772
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
9773
+ balanceChainId: destinationChainId,
9774
+ balanceTokenAddress: destinationTokenAddress,
9775
+ projectName: projectConfig?.project_name,
9776
+ publishableKey
9954
9777
  }
9955
9778
  ),
9956
9779
  /* @__PURE__ */ jsx46(
@@ -10100,6 +9923,7 @@ export {
10100
9923
  DepositExecutionItem,
10101
9924
  DepositHeader,
10102
9925
  DepositModal,
9926
+ DepositPollingUi,
10103
9927
  DepositSuccessToast,
10104
9928
  DepositTrackerButton,
10105
9929
  DepositWithCardButton,
@@ -10134,16 +9958,14 @@ export {
10134
9958
  TransferCryptoDoubleInput,
10135
9959
  TransferCryptoSingleInput,
10136
9960
  buttonVariants,
10137
- clearQRCodeCache,
10138
9961
  cn,
10139
9962
  colors,
10140
9963
  defaultColors,
10141
9964
  getColors,
10142
- isQRCodeCached,
10143
9965
  mergeColors,
10144
- preloadQRCode,
10145
9966
  resolveComponentTokens,
10146
9967
  truncateAddress,
10147
9968
  useAllowedCountry,
9969
+ useDepositPolling,
10148
9970
  useTheme
10149
9971
  };