@unifold/ui-react 0.1.69 → 0.1.70

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
@@ -114,6 +114,7 @@ __export(index_exports, {
114
114
  useDepositPolling: () => useDepositPolling,
115
115
  useDepositQuote: () => useDepositQuote,
116
116
  usePaymentIntent: () => usePaymentIntent,
117
+ usePublicIncident: () => usePublicIncident,
117
118
  useSourceTokenValidation: () => useSourceTokenValidation,
118
119
  useSupportedDepositTokens: () => useSupportedDepositTokens,
119
120
  useSupportedDestinationTokens: () => useSupportedDestinationTokens,
@@ -750,7 +751,13 @@ function useDepositAddress(params) {
750
751
  // 24 hours in cache
751
752
  refetchOnMount: false,
752
753
  refetchOnWindowFocus: false,
753
- retry: 3,
754
+ // Don't retry recipient-address validation errors — they're deterministic
755
+ // (a 400 won't succeed on retry) and we want to surface the invalid-address
756
+ // screen immediately rather than after 3 backoff attempts.
757
+ retry: (failureCount, error) => {
758
+ if ((0, import_core.isDepositAddressValidationError)(error)) return false;
759
+ return failureCount < 3;
760
+ },
754
761
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
755
762
  // 1s, 2s, 4s (max 10s)
756
763
  });
@@ -975,7 +982,8 @@ function DepositHeader({
975
982
  balanceChainId,
976
983
  balanceTokenAddress,
977
984
  projectName,
978
- publishableKey
985
+ publishableKey,
986
+ incident
979
987
  }) {
980
988
  const { colors: colors2, fonts, components } = useTheme();
981
989
  const [balance, setBalance] = (0, import_react2.useState)(null);
@@ -1073,19 +1081,64 @@ function DepositHeader({
1073
1081
  balanceTokenAddress,
1074
1082
  publishableKey
1075
1083
  ]);
1076
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
1077
- showBack ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1078
- "button",
1079
- {
1080
- onClick: onBack,
1081
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
1082
- style: { color: components.header.buttonColor },
1083
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ArrowLeft, { className: "uf-w-5 uf-h-5" })
1084
- }
1085
- ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
1086
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
1087
- badge ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1088
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1084
+ const incidentMessages = incident?.messages ?? [];
1085
+ const showIncident = incident?.enabled && incidentMessages.length > 0;
1086
+ const incidentSeverity = incident?.severity ?? "degraded";
1087
+ const incidentSeverityLabel = incidentSeverity === "outage" ? "Outage" : incidentSeverity === "info" ? "Info" : "Degraded service";
1088
+ const incidentStyles = incidentSeverity === "outage" ? {
1089
+ bg: "rgba(239, 68, 68, 0.12)",
1090
+ border: "rgba(239, 68, 68, 0.35)",
1091
+ text: "#fca5a5",
1092
+ link: "#fca5a5"
1093
+ } : incidentSeverity === "info" ? {
1094
+ bg: "rgba(59, 130, 246, 0.12)",
1095
+ border: "rgba(59, 130, 246, 0.35)",
1096
+ text: "#93c5fd",
1097
+ link: "#93c5fd"
1098
+ } : {
1099
+ bg: "rgba(245, 158, 11, 0.12)",
1100
+ border: "rgba(245, 158, 11, 0.35)",
1101
+ text: "#fcd34d",
1102
+ link: "#fcd34d"
1103
+ };
1104
+ const IncidentIcon = incidentSeverity === "info" ? import_lucide_react3.Info : import_lucide_react3.AlertTriangle;
1105
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1106
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
1107
+ showBack ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1108
+ "button",
1109
+ {
1110
+ onClick: onBack,
1111
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
1112
+ style: { color: components.header.buttonColor },
1113
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ArrowLeft, { className: "uf-w-5 uf-h-5" })
1114
+ }
1115
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
1116
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
1117
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1118
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1119
+ DialogTitle,
1120
+ {
1121
+ className: "uf-text-center uf-text-base",
1122
+ style: {
1123
+ color: components.header.titleColor,
1124
+ fontFamily: fonts.medium
1125
+ },
1126
+ children: title
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1130
+ "div",
1131
+ {
1132
+ className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
1133
+ style: {
1134
+ backgroundColor: colors2.card,
1135
+ color: colors2.foregroundMuted,
1136
+ fontFamily: fonts.regular
1137
+ },
1138
+ children: badge.count
1139
+ }
1140
+ )
1141
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1089
1142
  DialogTitle,
1090
1143
  {
1091
1144
  className: "uf-text-center uf-text-base",
@@ -1096,61 +1149,91 @@ function DepositHeader({
1096
1149
  children: title
1097
1150
  }
1098
1151
  ),
1099
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1152
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1100
1153
  "div",
1101
1154
  {
1102
- className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
1155
+ className: "uf-text-xs uf-mt-1",
1103
1156
  style: {
1104
- backgroundColor: colors2.card,
1105
1157
  color: colors2.foregroundMuted,
1106
1158
  fontFamily: fonts.regular
1107
1159
  },
1108
- children: badge.count
1160
+ children: subtitle
1109
1161
  }
1110
- )
1111
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1112
- DialogTitle,
1113
- {
1114
- className: "uf-text-center uf-text-base",
1115
- style: {
1116
- color: components.header.titleColor,
1117
- fontFamily: fonts.medium
1118
- },
1119
- children: title
1120
- }
1121
- ),
1122
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1123
- "div",
1124
- {
1125
- className: "uf-text-xs uf-mt-1",
1126
- style: {
1127
- color: colors2.foregroundMuted,
1128
- fontFamily: fonts.regular
1129
- },
1130
- children: subtitle
1131
- }
1132
- ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1133
- "div",
1162
+ ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1163
+ "div",
1164
+ {
1165
+ className: "uf-text-xs uf-mt-1",
1166
+ style: {
1167
+ color: colors2.foregroundMuted,
1168
+ fontFamily: fonts.regular
1169
+ },
1170
+ children: formatBalanceDisplay(balance, projectName)
1171
+ }
1172
+ ) : null : null
1173
+ ] }),
1174
+ showClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1175
+ "button",
1134
1176
  {
1135
- className: "uf-text-xs uf-mt-1",
1136
- style: {
1137
- color: colors2.foregroundMuted,
1138
- fontFamily: fonts.regular
1139
- },
1140
- children: formatBalanceDisplay(balance, projectName)
1177
+ onClick: onClose,
1178
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
1179
+ style: { color: components.header.buttonColor },
1180
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.X, { className: "uf-w-5 uf-h-5" })
1141
1181
  }
1142
- ) : null : null
1182
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
1143
1183
  ] }),
1144
- showClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1145
- "button",
1184
+ showIncident && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1185
+ "div",
1146
1186
  {
1147
- onClick: onClose,
1148
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
1149
- style: { color: components.header.buttonColor },
1150
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.X, { className: "uf-w-5 uf-h-5" })
1187
+ className: "uf-rounded-lg uf-px-3 uf-py-2.5 uf-mb-4",
1188
+ style: {
1189
+ backgroundColor: incidentStyles.bg,
1190
+ border: `1px solid ${incidentStyles.border}`
1191
+ },
1192
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-start uf-gap-2.5", children: [
1193
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1194
+ IncidentIcon,
1195
+ {
1196
+ className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
1197
+ style: { color: incidentStyles.text }
1198
+ }
1199
+ ),
1200
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-min-w-0 uf-flex-1", children: [
1201
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1202
+ "span",
1203
+ {
1204
+ className: "uf-text-[11px] uf-leading-none uf-px-1.5 uf-py-1 uf-rounded-md",
1205
+ style: {
1206
+ color: incidentStyles.text,
1207
+ border: `1px solid ${incidentStyles.border}`,
1208
+ fontFamily: fonts.medium
1209
+ },
1210
+ children: incidentSeverityLabel
1211
+ }
1212
+ ) }),
1213
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1214
+ "div",
1215
+ {
1216
+ className: "uf-space-y-1",
1217
+ style: { color: incidentStyles.text, fontFamily: fonts.regular },
1218
+ children: incidentMessages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "uf-text-xs uf-leading-relaxed", children: message }, `${message}-${index}`))
1219
+ }
1220
+ ),
1221
+ incident.statusPageUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1222
+ "a",
1223
+ {
1224
+ href: incident.statusPageUrl,
1225
+ target: "_blank",
1226
+ rel: "noreferrer",
1227
+ className: "uf-inline-block uf-mt-1.5 uf-text-xs uf-underline uf-underline-offset-2",
1228
+ style: { color: incidentStyles.link, fontFamily: fonts.medium },
1229
+ children: "View status"
1230
+ }
1231
+ )
1232
+ ] })
1233
+ ] })
1151
1234
  }
1152
- ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
1153
- ] }) });
1235
+ )
1236
+ ] });
1154
1237
  }
1155
1238
 
1156
1239
  // src/components/currency/CurrencyListItem.tsx
@@ -1488,7 +1571,8 @@ var en_default = {
1488
1571
  },
1489
1572
  stripeLink: {
1490
1573
  title: "Pay with Link",
1491
- subtitle: "Buy with card or bank"
1574
+ subtitle: "Buy with card or bank",
1575
+ unavailableInRegionMessage: "Pay with Link is currently unavailable in your region."
1492
1576
  },
1493
1577
  browserWallet: {
1494
1578
  title: "Connect Wallet",
@@ -6618,7 +6702,7 @@ function BankTransfer({
6618
6702
  subdivision_code: userIpInfo?.subdivisionCode || void 0,
6619
6703
  // A provider may advertise multiple rails; default to the first.
6620
6704
  // UIs that want per-rail rows would need to render one entry per element.
6621
- payment_method: provider.payment_methods[0]
6705
+ payment_method_type: provider.payment_methods[0]
6622
6706
  });
6623
6707
  setActiveProvider(provider);
6624
6708
  const convertedPrefilled = await resolvePrefilledSourceAmount(provider.source_currency);
@@ -7949,7 +8033,7 @@ function AppleLogo({ className, style }) {
7949
8033
  }
7950
8034
  );
7951
8035
  }
7952
- function ApplePayButton({ onClick, title, subtitle }) {
8036
+ function ApplePayButton({ onClick, title, subtitle, iconUrl }) {
7953
8037
  const { colors: colors2, fonts, components } = useTheme();
7954
8038
  const [isHovered, setIsHovered] = React14.useState(false);
7955
8039
  const [isTouchDevice, setIsTouchDevice] = React14.useState(false);
@@ -7971,7 +8055,14 @@ function ApplePayButton({ onClick, title, subtitle }) {
7971
8055
  },
7972
8056
  children: [
7973
8057
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
7974
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) }),
8058
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "uf-rounded-lg uf-overflow-hidden uf-w-9 uf-h-9 uf-flex uf-items-center uf-justify-center", children: iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("img", { src: iconUrl, alt: "Apple Pay", width: 36, height: 36, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8059
+ "div",
8060
+ {
8061
+ className: "uf-w-9 uf-h-9 uf-rounded-lg uf-flex uf-items-center uf-justify-center",
8062
+ style: { backgroundColor: "#000" },
8063
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: "#fff" } })
8064
+ }
8065
+ ) }),
7975
8066
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "uf-text-left", children: [
7976
8067
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
7977
8068
  "div",
@@ -8205,13 +8296,6 @@ function solanaCandidate(provider, type, name, icon) {
8205
8296
  if (provider.isConnected && provider.publicKey) {
8206
8297
  return { type, name, address: provider.publicKey.toString(), icon };
8207
8298
  }
8208
- try {
8209
- const resp = await provider.connect({ onlyIfTrusted: true });
8210
- if (resp.publicKey) {
8211
- return { type, name, address: resp.publicKey.toString(), icon };
8212
- }
8213
- } catch {
8214
- }
8215
8299
  return null;
8216
8300
  }
8217
8301
  };
@@ -8440,6 +8524,180 @@ async function disconnectInjectedBrowserWallet(wallet) {
8440
8524
  );
8441
8525
  }
8442
8526
 
8527
+ // src/components/deposits/browser-wallets/providerResolvers.ts
8528
+ var STORED_TYPE_TO_EIP6963_WALLET_ID = {
8529
+ metamask: "metamask",
8530
+ "phantom-ethereum": "phantom",
8531
+ coinbase: "coinbase",
8532
+ trust: "trust",
8533
+ rainbow: "rainbow",
8534
+ rabby: "rabby",
8535
+ okx: "okx"
8536
+ };
8537
+ var EIP6963_WALLET_ID_TO_INFO = {
8538
+ metamask: { walletType: "metamask", name: "MetaMask", icon: "metamask" },
8539
+ phantom: { walletType: "phantom-ethereum", name: "Phantom", icon: "phantom" },
8540
+ coinbase: { walletType: "coinbase", name: "Coinbase Wallet", icon: "coinbase" },
8541
+ trust: { walletType: "trust", name: "Trust Wallet", icon: "trust" },
8542
+ rainbow: { walletType: "rainbow", name: "Rainbow", icon: "rainbow" },
8543
+ rabby: { walletType: "rabby", name: "Rabby", icon: "rabby" },
8544
+ okx: { walletType: "okx", name: "OKX Wallet", icon: "okx" }
8545
+ };
8546
+ var WALLET_ID_TO_WALLET_TYPE = {
8547
+ phantom: "phantom-ethereum",
8548
+ coinbase: "coinbase",
8549
+ trust: "trust",
8550
+ rainbow: "rainbow",
8551
+ rabby: "rabby",
8552
+ okx: "okx",
8553
+ metamask: "metamask"
8554
+ };
8555
+ var WALLET_TYPE_TO_WALLET_ID = {
8556
+ "phantom-ethereum": "phantom",
8557
+ coinbase: "coinbase",
8558
+ trust: "trust",
8559
+ okx: "okx",
8560
+ rainbow: "rainbow",
8561
+ rabby: "rabby",
8562
+ metamask: "metamask"
8563
+ };
8564
+ function isWalletType(value) {
8565
+ return value === "phantom-solana" || value === "phantom-ethereum" || value === "metamask" || value === "coinbase" || value === "solflare" || value === "backpack" || value === "glow" || value === "trust" || value === "rainbow" || value === "rabby" || value === "okx";
8566
+ }
8567
+ function walletIdToWalletType(walletId) {
8568
+ return WALLET_ID_TO_WALLET_TYPE[walletId] || "metamask";
8569
+ }
8570
+ function walletTypeToWalletId(walletType) {
8571
+ return WALLET_TYPE_TO_WALLET_ID[walletType] || walletType;
8572
+ }
8573
+ function getLegacyEvmProviders(win) {
8574
+ if (!win) return {};
8575
+ const anyWin = win;
8576
+ return {
8577
+ ethereum: anyWin.ethereum,
8578
+ phantomEthereum: anyWin.phantom?.ethereum,
8579
+ coinbaseEthereum: anyWin.coinbaseWalletExtension,
8580
+ trustEthereum: anyWin.trustwallet?.ethereum,
8581
+ okxEthereum: anyWin.okxwallet
8582
+ };
8583
+ }
8584
+ function getInjectedSolanaProviders(win) {
8585
+ if (!win) return {};
8586
+ const anyWin = win;
8587
+ return {
8588
+ phantomSolana: anyWin.phantom?.solana,
8589
+ solflare: anyWin.solflare,
8590
+ backpack: anyWin.backpack,
8591
+ glow: anyWin.glow,
8592
+ coinbaseSolana: anyWin.coinbaseSolana || anyWin.coinbaseWalletExtension?.solana,
8593
+ trustSolana: anyWin.trustwallet?.solana
8594
+ };
8595
+ }
8596
+ function describeEip6963Provider(wp) {
8597
+ const mapped = EIP6963_WALLET_ID_TO_INFO[wp.walletId];
8598
+ return {
8599
+ provider: wp.provider,
8600
+ walletType: mapped?.walletType ?? "metamask",
8601
+ name: mapped?.name ?? wp.info.name,
8602
+ icon: mapped?.icon ?? wp.info.icon
8603
+ };
8604
+ }
8605
+ function resolveQuickConnectEvmProvider(win) {
8606
+ const eip6963Providers = getEip6963Providers();
8607
+ if (eip6963Providers.length > 0) {
8608
+ const stored = getStoredWalletState();
8609
+ const preferredWalletId = stored?.walletType && isWalletType(stored.walletType) ? STORED_TYPE_TO_EIP6963_WALLET_ID[stored.walletType] : void 0;
8610
+ if (preferredWalletId) {
8611
+ const preferred = findProviderByWalletId(preferredWalletId);
8612
+ if (preferred) return describeEip6963Provider(preferred);
8613
+ }
8614
+ if (eip6963Providers.length === 1) {
8615
+ return describeEip6963Provider(eip6963Providers[0]);
8616
+ }
8617
+ return void 0;
8618
+ }
8619
+ const anyWin = win;
8620
+ const legacy = anyWin.phantom?.ethereum || anyWin.ethereum;
8621
+ if (!legacy) return void 0;
8622
+ const isPhantom = legacy.isPhantom;
8623
+ return {
8624
+ provider: legacy,
8625
+ walletType: isPhantom ? "phantom-ethereum" : "metamask",
8626
+ name: isPhantom ? "Phantom" : "MetaMask",
8627
+ icon: isPhantom ? "phantom" : "metamask"
8628
+ };
8629
+ }
8630
+ function resolveSolanaPublicKey(provider, response) {
8631
+ if (response?.publicKey) return { publicKey: response.publicKey };
8632
+ if (provider.publicKey) return { publicKey: provider.publicKey };
8633
+ return null;
8634
+ }
8635
+ function isUserRejectedSolanaConnectError(error) {
8636
+ if (!error || typeof error !== "object") return false;
8637
+ const maybeCode = "code" in error ? error.code : void 0;
8638
+ if (maybeCode === 4001) return true;
8639
+ const msg = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
8640
+ return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("rejected the request") || msg.includes("declined");
8641
+ }
8642
+ function isSolanaConnectTimeoutError(error) {
8643
+ return error instanceof Error && error.message.toLowerCase().includes("did not respond to the connection request");
8644
+ }
8645
+ async function connectSolanaProviderWithRecovery(provider, walletId, walletName) {
8646
+ if (provider.isConnected && provider.publicKey) {
8647
+ return { publicKey: provider.publicKey };
8648
+ }
8649
+ const connectOnce = () => provider.connect(walletId === "solflare" ? { onlyIfTrusted: false } : void 0);
8650
+ const withTimeout = async (ms = 2e4) => await Promise.race([
8651
+ connectOnce(),
8652
+ new Promise(
8653
+ (resolve, reject) => setTimeout(() => {
8654
+ const connected = resolveSolanaPublicKey(provider);
8655
+ if (connected) {
8656
+ resolve(connected);
8657
+ return;
8658
+ }
8659
+ reject(
8660
+ new Error(
8661
+ `${walletName} did not respond to the connection request. Please unlock the wallet and try again.`
8662
+ )
8663
+ );
8664
+ }, ms)
8665
+ )
8666
+ ]);
8667
+ if (walletId === "solflare") {
8668
+ await provider.disconnect?.().catch(() => {
8669
+ });
8670
+ }
8671
+ const connectAndResolve = async () => {
8672
+ try {
8673
+ const response = await withTimeout();
8674
+ const resolved = resolveSolanaPublicKey(provider, response);
8675
+ if (resolved) return resolved;
8676
+ await new Promise((resolve) => setTimeout(resolve, 120));
8677
+ const delayedResolved = resolveSolanaPublicKey(provider);
8678
+ if (delayedResolved) return delayedResolved;
8679
+ throw new Error(`${walletName} connected but did not expose a public key.`);
8680
+ } catch (error) {
8681
+ const connected = resolveSolanaPublicKey(provider);
8682
+ if (connected) return connected;
8683
+ throw error;
8684
+ }
8685
+ };
8686
+ try {
8687
+ return await connectAndResolve();
8688
+ } catch (err) {
8689
+ if (isUserRejectedSolanaConnectError(err)) throw err;
8690
+ if (isSolanaConnectTimeoutError(err)) throw err;
8691
+ if (walletId === "solflare") {
8692
+ await provider.disconnect?.().catch(() => {
8693
+ });
8694
+ await new Promise((resolve) => setTimeout(resolve, 150));
8695
+ return await connectAndResolve();
8696
+ }
8697
+ throw err;
8698
+ }
8699
+ }
8700
+
8443
8701
  // src/resources/icons/MetamaskIcon.tsx
8444
8702
  var React17 = __toESM(require("react"));
8445
8703
  var import_jsx_runtime28 = require("react/jsx-runtime");
@@ -10244,7 +10502,11 @@ function WalletIconWithNetwork({
10244
10502
  }
10245
10503
 
10246
10504
  // src/components/deposits/buttons/BrowserWalletButton.tsx
10247
- var import_jsx_runtime41 = require("react/jsx-runtime");
10505
+ var import_jsx_runtime41 = (
10506
+ // Wallet announced via EIP-6963 with no internal icon component: render its
10507
+ // own advertised icon (`info.icon`) rather than a generic placeholder.
10508
+ require("react/jsx-runtime")
10509
+ );
10248
10510
  var WALLET_ICON_COMPONENTS = {
10249
10511
  metamask: MetamaskIcon,
10250
10512
  phantom: PhantomIcon,
@@ -10352,21 +10614,19 @@ function BrowserWalletButton({
10352
10614
  }
10353
10615
  }
10354
10616
  if (!chainType || chainType === "ethereum") {
10355
- const ethProvider = window.phantom?.ethereum || window.ethereum;
10356
- if (ethProvider) {
10357
- const accounts = await ethProvider.request({
10617
+ const resolved = resolveQuickConnectEvmProvider(window);
10618
+ if (resolved) {
10619
+ const accounts = await resolved.provider.request({
10358
10620
  method: "eth_requestAccounts"
10359
10621
  });
10360
10622
  if (accounts && accounts.length > 0) {
10361
10623
  setUserDisconnectedWallet(false);
10362
- const isPhantom = ethProvider.isPhantom;
10363
- const walletType = isPhantom ? "phantom-ethereum" : "metamask";
10364
- setStoredWalletState(walletType);
10624
+ setStoredWalletState(resolved.walletType);
10365
10625
  setWallet({
10366
- type: walletType,
10367
- name: isPhantom ? "Phantom" : "MetaMask",
10626
+ type: resolved.walletType,
10627
+ name: resolved.name,
10368
10628
  address: accounts[0],
10369
- icon: isPhantom ? "phantom" : "metamask"
10629
+ icon: resolved.icon
10370
10630
  });
10371
10631
  }
10372
10632
  }
@@ -10400,7 +10660,10 @@ function BrowserWalletButton({
10400
10660
  if (isLoading) {
10401
10661
  return null;
10402
10662
  }
10403
- const hasWalletExtension = (!chainType || chainType === "ethereum") && getEip6963Providers().length > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && (window.phantom?.ethereum || window.ethereum);
10663
+ const eip6963EvmProviderCount = getEip6963Providers().length;
10664
+ const legacyEvmProviders = getLegacyEvmProviders(window);
10665
+ const hasLegacyEvmProvider = eip6963EvmProviderCount === 0 && !!(legacyEvmProviders.ethereum || legacyEvmProviders.phantomEthereum || legacyEvmProviders.coinbaseEthereum || legacyEvmProviders.trustEthereum || legacyEvmProviders.okxEthereum);
10666
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && eip6963EvmProviderCount > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && hasLegacyEvmProvider;
10404
10667
  if (!onConnectClick && !wallet && !hasWalletExtension) {
10405
10668
  return null;
10406
10669
  }
@@ -10410,11 +10673,21 @@ function BrowserWalletButton({
10410
10673
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
10411
10674
  };
10412
10675
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
10676
+ const isImageIcon = !!wallet && (wallet.icon.startsWith("data:") || wallet.icon.startsWith("http"));
10413
10677
  const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React29.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
10414
10678
  size: 36,
10415
10679
  className: "uf-rounded-lg",
10416
10680
  variant: "color"
10417
- }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react22.Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
10681
+ }) : isImageIcon ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10682
+ "img",
10683
+ {
10684
+ src: wallet.icon,
10685
+ alt: wallet.name,
10686
+ width: 36,
10687
+ height: 36,
10688
+ className: "uf-rounded-lg uf-w-9 uf-h-9"
10689
+ }
10690
+ ) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react22.Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
10418
10691
  const titleSubtitleBlock = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "uf-text-left uf-min-w-0", children: [
10419
10692
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10420
10693
  "div",
@@ -10984,6 +11257,13 @@ function setStoredSelectedToken(customerId, token) {
10984
11257
  } catch {
10985
11258
  }
10986
11259
  }
11260
+ function clearStoredSelectedToken(customerId) {
11261
+ try {
11262
+ if (typeof window === "undefined" || !customerId) return;
11263
+ localStorage.removeItem(selectedTokenKey(customerId));
11264
+ } catch {
11265
+ }
11266
+ }
10987
11267
 
10988
11268
  // src/components/deposits/stripe-link/PayWithStripeLink.tsx
10989
11269
  var import_jsx_runtime44 = require("react/jsx-runtime");
@@ -11001,6 +11281,31 @@ var STRIPE_SESSION_STATUS = {
11001
11281
  EXPIRED: "expired"
11002
11282
  };
11003
11283
  var STRIPE_SESSION_POLL_INTERVAL_MS = 3e3;
11284
+ var STRIPE_CONSUMED_PAYMENT_METHOD_CODE = "payment_method_unexpected_state";
11285
+ function isConsumedPaymentMethodError(err) {
11286
+ return err instanceof import_core21.StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
11287
+ }
11288
+ var STRIPE_PAYMENT_FAILURE_MESSAGES = {
11289
+ card_declined: "Your card was declined. Try again or use a different payment method.",
11290
+ insufficient_funds: "Your card has insufficient funds. Try a different payment method.",
11291
+ expired_card: "Your card has expired. Use a different payment method.",
11292
+ incorrect_cvc: "Your card\u2019s security code is incorrect. Try again or use a different card.",
11293
+ incorrect_number: "Your card number is incorrect. Try again or use a different card.",
11294
+ card_not_supported: "This card isn\u2019t supported for this purchase. Try a different payment method.",
11295
+ processing_error: "We couldn\u2019t process your card. Please try again in a moment.",
11296
+ authentication_required: "Your bank requires authentication for this payment. Please try again.",
11297
+ payment_intent_authentication_failure: "Card authentication failed. Try again or use a different card.",
11298
+ payment_method_provider_decline: "Your payment provider declined the charge. Try a different payment method.",
11299
+ payment_failed: "Your payment didn\u2019t go through. Try again or use a different payment method."
11300
+ };
11301
+ function describeStripePaymentFailure(reason) {
11302
+ if (!reason) return null;
11303
+ return STRIPE_PAYMENT_FAILURE_MESSAGES[reason] ?? null;
11304
+ }
11305
+ var PAYMENT_FAILED_LEAD = "We couldn\u2019t complete your payment.";
11306
+ function unmappedPaymentFailureMessage(stripeMessage) {
11307
+ return stripeMessage ? `${PAYMENT_FAILED_LEAD} ${stripeMessage}` : `${PAYMENT_FAILED_LEAD} Please try again.`;
11308
+ }
11004
11309
  var NO_AUTOFILL = {
11005
11310
  autoComplete: "off",
11006
11311
  "data-lpignore": "true",
@@ -11102,7 +11407,11 @@ function PayWithStripeLink({
11102
11407
  }, [controlledStep]);
11103
11408
  (0, import_react17.useEffect)(() => {
11104
11409
  setLoading(false);
11105
- setError(null);
11410
+ if (preserveErrorOnNextStepRef.current) {
11411
+ preserveErrorOnNextStepRef.current = false;
11412
+ } else {
11413
+ setError(null);
11414
+ }
11106
11415
  setKycPendingMessage(null);
11107
11416
  setQuoteLoading(false);
11108
11417
  if (step !== "checkout") {
@@ -11191,7 +11500,10 @@ function PayWithStripeLink({
11191
11500
  const pendingAddPaymentRef = (0, import_react17.useRef)(false);
11192
11501
  const autoOpenedAddPaymentRef = (0, import_react17.useRef)(false);
11193
11502
  const checkoutGenRef = (0, import_react17.useRef)(0);
11503
+ const preserveErrorOnNextStepRef = (0, import_react17.useRef)(false);
11504
+ const spentSessionIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
11194
11505
  const [stripePaymentUIReady, setStripePaymentUIReady] = (0, import_react17.useState)(false);
11506
+ const [addPaymentHovered, setAddPaymentHovered] = (0, import_react17.useState)(false);
11195
11507
  const [oauthToken, setOauthToken] = (0, import_react17.useState)(null);
11196
11508
  const [refreshTokenValue, setRefreshTokenValue] = (0, import_react17.useState)(null);
11197
11509
  const [customerId, setCustomerId] = (0, import_react17.useState)(null);
@@ -11340,7 +11652,7 @@ function PayWithStripeLink({
11340
11652
  const merged = [
11341
11653
  ...pmResult.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
11342
11654
  ...persistedNotInApi ? [persisted] : []
11343
- ];
11655
+ ].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
11344
11656
  if (merged.length > 0) {
11345
11657
  const preferred = persisted && merged.find((m) => m.id === persisted.id) || merged[0];
11346
11658
  selectPaymentToken(preferred);
@@ -11405,6 +11717,7 @@ function PayWithStripeLink({
11405
11717
  const [selectedPaymentToken, setSelectedPaymentToken] = (0, import_react17.useState)(null);
11406
11718
  const [paymentDisplay, setPaymentDisplay] = (0, import_react17.useState)(null);
11407
11719
  const selectedTokenSingleUseRef = (0, import_react17.useRef)(false);
11720
+ const deadPaymentTokenIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
11408
11721
  const selectPaymentToken = (0, import_react17.useCallback)(
11409
11722
  (token) => {
11410
11723
  selectedTokenSingleUseRef.current = !!token.singleUse;
@@ -11432,9 +11745,25 @@ function PayWithStripeLink({
11432
11745
  setStoredSelectedTokenState(null);
11433
11746
  }
11434
11747
  }, [customerId]);
11748
+ const forgetSelectedPaymentToken = (0, import_react17.useCallback)(
11749
+ (tokenId) => {
11750
+ selectedTokenSingleUseRef.current = false;
11751
+ if (customerId) {
11752
+ const persisted = getStoredSelectedToken(customerId);
11753
+ if (!tokenId || persisted?.id === tokenId) {
11754
+ clearStoredSelectedToken(customerId);
11755
+ }
11756
+ }
11757
+ setSelectedPaymentToken((prev) => !tokenId || prev === tokenId ? null : prev);
11758
+ setPaymentDisplay((prev) => !tokenId || !prev ? null : prev);
11759
+ setStoredSelectedTokenState((prev) => !tokenId || prev?.id === tokenId ? null : prev);
11760
+ },
11761
+ [customerId]
11762
+ );
11435
11763
  const displayPaymentTokens = (() => {
11436
- const apiDisplay = paymentTokens.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
11437
- if (storedSelectedToken && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
11764
+ const isDead = (id) => deadPaymentTokenIdsRef.current.has(id);
11765
+ const apiDisplay = paymentTokens.filter((t13) => !isDead(t13.id)).map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
11766
+ if (storedSelectedToken && !isDead(storedSelectedToken.id) && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
11438
11767
  return [...apiDisplay, storedSelectedToken];
11439
11768
  }
11440
11769
  return apiDisplay;
@@ -12083,7 +12412,7 @@ function PayWithStripeLink({
12083
12412
  const merged = [
12084
12413
  ...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
12085
12414
  ...storedNotInApi ? [stored] : []
12086
- ];
12415
+ ].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
12087
12416
  if (merged.length === 0) {
12088
12417
  if (!autoOpenedAddPaymentRef.current) {
12089
12418
  autoOpenedAddPaymentRef.current = true;
@@ -12125,6 +12454,9 @@ function PayWithStripeLink({
12125
12454
  paymentInnerRef.current.replaceChildren();
12126
12455
  };
12127
12456
  }, [step, oauthToken, customerId, publishableKey, coordinator]);
12457
+ (0, import_react17.useEffect)(() => {
12458
+ if (step !== "payment") setAddPaymentHovered(false);
12459
+ }, [step]);
12128
12460
  (0, import_react17.useEffect)(() => {
12129
12461
  if (step !== "add_payment") return;
12130
12462
  if (!isCustomerVerified(customer)) {
@@ -12275,6 +12607,17 @@ function PayWithStripeLink({
12275
12607
  }
12276
12608
  if (message) onDepositError?.({ message, error: err });
12277
12609
  };
12610
+ const isRetriablePaymentToken = (id) => !!id && paymentTokens.some((t13) => t13.id === id);
12611
+ const dropConsumedToken = (message, cause) => {
12612
+ if (selectedPaymentToken) deadPaymentTokenIdsRef.current.add(selectedPaymentToken);
12613
+ setSessionForCheckout(null);
12614
+ forgetSelectedPaymentToken(selectedPaymentToken);
12615
+ preserveErrorOnNextStepRef.current = true;
12616
+ setError(message);
12617
+ setStep("amount");
12618
+ onDepositError?.({ message, error: cause });
12619
+ };
12620
+ const CONSUMED_TOKEN_MESSAGE = "That payment method can\u2019t be used. Please choose another.";
12278
12621
  if (!sessionForCheckout || sessionForCheckout.amount !== amount || sessionForCheckout.paymentToken !== selectedPaymentToken) {
12279
12622
  return;
12280
12623
  }
@@ -12282,19 +12625,29 @@ function PayWithStripeLink({
12282
12625
  setLoading(true);
12283
12626
  setError(null);
12284
12627
  setStep("checkout");
12628
+ let lastConfirmError = null;
12285
12629
  try {
12286
- const runCheckout = (sid) => coordinator.performCheckout(sid, async (onrampSessionId) => {
12287
- try {
12288
- await withTokenRefresh(
12289
- (tok) => (0, import_core21.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
12290
- );
12291
- } catch {
12292
- }
12293
- const confirmResponse = await withTokenRefresh(
12294
- (tok) => (0, import_core21.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
12295
- );
12296
- return confirmResponse.client_secret ?? "";
12297
- });
12630
+ const runCheckout = (sid) => {
12631
+ spentSessionIdsRef.current.add(sid);
12632
+ return coordinator.performCheckout(sid, async (onrampSessionId) => {
12633
+ try {
12634
+ await withTokenRefresh(
12635
+ (tok) => (0, import_core21.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
12636
+ );
12637
+ } catch {
12638
+ }
12639
+ try {
12640
+ const confirmResponse = await withTokenRefresh(
12641
+ (tok) => (0, import_core21.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
12642
+ );
12643
+ lastConfirmError = null;
12644
+ return confirmResponse.client_secret ?? "";
12645
+ } catch (confirmErr) {
12646
+ lastConfirmError = confirmErr;
12647
+ throw confirmErr;
12648
+ }
12649
+ });
12650
+ };
12298
12651
  const lastErrorFor = async (sid) => {
12299
12652
  const sessionState = await withTokenRefresh(
12300
12653
  (tok) => (0, import_core21.stripeGetSession)(sid, tok, publishableKey)
@@ -12354,8 +12707,9 @@ function PayWithStripeLink({
12354
12707
  setStep("success");
12355
12708
  } else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
12356
12709
  setSessionForCheckout(null);
12357
- setStep("amount");
12710
+ preserveErrorOnNextStepRef.current = true;
12358
12711
  setError("Pricing updated. Please try again.");
12712
+ setStep("amount");
12359
12713
  } else if (lastError === "missing_document_verification") {
12360
12714
  surfaceStepUpOnAmount(void 0, void 0, "l2");
12361
12715
  } else if (lastError === "transaction_limit_reached") {
@@ -12366,28 +12720,52 @@ function PayWithStripeLink({
12366
12720
  } else if (lastError === "missing_consumer_wallet") {
12367
12721
  setStep("wallet");
12368
12722
  setError(null);
12723
+ } else if (isConsumedPaymentMethodError(lastConfirmError)) {
12724
+ dropConsumedToken(CONSUMED_TOKEN_MESSAGE, lastConfirmError);
12369
12725
  } else {
12370
- setSessionForCheckout(null);
12371
- setError(lastError ?? "Checkout failed. Please try again.");
12372
- setStep("amount");
12726
+ const confirmErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : void 0;
12727
+ const reason = describeStripePaymentFailure(lastError) ?? describeStripePaymentFailure(confirmErr?.stripeCode) ?? unmappedPaymentFailureMessage(confirmErr?.stripeMessage);
12728
+ if (!isRetriablePaymentToken(selectedPaymentToken)) {
12729
+ dropConsumedToken(reason, lastConfirmError ?? void 0);
12730
+ } else {
12731
+ setSessionForCheckout(null);
12732
+ preserveErrorOnNextStepRef.current = true;
12733
+ setError(reason);
12734
+ setStep("amount");
12735
+ onDepositError?.({
12736
+ message: lastError ?? confirmErr?.stripeCode ?? "checkout_failed",
12737
+ error: lastConfirmError ?? void 0
12738
+ });
12739
+ }
12373
12740
  }
12374
12741
  } catch (err) {
12375
12742
  if (isStale()) return;
12376
- const msg = err instanceof Error ? err.message : "Checkout failed";
12377
- const errorType = err instanceof import_core21.StripeApiResponseError ? err.errorType : void 0;
12378
- if (errorType === "stripe_onramp_missing_minimum_identity_verification") {
12743
+ const stripeErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : err instanceof import_core21.StripeApiResponseError ? err : void 0;
12744
+ const effectiveError = stripeErr ?? err;
12745
+ const msg = stripeErr?.message ?? (err instanceof Error ? err.message : "Checkout failed");
12746
+ const errorType = stripeErr?.errorType;
12747
+ if (isConsumedPaymentMethodError(effectiveError)) {
12748
+ dropConsumedToken(CONSUMED_TOKEN_MESSAGE, effectiveError);
12749
+ } else if (errorType === "stripe_onramp_missing_minimum_identity_verification") {
12379
12750
  setStep("kyc");
12380
12751
  setError(null);
12381
12752
  } else if (errorType === "stripe_onramp_missing_identity_verification") {
12382
- surfaceStepUpOnAmount(err, msg, "l1");
12753
+ surfaceStepUpOnAmount(effectiveError, msg, "l1");
12383
12754
  } else if (errorType === "stripe_onramp_missing_document_verification") {
12384
- surfaceStepUpOnAmount(err, msg, "l2");
12755
+ surfaceStepUpOnAmount(effectiveError, msg, "l2");
12385
12756
  } else if (errorType === "stripe_onramp_purchase_limit_reached") {
12386
- surfaceStepUpOnAmount(err, msg, null);
12757
+ surfaceStepUpOnAmount(effectiveError, msg, null);
12387
12758
  } else {
12388
- setError(msg);
12389
- setStep("amount");
12390
- onDepositError?.({ message: msg, error: err });
12759
+ const reason = describeStripePaymentFailure(stripeErr?.stripeCode) ?? (stripeErr?.stripeMessage ? unmappedPaymentFailureMessage(stripeErr.stripeMessage) : msg || unmappedPaymentFailureMessage());
12760
+ if (!isRetriablePaymentToken(selectedPaymentToken)) {
12761
+ dropConsumedToken(reason, effectiveError);
12762
+ } else {
12763
+ setSessionForCheckout(null);
12764
+ preserveErrorOnNextStepRef.current = true;
12765
+ setError(reason);
12766
+ setStep("amount");
12767
+ onDepositError?.({ message: msg || "checkout_failed", error: effectiveError });
12768
+ }
12391
12769
  }
12392
12770
  } finally {
12393
12771
  setLoading(false);
@@ -12413,7 +12791,7 @@ function PayWithStripeLink({
12413
12791
  const merged = [
12414
12792
  ...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
12415
12793
  ...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
12416
- ];
12794
+ ].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
12417
12795
  if (merged.length > 0) {
12418
12796
  const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
12419
12797
  selectPaymentToken(preferred);
@@ -12492,7 +12870,7 @@ function PayWithStripeLink({
12492
12870
  (0, import_react17.useEffect)(() => {
12493
12871
  if (step === "review") {
12494
12872
  const existing = sessionForCheckoutRef.current;
12495
- const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken);
12873
+ const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(existing.id));
12496
12874
  if (quoteNonce === quoteNonceAtReviewRef.current && hasFreshSession) return;
12497
12875
  quoteNonceAtReviewRef.current = quoteNonce;
12498
12876
  } else if (step !== "amount") {
@@ -12516,7 +12894,9 @@ function PayWithStripeLink({
12516
12894
  const hasPaymentMethod = !!(isAuthenticated && selectedPaymentToken && onrampWalletAddress && isOnrampWalletRegistered);
12517
12895
  if (hasPaymentMethod) {
12518
12896
  const existing = sessionForCheckoutRef.current;
12519
- const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken;
12897
+ const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken && // Never refresh (and thereby reuse) a session already checked out —
12898
+ // its PaymentIntent is spent. Build a fresh one instead.
12899
+ !spentSessionIdsRef.current.has(existing.id);
12520
12900
  const session = canRefreshExisting ? await withTokenRefresh((tok) => (0, import_core21.stripeRefreshQuote)(existing.id, tok, publishableKey)) : await withTokenRefresh(
12521
12901
  (tok) => (0, import_core21.stripeCreateSession)(
12522
12902
  {
@@ -12644,7 +13024,7 @@ function PayWithStripeLink({
12644
13024
  const exceedsReachedLimit = limitReachedAmount !== null && hasInput && amountNum >= limitReachedAmount;
12645
13025
  const exceedsLimit = exceedsKnownLimit || exceedsReachedLimit || requiredStepUp !== null;
12646
13026
  const isValidAmount = hasInput && amountNum >= 5 && !exceedsLimit;
12647
- const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken);
13027
+ const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(sessionForCheckout.id));
12648
13028
  const canCheckoutDirectly = !!(oauthToken && customerId && selectedPaymentToken && isOnrampWalletRegistered);
12649
13029
  const isPreparingSession = canCheckoutDirectly && isValidAmount && !quoteError && (quoteLoading || !hasValidSession);
12650
13030
  const custTiers = customer?.kyc_tiers ?? [];
@@ -13161,7 +13541,7 @@ function PayWithStripeLink({
13161
13541
  {
13162
13542
  onClick: kycFormMode === "name" ? handleNameNext : handleKycSubmit,
13163
13543
  disabled: loading || (kycFormMode === "name" ? !kycForm.givenName || !kycForm.surname : kycFormMode === "address" ? !kycForm.addressLine1 || !kycForm.addressCity || !kycForm.addressState || !kycForm.addressPostalCode : !kycForm.ssn || !kycForm.dob.day || !kycForm.dob.month || !kycForm.dob.year),
13164
- className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
13544
+ className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
13165
13545
  style: {
13166
13546
  backgroundColor: components.button.primaryBackground,
13167
13547
  fontFamily: fonts.medium,
@@ -13220,7 +13600,17 @@ function PayWithStripeLink({
13220
13600
  className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
13221
13601
  }
13222
13602
  ),
13223
- !stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react25.Loader2, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }) }),
13603
+ !stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-gap-3 uf-py-10", children: [
13604
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react25.Loader2, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }),
13605
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13606
+ "p",
13607
+ {
13608
+ className: "uf-text-sm uf-text-center",
13609
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
13610
+ children: "Setting up secure payment\u2026"
13611
+ }
13612
+ )
13613
+ ] }),
13224
13614
  error && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13225
13615
  "div",
13226
13616
  {
@@ -13327,35 +13717,14 @@ function PayWithStripeLink({
13327
13717
  isCustomerVerified(customer) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "uf-px-1", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
13328
13718
  "button",
13329
13719
  {
13330
- onClick: async () => {
13331
- if (coordinator && sdkAuthenticatedRef.current) {
13332
- setStep("add_payment");
13333
- return;
13334
- }
13335
- pendingAddPaymentRef.current = true;
13336
- if (accessTokenRef.current && email) {
13337
- setLoading(true);
13338
- try {
13339
- await withTokenRefresh(
13340
- (tok) => (0, import_core21.stripeGetCustomer)(customerId, tok, publishableKey)
13341
- );
13342
- const sdk = await initialize();
13343
- if (!sdk) throw new Error("SDK failed to load");
13344
- const authResult = await (0, import_core21.stripeCreateAuthIntent)(email, publishableKey);
13345
- setAuthIntentId(authResult.auth_intent_id);
13346
- setStep("auth");
13347
- } catch {
13348
- setStep("email");
13349
- } finally {
13350
- setLoading(false);
13351
- }
13352
- return;
13353
- }
13354
- setStep("email");
13720
+ onClick: () => {
13721
+ setStep("add_payment");
13355
13722
  },
13723
+ onMouseEnter: () => setAddPaymentHovered(true),
13724
+ onMouseLeave: () => setAddPaymentHovered(false),
13356
13725
  className: "uf-w-full uf-p-3 uf-flex uf-items-center uf-gap-3 uf-transition-colors",
13357
13726
  style: {
13358
- backgroundColor: components.card.backgroundColor,
13727
+ backgroundColor: addPaymentHovered ? colors2.cardHover : components.card.backgroundColor,
13359
13728
  borderRadius: components.card.borderRadius,
13360
13729
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
13361
13730
  },
@@ -13470,7 +13839,7 @@ function PayWithStripeLink({
13470
13839
  {
13471
13840
  onClick: () => handleEmailSubmit(),
13472
13841
  disabled: loading || !email.trim(),
13473
- className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
13842
+ className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
13474
13843
  style: {
13475
13844
  backgroundColor: components.button.primaryBackground,
13476
13845
  fontFamily: fonts.medium,
@@ -13699,7 +14068,7 @@ function PayWithStripeLink({
13699
14068
  {
13700
14069
  onClick: handleRegisterSubmit,
13701
14070
  disabled: loading || phone.length !== 10,
13702
- className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
14071
+ className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
13703
14072
  style: {
13704
14073
  backgroundColor: components.button.primaryBackground,
13705
14074
  fontFamily: fonts.medium,
@@ -13833,7 +14202,9 @@ function PayWithStripeLink({
13833
14202
  );
13834
14203
  }
13835
14204
  if (step === "amount") {
13836
- const paymentSelector = oauthToken && customerId && isCustomerVerified(customer) ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
14205
+ const canSelectPaymentMethod = !!(oauthToken && customerId && isCustomerVerified(customer));
14206
+ const needsPaymentMethodSelection = canSelectPaymentMethod && !selectedPaymentToken;
14207
+ const paymentSelector = canSelectPaymentMethod ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
13837
14208
  "button",
13838
14209
  {
13839
14210
  onClick: () => setStep("payment"),
@@ -13907,6 +14278,35 @@ function PayWithStripeLink({
13907
14278
  style: { backgroundColor: colors2.background },
13908
14279
  children: [
13909
14280
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-mb-6 uf-pt-2", children: [
14281
+ error && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
14282
+ "div",
14283
+ {
14284
+ className: "uf-flex uf-items-start uf-gap-2 uf-mx-1 uf-mb-4 uf-px-3 uf-py-2.5",
14285
+ role: "alert",
14286
+ style: {
14287
+ backgroundColor: `${colors2.error}14`,
14288
+ border: `1px solid ${colors2.error}40`,
14289
+ borderRadius: components.card.borderRadius
14290
+ },
14291
+ children: [
14292
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
14293
+ import_lucide_react25.AlertTriangle,
14294
+ {
14295
+ className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
14296
+ style: { color: colors2.error }
14297
+ }
14298
+ ),
14299
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
14300
+ "span",
14301
+ {
14302
+ className: "uf-text-xs uf-text-left",
14303
+ style: { color: colors2.error, fontFamily: fonts.regular },
14304
+ children: error
14305
+ }
14306
+ )
14307
+ ]
14308
+ }
14309
+ ),
13910
14310
  paymentSelector,
13911
14311
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-text-center uf-mb-4", children: [
13912
14312
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
@@ -13943,7 +14343,7 @@ function PayWithStripeLink({
13943
14343
  children: amount && amountNum < 5 && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: "Minimum amount is $5" }) : exceedsLimit && canRaiseLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { style: { color: colors2.foregroundMuted }, children: [
13944
14344
  purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 ` : "Limit reached \xB7 ",
13945
14345
  "Verify to raise"
13946
- ] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: error }) : quoteError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: quoteError }) : quoteLoading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
14346
+ ] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) : quoteError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: quoteError }) : quoteLoading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
13947
14347
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13948
14348
  import_lucide_react25.Loader2,
13949
14349
  {
@@ -14033,7 +14433,7 @@ function PayWithStripeLink({
14033
14433
  {
14034
14434
  onClick: startLimitStepUp,
14035
14435
  disabled: loading,
14036
- className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
14436
+ className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
14037
14437
  style: {
14038
14438
  backgroundColor: components.button.primaryBackground,
14039
14439
  fontFamily: fonts.medium,
@@ -14045,8 +14445,8 @@ function PayWithStripeLink({
14045
14445
  "button",
14046
14446
  {
14047
14447
  onClick: handleAmountContinue,
14048
- disabled: loading || !isValidAmount || !quote || isPreparingSession,
14049
- className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
14448
+ disabled: loading || !isValidAmount || !quote || isPreparingSession || needsPaymentMethodSelection,
14449
+ className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
14050
14450
  style: {
14051
14451
  backgroundColor: components.button.primaryBackground,
14052
14452
  fontFamily: fonts.medium,
@@ -14176,7 +14576,7 @@ function PayWithStripeLink({
14176
14576
  {
14177
14577
  onClick: isBuyNow ? handleCheckout : handleReviewContinue,
14178
14578
  disabled: loading || !quote || isBuyNow && !hasValidSession,
14179
- className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-colors disabled:uf-opacity-40",
14579
+ className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
14180
14580
  style: {
14181
14581
  backgroundColor: components.button.primaryBackground,
14182
14582
  fontFamily: fonts.medium,
@@ -16423,16 +16823,38 @@ function useExchanges({
16423
16823
  return { exchanges, isLoading };
16424
16824
  }
16425
16825
 
16426
- // src/hooks/use-apple-pay-providers.ts
16826
+ // src/hooks/use-public-incident.ts
16427
16827
  var import_react_query13 = require("@tanstack/react-query");
16428
16828
  var import_core27 = require("@unifold/core");
16829
+ function usePublicIncident({
16830
+ publishableKey,
16831
+ enabled = true
16832
+ }) {
16833
+ const {
16834
+ data: incident,
16835
+ isLoading,
16836
+ error
16837
+ } = (0, import_react_query13.useQuery)({
16838
+ queryKey: ["unifold", "publicIncident", publishableKey],
16839
+ queryFn: () => (0, import_core27.getPublicIncident)(publishableKey),
16840
+ enabled,
16841
+ staleTime: 1e3 * 30,
16842
+ refetchInterval: 1e3 * 30,
16843
+ refetchOnWindowFocus: true
16844
+ });
16845
+ return { incident, isLoading, error: error ?? null };
16846
+ }
16847
+
16848
+ // src/hooks/use-apple-pay-providers.ts
16849
+ var import_react_query14 = require("@tanstack/react-query");
16850
+ var import_core28 = require("@unifold/core");
16429
16851
  function useApplePayProviders({
16430
16852
  publishableKey,
16431
16853
  enabled = true
16432
16854
  }) {
16433
- const { data: providers, isLoading } = (0, import_react_query13.useQuery)({
16855
+ const { data: providers, isLoading } = (0, import_react_query14.useQuery)({
16434
16856
  queryKey: ["unifold", "applePayProviders", publishableKey],
16435
- queryFn: () => (0, import_core27.getApplePayProviders)(publishableKey),
16857
+ queryFn: () => (0, import_core28.getApplePayProviders)(publishableKey),
16436
16858
  enabled,
16437
16859
  staleTime: 1e3 * 60 * 30,
16438
16860
  refetchOnMount: true,
@@ -16442,7 +16864,7 @@ function useApplePayProviders({
16442
16864
  }
16443
16865
 
16444
16866
  // src/components/deposits/DepositModal.tsx
16445
- var import_core37 = require("@unifold/core");
16867
+ var import_core38 = require("@unifold/core");
16446
16868
 
16447
16869
  // src/hooks/use-allowed-country.ts
16448
16870
  function useAllowedCountry(publishableKey) {
@@ -16487,8 +16909,8 @@ function useAllowedCountry(publishableKey) {
16487
16909
  }
16488
16910
 
16489
16911
  // src/hooks/use-address-validation.ts
16490
- var import_react_query14 = require("@tanstack/react-query");
16491
- var import_core28 = require("@unifold/core");
16912
+ var import_react_query15 = require("@tanstack/react-query");
16913
+ var import_core29 = require("@unifold/core");
16492
16914
  function useAddressValidation({
16493
16915
  recipientAddress,
16494
16916
  destinationChainType,
@@ -16499,7 +16921,7 @@ function useAddressValidation({
16499
16921
  refetchOnMount = false
16500
16922
  }) {
16501
16923
  const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
16502
- const { data, isLoading, error } = (0, import_react_query14.useQuery)({
16924
+ const { data, isLoading, error } = (0, import_react_query15.useQuery)({
16503
16925
  queryKey: [
16504
16926
  "unifold",
16505
16927
  "addressValidation",
@@ -16508,7 +16930,7 @@ function useAddressValidation({
16508
16930
  destinationChainId,
16509
16931
  destinationTokenAddress
16510
16932
  ],
16511
- queryFn: () => (0, import_core28.verifyRecipientAddress)(
16933
+ queryFn: () => (0, import_core29.verifyRecipientAddress)(
16512
16934
  {
16513
16935
  chain_type: destinationChainType,
16514
16936
  chain_id: destinationChainId,
@@ -16530,6 +16952,7 @@ function useAddressValidation({
16530
16952
  return {
16531
16953
  isValid: null,
16532
16954
  failureCode: null,
16955
+ message: null,
16533
16956
  metadata: null,
16534
16957
  isLoading: false,
16535
16958
  error: null
@@ -16538,6 +16961,7 @@ function useAddressValidation({
16538
16961
  return {
16539
16962
  isValid: data?.valid ?? null,
16540
16963
  failureCode: data?.failure_code ?? null,
16964
+ message: data?.message ?? null,
16541
16965
  metadata: data?.metadata ?? null,
16542
16966
  isLoading,
16543
16967
  error: error ?? null
@@ -16789,7 +17213,7 @@ function PoweredByUnifold({
16789
17213
  }
16790
17214
 
16791
17215
  // src/components/deposits/DepositsModal.tsx
16792
- var import_core29 = require("@unifold/core");
17216
+ var import_core30 = require("@unifold/core");
16793
17217
  var import_jsx_runtime48 = require("react/jsx-runtime");
16794
17218
  function DepositsModal({
16795
17219
  open,
@@ -16807,7 +17231,7 @@ function DepositsModal({
16807
17231
  if (!open || !userId) return;
16808
17232
  const fetchExecutions = async () => {
16809
17233
  try {
16810
- const response = await (0, import_core29.queryExecutions)(userId, publishableKey, import_core29.ActionType.Deposit);
17234
+ const response = await (0, import_core30.queryExecutions)(userId, publishableKey, import_core30.ActionType.Deposit);
16811
17235
  const sorted = [...response.data].sort((a, b) => {
16812
17236
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
16813
17237
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -17390,6 +17814,37 @@ var import_react21 = require("react");
17390
17814
  var getChainKey = (chainId, chainType) => {
17391
17815
  return `${chainType}:${chainId}`;
17392
17816
  };
17817
+ function getStoredSelection(key) {
17818
+ if (typeof window === "undefined") return null;
17819
+ try {
17820
+ const raw = localStorage.getItem(key);
17821
+ if (!raw) return null;
17822
+ const parsed = JSON.parse(raw);
17823
+ if (parsed && typeof parsed.symbol === "string" && typeof parsed.chainType === "string" && typeof parsed.chainId === "string") {
17824
+ return parsed;
17825
+ }
17826
+ } catch {
17827
+ }
17828
+ return null;
17829
+ }
17830
+ function saveStoredSelection(key, symbol, chainType, chainId) {
17831
+ if (typeof window === "undefined") return;
17832
+ try {
17833
+ localStorage.setItem(key, JSON.stringify({ symbol, chainType, chainId }));
17834
+ } catch {
17835
+ }
17836
+ }
17837
+ function resolveFromStorage(tokens, stored) {
17838
+ for (const t13 of tokens) {
17839
+ if (t13.symbol !== stored.symbol) continue;
17840
+ const matchedChain = t13.chains.find(
17841
+ (c) => c.chain_type === stored.chainType && c.chain_id === stored.chainId
17842
+ );
17843
+ if (matchedChain) return { token: t13, chain: matchedChain };
17844
+ if (t13.chains.length > 0) return { token: t13, chain: t13.chains[0] };
17845
+ }
17846
+ return null;
17847
+ }
17393
17848
  function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
17394
17849
  if (!tokens.length) return null;
17395
17850
  let selectedToken;
@@ -17439,27 +17894,73 @@ function useDefaultToken({
17439
17894
  defaultChainType,
17440
17895
  defaultChainId,
17441
17896
  defaultTokenAddress,
17442
- defaultSymbol
17897
+ defaultSymbol,
17898
+ storageKey: storageKey2
17443
17899
  }) {
17444
- const [token, setToken] = (0, import_react21.useState)(null);
17445
- const [chain, setChain] = (0, import_react21.useState)(null);
17900
+ const [token, setTokenState] = (0, import_react21.useState)(null);
17901
+ const [chain, setChainState] = (0, import_react21.useState)(null);
17446
17902
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react21.useState)(false);
17447
17903
  const appliedDefaultsRef = (0, import_react21.useRef)("");
17904
+ const tokenRef = (0, import_react21.useRef)(null);
17905
+ const chainRef = (0, import_react21.useRef)(null);
17906
+ tokenRef.current = token;
17907
+ chainRef.current = chain;
17908
+ const setToken = (0, import_react21.useCallback)(
17909
+ (newToken) => {
17910
+ tokenRef.current = newToken;
17911
+ setTokenState(newToken);
17912
+ if (storageKey2 && chainRef.current) {
17913
+ const [chainType, chainId] = chainRef.current.split(":");
17914
+ saveStoredSelection(storageKey2, newToken, chainType, chainId);
17915
+ }
17916
+ },
17917
+ [storageKey2]
17918
+ );
17919
+ const setChain = (0, import_react21.useCallback)(
17920
+ (newChain) => {
17921
+ chainRef.current = newChain;
17922
+ setChainState(newChain);
17923
+ if (storageKey2 && tokenRef.current) {
17924
+ const [chainType, chainId] = newChain.split(":");
17925
+ saveStoredSelection(storageKey2, tokenRef.current, chainType, chainId);
17926
+ }
17927
+ },
17928
+ [storageKey2]
17929
+ );
17448
17930
  (0, import_react21.useEffect)(() => {
17449
17931
  if (!tokens.length) return;
17450
17932
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
17451
17933
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
17452
17934
  if (initialSelectionDone && !defaultsChanged) return;
17453
- const result = resolveToken(
17454
- tokens,
17455
- defaultChainType,
17456
- defaultChainId,
17457
- defaultTokenAddress,
17458
- defaultSymbol
17459
- );
17935
+ const hasExplicitDefaults = defaultTokenAddress && defaultChainType && defaultChainId || defaultSymbol && defaultChainType && defaultChainId;
17936
+ let result = null;
17937
+ if (hasExplicitDefaults) {
17938
+ result = resolveToken(
17939
+ tokens,
17940
+ defaultChainType,
17941
+ defaultChainId,
17942
+ defaultTokenAddress,
17943
+ defaultSymbol
17944
+ );
17945
+ if (result) {
17946
+ const matched = defaultTokenAddress && result.chain.token_address.toLowerCase() === defaultTokenAddress.toLowerCase() && result.chain.chain_type === defaultChainType && result.chain.chain_id === defaultChainId || defaultSymbol && result.token.symbol === defaultSymbol && result.chain.chain_type === defaultChainType && result.chain.chain_id === defaultChainId;
17947
+ if (!matched) {
17948
+ result = null;
17949
+ }
17950
+ }
17951
+ }
17952
+ if (!result && storageKey2) {
17953
+ const stored = getStoredSelection(storageKey2);
17954
+ if (stored) {
17955
+ result = resolveFromStorage(tokens, stored);
17956
+ }
17957
+ }
17958
+ if (!result) {
17959
+ result = resolveToken(tokens);
17960
+ }
17460
17961
  if (result) {
17461
- setToken(result.token.symbol);
17462
- setChain(getChainKey(result.chain.chain_id, result.chain.chain_type));
17962
+ setTokenState(result.token.symbol);
17963
+ setChainState(getChainKey(result.chain.chain_id, result.chain.chain_type));
17463
17964
  appliedDefaultsRef.current = defaultsKey;
17464
17965
  setInitialSelectionDone(true);
17465
17966
  }
@@ -17469,7 +17970,8 @@ function useDefaultToken({
17469
17970
  defaultSymbol,
17470
17971
  defaultChainType,
17471
17972
  defaultChainId,
17472
- initialSelectionDone
17973
+ initialSelectionDone,
17974
+ storageKey2
17473
17975
  ]);
17474
17976
  (0, import_react21.useEffect)(() => {
17475
17977
  if (!tokens.length || !token) return;
@@ -17480,13 +17982,14 @@ function useDefaultToken({
17480
17982
  });
17481
17983
  if (!isChainAvailable) {
17482
17984
  const firstChain = currentToken.chains[0];
17483
- setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
17985
+ setChainState(getChainKey(firstChain.chain_id, firstChain.chain_type));
17484
17986
  }
17485
17987
  }, [token, tokens, chain]);
17486
17988
  return { token, chain, setToken, setChain, initialSelectionDone };
17487
17989
  }
17488
17990
 
17489
17991
  // src/hooks/use-default-source-token.ts
17992
+ var STORAGE_KEY2 = "unifold_last_deposit_from_token";
17490
17993
  function useDefaultSourceToken({
17491
17994
  supportedTokens,
17492
17995
  defaultSourceChainType,
@@ -17499,7 +18002,8 @@ function useDefaultSourceToken({
17499
18002
  defaultChainType: defaultSourceChainType,
17500
18003
  defaultChainId: defaultSourceChainId,
17501
18004
  defaultTokenAddress: defaultSourceTokenAddress,
17502
- defaultSymbol: defaultSourceSymbol
18005
+ defaultSymbol: defaultSourceSymbol,
18006
+ storageKey: STORAGE_KEY2
17503
18007
  });
17504
18008
  }
17505
18009
 
@@ -17844,11 +18348,11 @@ var TooltipContent = React33.forwardRef(({ className, sideOffset = 4, ...props }
17844
18348
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
17845
18349
 
17846
18350
  // src/components/deposits/TransferCryptoSingleInput.tsx
17847
- var import_core31 = require("@unifold/core");
18351
+ var import_core32 = require("@unifold/core");
17848
18352
 
17849
18353
  // src/hooks/use-hypercore-activation.ts
17850
- var import_react_query15 = require("@tanstack/react-query");
17851
- var import_core30 = require("@unifold/core");
18354
+ var import_react_query16 = require("@tanstack/react-query");
18355
+ var import_core31 = require("@unifold/core");
17852
18356
 
17853
18357
  // src/lib/constants.ts
17854
18358
  var HYPERCORE_CHAIN_ID = "1337";
@@ -17866,9 +18370,9 @@ function useHypercoreActivation(params) {
17866
18370
  const recipient = recipientAddress?.trim() ?? "";
17867
18371
  const source = sourceAddress?.trim() ?? "";
17868
18372
  const hasAddresses = !!recipient && !!source;
17869
- const { data, isLoading } = (0, import_react_query15.useQuery)({
18373
+ const { data, isLoading } = (0, import_react_query16.useQuery)({
17870
18374
  queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
17871
- queryFn: () => (0, import_core30.checkHypercoreActivation)(
18375
+ queryFn: () => (0, import_core31.checkHypercoreActivation)(
17872
18376
  {
17873
18377
  source_address: source,
17874
18378
  recipient_address: recipient
@@ -18017,7 +18521,7 @@ function TransferCryptoSingleInput({
18017
18521
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
18018
18522
  ) : void 0;
18019
18523
  const currentChainType = currentChainData?.chain_type || "ethereum";
18020
- const currentWallet = (0, import_core31.getWalletByChainType)(wallets, currentChainType);
18524
+ const currentWallet = (0, import_core32.getWalletByChainType)(wallets, currentChainType);
18021
18525
  const depositAddress = currentWallet?.address || "";
18022
18526
  const {
18023
18527
  executions: depositExecutions,
@@ -18262,7 +18766,7 @@ function TransferCryptoSingleInput({
18262
18766
  className: "uf-text-sm uf-font-semibold",
18263
18767
  style: { color: components.card.titleColor, fontFamily: fonts.semibold },
18264
18768
  children: [
18265
- checkoutQuote.isStablecoin ? (0, import_core31.formatStablecoinAmount)(
18769
+ checkoutQuote.isStablecoin ? (0, import_core32.formatStablecoinAmount)(
18266
18770
  checkoutQuote.sourceAmount,
18267
18771
  checkoutQuote.sourceTokenDecimals
18268
18772
  ) : (Number(checkoutQuote.sourceAmount) / 10 ** checkoutQuote.sourceTokenDecimals).toFixed(Math.min(checkoutQuote.sourceTokenDecimals, 6)),
@@ -18747,7 +19251,7 @@ var SelectSeparator = React34.forwardRef(({ className, ...props }, ref) => /* @_
18747
19251
  SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
18748
19252
 
18749
19253
  // src/components/deposits/TransferCryptoDoubleInput.tsx
18750
- var import_core32 = require("@unifold/core");
19254
+ var import_core33 = require("@unifold/core");
18751
19255
  var import_jsx_runtime56 = require("react/jsx-runtime");
18752
19256
  var t7 = i18n.transferCrypto;
18753
19257
  var getChainKey3 = (chainId, chainType) => {
@@ -18832,7 +19336,7 @@ function TransferCryptoDoubleInput({
18832
19336
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
18833
19337
  ) : void 0;
18834
19338
  const currentChainType = currentChainData?.chain_type || "ethereum";
18835
- const currentWallet = (0, import_core32.getWalletByChainType)(wallets, currentChainType);
19339
+ const currentWallet = (0, import_core33.getWalletByChainType)(wallets, currentChainType);
18836
19340
  const depositAddress = currentWallet?.address || "";
18837
19341
  const {
18838
19342
  executions: depositExecutions,
@@ -19402,10 +19906,10 @@ function TransferCryptoDoubleInput({
19402
19906
  // src/components/deposits/WalletConnect.tsx
19403
19907
  var React35 = __toESM(require("react"));
19404
19908
  var import_lucide_react36 = require("lucide-react");
19405
- var import_core36 = require("@unifold/core");
19909
+ var import_core37 = require("@unifold/core");
19406
19910
 
19407
19911
  // src/lib/send-hypercore.ts
19408
- var import_core33 = require("@unifold/core");
19912
+ var import_core34 = require("@unifold/core");
19409
19913
  function isHypercoreChain(chainId) {
19410
19914
  return chainId === HYPERCORE_CHAIN_ID;
19411
19915
  }
@@ -19416,7 +19920,7 @@ async function sendHypercoreEvmTransfer(params) {
19416
19920
  params: []
19417
19921
  });
19418
19922
  const activeChainId = String(parseInt(currentChainHex, 16));
19419
- const buildResult = await (0, import_core33.buildHypercoreTransaction)(
19923
+ const buildResult = await (0, import_core34.buildHypercoreTransaction)(
19420
19924
  {
19421
19925
  signature_chain_id: activeChainId,
19422
19926
  recipient_address: recipientAddress,
@@ -19429,7 +19933,7 @@ async function sendHypercoreEvmTransfer(params) {
19429
19933
  method: "eth_signTypedData_v4",
19430
19934
  params: [fromAddress, JSON.stringify(buildResult.typed_data)]
19431
19935
  });
19432
- await (0, import_core33.sendHypercoreTransaction)(
19936
+ await (0, import_core34.sendHypercoreTransaction)(
19433
19937
  {
19434
19938
  action_payload: buildResult.action_payload,
19435
19939
  signature,
@@ -19441,8 +19945,8 @@ async function sendHypercoreEvmTransfer(params) {
19441
19945
  }
19442
19946
 
19443
19947
  // src/hooks/use-deposit-quote.ts
19444
- var import_react_query16 = require("@tanstack/react-query");
19445
- var import_core34 = require("@unifold/core");
19948
+ var import_react_query17 = require("@tanstack/react-query");
19949
+ var import_core35 = require("@unifold/core");
19446
19950
  function useDepositQuote(params) {
19447
19951
  const {
19448
19952
  publishableKey,
@@ -19468,7 +19972,7 @@ function useDepositQuote(params) {
19468
19972
  ...adjustForSlippage ? { adjust_for_slippage: true } : {},
19469
19973
  ...stablecoinParity ? { stablecoin_parity: true } : {}
19470
19974
  };
19471
- return (0, import_react_query16.useQuery)({
19975
+ return (0, import_react_query17.useQuery)({
19472
19976
  queryKey: [
19473
19977
  "unifold",
19474
19978
  "depositQuote",
@@ -19483,7 +19987,7 @@ function useDepositQuote(params) {
19483
19987
  stablecoinParity,
19484
19988
  publishableKey
19485
19989
  ],
19486
- queryFn: () => (0, import_core34.getDepositQuote)(request, publishableKey),
19990
+ queryFn: () => (0, import_core35.getDepositQuote)(request, publishableKey),
19487
19991
  enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
19488
19992
  staleTime: 3e4,
19489
19993
  gcTime: 5 * 6e4,
@@ -19496,15 +20000,15 @@ function useDepositQuote(params) {
19496
20000
  }
19497
20001
 
19498
20002
  // src/hooks/use-external-wallets.ts
19499
- var import_react_query17 = require("@tanstack/react-query");
19500
- var import_core35 = require("@unifold/core");
20003
+ var import_react_query18 = require("@tanstack/react-query");
20004
+ var import_core36 = require("@unifold/core");
19501
20005
  function useExternalWallets({
19502
20006
  publishableKey,
19503
20007
  enabled = true
19504
20008
  }) {
19505
- const { data: wallets = [], isLoading } = (0, import_react_query17.useQuery)({
20009
+ const { data: wallets = [], isLoading } = (0, import_react_query18.useQuery)({
19506
20010
  queryKey: ["unifold", "external-wallets", publishableKey],
19507
- queryFn: () => (0, import_core35.getExternalWallets)(publishableKey).then((res) => res.data),
20011
+ queryFn: () => (0, import_core36.getExternalWallets)(publishableKey).then((res) => res.data),
19508
20012
  enabled: enabled && !!publishableKey,
19509
20013
  staleTime: 1e3 * 60 * 30,
19510
20014
  refetchOnMount: false,
@@ -20613,33 +21117,11 @@ function balancesRepresentSameToken(a, b) {
20613
21117
  if (!tokenA || !tokenB) return false;
20614
21118
  return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
20615
21119
  }
20616
- function getSolanaProviders() {
20617
- if (typeof window === "undefined") return {};
20618
- const win = window;
20619
- return {
20620
- phantomSolana: win.phantom?.solana,
20621
- solflare: win.solflare,
20622
- backpack: win.backpack,
20623
- glow: win.glow,
20624
- coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
20625
- };
20626
- }
20627
- function getLegacyEvmProviders() {
20628
- if (typeof window === "undefined") return {};
20629
- const win = window;
20630
- return {
20631
- ethereum: win.ethereum,
20632
- phantomEthereum: win.phantom?.ethereum,
20633
- coinbaseEthereum: win.coinbaseWalletExtension,
20634
- trustEthereum: win.trustwallet?.ethereum,
20635
- okxEthereum: win.okxwallet
20636
- };
20637
- }
20638
21120
  function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
20639
- const solProviders = getSolanaProviders();
20640
- const legacyEvm = getLegacyEvmProviders();
20641
- const eip6963List = getEip6963Providers();
20642
21121
  const win = typeof window !== "undefined" ? window : null;
21122
+ const solProviders = getInjectedSolanaProviders(win);
21123
+ const legacyEvm = getLegacyEvmProviders(win);
21124
+ const eip6963List = getEip6963Providers();
20643
21125
  const hasEip6963 = (walletId) => eip6963List.some((d) => {
20644
21126
  const rdns = d.info?.rdns || "";
20645
21127
  switch (walletId) {
@@ -20891,7 +21373,7 @@ function WalletConnect({
20891
21373
  const chainType = activeDepositWallet?.chain_type ?? "ethereum";
20892
21374
  const recipientAddress = activeDepositWallet?.address ?? "";
20893
21375
  const isCheckoutMode = !!checkoutAmountUsd;
20894
- const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
21376
+ const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" || chainType === "tron" ? "ethereum" : chainType;
20895
21377
  const transitionTo = React35.useCallback((nextView) => {
20896
21378
  if (nextView === viewRef.current) return;
20897
21379
  setIsTransitioning(true);
@@ -20908,10 +21390,13 @@ function WalletConnect({
20908
21390
  };
20909
21391
  const openMobileWalletBrowse = async (wallet, depositAddresses) => {
20910
21392
  try {
20911
- const res = await (0, import_core36.getWalletMobileDeepLink)(
21393
+ const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
21394
+ const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
21395
+ const res = await (0, import_core37.getWalletMobileDeepLink)(
20912
21396
  wallet.id,
20913
21397
  depositAddresses,
20914
- publishableKey
21398
+ publishableKey,
21399
+ forwardedAmountUsd
20915
21400
  );
20916
21401
  if (res.deeplink) {
20917
21402
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
@@ -21000,7 +21485,7 @@ function WalletConnect({
21000
21485
  const eip6963Match = findProviderByWalletId(wallet.id);
21001
21486
  let provider = eip6963Match?.provider;
21002
21487
  if (!provider) {
21003
- const legacyEvm = getLegacyEvmProviders();
21488
+ const legacyEvm = getLegacyEvmProviders(win);
21004
21489
  switch (wallet.id) {
21005
21490
  case "metamask":
21006
21491
  if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom)
@@ -21032,16 +21517,7 @@ function WalletConnect({
21032
21517
  const accounts = await provider.request({ method: "eth_requestAccounts" });
21033
21518
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
21034
21519
  setUserDisconnectedWallet(false);
21035
- const walletIdToType = {
21036
- phantom: "phantom-ethereum",
21037
- coinbase: "coinbase",
21038
- trust: "trust",
21039
- rainbow: "rainbow",
21040
- rabby: "rabby",
21041
- okx: "okx",
21042
- metamask: "metamask"
21043
- };
21044
- const walletType = walletIdToType[wallet.id] || "metamask";
21520
+ const walletType = walletIdToWalletType(wallet.id);
21045
21521
  setStoredWalletState(walletType);
21046
21522
  connectedInfo = {
21047
21523
  type: walletType,
@@ -21050,7 +21526,7 @@ function WalletConnect({
21050
21526
  icon: wallet.id
21051
21527
  };
21052
21528
  } else {
21053
- const solProviders = getSolanaProviders();
21529
+ const solProviders = getInjectedSolanaProviders(win);
21054
21530
  let provider;
21055
21531
  switch (wallet.id) {
21056
21532
  case "phantom":
@@ -21069,11 +21545,11 @@ function WalletConnect({
21069
21545
  provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
21070
21546
  break;
21071
21547
  case "trust":
21072
- provider = win?.trustwallet?.solana;
21548
+ provider = solProviders.trustSolana;
21073
21549
  break;
21074
21550
  }
21075
21551
  if (!provider) throw new Error(`${wallet.name} Solana wallet not found.`);
21076
- const response = await provider.connect();
21552
+ const response = await connectSolanaProviderWithRecovery(provider, wallet.id, wallet.name);
21077
21553
  setUserDisconnectedWallet(false);
21078
21554
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
21079
21555
  setStoredWalletState(walletType);
@@ -21219,7 +21695,7 @@ function WalletConnect({
21219
21695
  destination_chain_type: activeDepositWallet.destination_chain_type,
21220
21696
  ...productType ? { product_type: productType } : {}
21221
21697
  };
21222
- const response = await (0, import_core36.getSupportedDepositTokens)(publishableKey, options);
21698
+ const response = await (0, import_core37.getSupportedDepositTokens)(publishableKey, options);
21223
21699
  if (cancelled) return;
21224
21700
  const supportedToken = response.data.find(
21225
21701
  (t13) => t13.symbol.toLowerCase() === token.symbol.toLowerCase()
@@ -21246,8 +21722,8 @@ function WalletConnect({
21246
21722
  let cancelled = false;
21247
21723
  setIsLoading(true);
21248
21724
  setError(null);
21249
- const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
21250
- (0, import_core36.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
21725
+ const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" || activeDepositWallet.chain_type === "tron" ? "ethereum" : activeDepositWallet.chain_type;
21726
+ (0, import_core37.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
21251
21727
  if (cancelled) return;
21252
21728
  const nonZero = response.balances.filter((b) => b.amount !== "0");
21253
21729
  const defaultSource = {
@@ -21424,16 +21900,7 @@ function WalletConnect({
21424
21900
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
21425
21901
  };
21426
21902
  const resolveEvmProvider = () => {
21427
- const walletIdMap = {
21428
- "phantom-ethereum": "phantom",
21429
- coinbase: "coinbase",
21430
- trust: "trust",
21431
- okx: "okx",
21432
- rainbow: "rainbow",
21433
- rabby: "rabby",
21434
- metamask: "metamask"
21435
- };
21436
- const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
21903
+ const lookupId = walletTypeToWalletId(walletInfo.type);
21437
21904
  const eip6963Match = findProviderByWalletId(lookupId);
21438
21905
  let provider = eip6963Match?.provider;
21439
21906
  if (!provider) {
@@ -21523,7 +21990,7 @@ function WalletConnect({
21523
21990
  if (!provider.publicKey) await provider.connect();
21524
21991
  const isNative = token.token_address === "native" || token.token_address === "So11111111111111111111111111111111111111112" || token.token_address === "";
21525
21992
  const smallestUnit = isNative ? decimalToSmallestUnit(amountStr, 9) : decimalToSmallestUnit(amountStr, token.decimals);
21526
- const buildResp = await (0, import_core36.buildSolanaTransaction)(
21993
+ const buildResp = await (0, import_core37.buildSolanaTransaction)(
21527
21994
  {
21528
21995
  chain_id: "mainnet",
21529
21996
  token_address: token.token_address === "" ? "native" : token.token_address,
@@ -21545,7 +22012,7 @@ function WalletConnect({
21545
22012
  const ser = signed.serialize();
21546
22013
  let bs = "";
21547
22014
  for (let i = 0; i < ser.length; i++) bs += String.fromCharCode(ser[i]);
21548
- const resp = await (0, import_core36.sendSolanaTransaction)(
22015
+ const resp = await (0, import_core37.sendSolanaTransaction)(
21549
22016
  { chain_id: "mainnet", signed_transaction: btoa(bs) },
21550
22017
  publishableKey
21551
22018
  );
@@ -21591,7 +22058,7 @@ function WalletConnect({
21591
22058
  } else if (isHypercoreToken) {
21592
22059
  let sendAmount = tokenAmount;
21593
22060
  try {
21594
- const activation = await (0, import_core36.checkHypercoreActivation)(
22061
+ const activation = await (0, import_core37.checkHypercoreActivation)(
21595
22062
  { source_address: walletInfo.address, recipient_address: recipientAddress },
21596
22063
  publishableKey
21597
22064
  );
@@ -21968,8 +22435,8 @@ function WalletConnect({
21968
22435
  ] }) });
21969
22436
  }
21970
22437
  if (view === "mobile_deposit_status" && latestDepositExecution) {
21971
- const isComplete = latestDepositExecution.status === import_core36.ExecutionStatus.SUCCEEDED;
21972
- const isFailed = latestDepositExecution.status === import_core36.ExecutionStatus.FAILED;
22438
+ const isComplete = latestDepositExecution.status === import_core37.ExecutionStatus.SUCCEEDED;
22439
+ const isFailed = latestDepositExecution.status === import_core37.ExecutionStatus.FAILED;
21973
22440
  const title = isComplete ? "Payment Complete" : isFailed ? "Payment Failed" : "Payment Processing";
21974
22441
  return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { style: viewTransitionStyle, children: [
21975
22442
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
@@ -22165,6 +22632,7 @@ function DepositModal({
22165
22632
  applePayTitle = "Pay with Apple Pay",
22166
22633
  applePaySubTitle = "Instant",
22167
22634
  enableBankTransfer,
22635
+ enableIncidentBanner = false,
22168
22636
  // No default: left undefined so the backend `stripe_link.enabled` can govern
22169
22637
  // (via the `??` chain in showStripeLink) once a dashboard toggle exists.
22170
22638
  enableStripeLink,
@@ -22210,7 +22678,7 @@ function DepositModal({
22210
22678
  const s = initialScreen ?? "main";
22211
22679
  if (s === "tracker" && hideDepositTracker === true) return "main";
22212
22680
  if (s === "cashapp" && enableCashApp === false) return "main";
22213
- if (s === "stripe_link" && !enableStripeLink) return "main";
22681
+ if (s === "stripe_link" && enableStripeLink === false) return "main";
22214
22682
  if (s === "apple_pay" && enableApplePay === false) return "main";
22215
22683
  if (s === "card" && enableFiatOnramp === false) return "main";
22216
22684
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
@@ -22269,21 +22737,31 @@ function DepositModal({
22269
22737
  const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
22270
22738
  const showBankTransfer = enableBankTransfer ?? projectConfig?.bank_transfer?.enabled ?? true;
22271
22739
  const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
22740
+ const { incident: publicIncident } = usePublicIncident({
22741
+ publishableKey,
22742
+ enabled: open && enableIncidentBanner
22743
+ });
22744
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
22745
+ enabled: true,
22746
+ messages: publicIncident.messages,
22747
+ severity: publicIncident.severity,
22748
+ statusPageUrl: publicIncident.status_page_url
22749
+ } : void 0;
22272
22750
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react26.useState)([]);
22273
22751
  (0, import_react26.useEffect)(() => {
22274
22752
  if (!showConnectExchange || !open) return;
22275
- (0, import_core37.getIntegrationExchanges)(publishableKey).then((res) => setIntegrationExchanges(res.data)).catch(() => {
22753
+ (0, import_core38.getIntegrationExchanges)(publishableKey).then((res) => setIntegrationExchanges(res.data)).catch(() => {
22276
22754
  });
22277
22755
  }, [showConnectExchange, open, publishableKey]);
22278
22756
  const [connectedExchange, setConnectedExchange] = (0, import_react26.useState)(() => {
22279
22757
  if (!showConnectExchange) return null;
22280
- const stored = getStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE);
22758
+ const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
22281
22759
  if (!stored) return null;
22282
22760
  return { name: "Coinbase", iconUrl: void 0, balanceUsd: null, isLoading: true };
22283
22761
  });
22284
22762
  (0, import_react26.useEffect)(() => {
22285
22763
  if (!showConnectExchange || !open || view !== "main") return;
22286
- const stored = getStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE);
22764
+ const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
22287
22765
  if (!stored) {
22288
22766
  setConnectedExchange(null);
22289
22767
  return;
@@ -22303,24 +22781,24 @@ function DepositModal({
22303
22781
  }) : null;
22304
22782
  setConnectedExchange((prev) => prev ? { ...prev, balanceUsd, isLoading: false } : null);
22305
22783
  };
22306
- (0, import_core37.getIntegrationHoldings)(import_core37.IntegrationProvider.COINBASE, stored.access_token, publishableKey).then(processHoldings).catch(async () => {
22784
+ (0, import_core38.getIntegrationHoldings)(import_core38.IntegrationProvider.COINBASE, stored.access_token, publishableKey).then(processHoldings).catch(async () => {
22307
22785
  try {
22308
- const refreshResult = await (0, import_core37.refreshIntegrationToken)(stored.access_token, publishableKey);
22309
- if (!getStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE)) return;
22786
+ const refreshResult = await (0, import_core38.refreshIntegrationToken)(stored.access_token, publishableKey);
22787
+ if (!getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE)) return;
22310
22788
  setStoredIntegrationToken({
22311
- integration_provider: import_core37.IntegrationProvider.COINBASE,
22789
+ integration_provider: import_core38.IntegrationProvider.COINBASE,
22312
22790
  access_token: refreshResult.access_token,
22313
22791
  expires_at: refreshResult.expires_at
22314
22792
  });
22315
- const retryResult = await (0, import_core37.getIntegrationHoldings)(
22316
- import_core37.IntegrationProvider.COINBASE,
22793
+ const retryResult = await (0, import_core38.getIntegrationHoldings)(
22794
+ import_core38.IntegrationProvider.COINBASE,
22317
22795
  refreshResult.access_token,
22318
22796
  publishableKey
22319
22797
  );
22320
22798
  processHoldings(retryResult);
22321
22799
  } catch {
22322
- if (!getStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE)) return;
22323
- clearStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE);
22800
+ if (!getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE)) return;
22801
+ clearStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
22324
22802
  setConnectedExchange(null);
22325
22803
  }
22326
22804
  });
@@ -22328,14 +22806,18 @@ function DepositModal({
22328
22806
  (0, import_react26.useEffect)(() => {
22329
22807
  if (!connectedExchange || integrationExchanges.length === 0) return;
22330
22808
  const cbExchange = integrationExchanges.find(
22331
- (e) => e.service_provider === import_core37.IntegrationProvider.COINBASE
22809
+ (e) => e.service_provider === import_core38.IntegrationProvider.COINBASE
22332
22810
  );
22333
22811
  const iconUrl = cbExchange?.icon_urls?.find((u) => u.format === "svg")?.url || cbExchange?.icon_urls?.find((u) => u.format === "png")?.url || cbExchange?.icon_url;
22334
22812
  if (iconUrl && iconUrl !== connectedExchange.iconUrl) {
22335
22813
  setConnectedExchange((prev) => prev ? { ...prev, iconUrl } : prev);
22336
22814
  }
22337
22815
  }, [integrationExchanges, connectedExchange]);
22338
- const { data: depositAddressResponse, isLoading: walletsLoading } = useDepositAddress({
22816
+ const {
22817
+ data: depositAddressResponse,
22818
+ isLoading: walletsLoading,
22819
+ error: walletsError
22820
+ } = useDepositAddress({
22339
22821
  userId,
22340
22822
  publishableKey,
22341
22823
  recipientAddress,
@@ -22433,7 +22915,7 @@ function DepositModal({
22433
22915
  if (view !== "tracker" || !userId) return;
22434
22916
  const fetchExecutions = async () => {
22435
22917
  try {
22436
- const response = await (0, import_core37.queryExecutions)(userId, publishableKey, import_core37.ActionType.Deposit);
22918
+ const response = await (0, import_core38.queryExecutions)(userId, publishableKey, import_core38.ActionType.Deposit);
22437
22919
  const sorted = [...response.data].sort((a, b) => {
22438
22920
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
22439
22921
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -22468,6 +22950,7 @@ function DepositModal({
22468
22950
  const {
22469
22951
  isValid: isAddressValid,
22470
22952
  failureCode: addressFailureCode,
22953
+ message: addressFailureMessage,
22471
22954
  metadata: addressFailureMetadata,
22472
22955
  isLoading: isAddressValidationLoading
22473
22956
  } = useAddressValidation({
@@ -22481,17 +22964,31 @@ function DepositModal({
22481
22964
  refetchOnMount: "always"
22482
22965
  });
22483
22966
  const addressValidationMessages = i18n.transferCrypto.addressValidation;
22484
- const getAddressValidationErrorMessage = (code, metadata) => {
22967
+ const getAddressValidationErrorMessage = (message, code, metadata) => {
22968
+ if (message && message.trim().length > 0) return message;
22485
22969
  if (!code) return addressValidationMessages.defaultError;
22486
22970
  const errors = addressValidationMessages.errors;
22487
22971
  const template = errors[code] ?? addressValidationMessages.defaultError;
22488
22972
  return interpolate(template, metadata);
22489
22973
  };
22974
+ const walletsRecipientError = (0, import_core38.isDepositAddressValidationError)(walletsError) ? walletsError.message : null;
22975
+ const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
22976
+ const recipientInvalidMessage = getAddressValidationErrorMessage(
22977
+ addressFailureMessage ?? walletsRecipientError,
22978
+ addressFailureCode,
22979
+ addressFailureMetadata
22980
+ );
22490
22981
  const openingScreen = effectiveInitialScreen;
22491
22982
  const sessionOpenedFromMenu = openingScreen === "main";
22492
22983
  const standaloneNeedsDepositPrereq = openingScreen !== "main" && (view === "transfer" || view === "card");
22493
22984
  let depositPrerequisiteBody;
22494
- if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
22985
+ if (isRecipientAddressInvalid) {
22986
+ depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
22987
+ /* @__PURE__ */ (0, import_jsx_runtime63.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_runtime63.jsx)(import_lucide_react37.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
22988
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
22989
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: recipientInvalidMessage })
22990
+ ] });
22991
+ } else if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
22495
22992
  // fetch — block the menu on it so the row never flashes in or out.
22496
22993
  showBankTransfer && bankTransferProvidersLoading || // Same for Apple Pay: row visibility depends on the geo/platform-gated
22497
22994
  // providers fetch — block the menu so the row doesn't pop in or out.
@@ -22513,12 +23010,6 @@ function DepositModal({
22513
23010
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
22514
23011
  /* @__PURE__ */ (0, import_jsx_runtime63.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." })
22515
23012
  ] });
22516
- } else if (isAddressValid === false) {
22517
- depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
22518
- /* @__PURE__ */ (0, import_jsx_runtime63.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_runtime63.jsx)(import_lucide_react37.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
22519
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
22520
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(addressFailureCode, addressFailureMetadata) })
22521
- ] });
22522
23013
  } else {
22523
23014
  depositPrerequisiteBody = null;
22524
23015
  }
@@ -22535,11 +23026,11 @@ function DepositModal({
22535
23026
  if (view === "wallet_connect" && sessionOpenedFromMenu) setView("main");
22536
23027
  };
22537
23028
  const handleExchangeDisconnect = () => {
22538
- const stored = getStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE);
23029
+ const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
22539
23030
  if (stored) {
22540
- (0, import_core37.revokeIntegrationToken)(stored.access_token, publishableKey);
23031
+ (0, import_core38.revokeIntegrationToken)(stored.access_token, publishableKey);
22541
23032
  }
22542
- clearStoredIntegrationToken(import_core37.IntegrationProvider.COINBASE);
23033
+ clearStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
22543
23034
  setConnectedExchange(null);
22544
23035
  if (view === "coinbase_connect" && sessionOpenedFromMenu) setView("main");
22545
23036
  };
@@ -23012,6 +23503,7 @@ function DepositModal({
23012
23503
  title: modalTitle || "Deposit",
23013
23504
  showClose: !hideOverlay,
23014
23505
  onClose: handleClose,
23506
+ incident: activeIncident,
23015
23507
  showBalance: showBalanceHeader,
23016
23508
  balanceAddress: recipientAddress,
23017
23509
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -23031,6 +23523,7 @@ function DepositModal({
23031
23523
  showBack: showBackTransfer,
23032
23524
  onBack: handleBack,
23033
23525
  onClose: handleClose,
23526
+ incident: activeIncident,
23034
23527
  showBalance: showBalanceHeader,
23035
23528
  balanceAddress: recipientAddress,
23036
23529
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -23091,7 +23584,8 @@ function DepositModal({
23091
23584
  title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
23092
23585
  showBack: showBackTracker,
23093
23586
  onBack: handleBack,
23094
- onClose: handleClose
23587
+ onClose: handleClose,
23588
+ incident: activeIncident
23095
23589
  }
23096
23590
  ),
23097
23591
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -23123,6 +23617,7 @@ function DepositModal({
23123
23617
  showBack: showBackCard,
23124
23618
  onBack: handleBack,
23125
23619
  onClose: handleClose,
23620
+ incident: activeIncident,
23126
23621
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
23127
23622
  showBalance: showBalanceHeader,
23128
23623
  balanceAddress: recipientAddress,
@@ -23172,7 +23667,8 @@ function DepositModal({
23172
23667
  title: payWithExchangeTitle,
23173
23668
  showBack: exchangeView === "pending" || sessionOpenedFromMenu,
23174
23669
  onBack: handleBack,
23175
- onClose: handleClose
23670
+ onClose: handleClose,
23671
+ incident: activeIncident
23176
23672
  }
23177
23673
  ),
23178
23674
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -23286,7 +23782,8 @@ function DepositModal({
23286
23782
  title: t8.bankTransfer.title,
23287
23783
  showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
23288
23784
  onBack: handleBack,
23289
- onClose: handleClose
23785
+ onClose: handleClose,
23786
+ incident: activeIncident
23290
23787
  }
23291
23788
  ),
23292
23789
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -23320,26 +23817,24 @@ function DepositModal({
23320
23817
  title: "Deposit with Link",
23321
23818
  showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
23322
23819
  onBack: handleBack,
23820
+ incident: activeIncident,
23323
23821
  showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
23324
23822
  onClose: handleClose
23325
23823
  }
23326
23824
  ),
23327
23825
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23328
23826
  isLoadingIp ? (
23329
- // Hold the geo decision until IP resolves so we don't mount
23330
- // PayWithStripeLink (which kicks off config/OAuth work) for a
23331
- // deep-link user who turns out to be outside the US.
23827
+ // Wait for location so the first config fetch is region-aware.
23332
23828
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(SkeletonButton, { variant: "with-icons" })
23333
23829
  ) : !showStripeLink ? (
23334
- // Stripe Link's crypto on-ramp is US-only. On a direct open
23335
- // (initialScreen="stripe_link") the row isn't in a menu to
23336
- // fall back to, so show a geo-restriction screen rather than
23337
- // the Link UI.
23830
+ // Direct opens (initialScreen="stripe_link") have no menu row
23831
+ // to fall back to, so render an unavailable state when backend
23832
+ // config resolves Stripe Link disabled/hidden.
23338
23833
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
23339
23834
  GeoRestrictionScreen,
23340
23835
  {
23341
23836
  methodName: t8.stripeLink.title,
23342
- message: "Pay with Link is only available in the US."
23837
+ message: t8.stripeLink.unavailableInRegionMessage
23343
23838
  }
23344
23839
  )
23345
23840
  ) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
@@ -23372,7 +23867,8 @@ function DepositModal({
23372
23867
  title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
23373
23868
  showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
23374
23869
  onBack: handleBack,
23375
- onClose: handleClose
23870
+ onClose: handleClose,
23871
+ incident: activeIncident
23376
23872
  }
23377
23873
  ),
23378
23874
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -23408,7 +23904,8 @@ function DepositModal({
23408
23904
  const handled = applePayHandleRef.current?.requestBack() ?? false;
23409
23905
  if (!handled) handleBack();
23410
23906
  },
23411
- onClose: handleClose
23907
+ onClose: handleClose,
23908
+ incident: activeIncident
23412
23909
  }
23413
23910
  ),
23414
23911
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -23454,14 +23951,14 @@ var import_react27 = require("react");
23454
23951
  var import_lucide_react38 = require("lucide-react");
23455
23952
 
23456
23953
  // src/hooks/use-payment-intent.ts
23457
- var import_react_query18 = require("@tanstack/react-query");
23458
- var import_core38 = require("@unifold/core");
23954
+ var import_react_query19 = require("@tanstack/react-query");
23955
+ var import_core39 = require("@unifold/core");
23459
23956
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
23460
23957
  function usePaymentIntent(params) {
23461
23958
  const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
23462
- return (0, import_react_query18.useQuery)({
23959
+ return (0, import_react_query19.useQuery)({
23463
23960
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
23464
- queryFn: () => (0, import_core38.retrievePaymentIntent)(clientSecret, publishableKey),
23961
+ queryFn: () => (0, import_core39.retrievePaymentIntent)(clientSecret, publishableKey),
23465
23962
  enabled: enabled && !!clientSecret && !!publishableKey,
23466
23963
  staleTime: 0,
23467
23964
  refetchInterval: (query) => {
@@ -23477,7 +23974,7 @@ function usePaymentIntent(params) {
23477
23974
  }
23478
23975
 
23479
23976
  // src/components/checkout/CheckoutModal.tsx
23480
- var import_core39 = require("@unifold/core");
23977
+ var import_core40 = require("@unifold/core");
23481
23978
  var import_jsx_runtime64 = require("react/jsx-runtime");
23482
23979
  function mapToCheckoutPaymentIntent(pi) {
23483
23980
  return {
@@ -23535,6 +24032,7 @@ function CheckoutModal({
23535
24032
  modalTitle,
23536
24033
  enableTransferCrypto,
23537
24034
  enableConnectWallet,
24035
+ enableIncidentBanner = false,
23538
24036
  defaultSourceChainType,
23539
24037
  defaultSourceChainId,
23540
24038
  defaultSourceTokenAddress,
@@ -23563,8 +24061,8 @@ function CheckoutModal({
23563
24061
  if (isSucceeded && richIntent) {
23564
24062
  const createdSec = data.paymentIntent?.updated_at ? Math.floor(new Date(data.paymentIntent.updated_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3);
23565
24063
  onEvent?.({
23566
- id: (0, import_core39.generatePrefixedKSUID)("sevt"),
23567
- type: import_core39.CheckoutEventType.PAYMENT_INTENT_SUCCEEDED,
24064
+ id: (0, import_core40.generatePrefixedKSUID)("sevt"),
24065
+ type: import_core40.CheckoutEventType.PAYMENT_INTENT_SUCCEEDED,
23568
24066
  created: createdSec,
23569
24067
  method,
23570
24068
  data: { object: richIntent }
@@ -23606,6 +24104,16 @@ function CheckoutModal({
23606
24104
  });
23607
24105
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
23608
24106
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
24107
+ const { incident: publicIncident } = usePublicIncident({
24108
+ publishableKey,
24109
+ enabled: open && enableIncidentBanner
24110
+ });
24111
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
24112
+ enabled: true,
24113
+ messages: publicIncident.messages,
24114
+ severity: publicIncident.severity,
24115
+ statusPageUrl: publicIncident.status_page_url
24116
+ } : void 0;
23609
24117
  (0, import_react27.useEffect)(() => {
23610
24118
  if (view === "transfer" && !showTransferCrypto) {
23611
24119
  setView("main");
@@ -23907,7 +24415,15 @@ function CheckoutModal({
23907
24415
  {
23908
24416
  className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
23909
24417
  children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
23910
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
24418
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
24419
+ DepositHeader,
24420
+ {
24421
+ title: modalTitle || "Checkout",
24422
+ showClose: true,
24423
+ onClose: handleClose,
24424
+ incident: activeIncident
24425
+ }
24426
+ ),
23911
24427
  /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23912
24428
  piLoading ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-space-y-3", children: [
23913
24429
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
@@ -24005,7 +24521,8 @@ function CheckoutModal({
24005
24521
  title: modalTitle || "Checkout",
24006
24522
  showBack: true,
24007
24523
  onBack: handleBack,
24008
- onClose: handleClose
24524
+ onClose: handleClose,
24525
+ incident: activeIncident
24009
24526
  }
24010
24527
  ),
24011
24528
  /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -24170,12 +24687,12 @@ var import_react32 = require("react");
24170
24687
  var import_lucide_react41 = require("lucide-react");
24171
24688
 
24172
24689
  // src/hooks/use-supported-destination-tokens.ts
24173
- var import_react_query19 = require("@tanstack/react-query");
24174
- var import_core40 = require("@unifold/core");
24690
+ var import_react_query20 = require("@tanstack/react-query");
24691
+ var import_core41 = require("@unifold/core");
24175
24692
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
24176
- return (0, import_react_query19.useQuery)({
24693
+ return (0, import_react_query20.useQuery)({
24177
24694
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
24178
- queryFn: () => (0, import_core40.getSupportedDestinationTokens)(publishableKey),
24695
+ queryFn: () => (0, import_core41.getSupportedDestinationTokens)(publishableKey),
24179
24696
  staleTime: 1e3 * 60 * 5,
24180
24697
  gcTime: 1e3 * 60 * 30,
24181
24698
  refetchOnMount: false,
@@ -24185,6 +24702,7 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
24185
24702
  }
24186
24703
 
24187
24704
  // src/hooks/use-default-destination-token.ts
24705
+ var STORAGE_KEY3 = "unifold_last_withdraw_to_token";
24188
24706
  function useDefaultDestinationToken({
24189
24707
  destinationTokens,
24190
24708
  defaultDestinationChainType,
@@ -24197,13 +24715,14 @@ function useDefaultDestinationToken({
24197
24715
  defaultChainType: defaultDestinationChainType,
24198
24716
  defaultChainId: defaultDestinationChainId,
24199
24717
  defaultTokenAddress: defaultDestinationTokenAddress,
24200
- defaultSymbol: defaultDestinationSymbol
24718
+ defaultSymbol: defaultDestinationSymbol,
24719
+ storageKey: STORAGE_KEY3
24201
24720
  });
24202
24721
  }
24203
24722
 
24204
24723
  // src/hooks/use-source-token-validation.ts
24205
- var import_react_query20 = require("@tanstack/react-query");
24206
- var import_core41 = require("@unifold/core");
24724
+ var import_react_query21 = require("@tanstack/react-query");
24725
+ var import_core42 = require("@unifold/core");
24207
24726
  function useSourceTokenValidation(params) {
24208
24727
  const {
24209
24728
  sourceChainType,
@@ -24214,7 +24733,7 @@ function useSourceTokenValidation(params) {
24214
24733
  enabled = true
24215
24734
  } = params;
24216
24735
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
24217
- return (0, import_react_query20.useQuery)({
24736
+ return (0, import_react_query21.useQuery)({
24218
24737
  queryKey: [
24219
24738
  "unifold",
24220
24739
  "sourceTokenValidation",
@@ -24224,7 +24743,7 @@ function useSourceTokenValidation(params) {
24224
24743
  publishableKey
24225
24744
  ],
24226
24745
  queryFn: async () => {
24227
- const res = await (0, import_core41.getSupportedDepositTokens)(publishableKey);
24746
+ const res = await (0, import_core42.getSupportedDepositTokens)(publishableKey);
24228
24747
  let matchedMinUsd = null;
24229
24748
  let matchedProcessingTime = null;
24230
24749
  let matchedSlippage = null;
@@ -24262,12 +24781,12 @@ function useSourceTokenValidation(params) {
24262
24781
  }
24263
24782
 
24264
24783
  // src/hooks/use-address-balance.ts
24265
- var import_react_query21 = require("@tanstack/react-query");
24266
- var import_core42 = require("@unifold/core");
24784
+ var import_react_query22 = require("@tanstack/react-query");
24785
+ var import_core43 = require("@unifold/core");
24267
24786
  function useAddressBalance(params) {
24268
24787
  const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
24269
24788
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
24270
- return (0, import_react_query21.useQuery)({
24789
+ return (0, import_react_query22.useQuery)({
24271
24790
  queryKey: [
24272
24791
  "unifold",
24273
24792
  "addressBalance",
@@ -24278,7 +24797,7 @@ function useAddressBalance(params) {
24278
24797
  publishableKey
24279
24798
  ],
24280
24799
  queryFn: async () => {
24281
- const res = await (0, import_core42.getAddressBalance)(
24800
+ const res = await (0, import_core43.getAddressBalance)(
24282
24801
  address,
24283
24802
  chainType,
24284
24803
  chainId,
@@ -24323,13 +24842,13 @@ function useAddressBalance(params) {
24323
24842
  }
24324
24843
 
24325
24844
  // src/hooks/use-executions.ts
24326
- var import_react_query22 = require("@tanstack/react-query");
24327
- var import_core43 = require("@unifold/core");
24845
+ var import_react_query23 = require("@tanstack/react-query");
24846
+ var import_core44 = require("@unifold/core");
24328
24847
  function useExecutions(userId, publishableKey, options) {
24329
- const actionType = options?.actionType ?? import_core43.ActionType.Deposit;
24330
- return (0, import_react_query22.useQuery)({
24848
+ const actionType = options?.actionType ?? import_core44.ActionType.Deposit;
24849
+ return (0, import_react_query23.useQuery)({
24331
24850
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
24332
- queryFn: () => (0, import_core43.queryExecutions)(userId, publishableKey, actionType),
24851
+ queryFn: () => (0, import_core44.queryExecutions)(userId, publishableKey, actionType),
24333
24852
  enabled: (options?.enabled ?? true) && !!userId,
24334
24853
  refetchInterval: options?.refetchInterval ?? 3e3,
24335
24854
  staleTime: 0,
@@ -24340,7 +24859,7 @@ function useExecutions(userId, publishableKey, options) {
24340
24859
 
24341
24860
  // src/hooks/use-withdraw-polling.ts
24342
24861
  var import_react28 = require("react");
24343
- var import_core44 = require("@unifold/core");
24862
+ var import_core45 = require("@unifold/core");
24344
24863
  var POLL_INTERVAL_MS3 = 2500;
24345
24864
  var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
24346
24865
  var CUTOFF_BUFFER_MS2 = 6e4;
@@ -24353,8 +24872,8 @@ function useWithdrawPolling({
24353
24872
  onWithdrawError
24354
24873
  }) {
24355
24874
  const createExecutionSuccessEvent = (execution) => ({
24356
- id: (0, import_core44.generatePrefixedKSUID)("sevt"),
24357
- type: import_core44.WithdrawEventType.DIRECT_EXECUTION_SUCCEEDED,
24875
+ id: (0, import_core45.generatePrefixedKSUID)("sevt"),
24876
+ type: import_core45.WithdrawEventType.DIRECT_EXECUTION_SUCCEEDED,
24358
24877
  created: execution.updated_at ? Math.floor(new Date(execution.updated_at).getTime() / 1e3) : execution.created_at ? Math.floor(new Date(execution.created_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3),
24359
24878
  data: { object: mapToDirectExecution(execution) }
24360
24879
  });
@@ -24405,7 +24924,7 @@ function useWithdrawPolling({
24405
24924
  const enabledAt = enabledAtRef.current;
24406
24925
  const poll = async () => {
24407
24926
  try {
24408
- const response = await (0, import_core44.queryExecutions)(userId, publishableKey, import_core44.ActionType.Withdraw);
24927
+ const response = await (0, import_core45.queryExecutions)(userId, publishableKey, import_core45.ActionType.Withdraw);
24409
24928
  const cutoff = new Date(enabledAt.getTime() - CUTOFF_BUFFER_MS2);
24410
24929
  const sorted = [...response.data].sort((a, b) => {
24411
24930
  const tA = a.created_at ? new Date(a.created_at).getTime() : 0;
@@ -24413,11 +24932,11 @@ function useWithdrawPolling({
24413
24932
  return tB - tA;
24414
24933
  });
24415
24934
  const inProgress = [
24416
- import_core44.ExecutionStatus.PENDING,
24417
- import_core44.ExecutionStatus.WAITING,
24418
- import_core44.ExecutionStatus.DELAYED
24935
+ import_core45.ExecutionStatus.PENDING,
24936
+ import_core45.ExecutionStatus.WAITING,
24937
+ import_core45.ExecutionStatus.DELAYED
24419
24938
  ];
24420
- const terminal = [import_core44.ExecutionStatus.SUCCEEDED, import_core44.ExecutionStatus.FAILED];
24939
+ const terminal = [import_core45.ExecutionStatus.SUCCEEDED, import_core45.ExecutionStatus.FAILED];
24421
24940
  let target = null;
24422
24941
  for (const ex of sorted) {
24423
24942
  const t13 = ex.created_at ? new Date(ex.created_at) : null;
@@ -24447,7 +24966,7 @@ function useWithdrawPolling({
24447
24966
  }
24448
24967
  return [...list, ex];
24449
24968
  });
24450
- if (ex.status === import_core44.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
24969
+ if (ex.status === import_core45.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
24451
24970
  onSuccessRef.current?.({
24452
24971
  message: "Withdrawal completed successfully",
24453
24972
  executionId: ex.id,
@@ -24455,7 +24974,7 @@ function useWithdrawPolling({
24455
24974
  transaction: ex,
24456
24975
  execution: createExecutionSuccessEvent(ex)
24457
24976
  });
24458
- } else if (ex.status === import_core44.ExecutionStatus.FAILED && prev !== import_core44.ExecutionStatus.FAILED) {
24977
+ } else if (ex.status === import_core45.ExecutionStatus.FAILED && prev !== import_core45.ExecutionStatus.FAILED) {
24459
24978
  onErrorRef.current?.({
24460
24979
  message: "Withdrawal failed",
24461
24980
  code: "WITHDRAW_FAILED",
@@ -24484,7 +25003,7 @@ function useWithdrawPolling({
24484
25003
  if (!enabled || !depositWalletId) return;
24485
25004
  const trigger = async () => {
24486
25005
  try {
24487
- await (0, import_core44.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
25006
+ await (0, import_core45.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
24488
25007
  } catch {
24489
25008
  }
24490
25009
  };
@@ -24653,11 +25172,11 @@ function WithdrawDoubleInput({
24653
25172
  // src/components/withdrawals/WithdrawForm.tsx
24654
25173
  var import_react30 = require("react");
24655
25174
  var import_lucide_react39 = require("lucide-react");
24656
- var import_core49 = require("@unifold/core");
25175
+ var import_core50 = require("@unifold/core");
24657
25176
 
24658
25177
  // src/hooks/use-verify-recipient-address.ts
24659
- var import_react_query23 = require("@tanstack/react-query");
24660
- var import_core45 = require("@unifold/core");
25178
+ var import_react_query24 = require("@tanstack/react-query");
25179
+ var import_core46 = require("@unifold/core");
24661
25180
  function useVerifyRecipientAddress(params) {
24662
25181
  const {
24663
25182
  chainType,
@@ -24669,7 +25188,7 @@ function useVerifyRecipientAddress(params) {
24669
25188
  } = params;
24670
25189
  const trimmedAddress = recipientAddress?.trim() || "";
24671
25190
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
24672
- return (0, import_react_query23.useQuery)({
25191
+ return (0, import_react_query24.useQuery)({
24673
25192
  queryKey: [
24674
25193
  "unifold",
24675
25194
  "verifyRecipientAddress",
@@ -24679,7 +25198,7 @@ function useVerifyRecipientAddress(params) {
24679
25198
  trimmedAddress,
24680
25199
  publishableKey
24681
25200
  ],
24682
- queryFn: () => (0, import_core45.verifyRecipientAddress)(
25201
+ queryFn: () => (0, import_core46.verifyRecipientAddress)(
24683
25202
  {
24684
25203
  chain_type: chainType,
24685
25204
  chain_id: chainId,
@@ -24698,7 +25217,7 @@ function useVerifyRecipientAddress(params) {
24698
25217
  }
24699
25218
 
24700
25219
  // src/components/withdrawals/send-withdraw.ts
24701
- var import_core46 = require("@unifold/core");
25220
+ var import_core47 = require("@unifold/core");
24702
25221
  async function sendEvmWithdraw(params) {
24703
25222
  const {
24704
25223
  provider,
@@ -24787,7 +25306,7 @@ async function sendSolanaWithdraw(params) {
24787
25306
  if (!provider.publicKey) {
24788
25307
  await provider.connect();
24789
25308
  }
24790
- const buildResponse = await (0, import_core46.buildSolanaTransaction)(
25309
+ const buildResponse = await (0, import_core47.buildSolanaTransaction)(
24791
25310
  {
24792
25311
  chain_id: "mainnet",
24793
25312
  token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
@@ -24813,7 +25332,7 @@ async function sendSolanaWithdraw(params) {
24813
25332
  for (let i = 0; i < serialized.length; i++) {
24814
25333
  binaryStr += String.fromCharCode(serialized[i]);
24815
25334
  }
24816
- const sendResponse = await (0, import_core46.sendSolanaTransaction)(
25335
+ const sendResponse = await (0, import_core47.sendSolanaTransaction)(
24817
25336
  { chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
24818
25337
  publishableKey
24819
25338
  );
@@ -24914,11 +25433,11 @@ async function detectBrowserWallet(chainType, senderAddress) {
24914
25433
 
24915
25434
  // src/hooks/use-hypercore-withdraw-activation.ts
24916
25435
  var import_react29 = require("react");
24917
- var import_core48 = require("@unifold/core");
25436
+ var import_core49 = require("@unifold/core");
24918
25437
 
24919
25438
  // src/hooks/use-get-deposit-address.ts
24920
- var import_react_query24 = require("@tanstack/react-query");
24921
- var import_core47 = require("@unifold/core");
25439
+ var import_react_query25 = require("@tanstack/react-query");
25440
+ var import_core48 = require("@unifold/core");
24922
25441
  function useGetDepositAddress(params) {
24923
25442
  const {
24924
25443
  userId,
@@ -24931,7 +25450,7 @@ function useGetDepositAddress(params) {
24931
25450
  enabled = true
24932
25451
  } = params;
24933
25452
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
24934
- return (0, import_react_query24.useQuery)({
25453
+ return (0, import_react_query25.useQuery)({
24935
25454
  queryKey: [
24936
25455
  "unifold",
24937
25456
  "getDepositAddress",
@@ -24943,7 +25462,7 @@ function useGetDepositAddress(params) {
24943
25462
  actionType ?? null,
24944
25463
  publishableKey
24945
25464
  ],
24946
- queryFn: () => (0, import_core47.getDepositAddress)(
25465
+ queryFn: () => (0, import_core48.getDepositAddress)(
24947
25466
  {
24948
25467
  external_user_id: userId,
24949
25468
  recipient_address: recipientAddress,
@@ -24997,7 +25516,7 @@ function useHypercoreWithdrawActivation(params) {
24997
25516
  destinationChainType,
24998
25517
  destinationChainId,
24999
25518
  destinationTokenAddress,
25000
- actionType: import_core48.ActionType.Withdraw,
25519
+ actionType: import_core49.ActionType.Withdraw,
25001
25520
  enabled: enabled && isHypercore(sourceChainId)
25002
25521
  });
25003
25522
  const depositWalletAddress = (0, import_react29.useMemo)(() => {
@@ -25127,6 +25646,9 @@ function WithdrawForm({
25127
25646
  if (isDebouncing || isVerifyingAddress) return null;
25128
25647
  if (verifyError) return t10.invalidAddress;
25129
25648
  if (addressVerification && !addressVerification.valid) {
25649
+ if (addressVerification.message && addressVerification.message.trim().length > 0) {
25650
+ return addressVerification.message;
25651
+ }
25130
25652
  if (addressVerification.failure_code === "account_not_found")
25131
25653
  return `Account not found on ${selectedChain?.chain_name}`;
25132
25654
  if (addressVerification.failure_code === "not_opted_in")
@@ -25288,7 +25810,7 @@ function WithdrawForm({
25288
25810
  let humanAmount = isMaxed ? balanceData.balanceHuman : toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
25289
25811
  if (isHypercoreChain(sourceChainId)) {
25290
25812
  try {
25291
- const check = await (0, import_core49.checkHypercoreActivation)(
25813
+ const check = await (0, import_core50.checkHypercoreActivation)(
25292
25814
  {
25293
25815
  source_address: senderAddress,
25294
25816
  recipient_address: depositWallet.address
@@ -25737,11 +26259,11 @@ function WithdrawForm({
25737
26259
 
25738
26260
  // src/components/withdrawals/WithdrawExecutionItem.tsx
25739
26261
  var import_lucide_react40 = require("lucide-react");
25740
- var import_core50 = require("@unifold/core");
26262
+ var import_core51 = require("@unifold/core");
25741
26263
  var import_jsx_runtime67 = require("react/jsx-runtime");
25742
26264
  function WithdrawExecutionItem({ execution, onClick }) {
25743
26265
  const { colors: colors2, fonts, components } = useTheme();
25744
- const isPending = execution.status === import_core50.ExecutionStatus.PENDING || execution.status === import_core50.ExecutionStatus.WAITING || execution.status === import_core50.ExecutionStatus.DELAYED;
26266
+ const isPending = execution.status === import_core51.ExecutionStatus.PENDING || execution.status === import_core51.ExecutionStatus.WAITING || execution.status === import_core51.ExecutionStatus.DELAYED;
25745
26267
  const formatDateTime = (timestamp) => {
25746
26268
  try {
25747
26269
  const date = new Date(timestamp);
@@ -25788,7 +26310,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
25788
26310
  /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
25789
26311
  "img",
25790
26312
  {
25791
- src: execution.destination_token_metadata?.icon_url || (0, import_core50.getIconUrl)("/icons/tokens/svg/usdc.svg"),
26313
+ src: execution.destination_token_metadata?.icon_url || (0, import_core51.getIconUrl)("/icons/tokens/svg/usdc.svg"),
25792
26314
  alt: "Token",
25793
26315
  width: 36,
25794
26316
  height: 36,
@@ -26024,7 +26546,7 @@ function WithdrawConfirmingView({
26024
26546
  }
26025
26547
 
26026
26548
  // src/components/withdrawals/WithdrawModal.tsx
26027
- var import_core51 = require("@unifold/core");
26549
+ var import_core52 = require("@unifold/core");
26028
26550
  var import_jsx_runtime69 = require("react/jsx-runtime");
26029
26551
  var t11 = i18n.withdrawModal;
26030
26552
  var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
@@ -26130,26 +26652,26 @@ function WithdrawModal({
26130
26652
  onWithdrawError
26131
26653
  });
26132
26654
  const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
26133
- actionType: import_core51.ActionType.Withdraw,
26655
+ actionType: import_core52.ActionType.Withdraw,
26134
26656
  enabled: open,
26135
26657
  refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
26136
26658
  });
26137
26659
  const allWithdrawals = allWithdrawalsData?.data ?? [];
26138
26660
  const handleDepositWalletCreation = (0, import_react32.useCallback)(
26139
26661
  async (params) => {
26140
- const { data: wallets } = await (0, import_core51.createDepositAddress)(
26662
+ const { data: wallets } = await (0, import_core52.createDepositAddress)(
26141
26663
  {
26142
26664
  external_user_id: externalUserId,
26143
26665
  destination_chain_type: params.destinationChainType,
26144
26666
  destination_chain_id: params.destinationChainId,
26145
26667
  destination_token_address: params.destinationTokenAddress,
26146
26668
  recipient_address: params.recipientAddress,
26147
- action_type: import_core51.ActionType.Withdraw,
26669
+ action_type: import_core52.ActionType.Withdraw,
26148
26670
  source_chain_type: sourceChainType
26149
26671
  },
26150
26672
  publishableKey
26151
26673
  );
26152
- const depositWallet = (0, import_core51.getWalletByChainType)(wallets, sourceChainType);
26674
+ const depositWallet = (0, import_core52.getWalletByChainType)(wallets, sourceChainType);
26153
26675
  if (!depositWallet) {
26154
26676
  throw new Error(`No deposit wallet available for ${sourceChainType}`);
26155
26677
  }
@@ -26674,6 +27196,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
26674
27196
  useDepositPolling,
26675
27197
  useDepositQuote,
26676
27198
  usePaymentIntent,
27199
+ usePublicIncident,
26677
27200
  useSourceTokenValidation,
26678
27201
  useSupportedDepositTokens,
26679
27202
  useSupportedDestinationTokens,