@unifold/connect-react 0.1.69 → 0.1.70-beta.1

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
@@ -1211,7 +1211,10 @@ var import_react41 = __toESM(require("react"));
1211
1211
  var import_react = require("react");
1212
1212
  var import_react_query = require("@tanstack/react-query");
1213
1213
  var import_jsx_runtime = require("react/jsx-runtime");
1214
- var UnifoldContext = (0, import_react.createContext)(null);
1214
+ var UNIFOLD_CONTEXT_KEY = /* @__PURE__ */ Symbol.for("unifold.react-provider.context");
1215
+ var globalRef = globalThis;
1216
+ var UnifoldContext = globalRef[UNIFOLD_CONTEXT_KEY] ?? (0, import_react.createContext)(null);
1217
+ globalRef[UNIFOLD_CONTEXT_KEY] = UnifoldContext;
1215
1218
  var createQueryClient = () => new import_react_query.QueryClient({
1216
1219
  defaultOptions: {
1217
1220
  queries: {
@@ -6196,6 +6199,9 @@ var import_react_query3 = require("@tanstack/react-query");
6196
6199
 
6197
6200
  // ../core/dist/index.mjs
6198
6201
  var import_react_query2 = require("@tanstack/react-query");
6202
+ var __defProp2 = Object.defineProperty;
6203
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6204
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6199
6205
  function formatStablecoinAmount(baseUnits, decimals) {
6200
6206
  const raw = Number(baseUnits) / 10 ** decimals;
6201
6207
  const floored = Math.floor(raw * 100) / 100;
@@ -6289,6 +6295,16 @@ var ActionType = /* @__PURE__ */ ((ActionType2) => {
6289
6295
  ActionType2["Withdraw"] = "withdraw";
6290
6296
  return ActionType2;
6291
6297
  })(ActionType || {});
6298
+ var DepositAddressValidationError = class extends Error {
6299
+ constructor(message) {
6300
+ super(message);
6301
+ __publicField(this, "isDepositAddressValidationError", true);
6302
+ this.name = "DepositAddressValidationError";
6303
+ }
6304
+ };
6305
+ function isDepositAddressValidationError(error) {
6306
+ return error instanceof Error && error.isDepositAddressValidationError === true;
6307
+ }
6292
6308
  async function createDepositAddress(overrides, publishableKey) {
6293
6309
  if (!overrides?.external_user_id) {
6294
6310
  throw new Error("external_user_id is required");
@@ -6316,6 +6332,13 @@ async function createDepositAddress(overrides, publishableKey) {
6316
6332
  body: JSON.stringify(payload)
6317
6333
  });
6318
6334
  if (!response.ok) {
6335
+ if (response.status === 400) {
6336
+ const body = await response.json().catch(() => null);
6337
+ if (body?.error_type === "validation_error") {
6338
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
6339
+ throw new DepositAddressValidationError(firstError ?? "Invalid recipient address");
6340
+ }
6341
+ }
6319
6342
  throw new Error(`Failed to create EOA: ${response.statusText}`);
6320
6343
  }
6321
6344
  return response.json();
@@ -6672,6 +6695,21 @@ async function getProjectConfig(publishableKey, options) {
6672
6695
  const data = await response.json();
6673
6696
  return data;
6674
6697
  }
6698
+ async function getPublicIncident(publishableKey) {
6699
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6700
+ validatePublishableKey(pk);
6701
+ const response = await fetch(`${API_BASE_URL}/v1/public/projects/incident`, {
6702
+ method: "GET",
6703
+ headers: {
6704
+ accept: "application/json",
6705
+ "x-publishable-key": pk
6706
+ }
6707
+ });
6708
+ if (!response.ok) {
6709
+ throw new Error(`Failed to fetch public incident: ${response.statusText}`);
6710
+ }
6711
+ return response.json();
6712
+ }
6675
6713
  async function getIpAddress() {
6676
6714
  const response = await fetch(`${API_BASE_URL}/v1/public/ip_address`, {
6677
6715
  method: "GET",
@@ -6727,7 +6765,7 @@ async function getExternalWallets(publishableKey) {
6727
6765
  const data = await response.json();
6728
6766
  return data;
6729
6767
  }
6730
- async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey) {
6768
+ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey, amountUsd) {
6731
6769
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6732
6770
  validatePublishableKey(pk);
6733
6771
  const response = await fetch(`${API_BASE_URL}/v1/public/external_wallets/mobile_deeplink`, {
@@ -6737,7 +6775,11 @@ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey)
6737
6775
  accept: "application/json",
6738
6776
  "x-publishable-key": pk
6739
6777
  },
6740
- body: JSON.stringify({ wallet, deposit_addresses: depositAddresses })
6778
+ body: JSON.stringify({
6779
+ wallet,
6780
+ deposit_addresses: depositAddresses,
6781
+ ...amountUsd ? { amount_usd: amountUsd } : {}
6782
+ })
6741
6783
  });
6742
6784
  if (!response.ok) {
6743
6785
  throw new Error(`Failed to generate wallet deep link: ${response.statusText}`);
@@ -6782,6 +6824,15 @@ async function verifyRecipientAddress(request, publishableKey) {
6782
6824
  body: JSON.stringify(request)
6783
6825
  });
6784
6826
  if (!response.ok) {
6827
+ const body = await response.json().catch(() => null);
6828
+ if (response.status === 400 && body?.error_type === "validation_error") {
6829
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
6830
+ return {
6831
+ valid: false,
6832
+ failure_code: "validation_error",
6833
+ message: firstError ?? "Invalid recipient address"
6834
+ };
6835
+ }
6785
6836
  throw new Error(`Failed to verify recipient address: ${response.statusText}`);
6786
6837
  }
6787
6838
  return response.json();
@@ -8127,6 +8178,7 @@ var import_jsx_runtime62 = require("react/jsx-runtime");
8127
8178
  var import_react_query14 = require("@tanstack/react-query");
8128
8179
  var import_react_query15 = require("@tanstack/react-query");
8129
8180
  var import_react_query16 = require("@tanstack/react-query");
8181
+ var import_react_query17 = require("@tanstack/react-query");
8130
8182
  var import_react27 = require("react");
8131
8183
  var import_react28 = require("react");
8132
8184
  var React322 = __toESM(require("react"), 1);
@@ -12877,7 +12929,7 @@ var Content22 = TooltipContent;
12877
12929
 
12878
12930
  // ../ui-react/dist/index.mjs
12879
12931
  var import_jsx_runtime69 = require("react/jsx-runtime");
12880
- var import_react_query17 = require("@tanstack/react-query");
12932
+ var import_react_query18 = require("@tanstack/react-query");
12881
12933
  var import_jsx_runtime70 = require("react/jsx-runtime");
12882
12934
  var import_jsx_runtime71 = require("react/jsx-runtime");
12883
12935
  var import_react32 = require("react");
@@ -14119,8 +14171,8 @@ var Separator = SelectSeparator;
14119
14171
  var import_jsx_runtime72 = require("react/jsx-runtime");
14120
14172
  var import_jsx_runtime73 = require("react/jsx-runtime");
14121
14173
  var React352 = __toESM(require("react"), 1);
14122
- var import_react_query18 = require("@tanstack/react-query");
14123
14174
  var import_react_query19 = require("@tanstack/react-query");
14175
+ var import_react_query20 = require("@tanstack/react-query");
14124
14176
  var import_jsx_runtime74 = require("react/jsx-runtime");
14125
14177
  var import_jsx_runtime75 = require("react/jsx-runtime");
14126
14178
  var import_jsx_runtime76 = require("react/jsx-runtime");
@@ -14130,19 +14182,19 @@ var import_jsx_runtime78 = require("react/jsx-runtime");
14130
14182
  var import_jsx_runtime79 = require("react/jsx-runtime");
14131
14183
  var import_jsx_runtime80 = require("react/jsx-runtime");
14132
14184
  var import_react34 = require("react");
14133
- var import_react_query20 = require("@tanstack/react-query");
14185
+ var import_react_query21 = require("@tanstack/react-query");
14134
14186
  var import_jsx_runtime81 = require("react/jsx-runtime");
14135
14187
  var import_react35 = require("react");
14136
- var import_react_query21 = require("@tanstack/react-query");
14137
14188
  var import_react_query22 = require("@tanstack/react-query");
14138
14189
  var import_react_query23 = require("@tanstack/react-query");
14139
14190
  var import_react_query24 = require("@tanstack/react-query");
14191
+ var import_react_query25 = require("@tanstack/react-query");
14140
14192
  var import_react36 = require("react");
14141
14193
  var import_jsx_runtime82 = require("react/jsx-runtime");
14142
14194
  var import_react37 = require("react");
14143
- var import_react_query25 = require("@tanstack/react-query");
14144
- var import_react38 = require("react");
14145
14195
  var import_react_query26 = require("@tanstack/react-query");
14196
+ var import_react38 = require("react");
14197
+ var import_react_query27 = require("@tanstack/react-query");
14146
14198
  var import_jsx_runtime83 = require("react/jsx-runtime");
14147
14199
  var import_jsx_runtime84 = require("react/jsx-runtime");
14148
14200
  var import_react39 = require("react");
@@ -14731,7 +14783,13 @@ function useDepositAddress(params) {
14731
14783
  // 24 hours in cache
14732
14784
  refetchOnMount: false,
14733
14785
  refetchOnWindowFocus: false,
14734
- retry: 3,
14786
+ // Don't retry recipient-address validation errors — they're deterministic
14787
+ // (a 400 won't succeed on retry) and we want to surface the invalid-address
14788
+ // screen immediately rather than after 3 backoff attempts.
14789
+ retry: (failureCount, error) => {
14790
+ if (isDepositAddressValidationError(error)) return false;
14791
+ return failureCount < 3;
14792
+ },
14735
14793
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
14736
14794
  // 1s, 2s, 4s (max 10s)
14737
14795
  });
@@ -14939,7 +14997,8 @@ function DepositHeader({
14939
14997
  balanceChainId,
14940
14998
  balanceTokenAddress,
14941
14999
  projectName,
14942
- publishableKey
15000
+ publishableKey,
15001
+ incident
14943
15002
  }) {
14944
15003
  const { colors: colors2, fonts, components } = useTheme();
14945
15004
  const [balance, setBalance] = (0, import_react12.useState)(null);
@@ -15037,19 +15096,64 @@ function DepositHeader({
15037
15096
  balanceTokenAddress,
15038
15097
  publishableKey
15039
15098
  ]);
15040
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
15041
- showBack ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15042
- "button",
15043
- {
15044
- onClick: onBack,
15045
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
15046
- style: { color: components.header.buttonColor },
15047
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
15048
- }
15049
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
15050
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
15051
- badge ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
15052
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15099
+ const incidentMessages = incident?.messages ?? [];
15100
+ const showIncident = incident?.enabled && incidentMessages.length > 0;
15101
+ const incidentSeverity = incident?.severity ?? "degraded";
15102
+ const incidentSeverityLabel = incidentSeverity === "outage" ? "Outage" : incidentSeverity === "info" ? "Info" : "Degraded service";
15103
+ const incidentStyles = incidentSeverity === "outage" ? {
15104
+ bg: "rgba(239, 68, 68, 0.12)",
15105
+ border: "rgba(239, 68, 68, 0.35)",
15106
+ text: "#fca5a5",
15107
+ link: "#fca5a5"
15108
+ } : incidentSeverity === "info" ? {
15109
+ bg: "rgba(59, 130, 246, 0.12)",
15110
+ border: "rgba(59, 130, 246, 0.35)",
15111
+ text: "#93c5fd",
15112
+ link: "#93c5fd"
15113
+ } : {
15114
+ bg: "rgba(245, 158, 11, 0.12)",
15115
+ border: "rgba(245, 158, 11, 0.35)",
15116
+ text: "#fcd34d",
15117
+ link: "#fcd34d"
15118
+ };
15119
+ const IncidentIcon = incidentSeverity === "info" ? Info : TriangleAlert;
15120
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
15121
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
15122
+ showBack ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15123
+ "button",
15124
+ {
15125
+ onClick: onBack,
15126
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
15127
+ style: { color: components.header.buttonColor },
15128
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
15129
+ }
15130
+ ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
15131
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
15132
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
15133
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15134
+ DialogTitle2,
15135
+ {
15136
+ className: "uf-text-center uf-text-base",
15137
+ style: {
15138
+ color: components.header.titleColor,
15139
+ fontFamily: fonts.medium
15140
+ },
15141
+ children: title
15142
+ }
15143
+ ),
15144
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15145
+ "div",
15146
+ {
15147
+ className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
15148
+ style: {
15149
+ backgroundColor: colors2.card,
15150
+ color: colors2.foregroundMuted,
15151
+ fontFamily: fonts.regular
15152
+ },
15153
+ children: badge.count
15154
+ }
15155
+ )
15156
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15053
15157
  DialogTitle2,
15054
15158
  {
15055
15159
  className: "uf-text-center uf-text-base",
@@ -15060,61 +15164,91 @@ function DepositHeader({
15060
15164
  children: title
15061
15165
  }
15062
15166
  ),
15063
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15167
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15064
15168
  "div",
15065
15169
  {
15066
- className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
15170
+ className: "uf-text-xs uf-mt-1",
15067
15171
  style: {
15068
- backgroundColor: colors2.card,
15069
15172
  color: colors2.foregroundMuted,
15070
15173
  fontFamily: fonts.regular
15071
15174
  },
15072
- children: badge.count
15175
+ children: subtitle
15073
15176
  }
15074
- )
15075
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15076
- DialogTitle2,
15077
- {
15078
- className: "uf-text-center uf-text-base",
15079
- style: {
15080
- color: components.header.titleColor,
15081
- fontFamily: fonts.medium
15082
- },
15083
- children: title
15084
- }
15085
- ),
15086
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15087
- "div",
15088
- {
15089
- className: "uf-text-xs uf-mt-1",
15090
- style: {
15091
- color: colors2.foregroundMuted,
15092
- fontFamily: fonts.regular
15093
- },
15094
- children: subtitle
15095
- }
15096
- ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)(
15097
- "div",
15177
+ ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)(
15178
+ "div",
15179
+ {
15180
+ className: "uf-text-xs uf-mt-1",
15181
+ style: {
15182
+ color: colors2.foregroundMuted,
15183
+ fontFamily: fonts.regular
15184
+ },
15185
+ children: formatBalanceDisplay(balance, projectName)
15186
+ }
15187
+ ) : null : null
15188
+ ] }),
15189
+ showClose ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15190
+ "button",
15098
15191
  {
15099
- className: "uf-text-xs uf-mt-1",
15100
- style: {
15101
- color: colors2.foregroundMuted,
15102
- fontFamily: fonts.regular
15103
- },
15104
- children: formatBalanceDisplay(balance, projectName)
15192
+ onClick: onClose,
15193
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
15194
+ style: { color: components.header.buttonColor },
15195
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(X, { className: "uf-w-5 uf-h-5" })
15105
15196
  }
15106
- ) : null : null
15197
+ ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
15107
15198
  ] }),
15108
- showClose ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15109
- "button",
15199
+ showIncident && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15200
+ "div",
15110
15201
  {
15111
- onClick: onClose,
15112
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
15113
- style: { color: components.header.buttonColor },
15114
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(X, { className: "uf-w-5 uf-h-5" })
15202
+ className: "uf-rounded-lg uf-px-3 uf-py-2.5 uf-mb-4",
15203
+ style: {
15204
+ backgroundColor: incidentStyles.bg,
15205
+ border: `1px solid ${incidentStyles.border}`
15206
+ },
15207
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-flex uf-items-start uf-gap-2.5", children: [
15208
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15209
+ IncidentIcon,
15210
+ {
15211
+ className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
15212
+ style: { color: incidentStyles.text }
15213
+ }
15214
+ ),
15215
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "uf-min-w-0 uf-flex-1", children: [
15216
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15217
+ "span",
15218
+ {
15219
+ className: "uf-text-[11px] uf-leading-none uf-px-1.5 uf-py-1 uf-rounded-md",
15220
+ style: {
15221
+ color: incidentStyles.text,
15222
+ border: `1px solid ${incidentStyles.border}`,
15223
+ fontFamily: fonts.medium
15224
+ },
15225
+ children: incidentSeverityLabel
15226
+ }
15227
+ ) }),
15228
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15229
+ "div",
15230
+ {
15231
+ className: "uf-space-y-1",
15232
+ style: { color: incidentStyles.text, fontFamily: fonts.regular },
15233
+ children: incidentMessages.map((message, index2) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "uf-text-xs uf-leading-relaxed", children: message }, `${message}-${index2}`))
15234
+ }
15235
+ ),
15236
+ incident.statusPageUrl && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
15237
+ "a",
15238
+ {
15239
+ href: incident.statusPageUrl,
15240
+ target: "_blank",
15241
+ rel: "noreferrer",
15242
+ className: "uf-inline-block uf-mt-1.5 uf-text-xs uf-underline uf-underline-offset-2",
15243
+ style: { color: incidentStyles.link, fontFamily: fonts.medium },
15244
+ children: "View status"
15245
+ }
15246
+ )
15247
+ ] })
15248
+ ] })
15115
15249
  }
15116
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
15117
- ] }) });
15250
+ )
15251
+ ] });
15118
15252
  }
15119
15253
  function CurrencyListItem({ currency, isSelected, onSelect }) {
15120
15254
  const { colors: colors2, fonts, components } = useTheme();
@@ -15434,7 +15568,8 @@ var en_default2 = {
15434
15568
  },
15435
15569
  stripeLink: {
15436
15570
  title: "Pay with Link",
15437
- subtitle: "Buy with card or bank"
15571
+ subtitle: "Buy with card or bank",
15572
+ unavailableInRegionMessage: "Pay with Link is currently unavailable in your region."
15438
15573
  },
15439
15574
  browserWallet: {
15440
15575
  title: "Connect Wallet",
@@ -21741,7 +21876,7 @@ function AppleLogo({ className, style }) {
21741
21876
  }
21742
21877
  );
21743
21878
  }
21744
- function ApplePayButton({ onClick, title, subtitle }) {
21879
+ function ApplePayButton({ onClick, title, subtitle, iconUrl }) {
21745
21880
  const { colors: colors2, fonts, components } = useTheme();
21746
21881
  const [isHovered, setIsHovered] = React142.useState(false);
21747
21882
  const [isTouchDevice, setIsTouchDevice] = React142.useState(false);
@@ -21763,7 +21898,14 @@ function ApplePayButton({ onClick, title, subtitle }) {
21763
21898
  },
21764
21899
  children: [
21765
21900
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
21766
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) }),
21901
+ /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsx)("img", { src: iconUrl, alt: "Apple Pay", width: 36, height: 36, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
21902
+ "div",
21903
+ {
21904
+ className: "uf-w-9 uf-h-9 uf-rounded-lg uf-flex uf-items-center uf-justify-center",
21905
+ style: { backgroundColor: "#000" },
21906
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: "#fff" } })
21907
+ }
21908
+ ) }),
21767
21909
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "uf-text-left", children: [
21768
21910
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
21769
21911
  "div",
@@ -21979,13 +22121,6 @@ function solanaCandidate(provider, type, name, icon) {
21979
22121
  if (provider.isConnected && provider.publicKey) {
21980
22122
  return { type, name, address: provider.publicKey.toString(), icon };
21981
22123
  }
21982
- try {
21983
- const resp = await provider.connect({ onlyIfTrusted: true });
21984
- if (resp.publicKey) {
21985
- return { type, name, address: resp.publicKey.toString(), icon };
21986
- }
21987
- } catch {
21988
- }
21989
22124
  return null;
21990
22125
  }
21991
22126
  };
@@ -22209,6 +22344,178 @@ async function disconnectInjectedBrowserWallet(wallet) {
22209
22344
  collectEthereumProvidersForDisconnect(window)
22210
22345
  );
22211
22346
  }
22347
+ var STORED_TYPE_TO_EIP6963_WALLET_ID = {
22348
+ metamask: "metamask",
22349
+ "phantom-ethereum": "phantom",
22350
+ coinbase: "coinbase",
22351
+ trust: "trust",
22352
+ rainbow: "rainbow",
22353
+ rabby: "rabby",
22354
+ okx: "okx"
22355
+ };
22356
+ var EIP6963_WALLET_ID_TO_INFO = {
22357
+ metamask: { walletType: "metamask", name: "MetaMask", icon: "metamask" },
22358
+ phantom: { walletType: "phantom-ethereum", name: "Phantom", icon: "phantom" },
22359
+ coinbase: { walletType: "coinbase", name: "Coinbase Wallet", icon: "coinbase" },
22360
+ trust: { walletType: "trust", name: "Trust Wallet", icon: "trust" },
22361
+ rainbow: { walletType: "rainbow", name: "Rainbow", icon: "rainbow" },
22362
+ rabby: { walletType: "rabby", name: "Rabby", icon: "rabby" },
22363
+ okx: { walletType: "okx", name: "OKX Wallet", icon: "okx" }
22364
+ };
22365
+ var WALLET_ID_TO_WALLET_TYPE = {
22366
+ phantom: "phantom-ethereum",
22367
+ coinbase: "coinbase",
22368
+ trust: "trust",
22369
+ rainbow: "rainbow",
22370
+ rabby: "rabby",
22371
+ okx: "okx",
22372
+ metamask: "metamask"
22373
+ };
22374
+ var WALLET_TYPE_TO_WALLET_ID = {
22375
+ "phantom-ethereum": "phantom",
22376
+ coinbase: "coinbase",
22377
+ trust: "trust",
22378
+ okx: "okx",
22379
+ rainbow: "rainbow",
22380
+ rabby: "rabby",
22381
+ metamask: "metamask"
22382
+ };
22383
+ function isWalletType(value) {
22384
+ 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";
22385
+ }
22386
+ function walletIdToWalletType(walletId) {
22387
+ return WALLET_ID_TO_WALLET_TYPE[walletId] || "metamask";
22388
+ }
22389
+ function walletTypeToWalletId(walletType) {
22390
+ return WALLET_TYPE_TO_WALLET_ID[walletType] || walletType;
22391
+ }
22392
+ function getLegacyEvmProviders(win) {
22393
+ if (!win) return {};
22394
+ const anyWin = win;
22395
+ return {
22396
+ ethereum: anyWin.ethereum,
22397
+ phantomEthereum: anyWin.phantom?.ethereum,
22398
+ coinbaseEthereum: anyWin.coinbaseWalletExtension,
22399
+ trustEthereum: anyWin.trustwallet?.ethereum,
22400
+ okxEthereum: anyWin.okxwallet
22401
+ };
22402
+ }
22403
+ function getInjectedSolanaProviders(win) {
22404
+ if (!win) return {};
22405
+ const anyWin = win;
22406
+ return {
22407
+ phantomSolana: anyWin.phantom?.solana,
22408
+ solflare: anyWin.solflare,
22409
+ backpack: anyWin.backpack,
22410
+ glow: anyWin.glow,
22411
+ coinbaseSolana: anyWin.coinbaseSolana || anyWin.coinbaseWalletExtension?.solana,
22412
+ trustSolana: anyWin.trustwallet?.solana
22413
+ };
22414
+ }
22415
+ function describeEip6963Provider(wp) {
22416
+ const mapped = EIP6963_WALLET_ID_TO_INFO[wp.walletId];
22417
+ return {
22418
+ provider: wp.provider,
22419
+ walletType: mapped?.walletType ?? "metamask",
22420
+ name: mapped?.name ?? wp.info.name,
22421
+ icon: mapped?.icon ?? wp.info.icon
22422
+ };
22423
+ }
22424
+ function resolveQuickConnectEvmProvider(win) {
22425
+ const eip6963Providers = getEip6963Providers();
22426
+ if (eip6963Providers.length > 0) {
22427
+ const stored = getStoredWalletState();
22428
+ const preferredWalletId = stored?.walletType && isWalletType(stored.walletType) ? STORED_TYPE_TO_EIP6963_WALLET_ID[stored.walletType] : void 0;
22429
+ if (preferredWalletId) {
22430
+ const preferred = findProviderByWalletId(preferredWalletId);
22431
+ if (preferred) return describeEip6963Provider(preferred);
22432
+ }
22433
+ if (eip6963Providers.length === 1) {
22434
+ return describeEip6963Provider(eip6963Providers[0]);
22435
+ }
22436
+ return void 0;
22437
+ }
22438
+ const anyWin = win;
22439
+ const legacy = anyWin.phantom?.ethereum || anyWin.ethereum;
22440
+ if (!legacy) return void 0;
22441
+ const isPhantom = legacy.isPhantom;
22442
+ return {
22443
+ provider: legacy,
22444
+ walletType: isPhantom ? "phantom-ethereum" : "metamask",
22445
+ name: isPhantom ? "Phantom" : "MetaMask",
22446
+ icon: isPhantom ? "phantom" : "metamask"
22447
+ };
22448
+ }
22449
+ function resolveSolanaPublicKey(provider, response) {
22450
+ if (response?.publicKey) return { publicKey: response.publicKey };
22451
+ if (provider.publicKey) return { publicKey: provider.publicKey };
22452
+ return null;
22453
+ }
22454
+ function isUserRejectedSolanaConnectError(error) {
22455
+ if (!error || typeof error !== "object") return false;
22456
+ const maybeCode = "code" in error ? error.code : void 0;
22457
+ if (maybeCode === 4001) return true;
22458
+ const msg = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
22459
+ return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("rejected the request") || msg.includes("declined");
22460
+ }
22461
+ function isSolanaConnectTimeoutError(error) {
22462
+ return error instanceof Error && error.message.toLowerCase().includes("did not respond to the connection request");
22463
+ }
22464
+ async function connectSolanaProviderWithRecovery(provider, walletId, walletName) {
22465
+ if (provider.isConnected && provider.publicKey) {
22466
+ return { publicKey: provider.publicKey };
22467
+ }
22468
+ const connectOnce = () => provider.connect(walletId === "solflare" ? { onlyIfTrusted: false } : void 0);
22469
+ const withTimeout = async (ms = 2e4) => await Promise.race([
22470
+ connectOnce(),
22471
+ new Promise(
22472
+ (resolve, reject) => setTimeout(() => {
22473
+ const connected = resolveSolanaPublicKey(provider);
22474
+ if (connected) {
22475
+ resolve(connected);
22476
+ return;
22477
+ }
22478
+ reject(
22479
+ new Error(
22480
+ `${walletName} did not respond to the connection request. Please unlock the wallet and try again.`
22481
+ )
22482
+ );
22483
+ }, ms)
22484
+ )
22485
+ ]);
22486
+ if (walletId === "solflare") {
22487
+ await provider.disconnect?.().catch(() => {
22488
+ });
22489
+ }
22490
+ const connectAndResolve = async () => {
22491
+ try {
22492
+ const response = await withTimeout();
22493
+ const resolved = resolveSolanaPublicKey(provider, response);
22494
+ if (resolved) return resolved;
22495
+ await new Promise((resolve) => setTimeout(resolve, 120));
22496
+ const delayedResolved = resolveSolanaPublicKey(provider);
22497
+ if (delayedResolved) return delayedResolved;
22498
+ throw new Error(`${walletName} connected but did not expose a public key.`);
22499
+ } catch (error) {
22500
+ const connected = resolveSolanaPublicKey(provider);
22501
+ if (connected) return connected;
22502
+ throw error;
22503
+ }
22504
+ };
22505
+ try {
22506
+ return await connectAndResolve();
22507
+ } catch (err) {
22508
+ if (isUserRejectedSolanaConnectError(err)) throw err;
22509
+ if (isSolanaConnectTimeoutError(err)) throw err;
22510
+ if (walletId === "solflare") {
22511
+ await provider.disconnect?.().catch(() => {
22512
+ });
22513
+ await new Promise((resolve) => setTimeout(resolve, 150));
22514
+ return await connectAndResolve();
22515
+ }
22516
+ throw err;
22517
+ }
22518
+ }
22212
22519
  function MetamaskIcon({ size: size4 = 24, className, variant = "color" }) {
22213
22520
  const id = React172.useId();
22214
22521
  if (variant === "light" || variant === "dark") {
@@ -24068,21 +24375,19 @@ function BrowserWalletButton({
24068
24375
  }
24069
24376
  }
24070
24377
  if (!chainType || chainType === "ethereum") {
24071
- const ethProvider = window.phantom?.ethereum || window.ethereum;
24072
- if (ethProvider) {
24073
- const accounts = await ethProvider.request({
24378
+ const resolved = resolveQuickConnectEvmProvider(window);
24379
+ if (resolved) {
24380
+ const accounts = await resolved.provider.request({
24074
24381
  method: "eth_requestAccounts"
24075
24382
  });
24076
24383
  if (accounts && accounts.length > 0) {
24077
24384
  setUserDisconnectedWallet(false);
24078
- const isPhantom = ethProvider.isPhantom;
24079
- const walletType = isPhantom ? "phantom-ethereum" : "metamask";
24080
- setStoredWalletState(walletType);
24385
+ setStoredWalletState(resolved.walletType);
24081
24386
  setWallet({
24082
- type: walletType,
24083
- name: isPhantom ? "Phantom" : "MetaMask",
24387
+ type: resolved.walletType,
24388
+ name: resolved.name,
24084
24389
  address: accounts[0],
24085
- icon: isPhantom ? "phantom" : "metamask"
24390
+ icon: resolved.icon
24086
24391
  });
24087
24392
  }
24088
24393
  }
@@ -24116,7 +24421,10 @@ function BrowserWalletButton({
24116
24421
  if (isLoading) {
24117
24422
  return null;
24118
24423
  }
24119
- 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);
24424
+ const eip6963EvmProviderCount = getEip6963Providers().length;
24425
+ const legacyEvmProviders = getLegacyEvmProviders(window);
24426
+ const hasLegacyEvmProvider = eip6963EvmProviderCount === 0 && !!(legacyEvmProviders.ethereum || legacyEvmProviders.phantomEthereum || legacyEvmProviders.coinbaseEthereum || legacyEvmProviders.trustEthereum || legacyEvmProviders.okxEthereum);
24427
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && eip6963EvmProviderCount > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && hasLegacyEvmProvider;
24120
24428
  if (!onConnectClick && !wallet && !hasWalletExtension) {
24121
24429
  return null;
24122
24430
  }
@@ -24126,11 +24434,25 @@ function BrowserWalletButton({
24126
24434
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
24127
24435
  };
24128
24436
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
24437
+ const isImageIcon = !!wallet && (wallet.icon.startsWith("data:") || wallet.icon.startsWith("http"));
24129
24438
  const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React292.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
24130
24439
  size: 36,
24131
24440
  className: "uf-rounded-lg",
24132
24441
  variant: "color"
24133
- }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
24442
+ }) : isImageIcon ? (
24443
+ // Wallet announced via EIP-6963 with no internal icon component: render its
24444
+ // own advertised icon (`info.icon`) rather than a generic placeholder.
24445
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
24446
+ "img",
24447
+ {
24448
+ src: wallet.icon,
24449
+ alt: wallet.name,
24450
+ width: 36,
24451
+ height: 36,
24452
+ className: "uf-rounded-lg uf-w-9 uf-h-9"
24453
+ }
24454
+ )
24455
+ ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
24134
24456
  const titleSubtitleBlock = /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-text-left uf-min-w-0", children: [
24135
24457
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
24136
24458
  "div",
@@ -30088,11 +30410,29 @@ function useExchanges({
30088
30410
  });
30089
30411
  return { exchanges, isLoading };
30090
30412
  }
30413
+ function usePublicIncident({
30414
+ publishableKey,
30415
+ enabled = true
30416
+ }) {
30417
+ const {
30418
+ data: incident,
30419
+ isLoading,
30420
+ error
30421
+ } = (0, import_react_query15.useQuery)({
30422
+ queryKey: ["unifold", "publicIncident", publishableKey],
30423
+ queryFn: () => getPublicIncident(publishableKey),
30424
+ enabled,
30425
+ staleTime: 1e3 * 30,
30426
+ refetchInterval: 1e3 * 30,
30427
+ refetchOnWindowFocus: true
30428
+ });
30429
+ return { incident, isLoading, error: error ?? null };
30430
+ }
30091
30431
  function useApplePayProviders({
30092
30432
  publishableKey,
30093
30433
  enabled = true
30094
30434
  }) {
30095
- const { data: providers, isLoading } = (0, import_react_query15.useQuery)({
30435
+ const { data: providers, isLoading } = (0, import_react_query16.useQuery)({
30096
30436
  queryKey: ["unifold", "applePayProviders", publishableKey],
30097
30437
  queryFn: () => getApplePayProviders(publishableKey),
30098
30438
  enabled,
@@ -30152,7 +30492,7 @@ function useAddressValidation({
30152
30492
  refetchOnMount = false
30153
30493
  }) {
30154
30494
  const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
30155
- const { data, isLoading, error } = (0, import_react_query16.useQuery)({
30495
+ const { data, isLoading, error } = (0, import_react_query17.useQuery)({
30156
30496
  queryKey: [
30157
30497
  "unifold",
30158
30498
  "addressValidation",
@@ -30183,6 +30523,7 @@ function useAddressValidation({
30183
30523
  return {
30184
30524
  isValid: null,
30185
30525
  failureCode: null,
30526
+ message: null,
30186
30527
  metadata: null,
30187
30528
  isLoading: false,
30188
30529
  error: null
@@ -30191,6 +30532,7 @@ function useAddressValidation({
30191
30532
  return {
30192
30533
  isValid: data?.valid ?? null,
30193
30534
  failureCode: data?.failure_code ?? null,
30535
+ message: data?.message ?? null,
30194
30536
  metadata: data?.metadata ?? null,
30195
30537
  isLoading,
30196
30538
  error: error ?? null
@@ -31016,6 +31358,37 @@ function TokenSelectorSheet({
31016
31358
  var getChainKey = (chainId, chainType) => {
31017
31359
  return `${chainType}:${chainId}`;
31018
31360
  };
31361
+ function getStoredSelection(key) {
31362
+ if (typeof window === "undefined") return null;
31363
+ try {
31364
+ const raw = localStorage.getItem(key);
31365
+ if (!raw) return null;
31366
+ const parsed = JSON.parse(raw);
31367
+ if (parsed && typeof parsed.symbol === "string" && typeof parsed.chainType === "string" && typeof parsed.chainId === "string") {
31368
+ return parsed;
31369
+ }
31370
+ } catch {
31371
+ }
31372
+ return null;
31373
+ }
31374
+ function saveStoredSelection(key, symbol, chainType, chainId) {
31375
+ if (typeof window === "undefined") return;
31376
+ try {
31377
+ localStorage.setItem(key, JSON.stringify({ symbol, chainType, chainId }));
31378
+ } catch {
31379
+ }
31380
+ }
31381
+ function resolveFromStorage(tokens, stored) {
31382
+ for (const t13 of tokens) {
31383
+ if (t13.symbol !== stored.symbol) continue;
31384
+ const matchedChain = t13.chains.find(
31385
+ (c) => c.chain_type === stored.chainType && c.chain_id === stored.chainId
31386
+ );
31387
+ if (matchedChain) return { token: t13, chain: matchedChain };
31388
+ if (t13.chains.length > 0) return { token: t13, chain: t13.chains[0] };
31389
+ }
31390
+ return null;
31391
+ }
31019
31392
  function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
31020
31393
  if (!tokens.length) return null;
31021
31394
  let selectedToken;
@@ -31065,27 +31438,73 @@ function useDefaultToken({
31065
31438
  defaultChainType,
31066
31439
  defaultChainId,
31067
31440
  defaultTokenAddress,
31068
- defaultSymbol
31441
+ defaultSymbol,
31442
+ storageKey: storageKey2
31069
31443
  }) {
31070
- const [token, setToken] = (0, import_react30.useState)(null);
31071
- const [chain, setChain] = (0, import_react30.useState)(null);
31444
+ const [token, setTokenState] = (0, import_react30.useState)(null);
31445
+ const [chain, setChainState] = (0, import_react30.useState)(null);
31072
31446
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react30.useState)(false);
31073
31447
  const appliedDefaultsRef = (0, import_react30.useRef)("");
31448
+ const tokenRef = (0, import_react30.useRef)(null);
31449
+ const chainRef = (0, import_react30.useRef)(null);
31450
+ tokenRef.current = token;
31451
+ chainRef.current = chain;
31452
+ const setToken = (0, import_react30.useCallback)(
31453
+ (newToken) => {
31454
+ tokenRef.current = newToken;
31455
+ setTokenState(newToken);
31456
+ if (storageKey2 && chainRef.current) {
31457
+ const [chainType, chainId] = chainRef.current.split(":");
31458
+ saveStoredSelection(storageKey2, newToken, chainType, chainId);
31459
+ }
31460
+ },
31461
+ [storageKey2]
31462
+ );
31463
+ const setChain = (0, import_react30.useCallback)(
31464
+ (newChain) => {
31465
+ chainRef.current = newChain;
31466
+ setChainState(newChain);
31467
+ if (storageKey2 && tokenRef.current) {
31468
+ const [chainType, chainId] = newChain.split(":");
31469
+ saveStoredSelection(storageKey2, tokenRef.current, chainType, chainId);
31470
+ }
31471
+ },
31472
+ [storageKey2]
31473
+ );
31074
31474
  (0, import_react30.useEffect)(() => {
31075
31475
  if (!tokens.length) return;
31076
31476
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
31077
31477
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
31078
31478
  if (initialSelectionDone && !defaultsChanged) return;
31079
- const result = resolveToken(
31080
- tokens,
31081
- defaultChainType,
31082
- defaultChainId,
31083
- defaultTokenAddress,
31084
- defaultSymbol
31085
- );
31479
+ const hasExplicitDefaults = defaultTokenAddress && defaultChainType && defaultChainId || defaultSymbol && defaultChainType && defaultChainId;
31480
+ let result = null;
31481
+ if (hasExplicitDefaults) {
31482
+ result = resolveToken(
31483
+ tokens,
31484
+ defaultChainType,
31485
+ defaultChainId,
31486
+ defaultTokenAddress,
31487
+ defaultSymbol
31488
+ );
31489
+ if (result) {
31490
+ 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;
31491
+ if (!matched) {
31492
+ result = null;
31493
+ }
31494
+ }
31495
+ }
31496
+ if (!result && storageKey2) {
31497
+ const stored = getStoredSelection(storageKey2);
31498
+ if (stored) {
31499
+ result = resolveFromStorage(tokens, stored);
31500
+ }
31501
+ }
31502
+ if (!result) {
31503
+ result = resolveToken(tokens);
31504
+ }
31086
31505
  if (result) {
31087
- setToken(result.token.symbol);
31088
- setChain(getChainKey(result.chain.chain_id, result.chain.chain_type));
31506
+ setTokenState(result.token.symbol);
31507
+ setChainState(getChainKey(result.chain.chain_id, result.chain.chain_type));
31089
31508
  appliedDefaultsRef.current = defaultsKey;
31090
31509
  setInitialSelectionDone(true);
31091
31510
  }
@@ -31095,7 +31514,8 @@ function useDefaultToken({
31095
31514
  defaultSymbol,
31096
31515
  defaultChainType,
31097
31516
  defaultChainId,
31098
- initialSelectionDone
31517
+ initialSelectionDone,
31518
+ storageKey2
31099
31519
  ]);
31100
31520
  (0, import_react30.useEffect)(() => {
31101
31521
  if (!tokens.length || !token) return;
@@ -31106,11 +31526,12 @@ function useDefaultToken({
31106
31526
  });
31107
31527
  if (!isChainAvailable) {
31108
31528
  const firstChain = currentToken.chains[0];
31109
- setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
31529
+ setChainState(getChainKey(firstChain.chain_id, firstChain.chain_type));
31110
31530
  }
31111
31531
  }, [token, tokens, chain]);
31112
31532
  return { token, chain, setToken, setChain, initialSelectionDone };
31113
31533
  }
31534
+ var STORAGE_KEY2 = "unifold_last_deposit_from_token";
31114
31535
  function useDefaultSourceToken({
31115
31536
  supportedTokens,
31116
31537
  defaultSourceChainType,
@@ -31123,7 +31544,8 @@ function useDefaultSourceToken({
31123
31544
  defaultChainType: defaultSourceChainType,
31124
31545
  defaultChainId: defaultSourceChainId,
31125
31546
  defaultTokenAddress: defaultSourceTokenAddress,
31126
- defaultSymbol: defaultSourceSymbol
31547
+ defaultSymbol: defaultSourceSymbol,
31548
+ storageKey: STORAGE_KEY2
31127
31549
  });
31128
31550
  }
31129
31551
  function DepositFooterLinks({ onGlossaryClick, leftElement }) {
@@ -31454,7 +31876,7 @@ function useHypercoreActivation(params) {
31454
31876
  const recipient = recipientAddress?.trim() ?? "";
31455
31877
  const source = sourceAddress?.trim() ?? "";
31456
31878
  const hasAddresses = !!recipient && !!source;
31457
- const { data, isLoading } = (0, import_react_query17.useQuery)({
31879
+ const { data, isLoading } = (0, import_react_query18.useQuery)({
31458
31880
  queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
31459
31881
  queryFn: () => checkHypercoreActivation(
31460
31882
  {
@@ -33022,7 +33444,7 @@ function useDepositQuote(params) {
33022
33444
  ...adjustForSlippage ? { adjust_for_slippage: true } : {},
33023
33445
  ...stablecoinParity ? { stablecoin_parity: true } : {}
33024
33446
  };
33025
- return (0, import_react_query18.useQuery)({
33447
+ return (0, import_react_query19.useQuery)({
33026
33448
  queryKey: [
33027
33449
  "unifold",
33028
33450
  "depositQuote",
@@ -33052,7 +33474,7 @@ function useExternalWallets({
33052
33474
  publishableKey,
33053
33475
  enabled = true
33054
33476
  }) {
33055
- const { data: wallets = [], isLoading } = (0, import_react_query19.useQuery)({
33477
+ const { data: wallets = [], isLoading } = (0, import_react_query20.useQuery)({
33056
33478
  queryKey: ["unifold", "external-wallets", publishableKey],
33057
33479
  queryFn: () => getExternalWallets(publishableKey).then((res) => res.data),
33058
33480
  enabled: enabled && !!publishableKey,
@@ -34135,33 +34557,11 @@ function balancesRepresentSameToken(a, b) {
34135
34557
  if (!tokenA || !tokenB) return false;
34136
34558
  return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
34137
34559
  }
34138
- function getSolanaProviders() {
34139
- if (typeof window === "undefined") return {};
34140
- const win = window;
34141
- return {
34142
- phantomSolana: win.phantom?.solana,
34143
- solflare: win.solflare,
34144
- backpack: win.backpack,
34145
- glow: win.glow,
34146
- coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
34147
- };
34148
- }
34149
- function getLegacyEvmProviders() {
34150
- if (typeof window === "undefined") return {};
34151
- const win = window;
34152
- return {
34153
- ethereum: win.ethereum,
34154
- phantomEthereum: win.phantom?.ethereum,
34155
- coinbaseEthereum: win.coinbaseWalletExtension,
34156
- trustEthereum: win.trustwallet?.ethereum,
34157
- okxEthereum: win.okxwallet
34158
- };
34159
- }
34160
34560
  function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
34161
- const solProviders = getSolanaProviders();
34162
- const legacyEvm = getLegacyEvmProviders();
34163
- const eip6963List = getEip6963Providers();
34164
34561
  const win = typeof window !== "undefined" ? window : null;
34562
+ const solProviders = getInjectedSolanaProviders(win);
34563
+ const legacyEvm = getLegacyEvmProviders(win);
34564
+ const eip6963List = getEip6963Providers();
34165
34565
  const hasEip6963 = (walletId) => eip6963List.some((d) => {
34166
34566
  const rdns = d.info?.rdns || "";
34167
34567
  switch (walletId) {
@@ -34430,10 +34830,13 @@ function WalletConnect({
34430
34830
  };
34431
34831
  const openMobileWalletBrowse = async (wallet, depositAddresses) => {
34432
34832
  try {
34833
+ const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
34834
+ const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
34433
34835
  const res = await getWalletMobileDeepLink(
34434
34836
  wallet.id,
34435
34837
  depositAddresses,
34436
- publishableKey
34838
+ publishableKey,
34839
+ forwardedAmountUsd
34437
34840
  );
34438
34841
  if (res.deeplink) {
34439
34842
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
@@ -34522,7 +34925,7 @@ function WalletConnect({
34522
34925
  const eip6963Match = findProviderByWalletId(wallet.id);
34523
34926
  let provider = eip6963Match?.provider;
34524
34927
  if (!provider) {
34525
- const legacyEvm = getLegacyEvmProviders();
34928
+ const legacyEvm = getLegacyEvmProviders(win);
34526
34929
  switch (wallet.id) {
34527
34930
  case "metamask":
34528
34931
  if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom)
@@ -34554,16 +34957,7 @@ function WalletConnect({
34554
34957
  const accounts = await provider.request({ method: "eth_requestAccounts" });
34555
34958
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
34556
34959
  setUserDisconnectedWallet(false);
34557
- const walletIdToType = {
34558
- phantom: "phantom-ethereum",
34559
- coinbase: "coinbase",
34560
- trust: "trust",
34561
- rainbow: "rainbow",
34562
- rabby: "rabby",
34563
- okx: "okx",
34564
- metamask: "metamask"
34565
- };
34566
- const walletType = walletIdToType[wallet.id] || "metamask";
34960
+ const walletType = walletIdToWalletType(wallet.id);
34567
34961
  setStoredWalletState(walletType);
34568
34962
  connectedInfo = {
34569
34963
  type: walletType,
@@ -34572,7 +34966,7 @@ function WalletConnect({
34572
34966
  icon: wallet.id
34573
34967
  };
34574
34968
  } else {
34575
- const solProviders = getSolanaProviders();
34969
+ const solProviders = getInjectedSolanaProviders(win);
34576
34970
  let provider;
34577
34971
  switch (wallet.id) {
34578
34972
  case "phantom":
@@ -34591,11 +34985,11 @@ function WalletConnect({
34591
34985
  provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
34592
34986
  break;
34593
34987
  case "trust":
34594
- provider = win?.trustwallet?.solana;
34988
+ provider = solProviders.trustSolana;
34595
34989
  break;
34596
34990
  }
34597
34991
  if (!provider) throw new Error(`${wallet.name} Solana wallet not found.`);
34598
- const response = await provider.connect();
34992
+ const response = await connectSolanaProviderWithRecovery(provider, wallet.id, wallet.name);
34599
34993
  setUserDisconnectedWallet(false);
34600
34994
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
34601
34995
  setStoredWalletState(walletType);
@@ -34946,16 +35340,7 @@ function WalletConnect({
34946
35340
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
34947
35341
  };
34948
35342
  const resolveEvmProvider = () => {
34949
- const walletIdMap = {
34950
- "phantom-ethereum": "phantom",
34951
- coinbase: "coinbase",
34952
- trust: "trust",
34953
- okx: "okx",
34954
- rainbow: "rainbow",
34955
- rabby: "rabby",
34956
- metamask: "metamask"
34957
- };
34958
- const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
35343
+ const lookupId = walletTypeToWalletId(walletInfo.type);
34959
35344
  const eip6963Match = findProviderByWalletId(lookupId);
34960
35345
  let provider = eip6963Match?.provider;
34961
35346
  if (!provider) {
@@ -35684,6 +36069,7 @@ function DepositModal({
35684
36069
  applePayTitle = "Pay with Apple Pay",
35685
36070
  applePaySubTitle = "Instant",
35686
36071
  enableBankTransfer,
36072
+ enableIncidentBanner = false,
35687
36073
  // No default: left undefined so the backend `stripe_link.enabled` can govern
35688
36074
  // (via the `??` chain in showStripeLink) once a dashboard toggle exists.
35689
36075
  enableStripeLink,
@@ -35729,7 +36115,7 @@ function DepositModal({
35729
36115
  const s = initialScreen ?? "main";
35730
36116
  if (s === "tracker" && hideDepositTracker === true) return "main";
35731
36117
  if (s === "cashapp" && enableCashApp === false) return "main";
35732
- if (s === "stripe_link" && !enableStripeLink) return "main";
36118
+ if (s === "stripe_link" && enableStripeLink === false) return "main";
35733
36119
  if (s === "apple_pay" && enableApplePay === false) return "main";
35734
36120
  if (s === "card" && enableFiatOnramp === false) return "main";
35735
36121
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
@@ -35788,6 +36174,16 @@ function DepositModal({
35788
36174
  const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
35789
36175
  const showBankTransfer = enableBankTransfer ?? projectConfig?.bank_transfer?.enabled ?? true;
35790
36176
  const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
36177
+ const { incident: publicIncident } = usePublicIncident({
36178
+ publishableKey,
36179
+ enabled: open && enableIncidentBanner
36180
+ });
36181
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
36182
+ enabled: true,
36183
+ messages: publicIncident.messages,
36184
+ severity: publicIncident.severity,
36185
+ statusPageUrl: publicIncident.status_page_url
36186
+ } : void 0;
35791
36187
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react8.useState)([]);
35792
36188
  (0, import_react8.useEffect)(() => {
35793
36189
  if (!showConnectExchange || !open) return;
@@ -35854,7 +36250,11 @@ function DepositModal({
35854
36250
  setConnectedExchange((prev) => prev ? { ...prev, iconUrl } : prev);
35855
36251
  }
35856
36252
  }, [integrationExchanges, connectedExchange]);
35857
- const { data: depositAddressResponse, isLoading: walletsLoading } = useDepositAddress({
36253
+ const {
36254
+ data: depositAddressResponse,
36255
+ isLoading: walletsLoading,
36256
+ error: walletsError
36257
+ } = useDepositAddress({
35858
36258
  userId,
35859
36259
  publishableKey,
35860
36260
  recipientAddress,
@@ -35987,6 +36387,7 @@ function DepositModal({
35987
36387
  const {
35988
36388
  isValid: isAddressValid,
35989
36389
  failureCode: addressFailureCode,
36390
+ message: addressFailureMessage,
35990
36391
  metadata: addressFailureMetadata,
35991
36392
  isLoading: isAddressValidationLoading
35992
36393
  } = useAddressValidation({
@@ -36000,17 +36401,31 @@ function DepositModal({
36000
36401
  refetchOnMount: "always"
36001
36402
  });
36002
36403
  const addressValidationMessages = i18n2.transferCrypto.addressValidation;
36003
- const getAddressValidationErrorMessage = (code, metadata) => {
36404
+ const getAddressValidationErrorMessage = (message, code, metadata) => {
36405
+ if (message && message.trim().length > 0) return message;
36004
36406
  if (!code) return addressValidationMessages.defaultError;
36005
36407
  const errors = addressValidationMessages.errors;
36006
36408
  const template = errors[code] ?? addressValidationMessages.defaultError;
36007
36409
  return interpolate(template, metadata);
36008
36410
  };
36411
+ const walletsRecipientError = isDepositAddressValidationError(walletsError) ? walletsError.message : null;
36412
+ const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
36413
+ const recipientInvalidMessage = getAddressValidationErrorMessage(
36414
+ addressFailureMessage ?? walletsRecipientError,
36415
+ addressFailureCode,
36416
+ addressFailureMetadata
36417
+ );
36009
36418
  const openingScreen = effectiveInitialScreen;
36010
36419
  const sessionOpenedFromMenu = openingScreen === "main";
36011
36420
  const standaloneNeedsDepositPrereq = openingScreen !== "main" && (view === "transfer" || view === "card");
36012
36421
  let depositPrerequisiteBody;
36013
- if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
36422
+ if (isRecipientAddressInvalid) {
36423
+ depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
36424
+ /* @__PURE__ */ (0, import_jsx_runtime80.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_runtime80.jsx)(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
36425
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
36426
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: recipientInvalidMessage })
36427
+ ] });
36428
+ } else if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
36014
36429
  // fetch — block the menu on it so the row never flashes in or out.
36015
36430
  showBankTransfer && bankTransferProvidersLoading || // Same for Apple Pay: row visibility depends on the geo/platform-gated
36016
36431
  // providers fetch — block the menu so the row doesn't pop in or out.
@@ -36032,12 +36447,6 @@ function DepositModal({
36032
36447
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
36033
36448
  /* @__PURE__ */ (0, import_jsx_runtime80.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." })
36034
36449
  ] });
36035
- } else if (isAddressValid === false) {
36036
- depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
36037
- /* @__PURE__ */ (0, import_jsx_runtime80.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_runtime80.jsx)(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
36038
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
36039
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(addressFailureCode, addressFailureMetadata) })
36040
- ] });
36041
36450
  } else {
36042
36451
  depositPrerequisiteBody = null;
36043
36452
  }
@@ -36531,6 +36940,7 @@ function DepositModal({
36531
36940
  title: modalTitle || "Deposit",
36532
36941
  showClose: !hideOverlay,
36533
36942
  onClose: handleClose,
36943
+ incident: activeIncident,
36534
36944
  showBalance: showBalanceHeader,
36535
36945
  balanceAddress: recipientAddress,
36536
36946
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -36550,6 +36960,7 @@ function DepositModal({
36550
36960
  showBack: showBackTransfer,
36551
36961
  onBack: handleBack,
36552
36962
  onClose: handleClose,
36963
+ incident: activeIncident,
36553
36964
  showBalance: showBalanceHeader,
36554
36965
  balanceAddress: recipientAddress,
36555
36966
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -36610,7 +37021,8 @@ function DepositModal({
36610
37021
  title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
36611
37022
  showBack: showBackTracker,
36612
37023
  onBack: handleBack,
36613
- onClose: handleClose
37024
+ onClose: handleClose,
37025
+ incident: activeIncident
36614
37026
  }
36615
37027
  ),
36616
37028
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -36642,6 +37054,7 @@ function DepositModal({
36642
37054
  showBack: showBackCard,
36643
37055
  onBack: handleBack,
36644
37056
  onClose: handleClose,
37057
+ incident: activeIncident,
36645
37058
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
36646
37059
  showBalance: showBalanceHeader,
36647
37060
  balanceAddress: recipientAddress,
@@ -36691,7 +37104,8 @@ function DepositModal({
36691
37104
  title: payWithExchangeTitle,
36692
37105
  showBack: exchangeView === "pending" || sessionOpenedFromMenu,
36693
37106
  onBack: handleBack,
36694
- onClose: handleClose
37107
+ onClose: handleClose,
37108
+ incident: activeIncident
36695
37109
  }
36696
37110
  ),
36697
37111
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -36805,7 +37219,8 @@ function DepositModal({
36805
37219
  title: t8.bankTransfer.title,
36806
37220
  showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
36807
37221
  onBack: handleBack,
36808
- onClose: handleClose
37222
+ onClose: handleClose,
37223
+ incident: activeIncident
36809
37224
  }
36810
37225
  ),
36811
37226
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -36839,26 +37254,24 @@ function DepositModal({
36839
37254
  title: "Deposit with Link",
36840
37255
  showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
36841
37256
  onBack: handleBack,
37257
+ incident: activeIncident,
36842
37258
  showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
36843
37259
  onClose: handleClose
36844
37260
  }
36845
37261
  ),
36846
37262
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
36847
37263
  isLoadingIp ? (
36848
- // Hold the geo decision until IP resolves so we don't mount
36849
- // PayWithStripeLink (which kicks off config/OAuth work) for a
36850
- // deep-link user who turns out to be outside the US.
37264
+ // Wait for location so the first config fetch is region-aware.
36851
37265
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(SkeletonButton, { variant: "with-icons" })
36852
37266
  ) : !showStripeLink ? (
36853
- // Stripe Link's crypto on-ramp is US-only. On a direct open
36854
- // (initialScreen="stripe_link") the row isn't in a menu to
36855
- // fall back to, so show a geo-restriction screen rather than
36856
- // the Link UI.
37267
+ // Direct opens (initialScreen="stripe_link") have no menu row
37268
+ // to fall back to, so render an unavailable state when backend
37269
+ // config resolves Stripe Link disabled/hidden.
36857
37270
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
36858
37271
  GeoRestrictionScreen,
36859
37272
  {
36860
37273
  methodName: t8.stripeLink.title,
36861
- message: "Pay with Link is only available in the US."
37274
+ message: t8.stripeLink.unavailableInRegionMessage
36862
37275
  }
36863
37276
  )
36864
37277
  ) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
@@ -36891,7 +37304,8 @@ function DepositModal({
36891
37304
  title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
36892
37305
  showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
36893
37306
  onBack: handleBack,
36894
- onClose: handleClose
37307
+ onClose: handleClose,
37308
+ incident: activeIncident
36895
37309
  }
36896
37310
  ),
36897
37311
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -36927,7 +37341,8 @@ function DepositModal({
36927
37341
  const handled = applePayHandleRef.current?.requestBack() ?? false;
36928
37342
  if (!handled) handleBack();
36929
37343
  },
36930
- onClose: handleClose
37344
+ onClose: handleClose,
37345
+ incident: activeIncident
36931
37346
  }
36932
37347
  ),
36933
37348
  /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -36970,7 +37385,7 @@ function DepositModal({
36970
37385
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
36971
37386
  function usePaymentIntent(params) {
36972
37387
  const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
36973
- return (0, import_react_query20.useQuery)({
37388
+ return (0, import_react_query21.useQuery)({
36974
37389
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
36975
37390
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
36976
37391
  enabled: enabled && !!clientSecret && !!publishableKey,
@@ -37042,6 +37457,7 @@ function CheckoutModal({
37042
37457
  modalTitle,
37043
37458
  enableTransferCrypto,
37044
37459
  enableConnectWallet,
37460
+ enableIncidentBanner = false,
37045
37461
  defaultSourceChainType,
37046
37462
  defaultSourceChainId,
37047
37463
  defaultSourceTokenAddress,
@@ -37113,6 +37529,16 @@ function CheckoutModal({
37113
37529
  });
37114
37530
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
37115
37531
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
37532
+ const { incident: publicIncident } = usePublicIncident({
37533
+ publishableKey,
37534
+ enabled: open && enableIncidentBanner
37535
+ });
37536
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
37537
+ enabled: true,
37538
+ messages: publicIncident.messages,
37539
+ severity: publicIncident.severity,
37540
+ statusPageUrl: publicIncident.status_page_url
37541
+ } : void 0;
37116
37542
  (0, import_react34.useEffect)(() => {
37117
37543
  if (view === "transfer" && !showTransferCrypto) {
37118
37544
  setView("main");
@@ -37414,7 +37840,15 @@ function CheckoutModal({
37414
37840
  {
37415
37841
  className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
37416
37842
  children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
37417
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
37843
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
37844
+ DepositHeader,
37845
+ {
37846
+ title: modalTitle || "Checkout",
37847
+ showClose: true,
37848
+ onClose: handleClose,
37849
+ incident: activeIncident
37850
+ }
37851
+ ),
37418
37852
  /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
37419
37853
  piLoading ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "uf-space-y-3", children: [
37420
37854
  /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -37512,7 +37946,8 @@ function CheckoutModal({
37512
37946
  title: modalTitle || "Checkout",
37513
37947
  showBack: true,
37514
37948
  onBack: handleBack,
37515
- onClose: handleClose
37949
+ onClose: handleClose,
37950
+ incident: activeIncident
37516
37951
  }
37517
37952
  ),
37518
37953
  /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -37672,7 +38107,7 @@ function CheckoutModal({
37672
38107
  ) }) });
37673
38108
  }
37674
38109
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
37675
- return (0, import_react_query21.useQuery)({
38110
+ return (0, import_react_query22.useQuery)({
37676
38111
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
37677
38112
  queryFn: () => getSupportedDestinationTokens(publishableKey),
37678
38113
  staleTime: 1e3 * 60 * 5,
@@ -37682,6 +38117,7 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
37682
38117
  enabled
37683
38118
  });
37684
38119
  }
38120
+ var STORAGE_KEY3 = "unifold_last_withdraw_to_token";
37685
38121
  function useDefaultDestinationToken({
37686
38122
  destinationTokens,
37687
38123
  defaultDestinationChainType,
@@ -37694,7 +38130,8 @@ function useDefaultDestinationToken({
37694
38130
  defaultChainType: defaultDestinationChainType,
37695
38131
  defaultChainId: defaultDestinationChainId,
37696
38132
  defaultTokenAddress: defaultDestinationTokenAddress,
37697
- defaultSymbol: defaultDestinationSymbol
38133
+ defaultSymbol: defaultDestinationSymbol,
38134
+ storageKey: STORAGE_KEY3
37698
38135
  });
37699
38136
  }
37700
38137
  function useSourceTokenValidation(params) {
@@ -37707,7 +38144,7 @@ function useSourceTokenValidation(params) {
37707
38144
  enabled = true
37708
38145
  } = params;
37709
38146
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
37710
- return (0, import_react_query22.useQuery)({
38147
+ return (0, import_react_query23.useQuery)({
37711
38148
  queryKey: [
37712
38149
  "unifold",
37713
38150
  "sourceTokenValidation",
@@ -37756,7 +38193,7 @@ function useSourceTokenValidation(params) {
37756
38193
  function useAddressBalance(params) {
37757
38194
  const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
37758
38195
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
37759
- return (0, import_react_query23.useQuery)({
38196
+ return (0, import_react_query24.useQuery)({
37760
38197
  queryKey: [
37761
38198
  "unifold",
37762
38199
  "addressBalance",
@@ -37812,7 +38249,7 @@ function useAddressBalance(params) {
37812
38249
  }
37813
38250
  function useExecutions(userId, publishableKey, options) {
37814
38251
  const actionType = options?.actionType ?? ActionType.Deposit;
37815
- return (0, import_react_query24.useQuery)({
38252
+ return (0, import_react_query25.useQuery)({
37816
38253
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
37817
38254
  queryFn: () => queryExecutions(userId, publishableKey, actionType),
37818
38255
  enabled: (options?.enabled ?? true) && !!userId,
@@ -38138,7 +38575,7 @@ function useVerifyRecipientAddress(params) {
38138
38575
  } = params;
38139
38576
  const trimmedAddress = recipientAddress?.trim() || "";
38140
38577
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
38141
- return (0, import_react_query25.useQuery)({
38578
+ return (0, import_react_query26.useQuery)({
38142
38579
  queryKey: [
38143
38580
  "unifold",
38144
38581
  "verifyRecipientAddress",
@@ -38177,7 +38614,7 @@ function useGetDepositAddress(params) {
38177
38614
  enabled = true
38178
38615
  } = params;
38179
38616
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
38180
- return (0, import_react_query26.useQuery)({
38617
+ return (0, import_react_query27.useQuery)({
38181
38618
  queryKey: [
38182
38619
  "unifold",
38183
38620
  "getDepositAddress",
@@ -38368,6 +38805,9 @@ function WithdrawForm({
38368
38805
  if (isDebouncing || isVerifyingAddress) return null;
38369
38806
  if (verifyError) return t10.invalidAddress;
38370
38807
  if (addressVerification && !addressVerification.valid) {
38808
+ if (addressVerification.message && addressVerification.message.trim().length > 0) {
38809
+ return addressVerification.message;
38810
+ }
38371
38811
  if (addressVerification.failure_code === "account_not_found")
38372
38812
  return `Account not found on ${selectedChain?.chain_name}`;
38373
38813
  if (addressVerification.failure_code === "not_opted_in")
@@ -39627,6 +40067,7 @@ function UnifoldProvider2({
39627
40067
  const [isWithdrawOpen, setIsWithdrawOpen] = (0, import_react41.useState)(false);
39628
40068
  const [withdrawConfig, setWithdrawConfig] = (0, import_react41.useState)(null);
39629
40069
  const [resolvedTheme, setResolvedTheme] = import_react41.default.useState("dark");
40070
+ const incidentBannerEnabled = config?.notifications?.incidentBanner;
39630
40071
  (0, import_react41.useEffect)(() => {
39631
40072
  if (publishableKey) {
39632
40073
  setApiConfig({ publishableKey });
@@ -39924,6 +40365,7 @@ function UnifoldProvider2({
39924
40365
  publishableKey,
39925
40366
  enableTransferCrypto: config?.enableTransferCrypto,
39926
40367
  enableConnectWallet: config?.enableConnectWallet,
40368
+ enableIncidentBanner: incidentBannerEnabled,
39927
40369
  defaultSourceChainType: checkoutConfig.defaultSourceChainType,
39928
40370
  defaultSourceChainId: checkoutConfig.defaultSourceChainId,
39929
40371
  defaultSourceTokenAddress: checkoutConfig.defaultSourceTokenAddress,
@@ -39991,6 +40433,7 @@ function UnifoldProvider2({
39991
40433
  enableConnectExchange: config?.enableConnectExchange,
39992
40434
  enableCashApp: config?.enableCashApp,
39993
40435
  enableStripeLink: config?.enableStripeLink,
40436
+ enableIncidentBanner: incidentBannerEnabled,
39994
40437
  enableApplePay: config?.enableApplePay,
39995
40438
  applePayTitle: config?.applePayTitle,
39996
40439
  applePaySubTitle: config?.applePaySubTitle,