@unifold/ui-web 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.mjs CHANGED
@@ -38400,7 +38400,10 @@ ${new this._window.XMLSerializer().serializeToString(e3)}`;
38400
38400
  })()));
38401
38401
  }
38402
38402
  });
38403
- var UnifoldContext = (0, import_react2.createContext)(null);
38403
+ var UNIFOLD_CONTEXT_KEY = /* @__PURE__ */ Symbol.for("unifold.react-provider.context");
38404
+ var globalRef = globalThis;
38405
+ var UnifoldContext = globalRef[UNIFOLD_CONTEXT_KEY] ?? (0, import_react2.createContext)(null);
38406
+ globalRef[UNIFOLD_CONTEXT_KEY] = UnifoldContext;
38404
38407
  var createQueryClient = () => new QueryClient({
38405
38408
  defaultOptions: {
38406
38409
  queries: {
@@ -43160,6 +43163,9 @@ var getDefaultConfig = () => {
43160
43163
  };
43161
43164
  };
43162
43165
  var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
43166
+ var __defProp22 = Object.defineProperty;
43167
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp22(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
43168
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
43163
43169
  function formatStablecoinAmount(baseUnits, decimals) {
43164
43170
  const raw = Number(baseUnits) / 10 ** decimals;
43165
43171
  const floored = Math.floor(raw * 100) / 100;
@@ -43250,6 +43256,16 @@ var ActionType = /* @__PURE__ */ ((ActionType2) => {
43250
43256
  ActionType2["Withdraw"] = "withdraw";
43251
43257
  return ActionType2;
43252
43258
  })(ActionType || {});
43259
+ var DepositAddressValidationError = class extends Error {
43260
+ constructor(message) {
43261
+ super(message);
43262
+ __publicField(this, "isDepositAddressValidationError", true);
43263
+ this.name = "DepositAddressValidationError";
43264
+ }
43265
+ };
43266
+ function isDepositAddressValidationError(error) {
43267
+ return error instanceof Error && error.isDepositAddressValidationError === true;
43268
+ }
43253
43269
  async function createDepositAddress(overrides, publishableKey) {
43254
43270
  if (!overrides?.external_user_id) {
43255
43271
  throw new Error("external_user_id is required");
@@ -43277,6 +43293,13 @@ async function createDepositAddress(overrides, publishableKey) {
43277
43293
  body: JSON.stringify(payload)
43278
43294
  });
43279
43295
  if (!response.ok) {
43296
+ if (response.status === 400) {
43297
+ const body = await response.json().catch(() => null);
43298
+ if (body?.error_type === "validation_error") {
43299
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
43300
+ throw new DepositAddressValidationError(firstError ?? "Invalid recipient address");
43301
+ }
43302
+ }
43280
43303
  throw new Error(`Failed to create EOA: ${response.statusText}`);
43281
43304
  }
43282
43305
  return response.json();
@@ -43615,6 +43638,21 @@ async function getProjectConfig(publishableKey, options2) {
43615
43638
  const data = await response.json();
43616
43639
  return data;
43617
43640
  }
43641
+ async function getPublicIncident(publishableKey) {
43642
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43643
+ validatePublishableKey(pk);
43644
+ const response = await fetch(`${API_BASE_URL}/v1/public/projects/incident`, {
43645
+ method: "GET",
43646
+ headers: {
43647
+ accept: "application/json",
43648
+ "x-publishable-key": pk
43649
+ }
43650
+ });
43651
+ if (!response.ok) {
43652
+ throw new Error(`Failed to fetch public incident: ${response.statusText}`);
43653
+ }
43654
+ return response.json();
43655
+ }
43618
43656
  async function getIpAddress() {
43619
43657
  const response = await fetch(`${API_BASE_URL}/v1/public/ip_address`, {
43620
43658
  method: "GET",
@@ -43670,7 +43708,7 @@ async function getExternalWallets(publishableKey) {
43670
43708
  const data = await response.json();
43671
43709
  return data;
43672
43710
  }
43673
- async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey) {
43711
+ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey, amountUsd) {
43674
43712
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43675
43713
  validatePublishableKey(pk);
43676
43714
  const response = await fetch(`${API_BASE_URL}/v1/public/external_wallets/mobile_deeplink`, {
@@ -43680,7 +43718,11 @@ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey)
43680
43718
  accept: "application/json",
43681
43719
  "x-publishable-key": pk
43682
43720
  },
43683
- body: JSON.stringify({ wallet, deposit_addresses: depositAddresses })
43721
+ body: JSON.stringify({
43722
+ wallet,
43723
+ deposit_addresses: depositAddresses,
43724
+ ...amountUsd ? { amount_usd: amountUsd } : {}
43725
+ })
43684
43726
  });
43685
43727
  if (!response.ok) {
43686
43728
  throw new Error(`Failed to generate wallet deep link: ${response.statusText}`);
@@ -43725,6 +43767,15 @@ async function verifyRecipientAddress(request, publishableKey) {
43725
43767
  body: JSON.stringify(request)
43726
43768
  });
43727
43769
  if (!response.ok) {
43770
+ const body = await response.json().catch(() => null);
43771
+ if (response.status === 400 && body?.error_type === "validation_error") {
43772
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
43773
+ return {
43774
+ valid: false,
43775
+ failure_code: "validation_error",
43776
+ message: firstError ?? "Invalid recipient address"
43777
+ };
43778
+ }
43728
43779
  throw new Error(`Failed to verify recipient address: ${response.statusText}`);
43729
43780
  }
43730
43781
  return response.json();
@@ -51316,7 +51367,13 @@ function useDepositAddress(params) {
51316
51367
  // 24 hours in cache
51317
51368
  refetchOnMount: false,
51318
51369
  refetchOnWindowFocus: false,
51319
- retry: 3,
51370
+ // Don't retry recipient-address validation errors — they're deterministic
51371
+ // (a 400 won't succeed on retry) and we want to surface the invalid-address
51372
+ // screen immediately rather than after 3 backoff attempts.
51373
+ retry: (failureCount, error) => {
51374
+ if (isDepositAddressValidationError(error)) return false;
51375
+ return failureCount < 3;
51376
+ },
51320
51377
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
51321
51378
  // 1s, 2s, 4s (max 10s)
51322
51379
  });
@@ -51524,7 +51581,8 @@ function DepositHeader({
51524
51581
  balanceChainId,
51525
51582
  balanceTokenAddress,
51526
51583
  projectName,
51527
- publishableKey
51584
+ publishableKey,
51585
+ incident
51528
51586
  }) {
51529
51587
  const { colors: colors2, fonts, components } = useTheme();
51530
51588
  const [balance, setBalance] = (0, import_react10.useState)(null);
@@ -51622,19 +51680,64 @@ function DepositHeader({
51622
51680
  balanceTokenAddress,
51623
51681
  publishableKey
51624
51682
  ]);
51625
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
51626
- showBack ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51627
- "button",
51628
- {
51629
- onClick: onBack,
51630
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51631
- style: { color: components.header.buttonColor },
51632
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
51633
- }
51634
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
51635
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
51636
- badge ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
51637
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51683
+ const incidentMessages = incident?.messages ?? [];
51684
+ const showIncident = incident?.enabled && incidentMessages.length > 0;
51685
+ const incidentSeverity = incident?.severity ?? "degraded";
51686
+ const incidentSeverityLabel = incidentSeverity === "outage" ? "Outage" : incidentSeverity === "info" ? "Info" : "Degraded service";
51687
+ const incidentStyles = incidentSeverity === "outage" ? {
51688
+ bg: "rgba(239, 68, 68, 0.12)",
51689
+ border: "rgba(239, 68, 68, 0.35)",
51690
+ text: "#fca5a5",
51691
+ link: "#fca5a5"
51692
+ } : incidentSeverity === "info" ? {
51693
+ bg: "rgba(59, 130, 246, 0.12)",
51694
+ border: "rgba(59, 130, 246, 0.35)",
51695
+ text: "#93c5fd",
51696
+ link: "#93c5fd"
51697
+ } : {
51698
+ bg: "rgba(245, 158, 11, 0.12)",
51699
+ border: "rgba(245, 158, 11, 0.35)",
51700
+ text: "#fcd34d",
51701
+ link: "#fcd34d"
51702
+ };
51703
+ const IncidentIcon = incidentSeverity === "info" ? Info : TriangleAlert;
51704
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
51705
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
51706
+ showBack ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51707
+ "button",
51708
+ {
51709
+ onClick: onBack,
51710
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51711
+ style: { color: components.header.buttonColor },
51712
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
51713
+ }
51714
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
51715
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
51716
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
51717
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51718
+ DialogTitle2,
51719
+ {
51720
+ className: "uf-text-center uf-text-base",
51721
+ style: {
51722
+ color: components.header.titleColor,
51723
+ fontFamily: fonts.medium
51724
+ },
51725
+ children: title
51726
+ }
51727
+ ),
51728
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51729
+ "div",
51730
+ {
51731
+ className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
51732
+ style: {
51733
+ backgroundColor: colors2.card,
51734
+ color: colors2.foregroundMuted,
51735
+ fontFamily: fonts.regular
51736
+ },
51737
+ children: badge.count
51738
+ }
51739
+ )
51740
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51638
51741
  DialogTitle2,
51639
51742
  {
51640
51743
  className: "uf-text-center uf-text-base",
@@ -51645,61 +51748,91 @@ function DepositHeader({
51645
51748
  children: title
51646
51749
  }
51647
51750
  ),
51648
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51751
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51649
51752
  "div",
51650
51753
  {
51651
- className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
51754
+ className: "uf-text-xs uf-mt-1",
51652
51755
  style: {
51653
- backgroundColor: colors2.card,
51654
51756
  color: colors2.foregroundMuted,
51655
51757
  fontFamily: fonts.regular
51656
51758
  },
51657
- children: badge.count
51759
+ children: subtitle
51658
51760
  }
51659
- )
51660
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51661
- DialogTitle2,
51662
- {
51663
- className: "uf-text-center uf-text-base",
51664
- style: {
51665
- color: components.header.titleColor,
51666
- fontFamily: fonts.medium
51667
- },
51668
- children: title
51669
- }
51670
- ),
51671
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51672
- "div",
51673
- {
51674
- className: "uf-text-xs uf-mt-1",
51675
- style: {
51676
- color: colors2.foregroundMuted,
51677
- fontFamily: fonts.regular
51678
- },
51679
- children: subtitle
51680
- }
51681
- ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.jsx)(
51682
- "div",
51761
+ ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.jsx)(
51762
+ "div",
51763
+ {
51764
+ className: "uf-text-xs uf-mt-1",
51765
+ style: {
51766
+ color: colors2.foregroundMuted,
51767
+ fontFamily: fonts.regular
51768
+ },
51769
+ children: formatBalanceDisplay(balance, projectName)
51770
+ }
51771
+ ) : null : null
51772
+ ] }),
51773
+ showClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51774
+ "button",
51683
51775
  {
51684
- className: "uf-text-xs uf-mt-1",
51685
- style: {
51686
- color: colors2.foregroundMuted,
51687
- fontFamily: fonts.regular
51688
- },
51689
- children: formatBalanceDisplay(balance, projectName)
51776
+ onClick: onClose,
51777
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51778
+ style: { color: components.header.buttonColor },
51779
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(X, { className: "uf-w-5 uf-h-5" })
51690
51780
  }
51691
- ) : null : null
51781
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
51692
51782
  ] }),
51693
- showClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51694
- "button",
51783
+ showIncident && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51784
+ "div",
51695
51785
  {
51696
- onClick: onClose,
51697
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51698
- style: { color: components.header.buttonColor },
51699
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(X, { className: "uf-w-5 uf-h-5" })
51786
+ className: "uf-rounded-lg uf-px-3 uf-py-2.5 uf-mb-4",
51787
+ style: {
51788
+ backgroundColor: incidentStyles.bg,
51789
+ border: `1px solid ${incidentStyles.border}`
51790
+ },
51791
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-start uf-gap-2.5", children: [
51792
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51793
+ IncidentIcon,
51794
+ {
51795
+ className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
51796
+ style: { color: incidentStyles.text }
51797
+ }
51798
+ ),
51799
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-min-w-0 uf-flex-1", children: [
51800
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51801
+ "span",
51802
+ {
51803
+ className: "uf-text-[11px] uf-leading-none uf-px-1.5 uf-py-1 uf-rounded-md",
51804
+ style: {
51805
+ color: incidentStyles.text,
51806
+ border: `1px solid ${incidentStyles.border}`,
51807
+ fontFamily: fonts.medium
51808
+ },
51809
+ children: incidentSeverityLabel
51810
+ }
51811
+ ) }),
51812
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51813
+ "div",
51814
+ {
51815
+ className: "uf-space-y-1",
51816
+ style: { color: incidentStyles.text, fontFamily: fonts.regular },
51817
+ children: incidentMessages.map((message, index2) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "uf-text-xs uf-leading-relaxed", children: message }, `${message}-${index2}`))
51818
+ }
51819
+ ),
51820
+ incident.statusPageUrl && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51821
+ "a",
51822
+ {
51823
+ href: incident.statusPageUrl,
51824
+ target: "_blank",
51825
+ rel: "noreferrer",
51826
+ className: "uf-inline-block uf-mt-1.5 uf-text-xs uf-underline uf-underline-offset-2",
51827
+ style: { color: incidentStyles.link, fontFamily: fonts.medium },
51828
+ children: "View status"
51829
+ }
51830
+ )
51831
+ ] })
51832
+ ] })
51700
51833
  }
51701
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
51702
- ] }) });
51834
+ )
51835
+ ] });
51703
51836
  }
51704
51837
  function CurrencyListItem({ currency, isSelected, onSelect }) {
51705
51838
  const { colors: colors2, fonts, components } = useTheme();
@@ -52019,7 +52152,8 @@ var en_default2 = {
52019
52152
  },
52020
52153
  stripeLink: {
52021
52154
  title: "Pay with Link",
52022
- subtitle: "Buy with card or bank"
52155
+ subtitle: "Buy with card or bank",
52156
+ unavailableInRegionMessage: "Pay with Link is currently unavailable in your region."
52023
52157
  },
52024
52158
  browserWallet: {
52025
52159
  title: "Connect Wallet",
@@ -58326,7 +58460,7 @@ function AppleLogo({ className, style }) {
58326
58460
  }
58327
58461
  );
58328
58462
  }
58329
- function ApplePayButton({ onClick, title, subtitle }) {
58463
+ function ApplePayButton({ onClick, title, subtitle, iconUrl }) {
58330
58464
  const { colors: colors2, fonts, components } = useTheme();
58331
58465
  const [isHovered, setIsHovered] = React142.useState(false);
58332
58466
  const [isTouchDevice, setIsTouchDevice] = React142.useState(false);
@@ -58348,7 +58482,14 @@ function ApplePayButton({ onClick, title, subtitle }) {
58348
58482
  },
58349
58483
  children: [
58350
58484
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
58351
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) }),
58485
+ /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsx)("img", { src: iconUrl, alt: "Apple Pay", width: 36, height: 36, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
58486
+ "div",
58487
+ {
58488
+ className: "uf-w-9 uf-h-9 uf-rounded-lg uf-flex uf-items-center uf-justify-center",
58489
+ style: { backgroundColor: "#000" },
58490
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: "#fff" } })
58491
+ }
58492
+ ) }),
58352
58493
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uf-text-left", children: [
58353
58494
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
58354
58495
  "div",
@@ -58564,13 +58705,6 @@ function solanaCandidate(provider, type, name, icon) {
58564
58705
  if (provider.isConnected && provider.publicKey) {
58565
58706
  return { type, name, address: provider.publicKey.toString(), icon };
58566
58707
  }
58567
- try {
58568
- const resp = await provider.connect({ onlyIfTrusted: true });
58569
- if (resp.publicKey) {
58570
- return { type, name, address: resp.publicKey.toString(), icon };
58571
- }
58572
- } catch {
58573
- }
58574
58708
  return null;
58575
58709
  }
58576
58710
  };
@@ -58794,6 +58928,178 @@ async function disconnectInjectedBrowserWallet(wallet) {
58794
58928
  collectEthereumProvidersForDisconnect(window)
58795
58929
  );
58796
58930
  }
58931
+ var STORED_TYPE_TO_EIP6963_WALLET_ID = {
58932
+ metamask: "metamask",
58933
+ "phantom-ethereum": "phantom",
58934
+ coinbase: "coinbase",
58935
+ trust: "trust",
58936
+ rainbow: "rainbow",
58937
+ rabby: "rabby",
58938
+ okx: "okx"
58939
+ };
58940
+ var EIP6963_WALLET_ID_TO_INFO = {
58941
+ metamask: { walletType: "metamask", name: "MetaMask", icon: "metamask" },
58942
+ phantom: { walletType: "phantom-ethereum", name: "Phantom", icon: "phantom" },
58943
+ coinbase: { walletType: "coinbase", name: "Coinbase Wallet", icon: "coinbase" },
58944
+ trust: { walletType: "trust", name: "Trust Wallet", icon: "trust" },
58945
+ rainbow: { walletType: "rainbow", name: "Rainbow", icon: "rainbow" },
58946
+ rabby: { walletType: "rabby", name: "Rabby", icon: "rabby" },
58947
+ okx: { walletType: "okx", name: "OKX Wallet", icon: "okx" }
58948
+ };
58949
+ var WALLET_ID_TO_WALLET_TYPE = {
58950
+ phantom: "phantom-ethereum",
58951
+ coinbase: "coinbase",
58952
+ trust: "trust",
58953
+ rainbow: "rainbow",
58954
+ rabby: "rabby",
58955
+ okx: "okx",
58956
+ metamask: "metamask"
58957
+ };
58958
+ var WALLET_TYPE_TO_WALLET_ID = {
58959
+ "phantom-ethereum": "phantom",
58960
+ coinbase: "coinbase",
58961
+ trust: "trust",
58962
+ okx: "okx",
58963
+ rainbow: "rainbow",
58964
+ rabby: "rabby",
58965
+ metamask: "metamask"
58966
+ };
58967
+ function isWalletType(value) {
58968
+ 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";
58969
+ }
58970
+ function walletIdToWalletType(walletId) {
58971
+ return WALLET_ID_TO_WALLET_TYPE[walletId] || "metamask";
58972
+ }
58973
+ function walletTypeToWalletId(walletType) {
58974
+ return WALLET_TYPE_TO_WALLET_ID[walletType] || walletType;
58975
+ }
58976
+ function getLegacyEvmProviders(win) {
58977
+ if (!win) return {};
58978
+ const anyWin = win;
58979
+ return {
58980
+ ethereum: anyWin.ethereum,
58981
+ phantomEthereum: anyWin.phantom?.ethereum,
58982
+ coinbaseEthereum: anyWin.coinbaseWalletExtension,
58983
+ trustEthereum: anyWin.trustwallet?.ethereum,
58984
+ okxEthereum: anyWin.okxwallet
58985
+ };
58986
+ }
58987
+ function getInjectedSolanaProviders(win) {
58988
+ if (!win) return {};
58989
+ const anyWin = win;
58990
+ return {
58991
+ phantomSolana: anyWin.phantom?.solana,
58992
+ solflare: anyWin.solflare,
58993
+ backpack: anyWin.backpack,
58994
+ glow: anyWin.glow,
58995
+ coinbaseSolana: anyWin.coinbaseSolana || anyWin.coinbaseWalletExtension?.solana,
58996
+ trustSolana: anyWin.trustwallet?.solana
58997
+ };
58998
+ }
58999
+ function describeEip6963Provider(wp) {
59000
+ const mapped = EIP6963_WALLET_ID_TO_INFO[wp.walletId];
59001
+ return {
59002
+ provider: wp.provider,
59003
+ walletType: mapped?.walletType ?? "metamask",
59004
+ name: mapped?.name ?? wp.info.name,
59005
+ icon: mapped?.icon ?? wp.info.icon
59006
+ };
59007
+ }
59008
+ function resolveQuickConnectEvmProvider(win) {
59009
+ const eip6963Providers = getEip6963Providers();
59010
+ if (eip6963Providers.length > 0) {
59011
+ const stored = getStoredWalletState();
59012
+ const preferredWalletId = stored?.walletType && isWalletType(stored.walletType) ? STORED_TYPE_TO_EIP6963_WALLET_ID[stored.walletType] : void 0;
59013
+ if (preferredWalletId) {
59014
+ const preferred = findProviderByWalletId(preferredWalletId);
59015
+ if (preferred) return describeEip6963Provider(preferred);
59016
+ }
59017
+ if (eip6963Providers.length === 1) {
59018
+ return describeEip6963Provider(eip6963Providers[0]);
59019
+ }
59020
+ return void 0;
59021
+ }
59022
+ const anyWin = win;
59023
+ const legacy = anyWin.phantom?.ethereum || anyWin.ethereum;
59024
+ if (!legacy) return void 0;
59025
+ const isPhantom = legacy.isPhantom;
59026
+ return {
59027
+ provider: legacy,
59028
+ walletType: isPhantom ? "phantom-ethereum" : "metamask",
59029
+ name: isPhantom ? "Phantom" : "MetaMask",
59030
+ icon: isPhantom ? "phantom" : "metamask"
59031
+ };
59032
+ }
59033
+ function resolveSolanaPublicKey(provider, response) {
59034
+ if (response?.publicKey) return { publicKey: response.publicKey };
59035
+ if (provider.publicKey) return { publicKey: provider.publicKey };
59036
+ return null;
59037
+ }
59038
+ function isUserRejectedSolanaConnectError(error) {
59039
+ if (!error || typeof error !== "object") return false;
59040
+ const maybeCode = "code" in error ? error.code : void 0;
59041
+ if (maybeCode === 4001) return true;
59042
+ const msg = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
59043
+ return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("rejected the request") || msg.includes("declined");
59044
+ }
59045
+ function isSolanaConnectTimeoutError(error) {
59046
+ return error instanceof Error && error.message.toLowerCase().includes("did not respond to the connection request");
59047
+ }
59048
+ async function connectSolanaProviderWithRecovery(provider, walletId, walletName) {
59049
+ if (provider.isConnected && provider.publicKey) {
59050
+ return { publicKey: provider.publicKey };
59051
+ }
59052
+ const connectOnce = () => provider.connect(walletId === "solflare" ? { onlyIfTrusted: false } : void 0);
59053
+ const withTimeout = async (ms = 2e4) => await Promise.race([
59054
+ connectOnce(),
59055
+ new Promise(
59056
+ (resolve, reject) => setTimeout(() => {
59057
+ const connected = resolveSolanaPublicKey(provider);
59058
+ if (connected) {
59059
+ resolve(connected);
59060
+ return;
59061
+ }
59062
+ reject(
59063
+ new Error(
59064
+ `${walletName} did not respond to the connection request. Please unlock the wallet and try again.`
59065
+ )
59066
+ );
59067
+ }, ms)
59068
+ )
59069
+ ]);
59070
+ if (walletId === "solflare") {
59071
+ await provider.disconnect?.().catch(() => {
59072
+ });
59073
+ }
59074
+ const connectAndResolve = async () => {
59075
+ try {
59076
+ const response = await withTimeout();
59077
+ const resolved = resolveSolanaPublicKey(provider, response);
59078
+ if (resolved) return resolved;
59079
+ await new Promise((resolve) => setTimeout(resolve, 120));
59080
+ const delayedResolved = resolveSolanaPublicKey(provider);
59081
+ if (delayedResolved) return delayedResolved;
59082
+ throw new Error(`${walletName} connected but did not expose a public key.`);
59083
+ } catch (error) {
59084
+ const connected = resolveSolanaPublicKey(provider);
59085
+ if (connected) return connected;
59086
+ throw error;
59087
+ }
59088
+ };
59089
+ try {
59090
+ return await connectAndResolve();
59091
+ } catch (err) {
59092
+ if (isUserRejectedSolanaConnectError(err)) throw err;
59093
+ if (isSolanaConnectTimeoutError(err)) throw err;
59094
+ if (walletId === "solflare") {
59095
+ await provider.disconnect?.().catch(() => {
59096
+ });
59097
+ await new Promise((resolve) => setTimeout(resolve, 150));
59098
+ return await connectAndResolve();
59099
+ }
59100
+ throw err;
59101
+ }
59102
+ }
58797
59103
  function MetamaskIcon({ size: size4 = 24, className, variant = "color" }) {
58798
59104
  const id = React172.useId();
58799
59105
  if (variant === "light" || variant === "dark") {
@@ -60653,21 +60959,19 @@ function BrowserWalletButton({
60653
60959
  }
60654
60960
  }
60655
60961
  if (!chainType || chainType === "ethereum") {
60656
- const ethProvider = window.phantom?.ethereum || window.ethereum;
60657
- if (ethProvider) {
60658
- const accounts = await ethProvider.request({
60962
+ const resolved = resolveQuickConnectEvmProvider(window);
60963
+ if (resolved) {
60964
+ const accounts = await resolved.provider.request({
60659
60965
  method: "eth_requestAccounts"
60660
60966
  });
60661
60967
  if (accounts && accounts.length > 0) {
60662
60968
  setUserDisconnectedWallet(false);
60663
- const isPhantom = ethProvider.isPhantom;
60664
- const walletType = isPhantom ? "phantom-ethereum" : "metamask";
60665
- setStoredWalletState(walletType);
60969
+ setStoredWalletState(resolved.walletType);
60666
60970
  setWallet({
60667
- type: walletType,
60668
- name: isPhantom ? "Phantom" : "MetaMask",
60971
+ type: resolved.walletType,
60972
+ name: resolved.name,
60669
60973
  address: accounts[0],
60670
- icon: isPhantom ? "phantom" : "metamask"
60974
+ icon: resolved.icon
60671
60975
  });
60672
60976
  }
60673
60977
  }
@@ -60701,7 +61005,10 @@ function BrowserWalletButton({
60701
61005
  if (isLoading) {
60702
61006
  return null;
60703
61007
  }
60704
- 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);
61008
+ const eip6963EvmProviderCount = getEip6963Providers().length;
61009
+ const legacyEvmProviders = getLegacyEvmProviders(window);
61010
+ const hasLegacyEvmProvider = eip6963EvmProviderCount === 0 && !!(legacyEvmProviders.ethereum || legacyEvmProviders.phantomEthereum || legacyEvmProviders.coinbaseEthereum || legacyEvmProviders.trustEthereum || legacyEvmProviders.okxEthereum);
61011
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && eip6963EvmProviderCount > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && hasLegacyEvmProvider;
60705
61012
  if (!onConnectClick && !wallet && !hasWalletExtension) {
60706
61013
  return null;
60707
61014
  }
@@ -60711,11 +61018,25 @@ function BrowserWalletButton({
60711
61018
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
60712
61019
  };
60713
61020
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
61021
+ const isImageIcon = !!wallet && (wallet.icon.startsWith("data:") || wallet.icon.startsWith("http"));
60714
61022
  const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React292.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
60715
61023
  size: 36,
60716
61024
  className: "uf-rounded-lg",
60717
61025
  variant: "color"
60718
- }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
61026
+ }) : isImageIcon ? (
61027
+ // Wallet announced via EIP-6963 with no internal icon component: render its
61028
+ // own advertised icon (`info.icon`) rather than a generic placeholder.
61029
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
61030
+ "img",
61031
+ {
61032
+ src: wallet.icon,
61033
+ alt: wallet.name,
61034
+ width: 36,
61035
+ height: 36,
61036
+ className: "uf-rounded-lg uf-w-9 uf-h-9"
61037
+ }
61038
+ )
61039
+ ) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
60719
61040
  const titleSubtitleBlock = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "uf-text-left uf-min-w-0", children: [
60720
61041
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
60721
61042
  "div",
@@ -66673,6 +66994,24 @@ function useExchanges({
66673
66994
  });
66674
66995
  return { exchanges, isLoading };
66675
66996
  }
66997
+ function usePublicIncident({
66998
+ publishableKey,
66999
+ enabled = true
67000
+ }) {
67001
+ const {
67002
+ data: incident,
67003
+ isLoading,
67004
+ error
67005
+ } = useQuery({
67006
+ queryKey: ["unifold", "publicIncident", publishableKey],
67007
+ queryFn: () => getPublicIncident(publishableKey),
67008
+ enabled,
67009
+ staleTime: 1e3 * 30,
67010
+ refetchInterval: 1e3 * 30,
67011
+ refetchOnWindowFocus: true
67012
+ });
67013
+ return { incident, isLoading, error: error ?? null };
67014
+ }
66676
67015
  function useApplePayProviders({
66677
67016
  publishableKey,
66678
67017
  enabled = true
@@ -66768,6 +67107,7 @@ function useAddressValidation({
66768
67107
  return {
66769
67108
  isValid: null,
66770
67109
  failureCode: null,
67110
+ message: null,
66771
67111
  metadata: null,
66772
67112
  isLoading: false,
66773
67113
  error: null
@@ -66776,6 +67116,7 @@ function useAddressValidation({
66776
67116
  return {
66777
67117
  isValid: data?.valid ?? null,
66778
67118
  failureCode: data?.failure_code ?? null,
67119
+ message: data?.message ?? null,
66779
67120
  metadata: data?.metadata ?? null,
66780
67121
  isLoading,
66781
67122
  error: error ?? null
@@ -67601,6 +67942,37 @@ function TokenSelectorSheet({
67601
67942
  var getChainKey = (chainId, chainType) => {
67602
67943
  return `${chainType}:${chainId}`;
67603
67944
  };
67945
+ function getStoredSelection(key) {
67946
+ if (typeof window === "undefined") return null;
67947
+ try {
67948
+ const raw = localStorage.getItem(key);
67949
+ if (!raw) return null;
67950
+ const parsed = JSON.parse(raw);
67951
+ if (parsed && typeof parsed.symbol === "string" && typeof parsed.chainType === "string" && typeof parsed.chainId === "string") {
67952
+ return parsed;
67953
+ }
67954
+ } catch {
67955
+ }
67956
+ return null;
67957
+ }
67958
+ function saveStoredSelection(key, symbol, chainType, chainId) {
67959
+ if (typeof window === "undefined") return;
67960
+ try {
67961
+ localStorage.setItem(key, JSON.stringify({ symbol, chainType, chainId }));
67962
+ } catch {
67963
+ }
67964
+ }
67965
+ function resolveFromStorage(tokens, stored) {
67966
+ for (const t13 of tokens) {
67967
+ if (t13.symbol !== stored.symbol) continue;
67968
+ const matchedChain = t13.chains.find(
67969
+ (c) => c.chain_type === stored.chainType && c.chain_id === stored.chainId
67970
+ );
67971
+ if (matchedChain) return { token: t13, chain: matchedChain };
67972
+ if (t13.chains.length > 0) return { token: t13, chain: t13.chains[0] };
67973
+ }
67974
+ return null;
67975
+ }
67604
67976
  function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
67605
67977
  if (!tokens.length) return null;
67606
67978
  let selectedToken;
@@ -67650,27 +68022,73 @@ function useDefaultToken({
67650
68022
  defaultChainType,
67651
68023
  defaultChainId,
67652
68024
  defaultTokenAddress,
67653
- defaultSymbol
68025
+ defaultSymbol,
68026
+ storageKey: storageKey2
67654
68027
  }) {
67655
- const [token, setToken] = (0, import_react28.useState)(null);
67656
- const [chain, setChain] = (0, import_react28.useState)(null);
68028
+ const [token, setTokenState] = (0, import_react28.useState)(null);
68029
+ const [chain, setChainState] = (0, import_react28.useState)(null);
67657
68030
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react28.useState)(false);
67658
68031
  const appliedDefaultsRef = (0, import_react28.useRef)("");
68032
+ const tokenRef = (0, import_react28.useRef)(null);
68033
+ const chainRef = (0, import_react28.useRef)(null);
68034
+ tokenRef.current = token;
68035
+ chainRef.current = chain;
68036
+ const setToken = (0, import_react28.useCallback)(
68037
+ (newToken) => {
68038
+ tokenRef.current = newToken;
68039
+ setTokenState(newToken);
68040
+ if (storageKey2 && chainRef.current) {
68041
+ const [chainType, chainId] = chainRef.current.split(":");
68042
+ saveStoredSelection(storageKey2, newToken, chainType, chainId);
68043
+ }
68044
+ },
68045
+ [storageKey2]
68046
+ );
68047
+ const setChain = (0, import_react28.useCallback)(
68048
+ (newChain) => {
68049
+ chainRef.current = newChain;
68050
+ setChainState(newChain);
68051
+ if (storageKey2 && tokenRef.current) {
68052
+ const [chainType, chainId] = newChain.split(":");
68053
+ saveStoredSelection(storageKey2, tokenRef.current, chainType, chainId);
68054
+ }
68055
+ },
68056
+ [storageKey2]
68057
+ );
67659
68058
  (0, import_react28.useEffect)(() => {
67660
68059
  if (!tokens.length) return;
67661
68060
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
67662
68061
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
67663
68062
  if (initialSelectionDone && !defaultsChanged) return;
67664
- const result = resolveToken(
67665
- tokens,
67666
- defaultChainType,
67667
- defaultChainId,
67668
- defaultTokenAddress,
67669
- defaultSymbol
67670
- );
68063
+ const hasExplicitDefaults = defaultTokenAddress && defaultChainType && defaultChainId || defaultSymbol && defaultChainType && defaultChainId;
68064
+ let result = null;
68065
+ if (hasExplicitDefaults) {
68066
+ result = resolveToken(
68067
+ tokens,
68068
+ defaultChainType,
68069
+ defaultChainId,
68070
+ defaultTokenAddress,
68071
+ defaultSymbol
68072
+ );
68073
+ if (result) {
68074
+ 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;
68075
+ if (!matched) {
68076
+ result = null;
68077
+ }
68078
+ }
68079
+ }
68080
+ if (!result && storageKey2) {
68081
+ const stored = getStoredSelection(storageKey2);
68082
+ if (stored) {
68083
+ result = resolveFromStorage(tokens, stored);
68084
+ }
68085
+ }
68086
+ if (!result) {
68087
+ result = resolveToken(tokens);
68088
+ }
67671
68089
  if (result) {
67672
- setToken(result.token.symbol);
67673
- setChain(getChainKey(result.chain.chain_id, result.chain.chain_type));
68090
+ setTokenState(result.token.symbol);
68091
+ setChainState(getChainKey(result.chain.chain_id, result.chain.chain_type));
67674
68092
  appliedDefaultsRef.current = defaultsKey;
67675
68093
  setInitialSelectionDone(true);
67676
68094
  }
@@ -67680,7 +68098,8 @@ function useDefaultToken({
67680
68098
  defaultSymbol,
67681
68099
  defaultChainType,
67682
68100
  defaultChainId,
67683
- initialSelectionDone
68101
+ initialSelectionDone,
68102
+ storageKey2
67684
68103
  ]);
67685
68104
  (0, import_react28.useEffect)(() => {
67686
68105
  if (!tokens.length || !token) return;
@@ -67691,11 +68110,12 @@ function useDefaultToken({
67691
68110
  });
67692
68111
  if (!isChainAvailable) {
67693
68112
  const firstChain = currentToken.chains[0];
67694
- setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
68113
+ setChainState(getChainKey(firstChain.chain_id, firstChain.chain_type));
67695
68114
  }
67696
68115
  }, [token, tokens, chain]);
67697
68116
  return { token, chain, setToken, setChain, initialSelectionDone };
67698
68117
  }
68118
+ var STORAGE_KEY2 = "unifold_last_deposit_from_token";
67699
68119
  function useDefaultSourceToken({
67700
68120
  supportedTokens,
67701
68121
  defaultSourceChainType,
@@ -67708,7 +68128,8 @@ function useDefaultSourceToken({
67708
68128
  defaultChainType: defaultSourceChainType,
67709
68129
  defaultChainId: defaultSourceChainId,
67710
68130
  defaultTokenAddress: defaultSourceTokenAddress,
67711
- defaultSymbol: defaultSourceSymbol
68131
+ defaultSymbol: defaultSourceSymbol,
68132
+ storageKey: STORAGE_KEY2
67712
68133
  });
67713
68134
  }
67714
68135
  function DepositFooterLinks({ onGlossaryClick, leftElement }) {
@@ -70720,33 +71141,11 @@ function balancesRepresentSameToken(a, b) {
70720
71141
  if (!tokenA || !tokenB) return false;
70721
71142
  return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
70722
71143
  }
70723
- function getSolanaProviders() {
70724
- if (typeof window === "undefined") return {};
70725
- const win = window;
70726
- return {
70727
- phantomSolana: win.phantom?.solana,
70728
- solflare: win.solflare,
70729
- backpack: win.backpack,
70730
- glow: win.glow,
70731
- coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
70732
- };
70733
- }
70734
- function getLegacyEvmProviders() {
70735
- if (typeof window === "undefined") return {};
70736
- const win = window;
70737
- return {
70738
- ethereum: win.ethereum,
70739
- phantomEthereum: win.phantom?.ethereum,
70740
- coinbaseEthereum: win.coinbaseWalletExtension,
70741
- trustEthereum: win.trustwallet?.ethereum,
70742
- okxEthereum: win.okxwallet
70743
- };
70744
- }
70745
71144
  function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
70746
- const solProviders = getSolanaProviders();
70747
- const legacyEvm = getLegacyEvmProviders();
70748
- const eip6963List = getEip6963Providers();
70749
71145
  const win = typeof window !== "undefined" ? window : null;
71146
+ const solProviders = getInjectedSolanaProviders(win);
71147
+ const legacyEvm = getLegacyEvmProviders(win);
71148
+ const eip6963List = getEip6963Providers();
70750
71149
  const hasEip6963 = (walletId) => eip6963List.some((d) => {
70751
71150
  const rdns = d.info?.rdns || "";
70752
71151
  switch (walletId) {
@@ -71015,10 +71414,13 @@ function WalletConnect({
71015
71414
  };
71016
71415
  const openMobileWalletBrowse = async (wallet, depositAddresses) => {
71017
71416
  try {
71417
+ const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
71418
+ const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
71018
71419
  const res = await getWalletMobileDeepLink(
71019
71420
  wallet.id,
71020
71421
  depositAddresses,
71021
- publishableKey
71422
+ publishableKey,
71423
+ forwardedAmountUsd
71022
71424
  );
71023
71425
  if (res.deeplink) {
71024
71426
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
@@ -71107,7 +71509,7 @@ function WalletConnect({
71107
71509
  const eip6963Match = findProviderByWalletId(wallet.id);
71108
71510
  let provider = eip6963Match?.provider;
71109
71511
  if (!provider) {
71110
- const legacyEvm = getLegacyEvmProviders();
71512
+ const legacyEvm = getLegacyEvmProviders(win);
71111
71513
  switch (wallet.id) {
71112
71514
  case "metamask":
71113
71515
  if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom)
@@ -71139,16 +71541,7 @@ function WalletConnect({
71139
71541
  const accounts = await provider.request({ method: "eth_requestAccounts" });
71140
71542
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
71141
71543
  setUserDisconnectedWallet(false);
71142
- const walletIdToType = {
71143
- phantom: "phantom-ethereum",
71144
- coinbase: "coinbase",
71145
- trust: "trust",
71146
- rainbow: "rainbow",
71147
- rabby: "rabby",
71148
- okx: "okx",
71149
- metamask: "metamask"
71150
- };
71151
- const walletType = walletIdToType[wallet.id] || "metamask";
71544
+ const walletType = walletIdToWalletType(wallet.id);
71152
71545
  setStoredWalletState(walletType);
71153
71546
  connectedInfo = {
71154
71547
  type: walletType,
@@ -71157,7 +71550,7 @@ function WalletConnect({
71157
71550
  icon: wallet.id
71158
71551
  };
71159
71552
  } else {
71160
- const solProviders = getSolanaProviders();
71553
+ const solProviders = getInjectedSolanaProviders(win);
71161
71554
  let provider;
71162
71555
  switch (wallet.id) {
71163
71556
  case "phantom":
@@ -71176,11 +71569,11 @@ function WalletConnect({
71176
71569
  provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
71177
71570
  break;
71178
71571
  case "trust":
71179
- provider = win?.trustwallet?.solana;
71572
+ provider = solProviders.trustSolana;
71180
71573
  break;
71181
71574
  }
71182
71575
  if (!provider) throw new Error(`${wallet.name} Solana wallet not found.`);
71183
- const response = await provider.connect();
71576
+ const response = await connectSolanaProviderWithRecovery(provider, wallet.id, wallet.name);
71184
71577
  setUserDisconnectedWallet(false);
71185
71578
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
71186
71579
  setStoredWalletState(walletType);
@@ -71531,16 +71924,7 @@ function WalletConnect({
71531
71924
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
71532
71925
  };
71533
71926
  const resolveEvmProvider = () => {
71534
- const walletIdMap = {
71535
- "phantom-ethereum": "phantom",
71536
- coinbase: "coinbase",
71537
- trust: "trust",
71538
- okx: "okx",
71539
- rainbow: "rainbow",
71540
- rabby: "rabby",
71541
- metamask: "metamask"
71542
- };
71543
- const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
71927
+ const lookupId = walletTypeToWalletId(walletInfo.type);
71544
71928
  const eip6963Match = findProviderByWalletId(lookupId);
71545
71929
  let provider = eip6963Match?.provider;
71546
71930
  if (!provider) {
@@ -72269,6 +72653,7 @@ function DepositModal({
72269
72653
  applePayTitle = "Pay with Apple Pay",
72270
72654
  applePaySubTitle = "Instant",
72271
72655
  enableBankTransfer,
72656
+ enableIncidentBanner = false,
72272
72657
  // No default: left undefined so the backend `stripe_link.enabled` can govern
72273
72658
  // (via the `??` chain in showStripeLink) once a dashboard toggle exists.
72274
72659
  enableStripeLink,
@@ -72314,7 +72699,7 @@ function DepositModal({
72314
72699
  const s = initialScreen ?? "main";
72315
72700
  if (s === "tracker" && hideDepositTracker === true) return "main";
72316
72701
  if (s === "cashapp" && enableCashApp === false) return "main";
72317
- if (s === "stripe_link" && !enableStripeLink) return "main";
72702
+ if (s === "stripe_link" && enableStripeLink === false) return "main";
72318
72703
  if (s === "apple_pay" && enableApplePay === false) return "main";
72319
72704
  if (s === "card" && enableFiatOnramp === false) return "main";
72320
72705
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
@@ -72373,6 +72758,16 @@ function DepositModal({
72373
72758
  const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
72374
72759
  const showBankTransfer = enableBankTransfer ?? projectConfig?.bank_transfer?.enabled ?? true;
72375
72760
  const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
72761
+ const { incident: publicIncident } = usePublicIncident({
72762
+ publishableKey,
72763
+ enabled: open && enableIncidentBanner
72764
+ });
72765
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
72766
+ enabled: true,
72767
+ messages: publicIncident.messages,
72768
+ severity: publicIncident.severity,
72769
+ statusPageUrl: publicIncident.status_page_url
72770
+ } : void 0;
72376
72771
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react3.useState)([]);
72377
72772
  (0, import_react3.useEffect)(() => {
72378
72773
  if (!showConnectExchange || !open) return;
@@ -72439,7 +72834,11 @@ function DepositModal({
72439
72834
  setConnectedExchange((prev) => prev ? { ...prev, iconUrl } : prev);
72440
72835
  }
72441
72836
  }, [integrationExchanges, connectedExchange]);
72442
- const { data: depositAddressResponse, isLoading: walletsLoading } = useDepositAddress({
72837
+ const {
72838
+ data: depositAddressResponse,
72839
+ isLoading: walletsLoading,
72840
+ error: walletsError
72841
+ } = useDepositAddress({
72443
72842
  userId,
72444
72843
  publishableKey,
72445
72844
  recipientAddress,
@@ -72572,6 +72971,7 @@ function DepositModal({
72572
72971
  const {
72573
72972
  isValid: isAddressValid,
72574
72973
  failureCode: addressFailureCode,
72974
+ message: addressFailureMessage,
72575
72975
  metadata: addressFailureMetadata,
72576
72976
  isLoading: isAddressValidationLoading
72577
72977
  } = useAddressValidation({
@@ -72585,17 +72985,31 @@ function DepositModal({
72585
72985
  refetchOnMount: "always"
72586
72986
  });
72587
72987
  const addressValidationMessages = i18n2.transferCrypto.addressValidation;
72588
- const getAddressValidationErrorMessage = (code, metadata) => {
72988
+ const getAddressValidationErrorMessage = (message, code, metadata) => {
72989
+ if (message && message.trim().length > 0) return message;
72589
72990
  if (!code) return addressValidationMessages.defaultError;
72590
72991
  const errors = addressValidationMessages.errors;
72591
72992
  const template = errors[code] ?? addressValidationMessages.defaultError;
72592
72993
  return interpolate(template, metadata);
72593
72994
  };
72995
+ const walletsRecipientError = isDepositAddressValidationError(walletsError) ? walletsError.message : null;
72996
+ const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
72997
+ const recipientInvalidMessage = getAddressValidationErrorMessage(
72998
+ addressFailureMessage ?? walletsRecipientError,
72999
+ addressFailureCode,
73000
+ addressFailureMetadata
73001
+ );
72594
73002
  const openingScreen = effectiveInitialScreen;
72595
73003
  const sessionOpenedFromMenu = openingScreen === "main";
72596
73004
  const standaloneNeedsDepositPrereq = openingScreen !== "main" && (view === "transfer" || view === "card");
72597
73005
  let depositPrerequisiteBody;
72598
- if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
73006
+ if (isRecipientAddressInvalid) {
73007
+ depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
73008
+ /* @__PURE__ */ (0, import_jsx_runtime82.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_runtime82.jsx)(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
73009
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
73010
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: recipientInvalidMessage })
73011
+ ] });
73012
+ } else if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
72599
73013
  // fetch — block the menu on it so the row never flashes in or out.
72600
73014
  showBankTransfer && bankTransferProvidersLoading || // Same for Apple Pay: row visibility depends on the geo/platform-gated
72601
73015
  // providers fetch — block the menu so the row doesn't pop in or out.
@@ -72617,12 +73031,6 @@ function DepositModal({
72617
73031
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
72618
73032
  /* @__PURE__ */ (0, import_jsx_runtime82.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." })
72619
73033
  ] });
72620
- } else if (isAddressValid === false) {
72621
- depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
72622
- /* @__PURE__ */ (0, import_jsx_runtime82.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_runtime82.jsx)(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
72623
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
72624
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(addressFailureCode, addressFailureMetadata) })
72625
- ] });
72626
73034
  } else {
72627
73035
  depositPrerequisiteBody = null;
72628
73036
  }
@@ -73116,6 +73524,7 @@ function DepositModal({
73116
73524
  title: modalTitle || "Deposit",
73117
73525
  showClose: !hideOverlay,
73118
73526
  onClose: handleClose,
73527
+ incident: activeIncident,
73119
73528
  showBalance: showBalanceHeader,
73120
73529
  balanceAddress: recipientAddress,
73121
73530
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -73135,6 +73544,7 @@ function DepositModal({
73135
73544
  showBack: showBackTransfer,
73136
73545
  onBack: handleBack,
73137
73546
  onClose: handleClose,
73547
+ incident: activeIncident,
73138
73548
  showBalance: showBalanceHeader,
73139
73549
  balanceAddress: recipientAddress,
73140
73550
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -73195,7 +73605,8 @@ function DepositModal({
73195
73605
  title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
73196
73606
  showBack: showBackTracker,
73197
73607
  onBack: handleBack,
73198
- onClose: handleClose
73608
+ onClose: handleClose,
73609
+ incident: activeIncident
73199
73610
  }
73200
73611
  ),
73201
73612
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73227,6 +73638,7 @@ function DepositModal({
73227
73638
  showBack: showBackCard,
73228
73639
  onBack: handleBack,
73229
73640
  onClose: handleClose,
73641
+ incident: activeIncident,
73230
73642
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
73231
73643
  showBalance: showBalanceHeader,
73232
73644
  balanceAddress: recipientAddress,
@@ -73276,7 +73688,8 @@ function DepositModal({
73276
73688
  title: payWithExchangeTitle,
73277
73689
  showBack: exchangeView === "pending" || sessionOpenedFromMenu,
73278
73690
  onBack: handleBack,
73279
- onClose: handleClose
73691
+ onClose: handleClose,
73692
+ incident: activeIncident
73280
73693
  }
73281
73694
  ),
73282
73695
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73390,7 +73803,8 @@ function DepositModal({
73390
73803
  title: t8.bankTransfer.title,
73391
73804
  showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
73392
73805
  onBack: handleBack,
73393
- onClose: handleClose
73806
+ onClose: handleClose,
73807
+ incident: activeIncident
73394
73808
  }
73395
73809
  ),
73396
73810
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73424,26 +73838,24 @@ function DepositModal({
73424
73838
  title: "Deposit with Link",
73425
73839
  showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
73426
73840
  onBack: handleBack,
73841
+ incident: activeIncident,
73427
73842
  showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
73428
73843
  onClose: handleClose
73429
73844
  }
73430
73845
  ),
73431
73846
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
73432
73847
  isLoadingIp ? (
73433
- // Hold the geo decision until IP resolves so we don't mount
73434
- // PayWithStripeLink (which kicks off config/OAuth work) for a
73435
- // deep-link user who turns out to be outside the US.
73848
+ // Wait for location so the first config fetch is region-aware.
73436
73849
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(SkeletonButton, { variant: "with-icons" })
73437
73850
  ) : !showStripeLink ? (
73438
- // Stripe Link's crypto on-ramp is US-only. On a direct open
73439
- // (initialScreen="stripe_link") the row isn't in a menu to
73440
- // fall back to, so show a geo-restriction screen rather than
73441
- // the Link UI.
73851
+ // Direct opens (initialScreen="stripe_link") have no menu row
73852
+ // to fall back to, so render an unavailable state when backend
73853
+ // config resolves Stripe Link disabled/hidden.
73442
73854
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
73443
73855
  GeoRestrictionScreen,
73444
73856
  {
73445
73857
  methodName: t8.stripeLink.title,
73446
- message: "Pay with Link is only available in the US."
73858
+ message: t8.stripeLink.unavailableInRegionMessage
73447
73859
  }
73448
73860
  )
73449
73861
  ) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
@@ -73476,7 +73888,8 @@ function DepositModal({
73476
73888
  title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
73477
73889
  showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
73478
73890
  onBack: handleBack,
73479
- onClose: handleClose
73891
+ onClose: handleClose,
73892
+ incident: activeIncident
73480
73893
  }
73481
73894
  ),
73482
73895
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73512,7 +73925,8 @@ function DepositModal({
73512
73925
  const handled = applePayHandleRef.current?.requestBack() ?? false;
73513
73926
  if (!handled) handleBack();
73514
73927
  },
73515
- onClose: handleClose
73928
+ onClose: handleClose,
73929
+ incident: activeIncident
73516
73930
  }
73517
73931
  ),
73518
73932
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73627,6 +74041,7 @@ function CheckoutModal({
73627
74041
  modalTitle,
73628
74042
  enableTransferCrypto,
73629
74043
  enableConnectWallet,
74044
+ enableIncidentBanner = false,
73630
74045
  defaultSourceChainType,
73631
74046
  defaultSourceChainId,
73632
74047
  defaultSourceTokenAddress,
@@ -73698,6 +74113,16 @@ function CheckoutModal({
73698
74113
  });
73699
74114
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
73700
74115
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
74116
+ const { incident: publicIncident } = usePublicIncident({
74117
+ publishableKey,
74118
+ enabled: open && enableIncidentBanner
74119
+ });
74120
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
74121
+ enabled: true,
74122
+ messages: publicIncident.messages,
74123
+ severity: publicIncident.severity,
74124
+ statusPageUrl: publicIncident.status_page_url
74125
+ } : void 0;
73701
74126
  (0, import_react35.useEffect)(() => {
73702
74127
  if (view === "transfer" && !showTransferCrypto) {
73703
74128
  setView("main");
@@ -73999,7 +74424,15 @@ function CheckoutModal({
73999
74424
  {
74000
74425
  className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
74001
74426
  children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
74002
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
74427
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
74428
+ DepositHeader,
74429
+ {
74430
+ title: modalTitle || "Checkout",
74431
+ showClose: true,
74432
+ onClose: handleClose,
74433
+ incident: activeIncident
74434
+ }
74435
+ ),
74003
74436
  /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
74004
74437
  piLoading ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-space-y-3", children: [
74005
74438
  /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
@@ -74097,7 +74530,8 @@ function CheckoutModal({
74097
74530
  title: modalTitle || "Checkout",
74098
74531
  showBack: true,
74099
74532
  onBack: handleBack,
74100
- onClose: handleClose
74533
+ onClose: handleClose,
74534
+ incident: activeIncident
74101
74535
  }
74102
74536
  ),
74103
74537
  /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -74267,6 +74701,7 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
74267
74701
  enabled
74268
74702
  });
74269
74703
  }
74704
+ var STORAGE_KEY3 = "unifold_last_withdraw_to_token";
74270
74705
  function useDefaultDestinationToken({
74271
74706
  destinationTokens,
74272
74707
  defaultDestinationChainType,
@@ -74279,7 +74714,8 @@ function useDefaultDestinationToken({
74279
74714
  defaultChainType: defaultDestinationChainType,
74280
74715
  defaultChainId: defaultDestinationChainId,
74281
74716
  defaultTokenAddress: defaultDestinationTokenAddress,
74282
- defaultSymbol: defaultDestinationSymbol
74717
+ defaultSymbol: defaultDestinationSymbol,
74718
+ storageKey: STORAGE_KEY3
74283
74719
  });
74284
74720
  }
74285
74721
  function useSourceTokenValidation(params) {
@@ -74953,6 +75389,9 @@ function WithdrawForm({
74953
75389
  if (isDebouncing || isVerifyingAddress) return null;
74954
75390
  if (verifyError) return t10.invalidAddress;
74955
75391
  if (addressVerification && !addressVerification.valid) {
75392
+ if (addressVerification.message && addressVerification.message.trim().length > 0) {
75393
+ return addressVerification.message;
75394
+ }
74956
75395
  if (addressVerification.failure_code === "account_not_found")
74957
75396
  return `Account not found on ${selectedChain?.chain_name}`;
74958
75397
  if (addressVerification.failure_code === "not_opted_in")
@@ -76209,6 +76648,7 @@ function UnifoldProvider2({
76209
76648
  const [isWithdrawOpen, setIsWithdrawOpen] = (0, import_react.useState)(false);
76210
76649
  const [withdrawConfig, setWithdrawConfig] = (0, import_react.useState)(null);
76211
76650
  const [resolvedTheme, setResolvedTheme] = import_react.default.useState("dark");
76651
+ const incidentBannerEnabled = config?.notifications?.incidentBanner;
76212
76652
  (0, import_react.useEffect)(() => {
76213
76653
  if (publishableKey) {
76214
76654
  setApiConfig({ publishableKey });
@@ -76506,6 +76946,7 @@ function UnifoldProvider2({
76506
76946
  publishableKey,
76507
76947
  enableTransferCrypto: config?.enableTransferCrypto,
76508
76948
  enableConnectWallet: config?.enableConnectWallet,
76949
+ enableIncidentBanner: incidentBannerEnabled,
76509
76950
  defaultSourceChainType: checkoutConfig.defaultSourceChainType,
76510
76951
  defaultSourceChainId: checkoutConfig.defaultSourceChainId,
76511
76952
  defaultSourceTokenAddress: checkoutConfig.defaultSourceTokenAddress,
@@ -76573,6 +77014,7 @@ function UnifoldProvider2({
76573
77014
  enableConnectExchange: config?.enableConnectExchange,
76574
77015
  enableCashApp: config?.enableCashApp,
76575
77016
  enableStripeLink: config?.enableStripeLink,
77017
+ enableIncidentBanner: incidentBannerEnabled,
76576
77018
  enableApplePay: config?.enableApplePay,
76577
77019
  applePayTitle: config?.applePayTitle,
76578
77020
  applePaySubTitle: config?.applePaySubTitle,