@unifold/ui-react 0.1.21 → 0.1.22

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
@@ -85,7 +85,7 @@ __export(index_exports, {
85
85
  module.exports = __toCommonJS(index_exports);
86
86
 
87
87
  // src/components/deposits/DepositModal.tsx
88
- var import_react12 = require("react");
88
+ var import_react13 = require("react");
89
89
  var import_lucide_react15 = require("lucide-react");
90
90
 
91
91
  // src/components/shared/dialog.tsx
@@ -99,6 +99,29 @@ var import_tailwind_merge = require("tailwind-merge");
99
99
  function cn(...inputs) {
100
100
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
101
101
  }
102
+ function formatEstimatedTime(seconds) {
103
+ if (seconds == null) {
104
+ return "< 1 min";
105
+ }
106
+ if (seconds < 60) {
107
+ return `< ${seconds} sec${seconds > 1 ? "s" : ""}`;
108
+ } else if (seconds < 3600) {
109
+ const mins = Math.ceil(seconds / 60);
110
+ return `< ${mins} min${mins > 1 ? "s" : ""}`;
111
+ } else {
112
+ let hrs = Math.floor(seconds / 3600);
113
+ let mins = Math.ceil(seconds % 3600 / 60);
114
+ if (mins === 60) {
115
+ hrs += 1;
116
+ mins = 0;
117
+ }
118
+ const hrLabel = hrs > 1 ? "hrs" : "hr";
119
+ if (mins === 0) {
120
+ return `< ${hrs} ${hrLabel}`;
121
+ }
122
+ return `< ${hrs} ${hrLabel} ${mins} min${mins > 1 ? "s" : ""}`;
123
+ }
124
+ }
102
125
 
103
126
  // src/context/ThemeContext.tsx
104
127
  var React = __toESM(require("react"));
@@ -552,15 +575,17 @@ var DialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @
552
575
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
553
576
 
554
577
  // src/components/deposits/BuyWithCard.tsx
555
- var import_react6 = require("react");
578
+ var import_react7 = require("react");
556
579
  var import_lucide_react6 = require("lucide-react");
557
- var import_core6 = require("@unifold/core");
580
+ var import_core7 = require("@unifold/core");
558
581
 
559
582
  // src/components/deposits/CurrencyModal.tsx
560
- var import_react = require("react");
583
+ var import_react2 = require("react");
561
584
 
562
585
  // src/components/deposits/DepositHeader.tsx
563
586
  var import_lucide_react2 = require("lucide-react");
587
+ var import_react = require("react");
588
+ var import_core = require("@unifold/core");
564
589
  var import_jsx_runtime3 = require("react/jsx-runtime");
565
590
  function DepositHeader({
566
591
  title,
@@ -568,10 +593,83 @@ function DepositHeader({
568
593
  showClose = true,
569
594
  onBack,
570
595
  onClose,
571
- badge
596
+ badge,
597
+ showBalance = false,
598
+ balanceAddress,
599
+ balanceChainType,
600
+ balanceChainId,
601
+ balanceTokenAddress,
602
+ publishableKey
572
603
  }) {
573
604
  const { colors: colors2, fonts, components } = useTheme();
574
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
605
+ const [balance, setBalance] = (0, import_react.useState)(null);
606
+ const [isLoadingBalance, setIsLoadingBalance] = (0, import_react.useState)(false);
607
+ (0, import_react.useEffect)(() => {
608
+ if (!showBalance || !balanceAddress || !balanceChainType || !balanceChainId || !balanceTokenAddress || !publishableKey) {
609
+ setBalance(null);
610
+ setIsLoadingBalance(false);
611
+ return;
612
+ }
613
+ let cancelled = false;
614
+ setIsLoadingBalance(true);
615
+ (0, import_core.getAddressBalance)(
616
+ balanceAddress,
617
+ balanceChainType,
618
+ balanceChainId,
619
+ balanceTokenAddress,
620
+ publishableKey
621
+ ).then((response) => {
622
+ if (cancelled) return;
623
+ if (response.balance && response.balance.amount !== "0") {
624
+ const value = Number(response.balance.amount) / 10 ** response.balance.token.decimals;
625
+ let formatted;
626
+ let maxDecimals = 4;
627
+ const symbol = response.balance.token.symbol?.toUpperCase() || "";
628
+ if (symbol === "BTC" || symbol === "WBTC") {
629
+ maxDecimals = 8;
630
+ } else if (symbol === "ETH" || symbol === "WETH") {
631
+ maxDecimals = 6;
632
+ }
633
+ if (value >= 1) {
634
+ formatted = value.toLocaleString(void 0, {
635
+ minimumFractionDigits: 2,
636
+ maximumFractionDigits: maxDecimals
637
+ });
638
+ } else if (value > 0) {
639
+ formatted = value.toLocaleString(void 0, {
640
+ minimumFractionDigits: 2,
641
+ maximumFractionDigits: maxDecimals,
642
+ minimumSignificantDigits: 2,
643
+ maximumSignificantDigits: 6
644
+ });
645
+ } else {
646
+ formatted = value.toExponential(2);
647
+ }
648
+ const balanceText = response.balance.amount_usd ? `Balance: $${response.balance.amount_usd} (${formatted} ${response.balance.token.symbol})` : `Balance: ${formatted} ${response.balance.token.symbol}`;
649
+ setBalance(balanceText);
650
+ } else {
651
+ setBalance(null);
652
+ }
653
+ }).catch((error) => {
654
+ if (cancelled) return;
655
+ console.error("Error fetching balance:", error);
656
+ setBalance(null);
657
+ }).finally(() => {
658
+ if (cancelled) return;
659
+ setIsLoadingBalance(false);
660
+ });
661
+ return () => {
662
+ cancelled = true;
663
+ };
664
+ }, [
665
+ showBalance,
666
+ balanceAddress,
667
+ balanceChainType,
668
+ balanceChainId,
669
+ balanceTokenAddress,
670
+ publishableKey
671
+ ]);
672
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
575
673
  showBack ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
576
674
  "button",
577
675
  {
@@ -581,8 +679,32 @@ function DepositHeader({
581
679
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.ArrowLeft, { className: "uf-w-5 uf-h-5" })
582
680
  }
583
681
  ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
584
- badge ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
585
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
682
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
683
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
684
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
685
+ DialogTitle,
686
+ {
687
+ className: "uf-text-center uf-text-base",
688
+ style: {
689
+ color: components.header.titleColor,
690
+ fontFamily: fonts.medium
691
+ },
692
+ children: title
693
+ }
694
+ ),
695
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
696
+ "div",
697
+ {
698
+ className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
699
+ style: {
700
+ backgroundColor: colors2.card,
701
+ color: colors2.foregroundMuted,
702
+ fontFamily: fonts.regular
703
+ },
704
+ children: badge.count
705
+ }
706
+ )
707
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
586
708
  DialogTitle,
587
709
  {
588
710
  className: "uf-text-center uf-text-base",
@@ -593,29 +715,19 @@ function DepositHeader({
593
715
  children: title
594
716
  }
595
717
  ),
596
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
718
+ showBalance && (isLoadingBalance ? /* @__PURE__ */ (0, import_jsx_runtime3.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_runtime3.jsx)(
597
719
  "div",
598
720
  {
599
- className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
721
+ className: "uf-text-xs uf-mt-2",
600
722
  style: {
601
- backgroundColor: colors2.card,
602
- color: colors2.foregroundMuted,
603
- fontFamily: fonts.regular
723
+ color: colors2.foreground,
724
+ fontFamily: fonts.regular,
725
+ opacity: 0.7
604
726
  },
605
- children: badge.count
727
+ children: balance
606
728
  }
607
- )
608
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
609
- DialogTitle,
610
- {
611
- className: "uf-text-center uf-text-base",
612
- style: {
613
- color: components.header.titleColor,
614
- fontFamily: fonts.medium
615
- },
616
- children: title
617
- }
618
- ),
729
+ ) : null)
730
+ ] }),
619
731
  showClose ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
620
732
  "button",
621
733
  {
@@ -625,13 +737,13 @@ function DepositHeader({
625
737
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { className: "uf-w-5 uf-h-5" })
626
738
  }
627
739
  ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
628
- ] });
740
+ ] }) });
629
741
  }
630
742
 
631
743
  // src/components/currency/CurrencyListItem.tsx
632
744
  var React3 = __toESM(require("react"));
633
745
  var import_lucide_react3 = require("lucide-react");
634
- var import_core = require("@unifold/core");
746
+ var import_core2 = require("@unifold/core");
635
747
  var import_jsx_runtime4 = require("react/jsx-runtime");
636
748
  function CurrencyListItem({
637
749
  currency,
@@ -640,7 +752,7 @@ function CurrencyListItem({
640
752
  }) {
641
753
  const { colors: colors2, fonts, components } = useTheme();
642
754
  const [isHovered, setIsHovered] = React3.useState(false);
643
- const iconUrl = (0, import_core.getPreferredIconUrl)(currency.icon_urls, "png") || currency.icon_url;
755
+ const iconUrl = (0, import_core2.getPreferredIconUrl)(currency.icon_urls, "png") || currency.icon_url;
644
756
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
645
757
  "button",
646
758
  {
@@ -738,7 +850,7 @@ function CurrencyModal({
738
850
  themeClass = ""
739
851
  }) {
740
852
  const { colors: colors2, fonts, components } = useTheme();
741
- const [searchQuery, setSearchQuery] = (0, import_react.useState)("");
853
+ const [searchQuery, setSearchQuery] = (0, import_react2.useState)("");
742
854
  const preferredCurrencies = preferredCurrencyCodes.map(
743
855
  (code) => currencies.find(
744
856
  (currency) => currency.currency_code.toLowerCase() === code.toLowerCase()
@@ -834,7 +946,7 @@ function CurrencyModal({
834
946
 
835
947
  // src/hooks/use-user-ip.ts
836
948
  var import_react_query = require("@tanstack/react-query");
837
- var import_core2 = require("@unifold/core");
949
+ var import_core3 = require("@unifold/core");
838
950
  function useUserIp() {
839
951
  const {
840
952
  data: userIpInfo,
@@ -843,7 +955,7 @@ function useUserIp() {
843
955
  } = (0, import_react_query.useQuery)({
844
956
  queryKey: ["unifold", "userIpInfo"],
845
957
  queryFn: async () => {
846
- const data = await (0, import_core2.getIpAddress)();
958
+ const data = await (0, import_core3.getIpAddress)();
847
959
  return {
848
960
  alpha2: data.alpha2.toLowerCase(),
849
961
  alpha3: data.alpha3?.toLowerCase(),
@@ -914,7 +1026,19 @@ var en_default = {
914
1026
  minimumDeposit: "Minimum: {{amount}}",
915
1027
  minimumDepositTooltip: "The minimum amount you can deposit on the selected network.",
916
1028
  selectTokenDeposit: "Your deposit token",
917
- selectTokenDepositTooltip: "Select the token you want to deposit with in order to begin the deposit process."
1029
+ selectTokenDepositTooltip: "Select the token you want to deposit with in order to begin the deposit process.",
1030
+ addressValidation: {
1031
+ validating: "Verifying recipient address...",
1032
+ unableToReceiveFunds: "Unable to Receive Funds",
1033
+ errors: {
1034
+ token_not_supported: "The destination token is not supported",
1035
+ not_opted_in: "Please make sure you opt-in {{token_symbol}}({{chain_name}}) before receiving funds",
1036
+ insufficient_balance: "Recipient account does not meet the minimum balance requirement",
1037
+ account_not_found: "Recipient account does not exist on {{chain_name}}",
1038
+ validation_error: "Unable to verify recipient address on {{chain_name}}"
1039
+ },
1040
+ defaultError: "The recipient address cannot receive funds for the selected token"
1041
+ }
918
1042
  },
919
1043
  depositModal: {
920
1044
  transferCrypto: {
@@ -923,7 +1047,7 @@ var en_default = {
923
1047
  },
924
1048
  depositWithCard: {
925
1049
  title: "Deposit with Card",
926
- subtitle: "$50,000 limit \u2022 2 min"
1050
+ subtitle: "$50,000 limit"
927
1051
  },
928
1052
  quotes: "Quotes"
929
1053
  },
@@ -941,10 +1065,17 @@ var en_default = {
941
1065
 
942
1066
  // src/lib/i18n.ts
943
1067
  var i18n = en_default;
1068
+ function interpolate(template, params) {
1069
+ if (!params) return template;
1070
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
1071
+ const value = params[key];
1072
+ return value !== void 0 ? String(value) : `{{${key}}}`;
1073
+ });
1074
+ }
944
1075
 
945
1076
  // src/hooks/use-deposit-polling.ts
946
- var import_react2 = require("react");
947
- var import_core3 = require("@unifold/core");
1077
+ var import_react3 = require("react");
1078
+ var import_core4 = require("@unifold/core");
948
1079
  function useDepositPolling({
949
1080
  userId,
950
1081
  publishableKey,
@@ -952,18 +1083,18 @@ function useDepositPolling({
952
1083
  onDepositSuccess,
953
1084
  onDepositError
954
1085
  }) {
955
- const [executions, setExecutions] = (0, import_react2.useState)([]);
956
- const [isPolling, setIsPolling] = (0, import_react2.useState)(false);
957
- const pollingIntervalRef = (0, import_react2.useRef)(
1086
+ const [executions, setExecutions] = (0, import_react3.useState)([]);
1087
+ const [isPolling, setIsPolling] = (0, import_react3.useState)(false);
1088
+ const pollingIntervalRef = (0, import_react3.useRef)(
958
1089
  null
959
1090
  );
960
- const [modalOpenedAt] = (0, import_react2.useState)(/* @__PURE__ */ new Date());
961
- const [trackedExecutions, setTrackedExecutions] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
962
- (0, import_react2.useEffect)(() => {
1091
+ const [modalOpenedAt] = (0, import_react3.useState)(/* @__PURE__ */ new Date());
1092
+ const [trackedExecutions, setTrackedExecutions] = (0, import_react3.useState)(/* @__PURE__ */ new Map());
1093
+ (0, import_react3.useEffect)(() => {
963
1094
  if (!userId || !modalOpenedAt || !enabled) return;
964
1095
  const pollInterval = setInterval(async () => {
965
1096
  try {
966
- const response = await (0, import_core3.queryExecutions)(userId, publishableKey);
1097
+ const response = await (0, import_core4.queryExecutions)(userId, publishableKey);
967
1098
  let executionToShow = null;
968
1099
  for (const execution of response.data) {
969
1100
  const executionTime = execution.created_at ? new Date(execution.created_at) : null;
@@ -976,13 +1107,13 @@ function useDepositPolling({
976
1107
  break;
977
1108
  }
978
1109
  const inProgressStatuses = [
979
- import_core3.ExecutionStatus.PENDING,
980
- import_core3.ExecutionStatus.WAITING,
981
- import_core3.ExecutionStatus.DELAYED
1110
+ import_core4.ExecutionStatus.PENDING,
1111
+ import_core4.ExecutionStatus.WAITING,
1112
+ import_core4.ExecutionStatus.DELAYED
982
1113
  ];
983
1114
  const terminalStatuses = [
984
- import_core3.ExecutionStatus.SUCCEEDED,
985
- import_core3.ExecutionStatus.FAILED
1115
+ import_core4.ExecutionStatus.SUCCEEDED,
1116
+ import_core4.ExecutionStatus.FAILED
986
1117
  ];
987
1118
  if (inProgressStatuses.includes(trackedStatus) && terminalStatuses.includes(execution.status)) {
988
1119
  executionToShow = execution;
@@ -1008,17 +1139,17 @@ function useDepositPolling({
1008
1139
  return updated;
1009
1140
  });
1010
1141
  const inProgressStatuses = [
1011
- import_core3.ExecutionStatus.PENDING,
1012
- import_core3.ExecutionStatus.WAITING,
1013
- import_core3.ExecutionStatus.DELAYED
1142
+ import_core4.ExecutionStatus.PENDING,
1143
+ import_core4.ExecutionStatus.WAITING,
1144
+ import_core4.ExecutionStatus.DELAYED
1014
1145
  ];
1015
- if (execution.status === import_core3.ExecutionStatus.SUCCEEDED && onDepositSuccess && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
1146
+ if (execution.status === import_core4.ExecutionStatus.SUCCEEDED && onDepositSuccess && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
1016
1147
  onDepositSuccess({
1017
1148
  message: "Deposit completed successfully",
1018
1149
  executionId: execution.id,
1019
1150
  transaction: execution
1020
1151
  });
1021
- } else if (execution.status === import_core3.ExecutionStatus.FAILED && onDepositError && previousStatus !== import_core3.ExecutionStatus.FAILED) {
1152
+ } else if (execution.status === import_core4.ExecutionStatus.FAILED && onDepositError && previousStatus !== import_core4.ExecutionStatus.FAILED) {
1022
1153
  onDepositError({
1023
1154
  message: "Deposit failed",
1024
1155
  code: "DEPOSIT_FAILED",
@@ -1062,17 +1193,17 @@ function useDepositPolling({
1062
1193
  }
1063
1194
 
1064
1195
  // src/components/deposits/DepositPollingToasts.tsx
1065
- var import_react5 = require("react");
1196
+ var import_react6 = require("react");
1066
1197
 
1067
1198
  // src/components/deposits/DepositSuccessToast.tsx
1068
- var import_react4 = require("react");
1199
+ var import_react5 = require("react");
1069
1200
  var import_lucide_react5 = require("lucide-react");
1070
- var import_core5 = require("@unifold/core");
1201
+ var import_core6 = require("@unifold/core");
1071
1202
 
1072
1203
  // src/components/deposits/DepositDetailContent.tsx
1073
- var import_react3 = require("react");
1204
+ var import_react4 = require("react");
1074
1205
  var import_lucide_react4 = require("lucide-react");
1075
- var import_core4 = require("@unifold/core");
1206
+ var import_core5 = require("@unifold/core");
1076
1207
  var import_jsx_runtime7 = require("react/jsx-runtime");
1077
1208
  function formatCurrency(currency) {
1078
1209
  if (!currency) return "";
@@ -1084,15 +1215,15 @@ function formatCurrency(currency) {
1084
1215
  }
1085
1216
  function DepositDetailContent({ execution }) {
1086
1217
  const { colors: colors2, fonts, components } = useTheme();
1087
- const [chains, setChains] = (0, import_react3.useState)([]);
1088
- const [showNetworkDetails, setShowNetworkDetails] = (0, import_react3.useState)(false);
1089
- (0, import_react3.useEffect)(() => {
1090
- (0, import_core4.getTokenChains)().then((response) => setChains(response.data)).catch((err) => console.error("Failed to fetch chains:", err));
1218
+ const [chains, setChains] = (0, import_react4.useState)([]);
1219
+ const [showNetworkDetails, setShowNetworkDetails] = (0, import_react4.useState)(false);
1220
+ (0, import_react4.useEffect)(() => {
1221
+ (0, import_core5.getTokenChains)().then((response) => setChains(response.data)).catch((err) => console.error("Failed to fetch chains:", err));
1091
1222
  }, []);
1092
- (0, import_react3.useEffect)(() => {
1223
+ (0, import_react4.useEffect)(() => {
1093
1224
  setShowNetworkDetails(false);
1094
1225
  }, [execution?.id]);
1095
- const isPending = execution.status === import_core4.ExecutionStatus.PENDING || execution.status === import_core4.ExecutionStatus.WAITING || execution.status === import_core4.ExecutionStatus.DELAYED;
1226
+ const isPending = execution.status === import_core5.ExecutionStatus.PENDING || execution.status === import_core5.ExecutionStatus.WAITING || execution.status === import_core5.ExecutionStatus.DELAYED;
1096
1227
  const formatDateTime = (timestamp) => {
1097
1228
  try {
1098
1229
  const date = new Date(timestamp);
@@ -1162,7 +1293,7 @@ function DepositDetailContent({ execution }) {
1162
1293
  return "$0.00";
1163
1294
  };
1164
1295
  const getNetworkName = (chainType, chainId) => {
1165
- return (0, import_core4.getChainName)(chains, chainType, chainId);
1296
+ return (0, import_core5.getChainName)(chains, chainType, chainId);
1166
1297
  };
1167
1298
  const formatTransactionHash = (hash) => {
1168
1299
  if (!hash || hash.length < 12) return hash;
@@ -1174,7 +1305,7 @@ function DepositDetailContent({ execution }) {
1174
1305
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1175
1306
  "img",
1176
1307
  {
1177
- src: execution.destination_token_metadata?.icon_url || (0, import_core4.getIconUrl)("/icons/tokens/svg/usdc.svg"),
1308
+ src: execution.destination_token_metadata?.icon_url || (0, import_core5.getIconUrl)("/icons/tokens/svg/usdc.svg"),
1178
1309
  alt: "Token",
1179
1310
  width: 64,
1180
1311
  height: 64,
@@ -1384,6 +1515,37 @@ function DepositDetailContent({ execution }) {
1384
1515
  ]
1385
1516
  }
1386
1517
  ),
1518
+ isPending && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1519
+ "div",
1520
+ {
1521
+ className: "uf-flex uf-justify-between uf-items-center uf-px-4 uf-py-3 uf-border-b",
1522
+ style: { borderColor: colors2.border },
1523
+ children: [
1524
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1525
+ "span",
1526
+ {
1527
+ className: "uf-text-sm",
1528
+ style: {
1529
+ color: components.card.labelColor,
1530
+ fontFamily: fonts.regular
1531
+ },
1532
+ children: "Estimated delivery time"
1533
+ }
1534
+ ),
1535
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1536
+ "span",
1537
+ {
1538
+ style: {
1539
+ color: components.card.titleColor,
1540
+ fontFamily: fonts.regular,
1541
+ fontSize: "14px"
1542
+ },
1543
+ children: formatEstimatedTime(execution?.estimated_processing_time)
1544
+ }
1545
+ )
1546
+ ]
1547
+ }
1548
+ ),
1387
1549
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1388
1550
  "div",
1389
1551
  {
@@ -1570,9 +1732,9 @@ function DepositSuccessToast({
1570
1732
  onClose,
1571
1733
  execution
1572
1734
  }) {
1573
- const [detailModalOpen, setDetailModalOpen] = (0, import_react4.useState)(false);
1735
+ const [detailModalOpen, setDetailModalOpen] = (0, import_react5.useState)(false);
1574
1736
  const { themeClass, colors: colors2, fonts, components } = useTheme();
1575
- const isPending = status === import_core5.ExecutionStatus.PENDING || status === import_core5.ExecutionStatus.WAITING || status === import_core5.ExecutionStatus.DELAYED;
1737
+ const isPending = status === import_core6.ExecutionStatus.PENDING || status === import_core6.ExecutionStatus.WAITING || status === import_core6.ExecutionStatus.DELAYED;
1576
1738
  const formatDateTime = (timestamp) => {
1577
1739
  try {
1578
1740
  const date = new Date(timestamp);
@@ -1650,7 +1812,7 @@ function DepositSuccessToast({
1650
1812
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1651
1813
  "img",
1652
1814
  {
1653
- src: tokenIconUrl || (0, import_core5.getIconUrl)("/icons/tokens/svg/usdc.svg"),
1815
+ src: tokenIconUrl || (0, import_core6.getIconUrl)("/icons/tokens/svg/usdc.svg"),
1654
1816
  alt: "Token",
1655
1817
  width: 36,
1656
1818
  height: 36,
@@ -1704,14 +1866,27 @@ function DepositSuccessToast({
1704
1866
  }
1705
1867
  )
1706
1868
  ] }),
1707
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1708
- "div",
1709
- {
1710
- className: "uf-font-medium uf-text-sm uf-flex-shrink-0",
1711
- style: { color: colors2.background },
1712
- children: formatUsdAmount(sourceAmountUsd)
1713
- }
1714
- ),
1869
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "uf-flex-shrink-0 uf-text-right", children: [
1870
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1871
+ "div",
1872
+ {
1873
+ className: "uf-font-medium uf-text-sm",
1874
+ style: { color: colors2.background },
1875
+ children: formatUsdAmount(sourceAmountUsd)
1876
+ }
1877
+ ),
1878
+ isPending && execution?.estimated_processing_time && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1879
+ "p",
1880
+ {
1881
+ className: "uf-text-xs",
1882
+ style: { color: colors2.foregroundMuted },
1883
+ children: [
1884
+ "Est. ",
1885
+ formatEstimatedTime(execution.estimated_processing_time)
1886
+ ]
1887
+ }
1888
+ )
1889
+ ] }),
1715
1890
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1716
1891
  "button",
1717
1892
  {
@@ -1760,7 +1935,7 @@ function DepositPollingToasts({
1760
1935
  executions,
1761
1936
  horizontalPadding = "24px"
1762
1937
  }) {
1763
- const [closedExecutionIds, setClosedExecutionIds] = (0, import_react5.useState)(
1938
+ const [closedExecutionIds, setClosedExecutionIds] = (0, import_react6.useState)(
1764
1939
  /* @__PURE__ */ new Set()
1765
1940
  );
1766
1941
  const handleClose = (executionId) => {
@@ -1841,28 +2016,28 @@ function BuyWithCard({
1841
2016
  assetCdnUrl
1842
2017
  }) {
1843
2018
  const { colors: colors2, fonts, components } = useTheme();
1844
- const [amount, setAmount] = (0, import_react6.useState)("");
1845
- const [currency, setCurrency] = (0, import_react6.useState)("usd");
1846
- const [hasManualCurrencySelection, setHasManualCurrencySelection] = (0, import_react6.useState)(false);
1847
- const [hasManualAmountEntry, setHasManualAmountEntry] = (0, import_react6.useState)(false);
1848
- const [showCurrencyModal, setShowCurrencyModal] = (0, import_react6.useState)(false);
1849
- const [quotes, setQuotes] = (0, import_react6.useState)([]);
1850
- const [quotesLoading, setQuotesLoading] = (0, import_react6.useState)(false);
1851
- const [quotesError, setQuotesError] = (0, import_react6.useState)(null);
1852
- const [amountValidationError, setAmountValidationError] = (0, import_react6.useState)(null);
1853
- const [internalView, setInternalView] = (0, import_react6.useState)("amount");
1854
- const [defaultToken, setDefaultToken] = (0, import_react6.useState)(
2019
+ const [amount, setAmount] = (0, import_react7.useState)("");
2020
+ const [currency, setCurrency] = (0, import_react7.useState)("usd");
2021
+ const [hasManualCurrencySelection, setHasManualCurrencySelection] = (0, import_react7.useState)(false);
2022
+ const [hasManualAmountEntry, setHasManualAmountEntry] = (0, import_react7.useState)(false);
2023
+ const [showCurrencyModal, setShowCurrencyModal] = (0, import_react7.useState)(false);
2024
+ const [quotes, setQuotes] = (0, import_react7.useState)([]);
2025
+ const [quotesLoading, setQuotesLoading] = (0, import_react7.useState)(false);
2026
+ const [quotesError, setQuotesError] = (0, import_react7.useState)(null);
2027
+ const [amountValidationError, setAmountValidationError] = (0, import_react7.useState)(null);
2028
+ const [internalView, setInternalView] = (0, import_react7.useState)("amount");
2029
+ const [defaultToken, setDefaultToken] = (0, import_react7.useState)(
1855
2030
  null
1856
2031
  );
1857
- const [defaultTokenLoading, setDefaultTokenLoading] = (0, import_react6.useState)(false);
2032
+ const [defaultTokenLoading, setDefaultTokenLoading] = (0, import_react7.useState)(false);
1858
2033
  const { userIpInfo, isLoading: isLoadingIp } = useUserIp();
1859
- const [onrampSession, setOnrampSession] = (0, import_react6.useState)(
2034
+ const [onrampSession, setOnrampSession] = (0, import_react7.useState)(
1860
2035
  null
1861
2036
  );
1862
2037
  const currentView = externalView ?? internalView;
1863
2038
  const showQuotesView = currentView === "quotes";
1864
2039
  const showOnrampView = currentView === "onramp";
1865
- (0, import_react6.useEffect)(() => {
2040
+ (0, import_react7.useEffect)(() => {
1866
2041
  if (externalView) {
1867
2042
  setInternalView(externalView);
1868
2043
  }
@@ -1875,31 +2050,31 @@ function BuyWithCard({
1875
2050
  onViewChange?.(newView);
1876
2051
  }
1877
2052
  };
1878
- const [selectedProvider, setSelectedProvider] = (0, import_react6.useState)(
2053
+ const [selectedProvider, setSelectedProvider] = (0, import_react7.useState)(
1879
2054
  null
1880
2055
  );
1881
- const [isAutoSelected, setIsAutoSelected] = (0, import_react6.useState)(true);
1882
- const [autoSelectedProvider, setAutoSelectedProvider] = (0, import_react6.useState)(null);
1883
- const [hoveredProviderIndex, setHoveredProviderIndex] = (0, import_react6.useState)(null);
1884
- const [hasManualSelection, setHasManualSelection] = (0, import_react6.useState)(false);
1885
- const selectedProviderRef = (0, import_react6.useRef)(null);
1886
- const hasManualSelectionRef = (0, import_react6.useRef)(false);
1887
- (0, import_react6.useEffect)(() => {
2056
+ const [isAutoSelected, setIsAutoSelected] = (0, import_react7.useState)(true);
2057
+ const [autoSelectedProvider, setAutoSelectedProvider] = (0, import_react7.useState)(null);
2058
+ const [hoveredProviderIndex, setHoveredProviderIndex] = (0, import_react7.useState)(null);
2059
+ const [hasManualSelection, setHasManualSelection] = (0, import_react7.useState)(false);
2060
+ const selectedProviderRef = (0, import_react7.useRef)(null);
2061
+ const hasManualSelectionRef = (0, import_react7.useRef)(false);
2062
+ (0, import_react7.useEffect)(() => {
1888
2063
  selectedProviderRef.current = selectedProvider;
1889
2064
  }, [selectedProvider]);
1890
- (0, import_react6.useEffect)(() => {
2065
+ (0, import_react7.useEffect)(() => {
1891
2066
  hasManualSelectionRef.current = hasManualSelection;
1892
2067
  }, [hasManualSelection]);
1893
- const [internalWallets, setInternalWallets] = (0, import_react6.useState)([]);
1894
- const [walletsLoading, setWalletsLoading] = (0, import_react6.useState)(
2068
+ const [internalWallets, setInternalWallets] = (0, import_react7.useState)([]);
2069
+ const [walletsLoading, setWalletsLoading] = (0, import_react7.useState)(
1895
2070
  !externalWallets?.length
1896
2071
  );
1897
2072
  const wallets = externalWallets?.length ? externalWallets : internalWallets;
1898
- const [countdown, setCountdown] = (0, import_react6.useState)(60);
1899
- const [fiatCurrencies, setFiatCurrencies] = (0, import_react6.useState)([]);
1900
- const [preferredCurrencyCodes, setPreferredCurrencyCodes] = (0, import_react6.useState)([]);
1901
- const [currenciesLoading, setCurrenciesLoading] = (0, import_react6.useState)(true);
1902
- const [destinationToken, setDestinationToken] = (0, import_react6.useState)(null);
2073
+ const [countdown, setCountdown] = (0, import_react7.useState)(60);
2074
+ const [fiatCurrencies, setFiatCurrencies] = (0, import_react7.useState)([]);
2075
+ const [preferredCurrencyCodes, setPreferredCurrencyCodes] = (0, import_react7.useState)([]);
2076
+ const [currenciesLoading, setCurrenciesLoading] = (0, import_react7.useState)(true);
2077
+ const [destinationToken, setDestinationToken] = (0, import_react7.useState)(null);
1903
2078
  const { executions, isPolling } = useDepositPolling({
1904
2079
  userId,
1905
2080
  publishableKey,
@@ -1911,10 +2086,10 @@ function BuyWithCard({
1911
2086
  const destinationTokenIcon = destinationToken?.icon_url;
1912
2087
  const destinationChainIcon = destinationToken?.chain_icon_url;
1913
2088
  const destinationChainName = destinationToken?.chain_name;
1914
- (0, import_react6.useEffect)(() => {
2089
+ (0, import_react7.useEffect)(() => {
1915
2090
  async function fetchFiatCurrencies() {
1916
2091
  try {
1917
- const response = await (0, import_core6.getFiatCurrencies)(publishableKey);
2092
+ const response = await (0, import_core7.getFiatCurrencies)(publishableKey);
1918
2093
  setFiatCurrencies(response.data);
1919
2094
  setPreferredCurrencyCodes(response.preferred || []);
1920
2095
  } catch (err) {
@@ -1925,7 +2100,7 @@ function BuyWithCard({
1925
2100
  }
1926
2101
  fetchFiatCurrencies();
1927
2102
  }, [publishableKey]);
1928
- (0, import_react6.useEffect)(() => {
2103
+ (0, import_react7.useEffect)(() => {
1929
2104
  if (hasManualCurrencySelection) return;
1930
2105
  if (fiatCurrencies.length === 0 || !userIpInfo?.alpha2) return;
1931
2106
  const userCountryCode = userIpInfo.alpha2.toUpperCase();
@@ -1952,8 +2127,8 @@ function BuyWithCard({
1952
2127
  amount,
1953
2128
  hasManualAmountEntry
1954
2129
  ]);
1955
- const prevCurrencyRef = (0, import_react6.useRef)(null);
1956
- (0, import_react6.useEffect)(() => {
2130
+ const prevCurrencyRef = (0, import_react7.useRef)(null);
2131
+ (0, import_react7.useEffect)(() => {
1957
2132
  if (fiatCurrencies.length === 0) return;
1958
2133
  if (prevCurrencyRef.current !== null && prevCurrencyRef.current !== currency) {
1959
2134
  const currentCurrency = fiatCurrencies.find(
@@ -1965,7 +2140,7 @@ function BuyWithCard({
1965
2140
  }
1966
2141
  prevCurrencyRef.current = currency;
1967
2142
  }, [currency]);
1968
- (0, import_react6.useEffect)(() => {
2143
+ (0, import_react7.useEffect)(() => {
1969
2144
  if (externalWallets?.length) {
1970
2145
  setWalletsLoading(false);
1971
2146
  return;
@@ -1980,7 +2155,7 @@ function BuyWithCard({
1980
2155
  if (isCancelled) return;
1981
2156
  setWalletsLoading(true);
1982
2157
  try {
1983
- const response = await (0, import_core6.createDepositAddress)(
2158
+ const response = await (0, import_core7.createDepositAddress)(
1984
2159
  {
1985
2160
  external_user_id: userId,
1986
2161
  recipient_address: recipientAddress,
@@ -2018,10 +2193,10 @@ function BuyWithCard({
2018
2193
  publishableKey,
2019
2194
  externalWallets
2020
2195
  ]);
2021
- (0, import_react6.useEffect)(() => {
2196
+ (0, import_react7.useEffect)(() => {
2022
2197
  async function fetchDestinationToken() {
2023
2198
  try {
2024
- const response = await (0, import_core6.getTokenMetadata)(
2199
+ const response = await (0, import_core7.getTokenMetadata)(
2025
2200
  {
2026
2201
  chain_type: destinationChainType || "",
2027
2202
  chain_id: destinationChainId || "",
@@ -2036,7 +2211,7 @@ function BuyWithCard({
2036
2211
  }
2037
2212
  fetchDestinationToken();
2038
2213
  }, [publishableKey]);
2039
- (0, import_react6.useEffect)(() => {
2214
+ (0, import_react7.useEffect)(() => {
2040
2215
  async function fetchDefaultToken() {
2041
2216
  if (!destinationTokenAddress || !destinationChainId || !destinationChainType) {
2042
2217
  return;
@@ -2046,7 +2221,7 @@ function BuyWithCard({
2046
2221
  }
2047
2222
  setDefaultTokenLoading(true);
2048
2223
  try {
2049
- const response = await (0, import_core6.getDefaultOnrampToken)(
2224
+ const response = await (0, import_core7.getDefaultOnrampToken)(
2050
2225
  {
2051
2226
  country_code: userIpInfo?.alpha2?.toUpperCase() || "US",
2052
2227
  subdivision_code: userIpInfo?.state || void 0,
@@ -2072,7 +2247,7 @@ function BuyWithCard({
2072
2247
  isLoadingIp,
2073
2248
  publishableKey
2074
2249
  ]);
2075
- (0, import_react6.useEffect)(() => {
2250
+ (0, import_react7.useEffect)(() => {
2076
2251
  const amountNum = parseFloat(amount);
2077
2252
  if (isNaN(amountNum) || amountNum <= 0) {
2078
2253
  setQuotes([]);
@@ -2134,7 +2309,7 @@ function BuyWithCard({
2134
2309
  destination_network: defaultToken.destination_network,
2135
2310
  subdivision_code: userIpInfo?.state || void 0
2136
2311
  };
2137
- const response = await (0, import_core6.getOnrampQuotes)(request, publishableKey);
2312
+ const response = await (0, import_core7.getOnrampQuotes)(request, publishableKey);
2138
2313
  setQuotes(response.data);
2139
2314
  const currentHasManualSelection = hasManualSelectionRef.current;
2140
2315
  const currentSelectedProvider = selectedProviderRef.current;
@@ -2181,7 +2356,7 @@ function BuyWithCard({
2181
2356
  setQuotesLoading(false);
2182
2357
  }
2183
2358
  };
2184
- (0, import_react6.useEffect)(() => {
2359
+ (0, import_react7.useEffect)(() => {
2185
2360
  if (quotes.length === 0) return;
2186
2361
  const timer = setInterval(() => {
2187
2362
  setCountdown((prev) => {
@@ -2218,7 +2393,7 @@ function BuyWithCard({
2218
2393
  const handleContinue = () => {
2219
2394
  if (!selectedProvider) return;
2220
2395
  if (!defaultToken) return;
2221
- const wallet = (0, import_core6.getWalletByChainType)(
2396
+ const wallet = (0, import_core7.getWalletByChainType)(
2222
2397
  wallets,
2223
2398
  defaultToken.destination_token_metadata.chain_type
2224
2399
  );
@@ -2236,7 +2411,7 @@ function BuyWithCard({
2236
2411
  wallet_address: wallet.address,
2237
2412
  subdivision_code: userIpInfo?.state || void 0
2238
2413
  };
2239
- const sessionStartUrl = (0, import_core6.getOnrampSessionStartUrl)(
2414
+ const sessionStartUrl = (0, import_core7.getOnrampSessionStartUrl)(
2240
2415
  sessionRequest,
2241
2416
  publishableKey
2242
2417
  );
@@ -2286,7 +2461,7 @@ function BuyWithCard({
2286
2461
  selectedCurrencyData && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2287
2462
  "img",
2288
2463
  {
2289
- src: (0, import_core6.getPreferredIconUrl)(
2464
+ src: (0, import_core7.getPreferredIconUrl)(
2290
2465
  selectedCurrencyData.icon_urls,
2291
2466
  "png"
2292
2467
  ) || selectedCurrencyData.icon_url,
@@ -2516,6 +2691,20 @@ function BuyWithCard({
2516
2691
  },
2517
2692
  children: quotesError
2518
2693
  }
2694
+ ),
2695
+ defaultToken?.estimated_processing_time && !quotesLoading && selectedProvider && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2696
+ "div",
2697
+ {
2698
+ className: "uf-text-xs uf-mt-2 uf-px-1",
2699
+ style: {
2700
+ color: components.card.subtitleColor,
2701
+ fontFamily: fonts.regular
2702
+ },
2703
+ children: [
2704
+ "Estimated delivery time: ",
2705
+ formatEstimatedTime(defaultToken.estimated_processing_time)
2706
+ ]
2707
+ }
2519
2708
  )
2520
2709
  ] }),
2521
2710
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -2633,7 +2822,7 @@ function BuyWithCard({
2633
2822
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uf-h-8 uf-flex uf-items-center uf-justify-center uf-mb-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2634
2823
  "img",
2635
2824
  {
2636
- src: (0, import_core6.getIconUrlWithCdn)(
2825
+ src: (0, import_core7.getIconUrlWithCdn)(
2637
2826
  `/icons/currencies/png/${onrampSession.sourceCurrency.toLowerCase()}.png`,
2638
2827
  assetCdnUrl
2639
2828
  ),
@@ -2650,7 +2839,7 @@ function BuyWithCard({
2650
2839
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2651
2840
  "img",
2652
2841
  {
2653
- src: defaultToken?.destination_token_metadata?.icon_url || (0, import_core6.getIconUrlWithCdn)(
2842
+ src: defaultToken?.destination_token_metadata?.icon_url || (0, import_core7.getIconUrlWithCdn)(
2654
2843
  "/icons/tokens/png/usdc.png",
2655
2844
  assetCdnUrl
2656
2845
  ),
@@ -2661,7 +2850,7 @@ function BuyWithCard({
2661
2850
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2662
2851
  "img",
2663
2852
  {
2664
- src: defaultToken?.destination_token_metadata?.chain.icon_url || (0, import_core6.getIconUrlWithCdn)(
2853
+ src: defaultToken?.destination_token_metadata?.chain.icon_url || (0, import_core7.getIconUrlWithCdn)(
2665
2854
  "/icons/networks/png/polygon.png",
2666
2855
  assetCdnUrl
2667
2856
  ),
@@ -2679,7 +2868,7 @@ function BuyWithCard({
2679
2868
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2680
2869
  "img",
2681
2870
  {
2682
- src: destinationTokenIcon || (0, import_core6.getIconUrlWithCdn)(
2871
+ src: destinationTokenIcon || (0, import_core7.getIconUrlWithCdn)(
2683
2872
  "/icons/tokens/png/usdc.png",
2684
2873
  assetCdnUrl
2685
2874
  ),
@@ -2733,18 +2922,18 @@ function BuyWithCard({
2733
2922
  }
2734
2923
 
2735
2924
  // src/components/deposits/DepositsModal.tsx
2736
- var import_react7 = require("react");
2925
+ var import_react8 = require("react");
2737
2926
 
2738
2927
  // src/components/deposits/DepositExecutionItem.tsx
2739
2928
  var import_lucide_react7 = require("lucide-react");
2740
- var import_core7 = require("@unifold/core");
2929
+ var import_core8 = require("@unifold/core");
2741
2930
  var import_jsx_runtime11 = require("react/jsx-runtime");
2742
2931
  function DepositExecutionItem({
2743
2932
  execution,
2744
2933
  onClick
2745
2934
  }) {
2746
2935
  const { colors: colors2, fonts, components } = useTheme();
2747
- const isPending = execution.status === import_core7.ExecutionStatus.PENDING || execution.status === import_core7.ExecutionStatus.WAITING || execution.status === import_core7.ExecutionStatus.DELAYED;
2936
+ const isPending = execution.status === import_core8.ExecutionStatus.PENDING || execution.status === import_core8.ExecutionStatus.WAITING || execution.status === import_core8.ExecutionStatus.DELAYED;
2748
2937
  const formatDateTime = (timestamp) => {
2749
2938
  try {
2750
2939
  const date = new Date(timestamp);
@@ -2787,7 +2976,7 @@ function DepositExecutionItem({
2787
2976
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2788
2977
  "img",
2789
2978
  {
2790
- src: execution.destination_token_metadata?.icon_url || (0, import_core7.getIconUrl)("/icons/tokens/svg/usdc.svg"),
2979
+ src: execution.destination_token_metadata?.icon_url || (0, import_core8.getIconUrl)("/icons/tokens/svg/usdc.svg"),
2791
2980
  alt: "Token",
2792
2981
  width: 36,
2793
2982
  height: 36,
@@ -2963,7 +3152,7 @@ function ThemeStyleInjector({
2963
3152
  }
2964
3153
 
2965
3154
  // src/components/deposits/DepositsModal.tsx
2966
- var import_core8 = require("@unifold/core");
3155
+ var import_core9 = require("@unifold/core");
2967
3156
  var import_jsx_runtime13 = require("react/jsx-runtime");
2968
3157
  function DepositsModal({
2969
3158
  open,
@@ -2975,13 +3164,13 @@ function DepositsModal({
2975
3164
  themeClass = ""
2976
3165
  }) {
2977
3166
  const { colors: colors2 } = useTheme();
2978
- const [allExecutions, setAllExecutions] = (0, import_react7.useState)(sessionExecutions);
2979
- const [selectedExecution, setSelectedExecution] = (0, import_react7.useState)(null);
2980
- (0, import_react7.useEffect)(() => {
3167
+ const [allExecutions, setAllExecutions] = (0, import_react8.useState)(sessionExecutions);
3168
+ const [selectedExecution, setSelectedExecution] = (0, import_react8.useState)(null);
3169
+ (0, import_react8.useEffect)(() => {
2981
3170
  if (!open || !userId) return;
2982
3171
  const fetchExecutions = async () => {
2983
3172
  try {
2984
- const response = await (0, import_core8.queryExecutions)(userId, publishableKey);
3173
+ const response = await (0, import_core9.queryExecutions)(userId, publishableKey);
2985
3174
  const sorted = [...response.data].sort((a, b) => {
2986
3175
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
2987
3176
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -2999,7 +3188,7 @@ function DepositsModal({
2999
3188
  clearInterval(pollInterval);
3000
3189
  };
3001
3190
  }, [open, userId, publishableKey, sessionExecutions]);
3002
- (0, import_react7.useEffect)(() => {
3191
+ (0, import_react8.useEffect)(() => {
3003
3192
  if (!open) {
3004
3193
  setSelectedExecution(null);
3005
3194
  }
@@ -3325,11 +3514,11 @@ function DepositTrackerButton({
3325
3514
  }
3326
3515
 
3327
3516
  // src/components/deposits/DepositModal.tsx
3328
- var import_core12 = require("@unifold/core");
3517
+ var import_core14 = require("@unifold/core");
3329
3518
 
3330
3519
  // src/hooks/use-allowed-country.ts
3331
3520
  var import_react_query2 = require("@tanstack/react-query");
3332
- var import_core9 = require("@unifold/core");
3521
+ var import_core10 = require("@unifold/core");
3333
3522
  function useAllowedCountry(publishableKey) {
3334
3523
  const {
3335
3524
  data: ipData,
@@ -3337,7 +3526,7 @@ function useAllowedCountry(publishableKey) {
3337
3526
  error: ipError
3338
3527
  } = (0, import_react_query2.useQuery)({
3339
3528
  queryKey: ["unifold", "ipAddress"],
3340
- queryFn: () => (0, import_core9.getIpAddress)(),
3529
+ queryFn: () => (0, import_core10.getIpAddress)(),
3341
3530
  refetchOnMount: false,
3342
3531
  refetchOnReconnect: true,
3343
3532
  refetchOnWindowFocus: false,
@@ -3352,7 +3541,7 @@ function useAllowedCountry(publishableKey) {
3352
3541
  error: configError
3353
3542
  } = (0, import_react_query2.useQuery)({
3354
3543
  queryKey: ["unifold", "projectConfig", publishableKey],
3355
- queryFn: () => (0, import_core9.getProjectConfig)(publishableKey),
3544
+ queryFn: () => (0, import_core10.getProjectConfig)(publishableKey),
3356
3545
  refetchOnMount: false,
3357
3546
  refetchOnReconnect: true,
3358
3547
  refetchOnWindowFocus: false,
@@ -3381,12 +3570,70 @@ function useAllowedCountry(publishableKey) {
3381
3570
  };
3382
3571
  }
3383
3572
 
3573
+ // src/hooks/use-address-validation.ts
3574
+ var import_react_query3 = require("@tanstack/react-query");
3575
+ var import_core11 = require("@unifold/core");
3576
+ function useAddressValidation({
3577
+ recipientAddress,
3578
+ destinationChainType,
3579
+ destinationChainId,
3580
+ destinationTokenAddress,
3581
+ publishableKey,
3582
+ enabled = true,
3583
+ refetchOnMount = false
3584
+ }) {
3585
+ const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
3586
+ const { data, isLoading, error } = (0, import_react_query3.useQuery)({
3587
+ queryKey: [
3588
+ "unifold",
3589
+ "addressValidation",
3590
+ recipientAddress,
3591
+ destinationChainType,
3592
+ destinationChainId,
3593
+ destinationTokenAddress
3594
+ ],
3595
+ queryFn: () => (0, import_core11.verifyRecipientAddress)(
3596
+ {
3597
+ chain_type: destinationChainType,
3598
+ chain_id: destinationChainId,
3599
+ token_address: destinationTokenAddress,
3600
+ recipient_address: recipientAddress
3601
+ },
3602
+ publishableKey
3603
+ ),
3604
+ enabled: shouldValidate,
3605
+ refetchOnMount,
3606
+ refetchOnReconnect: false,
3607
+ refetchOnWindowFocus: false,
3608
+ staleTime: 1e3 * 60 * 5,
3609
+ // 5 minutes - address state can change
3610
+ gcTime: 1e3 * 60 * 30
3611
+ // 30 minutes
3612
+ });
3613
+ if (!shouldValidate) {
3614
+ return {
3615
+ isValid: null,
3616
+ failureCode: null,
3617
+ metadata: null,
3618
+ isLoading: false,
3619
+ error: null
3620
+ };
3621
+ }
3622
+ return {
3623
+ isValid: data?.valid ?? null,
3624
+ failureCode: data?.failure_code ?? null,
3625
+ metadata: data?.metadata ?? null,
3626
+ isLoading,
3627
+ error: error ?? null
3628
+ };
3629
+ }
3630
+
3384
3631
  // src/components/deposits/TransferCryptoSingleInput.tsx
3385
- var import_react10 = require("react");
3632
+ var import_react11 = require("react");
3386
3633
  var import_lucide_react12 = require("lucide-react");
3387
3634
 
3388
3635
  // src/components/deposits/StyledQRCode.tsx
3389
- var import_react8 = require("react");
3636
+ var import_react9 = require("react");
3390
3637
  var import_qr_code_styling = __toESM(require("qr-code-styling"));
3391
3638
  var import_jsx_runtime17 = require("react/jsx-runtime");
3392
3639
  function StyledQRCode({
@@ -3396,9 +3643,9 @@ function StyledQRCode({
3396
3643
  imageSize = 50,
3397
3644
  darkMode = false
3398
3645
  }) {
3399
- const ref = (0, import_react8.useRef)(null);
3400
- const qrCodeRef = (0, import_react8.useRef)(null);
3401
- (0, import_react8.useEffect)(() => {
3646
+ const ref = (0, import_react9.useRef)(null);
3647
+ const qrCodeRef = (0, import_react9.useRef)(null);
3648
+ (0, import_react9.useEffect)(() => {
3402
3649
  if (!ref.current) return;
3403
3650
  if (!qrCodeRef.current) {
3404
3651
  qrCodeRef.current = new import_qr_code_styling.default({
@@ -3438,7 +3685,7 @@ function StyledQRCode({
3438
3685
  qrCodeRef.current.append(ref.current);
3439
3686
  }
3440
3687
  }, []);
3441
- (0, import_react8.useEffect)(() => {
3688
+ (0, import_react9.useEffect)(() => {
3442
3689
  if (qrCodeRef.current) {
3443
3690
  qrCodeRef.current.update({
3444
3691
  data: value,
@@ -3479,7 +3726,7 @@ function StyledQRCode({
3479
3726
  }
3480
3727
 
3481
3728
  // src/components/deposits/TokenSelectorSheet.tsx
3482
- var import_react9 = require("react");
3729
+ var import_react10 = require("react");
3483
3730
  var import_lucide_react11 = require("lucide-react");
3484
3731
  var import_jsx_runtime18 = require("react/jsx-runtime");
3485
3732
  var STORAGE_KEY = "unifold_recent_tokens";
@@ -3537,13 +3784,13 @@ function TokenSelectorSheet({
3537
3784
  }) {
3538
3785
  const { themeClass, colors: colors2, fonts, components } = useTheme();
3539
3786
  const isDarkMode = themeClass.includes("uf-dark");
3540
- const [searchQuery, setSearchQuery] = (0, import_react9.useState)("");
3541
- const [recentTokens, setRecentTokens] = (0, import_react9.useState)([]);
3542
- const [hoveredTokenKey, setHoveredTokenKey] = (0, import_react9.useState)(null);
3543
- (0, import_react9.useEffect)(() => {
3787
+ const [searchQuery, setSearchQuery] = (0, import_react10.useState)("");
3788
+ const [recentTokens, setRecentTokens] = (0, import_react10.useState)([]);
3789
+ const [hoveredTokenKey, setHoveredTokenKey] = (0, import_react10.useState)(null);
3790
+ (0, import_react10.useEffect)(() => {
3544
3791
  setRecentTokens(getRecentTokens());
3545
3792
  }, []);
3546
- const allOptions = (0, import_react9.useMemo)(() => {
3793
+ const allOptions = (0, import_react10.useMemo)(() => {
3547
3794
  const options = [];
3548
3795
  tokens.forEach((token) => {
3549
3796
  token.chains.forEach((chain) => {
@@ -3552,7 +3799,7 @@ function TokenSelectorSheet({
3552
3799
  });
3553
3800
  return options;
3554
3801
  }, [tokens]);
3555
- const quickSelectOptions = (0, import_react9.useMemo)(() => {
3802
+ const quickSelectOptions = (0, import_react10.useMemo)(() => {
3556
3803
  const result = [];
3557
3804
  const seen = /* @__PURE__ */ new Set();
3558
3805
  const addOption = (symbol, chainType, chainId, isRecent) => {
@@ -3584,7 +3831,7 @@ function TokenSelectorSheet({
3584
3831
  });
3585
3832
  setRecentTokens(updated);
3586
3833
  };
3587
- const filteredOptions = (0, import_react9.useMemo)(() => {
3834
+ const filteredOptions = (0, import_react10.useMemo)(() => {
3588
3835
  if (!searchQuery.trim()) return allOptions;
3589
3836
  const query = searchQuery.toLowerCase();
3590
3837
  return allOptions.filter(
@@ -3954,7 +4201,7 @@ var TooltipContent = React8.forwardRef(({ className, sideOffset = 4, ...props },
3954
4201
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
3955
4202
 
3956
4203
  // src/components/deposits/TransferCryptoSingleInput.tsx
3957
- var import_core10 = require("@unifold/core");
4204
+ var import_core12 = require("@unifold/core");
3958
4205
  var import_jsx_runtime20 = require("react/jsx-runtime");
3959
4206
  var t2 = i18n.transferCrypto;
3960
4207
  var getChainKey = (chainId, chainType) => {
@@ -3978,13 +4225,13 @@ function TransferCryptoSingleInput({
3978
4225
  }) {
3979
4226
  const { themeClass, colors: colors2, fonts, components } = useTheme();
3980
4227
  const isDarkMode = themeClass.includes("uf-dark");
3981
- const [token, setToken] = (0, import_react10.useState)("USDC");
3982
- const [chain, setChain] = (0, import_react10.useState)("solana:mainnet");
3983
- const [copied, setCopied] = (0, import_react10.useState)(false);
3984
- const [internalWallets, setInternalWallets] = (0, import_react10.useState)([]);
3985
- const [loading, setLoading] = (0, import_react10.useState)(!externalWallets?.length);
4228
+ const [token, setToken] = (0, import_react11.useState)("USDC");
4229
+ const [chain, setChain] = (0, import_react11.useState)("solana:mainnet");
4230
+ const [copied, setCopied] = (0, import_react11.useState)(false);
4231
+ const [internalWallets, setInternalWallets] = (0, import_react11.useState)([]);
4232
+ const [loading, setLoading] = (0, import_react11.useState)(!externalWallets?.length);
3986
4233
  const wallets = externalWallets?.length ? externalWallets : internalWallets;
3987
- const [error, setError] = (0, import_react10.useState)(null);
4234
+ const [error, setError] = (0, import_react11.useState)(null);
3988
4235
  const { executions: depositExecutions, isPolling } = useDepositPolling({
3989
4236
  userId,
3990
4237
  publishableKey,
@@ -3992,11 +4239,11 @@ function TransferCryptoSingleInput({
3992
4239
  onDepositSuccess,
3993
4240
  onDepositError
3994
4241
  });
3995
- const [supportedTokens, setSupportedTokens] = (0, import_react10.useState)([]);
3996
- const [tokensLoading, setTokensLoading] = (0, import_react10.useState)(true);
3997
- const [detailsExpanded, setDetailsExpanded] = (0, import_react10.useState)(false);
3998
- const [depositsModalOpen, setDepositsModalOpen] = (0, import_react10.useState)(false);
3999
- const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react10.useState)(false);
4242
+ const [supportedTokens, setSupportedTokens] = (0, import_react11.useState)([]);
4243
+ const [tokensLoading, setTokensLoading] = (0, import_react11.useState)(true);
4244
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react11.useState)(false);
4245
+ const [depositsModalOpen, setDepositsModalOpen] = (0, import_react11.useState)(false);
4246
+ const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react11.useState)(false);
4000
4247
  const allChainsMap = /* @__PURE__ */ new Map();
4001
4248
  supportedTokens.forEach((t5) => {
4002
4249
  t5.chains.forEach((c) => {
@@ -4012,9 +4259,9 @@ function TransferCryptoSingleInput({
4012
4259
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
4013
4260
  );
4014
4261
  const currentChainType = currentChainData?.chain_type || "ethereum";
4015
- const currentWallet = (0, import_core10.getWalletByChainType)(wallets, currentChainType);
4262
+ const currentWallet = (0, import_core12.getWalletByChainType)(wallets, currentChainType);
4016
4263
  const depositAddress = currentWallet?.address || "";
4017
- (0, import_react10.useEffect)(() => {
4264
+ (0, import_react11.useEffect)(() => {
4018
4265
  async function fetchSupportedTokens() {
4019
4266
  try {
4020
4267
  setTokensLoading(true);
@@ -4023,7 +4270,7 @@ function TransferCryptoSingleInput({
4023
4270
  destination_chain_id: destinationChainId,
4024
4271
  destination_chain_type: destinationChainType
4025
4272
  } : void 0;
4026
- const response = await (0, import_core10.getSupportedDepositTokens)(
4273
+ const response = await (0, import_core12.getSupportedDepositTokens)(
4027
4274
  publishableKey,
4028
4275
  options
4029
4276
  );
@@ -4086,12 +4333,12 @@ function TransferCryptoSingleInput({
4086
4333
  destinationChainId,
4087
4334
  destinationChainType
4088
4335
  ]);
4089
- (0, import_react10.useEffect)(() => {
4336
+ (0, import_react11.useEffect)(() => {
4090
4337
  if (onExecutionsChange) {
4091
4338
  onExecutionsChange(depositExecutions);
4092
4339
  }
4093
4340
  }, [depositExecutions, onExecutionsChange]);
4094
- (0, import_react10.useEffect)(() => {
4341
+ (0, import_react11.useEffect)(() => {
4095
4342
  if (externalWallets?.length) {
4096
4343
  setLoading(false);
4097
4344
  return;
@@ -4106,7 +4353,7 @@ function TransferCryptoSingleInput({
4106
4353
  if (isCancelled) return;
4107
4354
  setLoading(true);
4108
4355
  try {
4109
- const response = await (0, import_core10.createDepositAddress)(
4356
+ const response = await (0, import_core12.createDepositAddress)(
4110
4357
  {
4111
4358
  external_user_id: userId,
4112
4359
  recipient_address: recipientAddress,
@@ -4148,7 +4395,7 @@ function TransferCryptoSingleInput({
4148
4395
  publishableKey,
4149
4396
  externalWallets
4150
4397
  ]);
4151
- (0, import_react10.useEffect)(() => {
4398
+ (0, import_react11.useEffect)(() => {
4152
4399
  if (!supportedTokens.length) return;
4153
4400
  const currentToken = supportedTokens.find((t5) => t5.symbol === token);
4154
4401
  if (!currentToken || currentToken.chains.length === 0) return;
@@ -4526,7 +4773,7 @@ function TransferCryptoSingleInput({
4526
4773
  }
4527
4774
 
4528
4775
  // src/components/deposits/TransferCryptoDoubleInput.tsx
4529
- var import_react11 = require("react");
4776
+ var import_react12 = require("react");
4530
4777
  var import_lucide_react14 = require("lucide-react");
4531
4778
 
4532
4779
  // src/components/shared/select.tsx
@@ -4651,7 +4898,7 @@ var SelectSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__
4651
4898
  SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
4652
4899
 
4653
4900
  // src/components/deposits/TransferCryptoDoubleInput.tsx
4654
- var import_core11 = require("@unifold/core");
4901
+ var import_core13 = require("@unifold/core");
4655
4902
  var import_jsx_runtime22 = require("react/jsx-runtime");
4656
4903
  var t3 = i18n.transferCrypto;
4657
4904
  var getChainKey2 = (chainId, chainType) => {
@@ -4675,13 +4922,13 @@ function TransferCryptoDoubleInput({
4675
4922
  }) {
4676
4923
  const { themeClass, colors: colors2, fonts, components } = useTheme();
4677
4924
  const isDarkMode = themeClass.includes("uf-dark");
4678
- const [token, setToken] = (0, import_react11.useState)("USDC");
4679
- const [chain, setChain] = (0, import_react11.useState)("solana:mainnet");
4680
- const [copied, setCopied] = (0, import_react11.useState)(false);
4681
- const [internalWallets, setInternalWallets] = (0, import_react11.useState)([]);
4682
- const [loading, setLoading] = (0, import_react11.useState)(!externalWallets?.length);
4925
+ const [token, setToken] = (0, import_react12.useState)("USDC");
4926
+ const [chain, setChain] = (0, import_react12.useState)("solana:mainnet");
4927
+ const [copied, setCopied] = (0, import_react12.useState)(false);
4928
+ const [internalWallets, setInternalWallets] = (0, import_react12.useState)([]);
4929
+ const [loading, setLoading] = (0, import_react12.useState)(!externalWallets?.length);
4683
4930
  const wallets = externalWallets?.length ? externalWallets : internalWallets;
4684
- const [error, setError] = (0, import_react11.useState)(null);
4931
+ const [error, setError] = (0, import_react12.useState)(null);
4685
4932
  const { executions: depositExecutions, isPolling } = useDepositPolling({
4686
4933
  userId,
4687
4934
  publishableKey,
@@ -4689,10 +4936,10 @@ function TransferCryptoDoubleInput({
4689
4936
  onDepositSuccess,
4690
4937
  onDepositError
4691
4938
  });
4692
- const [supportedTokens, setSupportedTokens] = (0, import_react11.useState)([]);
4693
- const [tokensLoading, setTokensLoading] = (0, import_react11.useState)(true);
4694
- const [detailsExpanded, setDetailsExpanded] = (0, import_react11.useState)(false);
4695
- const [depositsModalOpen, setDepositsModalOpen] = (0, import_react11.useState)(false);
4939
+ const [supportedTokens, setSupportedTokens] = (0, import_react12.useState)([]);
4940
+ const [tokensLoading, setTokensLoading] = (0, import_react12.useState)(true);
4941
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react12.useState)(false);
4942
+ const [depositsModalOpen, setDepositsModalOpen] = (0, import_react12.useState)(false);
4696
4943
  const allChainsMap = /* @__PURE__ */ new Map();
4697
4944
  supportedTokens.forEach((t5) => {
4698
4945
  t5.chains.forEach((c) => {
@@ -4708,9 +4955,9 @@ function TransferCryptoDoubleInput({
4708
4955
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
4709
4956
  );
4710
4957
  const currentChainType = currentChainData?.chain_type || "ethereum";
4711
- const currentWallet = (0, import_core11.getWalletByChainType)(wallets, currentChainType);
4958
+ const currentWallet = (0, import_core13.getWalletByChainType)(wallets, currentChainType);
4712
4959
  const depositAddress = currentWallet?.address || "";
4713
- (0, import_react11.useEffect)(() => {
4960
+ (0, import_react12.useEffect)(() => {
4714
4961
  async function fetchSupportedTokens() {
4715
4962
  try {
4716
4963
  setTokensLoading(true);
@@ -4719,7 +4966,7 @@ function TransferCryptoDoubleInput({
4719
4966
  destination_chain_id: destinationChainId,
4720
4967
  destination_chain_type: destinationChainType
4721
4968
  } : void 0;
4722
- const response = await (0, import_core11.getSupportedDepositTokens)(
4969
+ const response = await (0, import_core13.getSupportedDepositTokens)(
4723
4970
  publishableKey,
4724
4971
  options
4725
4972
  );
@@ -4753,12 +5000,12 @@ function TransferCryptoDoubleInput({
4753
5000
  destinationChainId,
4754
5001
  destinationChainType
4755
5002
  ]);
4756
- (0, import_react11.useEffect)(() => {
5003
+ (0, import_react12.useEffect)(() => {
4757
5004
  if (onExecutionsChange) {
4758
5005
  onExecutionsChange(depositExecutions);
4759
5006
  }
4760
5007
  }, [depositExecutions, onExecutionsChange]);
4761
- (0, import_react11.useEffect)(() => {
5008
+ (0, import_react12.useEffect)(() => {
4762
5009
  if (externalWallets?.length) {
4763
5010
  setLoading(false);
4764
5011
  return;
@@ -4773,7 +5020,7 @@ function TransferCryptoDoubleInput({
4773
5020
  if (isCancelled) return;
4774
5021
  setLoading(true);
4775
5022
  try {
4776
- const response = await (0, import_core11.createDepositAddress)(
5023
+ const response = await (0, import_core13.createDepositAddress)(
4777
5024
  {
4778
5025
  external_user_id: userId,
4779
5026
  recipient_address: recipientAddress,
@@ -4815,7 +5062,7 @@ function TransferCryptoDoubleInput({
4815
5062
  publishableKey,
4816
5063
  externalWallets
4817
5064
  ]);
4818
- (0, import_react11.useEffect)(() => {
5065
+ (0, import_react12.useEffect)(() => {
4819
5066
  if (!supportedTokens.length) return;
4820
5067
  const currentToken = supportedTokens.find((t5) => t5.symbol === token);
4821
5068
  if (!currentToken || currentToken.chains.length === 0) return;
@@ -5266,26 +5513,27 @@ function DepositModal({
5266
5513
  destinationChainId,
5267
5514
  destinationTokenAddress,
5268
5515
  hideDepositTracker = false,
5516
+ showBalanceHeader = false,
5269
5517
  transferInputVariant = "double_input",
5270
5518
  onDepositSuccess,
5271
5519
  onDepositError,
5272
5520
  theme = "dark"
5273
5521
  }) {
5274
- const { colors: colors2 } = useTheme();
5275
- const [view, setView] = (0, import_react12.useState)("main");
5276
- const [cardView, setCardView] = (0, import_react12.useState)(
5522
+ const { colors: colors2, fonts } = useTheme();
5523
+ const [view, setView] = (0, import_react13.useState)("main");
5524
+ const [cardView, setCardView] = (0, import_react13.useState)(
5277
5525
  "amount"
5278
5526
  );
5279
- const [quotesCount, setQuotesCount] = (0, import_react12.useState)(0);
5280
- const [depositsModalOpen, setDepositsModalOpen] = (0, import_react12.useState)(false);
5281
- const [depositExecutions, setDepositExecutions] = (0, import_react12.useState)([]);
5282
- const [projectConfig, setProjectConfig] = (0, import_react12.useState)(null);
5283
- const [wallets, setWallets] = (0, import_react12.useState)([]);
5284
- const [walletsLoading, setWalletsLoading] = (0, import_react12.useState)(false);
5285
- (0, import_react12.useEffect)(() => {
5527
+ const [quotesCount, setQuotesCount] = (0, import_react13.useState)(0);
5528
+ const [depositsModalOpen, setDepositsModalOpen] = (0, import_react13.useState)(false);
5529
+ const [depositExecutions, setDepositExecutions] = (0, import_react13.useState)([]);
5530
+ const [projectConfig, setProjectConfig] = (0, import_react13.useState)(null);
5531
+ const [wallets, setWallets] = (0, import_react13.useState)([]);
5532
+ const [walletsLoading, setWalletsLoading] = (0, import_react13.useState)(false);
5533
+ (0, import_react13.useEffect)(() => {
5286
5534
  setProjectConfig(null);
5287
5535
  }, [publishableKey]);
5288
- (0, import_react12.useEffect)(() => {
5536
+ (0, import_react13.useEffect)(() => {
5289
5537
  setWallets([]);
5290
5538
  }, [
5291
5539
  userId,
@@ -5295,10 +5543,10 @@ function DepositModal({
5295
5543
  destinationTokenAddress,
5296
5544
  publishableKey
5297
5545
  ]);
5298
- const [resolvedTheme, setResolvedTheme] = (0, import_react12.useState)(
5546
+ const [resolvedTheme, setResolvedTheme] = (0, import_react13.useState)(
5299
5547
  theme === "auto" ? "dark" : theme
5300
5548
  );
5301
- (0, import_react12.useEffect)(() => {
5549
+ (0, import_react13.useEffect)(() => {
5302
5550
  if (theme === "auto") {
5303
5551
  const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
5304
5552
  setResolvedTheme(mediaQuery.matches ? "dark" : "light");
@@ -5311,9 +5559,9 @@ function DepositModal({
5311
5559
  setResolvedTheme(theme);
5312
5560
  }
5313
5561
  }, [theme]);
5314
- (0, import_react12.useEffect)(() => {
5562
+ (0, import_react13.useEffect)(() => {
5315
5563
  if (open && !projectConfig) {
5316
- (0, import_core12.getProjectConfig)(publishableKey).then(setProjectConfig).catch(console.error);
5564
+ (0, import_core14.getProjectConfig)(publishableKey).then(setProjectConfig).catch(console.error);
5317
5565
  }
5318
5566
  }, [open, publishableKey, projectConfig]);
5319
5567
  const {
@@ -5321,7 +5569,29 @@ function DepositModal({
5321
5569
  isLoading: isCountryLoading,
5322
5570
  error: countryError
5323
5571
  } = useAllowedCountry(publishableKey);
5324
- (0, import_react12.useEffect)(() => {
5572
+ const {
5573
+ isValid: isAddressValid,
5574
+ failureCode: addressFailureCode,
5575
+ metadata: addressFailureMetadata,
5576
+ isLoading: isAddressValidationLoading
5577
+ } = useAddressValidation({
5578
+ recipientAddress,
5579
+ destinationChainType,
5580
+ destinationChainId,
5581
+ destinationTokenAddress,
5582
+ publishableKey,
5583
+ enabled: open,
5584
+ // Only validate when modal is open
5585
+ refetchOnMount: "always"
5586
+ });
5587
+ const addressValidationMessages = i18n.transferCrypto.addressValidation;
5588
+ const getAddressValidationErrorMessage = (code, metadata) => {
5589
+ if (!code) return addressValidationMessages.defaultError;
5590
+ const errors = addressValidationMessages.errors;
5591
+ const template = errors[code] ?? addressValidationMessages.defaultError;
5592
+ return interpolate(template, metadata);
5593
+ };
5594
+ (0, import_react13.useEffect)(() => {
5325
5595
  if (!open || wallets.length > 0) return;
5326
5596
  let retryTimeout = null;
5327
5597
  let isCancelled = false;
@@ -5329,7 +5599,7 @@ function DepositModal({
5329
5599
  if (isCancelled) return;
5330
5600
  setWalletsLoading(true);
5331
5601
  try {
5332
- const response = await (0, import_core12.createDepositAddress)(
5602
+ const response = await (0, import_core14.createDepositAddress)(
5333
5603
  {
5334
5604
  external_user_id: userId,
5335
5605
  recipient_address: recipientAddress,
@@ -5405,10 +5675,16 @@ function DepositModal({
5405
5675
  DepositHeader,
5406
5676
  {
5407
5677
  title: modalTitle || "Deposit",
5408
- onClose: handleClose
5678
+ onClose: handleClose,
5679
+ showBalance: showBalanceHeader,
5680
+ balanceAddress: recipientAddress,
5681
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
5682
+ balanceChainId: destinationChainId,
5683
+ balanceTokenAddress: destinationTokenAddress,
5684
+ publishableKey
5409
5685
  }
5410
5686
  ),
5411
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: isCountryLoading || !projectConfig ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
5687
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: isCountryLoading || isAddressValidationLoading || !projectConfig ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
5412
5688
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonButton, { variant: "with-icons" }),
5413
5689
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonButton, { variant: "with-icons" }),
5414
5690
  !hideDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonButton, {})
@@ -5426,6 +5702,16 @@ function DepositModal({
5426
5702
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
5427
5703
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: "There are no supported tokens available from your current location." })
5428
5704
  ] })
5705
+ ) : isAddressValid === false ? (
5706
+ /* Invalid recipient address state (e.g., Algorand not opted in) */
5707
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
5708
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react15.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
5709
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
5710
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(
5711
+ addressFailureCode,
5712
+ addressFailureMetadata
5713
+ ) })
5714
+ ] })
5429
5715
  ) : (
5430
5716
  /* Normal deposit options */
5431
5717
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [