@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.js CHANGED
@@ -38413,7 +38413,10 @@ ${new this._window.XMLSerializer().serializeToString(e3)}`;
38413
38413
  })()));
38414
38414
  }
38415
38415
  });
38416
- var UnifoldContext = (0, import_react2.createContext)(null);
38416
+ var UNIFOLD_CONTEXT_KEY = /* @__PURE__ */ Symbol.for("unifold.react-provider.context");
38417
+ var globalRef = globalThis;
38418
+ var UnifoldContext = globalRef[UNIFOLD_CONTEXT_KEY] ?? (0, import_react2.createContext)(null);
38419
+ globalRef[UNIFOLD_CONTEXT_KEY] = UnifoldContext;
38417
38420
  var createQueryClient = () => new QueryClient({
38418
38421
  defaultOptions: {
38419
38422
  queries: {
@@ -43173,6 +43176,9 @@ var getDefaultConfig = () => {
43173
43176
  };
43174
43177
  };
43175
43178
  var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
43179
+ var __defProp22 = Object.defineProperty;
43180
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp22(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
43181
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
43176
43182
  function formatStablecoinAmount(baseUnits, decimals) {
43177
43183
  const raw = Number(baseUnits) / 10 ** decimals;
43178
43184
  const floored = Math.floor(raw * 100) / 100;
@@ -43263,6 +43269,16 @@ var ActionType = /* @__PURE__ */ ((ActionType2) => {
43263
43269
  ActionType2["Withdraw"] = "withdraw";
43264
43270
  return ActionType2;
43265
43271
  })(ActionType || {});
43272
+ var DepositAddressValidationError = class extends Error {
43273
+ constructor(message) {
43274
+ super(message);
43275
+ __publicField(this, "isDepositAddressValidationError", true);
43276
+ this.name = "DepositAddressValidationError";
43277
+ }
43278
+ };
43279
+ function isDepositAddressValidationError(error) {
43280
+ return error instanceof Error && error.isDepositAddressValidationError === true;
43281
+ }
43266
43282
  async function createDepositAddress(overrides, publishableKey) {
43267
43283
  if (!overrides?.external_user_id) {
43268
43284
  throw new Error("external_user_id is required");
@@ -43290,6 +43306,13 @@ async function createDepositAddress(overrides, publishableKey) {
43290
43306
  body: JSON.stringify(payload)
43291
43307
  });
43292
43308
  if (!response.ok) {
43309
+ if (response.status === 400) {
43310
+ const body = await response.json().catch(() => null);
43311
+ if (body?.error_type === "validation_error") {
43312
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
43313
+ throw new DepositAddressValidationError(firstError ?? "Invalid recipient address");
43314
+ }
43315
+ }
43293
43316
  throw new Error(`Failed to create EOA: ${response.statusText}`);
43294
43317
  }
43295
43318
  return response.json();
@@ -43628,6 +43651,21 @@ async function getProjectConfig(publishableKey, options2) {
43628
43651
  const data = await response.json();
43629
43652
  return data;
43630
43653
  }
43654
+ async function getPublicIncident(publishableKey) {
43655
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43656
+ validatePublishableKey(pk);
43657
+ const response = await fetch(`${API_BASE_URL}/v1/public/projects/incident`, {
43658
+ method: "GET",
43659
+ headers: {
43660
+ accept: "application/json",
43661
+ "x-publishable-key": pk
43662
+ }
43663
+ });
43664
+ if (!response.ok) {
43665
+ throw new Error(`Failed to fetch public incident: ${response.statusText}`);
43666
+ }
43667
+ return response.json();
43668
+ }
43631
43669
  async function getIpAddress() {
43632
43670
  const response = await fetch(`${API_BASE_URL}/v1/public/ip_address`, {
43633
43671
  method: "GET",
@@ -43683,7 +43721,7 @@ async function getExternalWallets(publishableKey) {
43683
43721
  const data = await response.json();
43684
43722
  return data;
43685
43723
  }
43686
- async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey) {
43724
+ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey, amountUsd) {
43687
43725
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43688
43726
  validatePublishableKey(pk);
43689
43727
  const response = await fetch(`${API_BASE_URL}/v1/public/external_wallets/mobile_deeplink`, {
@@ -43693,7 +43731,11 @@ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey)
43693
43731
  accept: "application/json",
43694
43732
  "x-publishable-key": pk
43695
43733
  },
43696
- body: JSON.stringify({ wallet, deposit_addresses: depositAddresses })
43734
+ body: JSON.stringify({
43735
+ wallet,
43736
+ deposit_addresses: depositAddresses,
43737
+ ...amountUsd ? { amount_usd: amountUsd } : {}
43738
+ })
43697
43739
  });
43698
43740
  if (!response.ok) {
43699
43741
  throw new Error(`Failed to generate wallet deep link: ${response.statusText}`);
@@ -43738,6 +43780,15 @@ async function verifyRecipientAddress(request, publishableKey) {
43738
43780
  body: JSON.stringify(request)
43739
43781
  });
43740
43782
  if (!response.ok) {
43783
+ const body = await response.json().catch(() => null);
43784
+ if (response.status === 400 && body?.error_type === "validation_error") {
43785
+ const firstError = Array.isArray(body.details?.errors) ? body.details?.errors[0] : void 0;
43786
+ return {
43787
+ valid: false,
43788
+ failure_code: "validation_error",
43789
+ message: firstError ?? "Invalid recipient address"
43790
+ };
43791
+ }
43741
43792
  throw new Error(`Failed to verify recipient address: ${response.statusText}`);
43742
43793
  }
43743
43794
  return response.json();
@@ -51329,7 +51380,13 @@ function useDepositAddress(params) {
51329
51380
  // 24 hours in cache
51330
51381
  refetchOnMount: false,
51331
51382
  refetchOnWindowFocus: false,
51332
- retry: 3,
51383
+ // Don't retry recipient-address validation errors — they're deterministic
51384
+ // (a 400 won't succeed on retry) and we want to surface the invalid-address
51385
+ // screen immediately rather than after 3 backoff attempts.
51386
+ retry: (failureCount, error) => {
51387
+ if (isDepositAddressValidationError(error)) return false;
51388
+ return failureCount < 3;
51389
+ },
51333
51390
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
51334
51391
  // 1s, 2s, 4s (max 10s)
51335
51392
  });
@@ -51537,7 +51594,8 @@ function DepositHeader({
51537
51594
  balanceChainId,
51538
51595
  balanceTokenAddress,
51539
51596
  projectName,
51540
- publishableKey
51597
+ publishableKey,
51598
+ incident
51541
51599
  }) {
51542
51600
  const { colors: colors2, fonts, components } = useTheme();
51543
51601
  const [balance, setBalance] = (0, import_react10.useState)(null);
@@ -51635,19 +51693,64 @@ function DepositHeader({
51635
51693
  balanceTokenAddress,
51636
51694
  publishableKey
51637
51695
  ]);
51638
- 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: [
51639
- showBack ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51640
- "button",
51641
- {
51642
- onClick: onBack,
51643
- className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51644
- style: { color: components.header.buttonColor },
51645
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
51646
- }
51647
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
51648
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
51649
- badge ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
51650
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51696
+ const incidentMessages = incident?.messages ?? [];
51697
+ const showIncident = incident?.enabled && incidentMessages.length > 0;
51698
+ const incidentSeverity = incident?.severity ?? "degraded";
51699
+ const incidentSeverityLabel = incidentSeverity === "outage" ? "Outage" : incidentSeverity === "info" ? "Info" : "Degraded service";
51700
+ const incidentStyles = incidentSeverity === "outage" ? {
51701
+ bg: "rgba(239, 68, 68, 0.12)",
51702
+ border: "rgba(239, 68, 68, 0.35)",
51703
+ text: "#fca5a5",
51704
+ link: "#fca5a5"
51705
+ } : incidentSeverity === "info" ? {
51706
+ bg: "rgba(59, 130, 246, 0.12)",
51707
+ border: "rgba(59, 130, 246, 0.35)",
51708
+ text: "#93c5fd",
51709
+ link: "#93c5fd"
51710
+ } : {
51711
+ bg: "rgba(245, 158, 11, 0.12)",
51712
+ border: "rgba(245, 158, 11, 0.35)",
51713
+ text: "#fcd34d",
51714
+ link: "#fcd34d"
51715
+ };
51716
+ const IncidentIcon = incidentSeverity === "info" ? Info : TriangleAlert;
51717
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
51718
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
51719
+ showBack ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51720
+ "button",
51721
+ {
51722
+ onClick: onBack,
51723
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51724
+ style: { color: components.header.buttonColor },
51725
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ArrowLeft, { className: "uf-w-5 uf-h-5" })
51726
+ }
51727
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
51728
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
51729
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
51730
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51731
+ DialogTitle2,
51732
+ {
51733
+ className: "uf-text-center uf-text-base",
51734
+ style: {
51735
+ color: components.header.titleColor,
51736
+ fontFamily: fonts.medium
51737
+ },
51738
+ children: title
51739
+ }
51740
+ ),
51741
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51742
+ "div",
51743
+ {
51744
+ className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
51745
+ style: {
51746
+ backgroundColor: colors2.card,
51747
+ color: colors2.foregroundMuted,
51748
+ fontFamily: fonts.regular
51749
+ },
51750
+ children: badge.count
51751
+ }
51752
+ )
51753
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51651
51754
  DialogTitle2,
51652
51755
  {
51653
51756
  className: "uf-text-center uf-text-base",
@@ -51658,61 +51761,91 @@ function DepositHeader({
51658
51761
  children: title
51659
51762
  }
51660
51763
  ),
51661
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51764
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51662
51765
  "div",
51663
51766
  {
51664
- className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
51767
+ className: "uf-text-xs uf-mt-1",
51665
51768
  style: {
51666
- backgroundColor: colors2.card,
51667
51769
  color: colors2.foregroundMuted,
51668
51770
  fontFamily: fonts.regular
51669
51771
  },
51670
- children: badge.count
51772
+ children: subtitle
51671
51773
  }
51672
- )
51673
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51674
- DialogTitle2,
51675
- {
51676
- className: "uf-text-center uf-text-base",
51677
- style: {
51678
- color: components.header.titleColor,
51679
- fontFamily: fonts.medium
51680
- },
51681
- children: title
51682
- }
51683
- ),
51684
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51685
- "div",
51686
- {
51687
- className: "uf-text-xs uf-mt-1",
51688
- style: {
51689
- color: colors2.foregroundMuted,
51690
- fontFamily: fonts.regular
51691
- },
51692
- children: subtitle
51693
- }
51694
- ) : 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)(
51695
- "div",
51774
+ ) : 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)(
51775
+ "div",
51776
+ {
51777
+ className: "uf-text-xs uf-mt-1",
51778
+ style: {
51779
+ color: colors2.foregroundMuted,
51780
+ fontFamily: fonts.regular
51781
+ },
51782
+ children: formatBalanceDisplay(balance, projectName)
51783
+ }
51784
+ ) : null : null
51785
+ ] }),
51786
+ showClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51787
+ "button",
51696
51788
  {
51697
- className: "uf-text-xs uf-mt-1",
51698
- style: {
51699
- color: colors2.foregroundMuted,
51700
- fontFamily: fonts.regular
51701
- },
51702
- children: formatBalanceDisplay(balance, projectName)
51789
+ onClick: onClose,
51790
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
51791
+ style: { color: components.header.buttonColor },
51792
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(X, { className: "uf-w-5 uf-h-5" })
51703
51793
  }
51704
- ) : null : null
51794
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
51705
51795
  ] }),
51706
- showClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51707
- "button",
51796
+ showIncident && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51797
+ "div",
51708
51798
  {
51709
- onClick: onClose,
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)(X, { className: "uf-w-5 uf-h-5" })
51799
+ className: "uf-rounded-lg uf-px-3 uf-py-2.5 uf-mb-4",
51800
+ style: {
51801
+ backgroundColor: incidentStyles.bg,
51802
+ border: `1px solid ${incidentStyles.border}`
51803
+ },
51804
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-flex uf-items-start uf-gap-2.5", children: [
51805
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51806
+ IncidentIcon,
51807
+ {
51808
+ className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
51809
+ style: { color: incidentStyles.text }
51810
+ }
51811
+ ),
51812
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uf-min-w-0 uf-flex-1", children: [
51813
+ /* @__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)(
51814
+ "span",
51815
+ {
51816
+ className: "uf-text-[11px] uf-leading-none uf-px-1.5 uf-py-1 uf-rounded-md",
51817
+ style: {
51818
+ color: incidentStyles.text,
51819
+ border: `1px solid ${incidentStyles.border}`,
51820
+ fontFamily: fonts.medium
51821
+ },
51822
+ children: incidentSeverityLabel
51823
+ }
51824
+ ) }),
51825
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51826
+ "div",
51827
+ {
51828
+ className: "uf-space-y-1",
51829
+ style: { color: incidentStyles.text, fontFamily: fonts.regular },
51830
+ children: incidentMessages.map((message, index2) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "uf-text-xs uf-leading-relaxed", children: message }, `${message}-${index2}`))
51831
+ }
51832
+ ),
51833
+ incident.statusPageUrl && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
51834
+ "a",
51835
+ {
51836
+ href: incident.statusPageUrl,
51837
+ target: "_blank",
51838
+ rel: "noreferrer",
51839
+ className: "uf-inline-block uf-mt-1.5 uf-text-xs uf-underline uf-underline-offset-2",
51840
+ style: { color: incidentStyles.link, fontFamily: fonts.medium },
51841
+ children: "View status"
51842
+ }
51843
+ )
51844
+ ] })
51845
+ ] })
51713
51846
  }
51714
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
51715
- ] }) });
51847
+ )
51848
+ ] });
51716
51849
  }
51717
51850
  function CurrencyListItem({ currency, isSelected, onSelect }) {
51718
51851
  const { colors: colors2, fonts, components } = useTheme();
@@ -52032,7 +52165,8 @@ var en_default2 = {
52032
52165
  },
52033
52166
  stripeLink: {
52034
52167
  title: "Pay with Link",
52035
- subtitle: "Buy with card or bank"
52168
+ subtitle: "Buy with card or bank",
52169
+ unavailableInRegionMessage: "Pay with Link is currently unavailable in your region."
52036
52170
  },
52037
52171
  browserWallet: {
52038
52172
  title: "Connect Wallet",
@@ -58339,7 +58473,7 @@ function AppleLogo({ className, style }) {
58339
58473
  }
58340
58474
  );
58341
58475
  }
58342
- function ApplePayButton({ onClick, title, subtitle }) {
58476
+ function ApplePayButton({ onClick, title, subtitle, iconUrl }) {
58343
58477
  const { colors: colors2, fonts, components } = useTheme();
58344
58478
  const [isHovered, setIsHovered] = React142.useState(false);
58345
58479
  const [isTouchDevice, setIsTouchDevice] = React142.useState(false);
@@ -58361,7 +58495,14 @@ function ApplePayButton({ onClick, title, subtitle }) {
58361
58495
  },
58362
58496
  children: [
58363
58497
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
58364
- /* @__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 } }) }),
58498
+ /* @__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)(
58499
+ "div",
58500
+ {
58501
+ className: "uf-w-9 uf-h-9 uf-rounded-lg uf-flex uf-items-center uf-justify-center",
58502
+ style: { backgroundColor: "#000" },
58503
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: "#fff" } })
58504
+ }
58505
+ ) }),
58365
58506
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uf-text-left", children: [
58366
58507
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
58367
58508
  "div",
@@ -58577,13 +58718,6 @@ function solanaCandidate(provider, type, name, icon) {
58577
58718
  if (provider.isConnected && provider.publicKey) {
58578
58719
  return { type, name, address: provider.publicKey.toString(), icon };
58579
58720
  }
58580
- try {
58581
- const resp = await provider.connect({ onlyIfTrusted: true });
58582
- if (resp.publicKey) {
58583
- return { type, name, address: resp.publicKey.toString(), icon };
58584
- }
58585
- } catch {
58586
- }
58587
58721
  return null;
58588
58722
  }
58589
58723
  };
@@ -58807,6 +58941,178 @@ async function disconnectInjectedBrowserWallet(wallet) {
58807
58941
  collectEthereumProvidersForDisconnect(window)
58808
58942
  );
58809
58943
  }
58944
+ var STORED_TYPE_TO_EIP6963_WALLET_ID = {
58945
+ metamask: "metamask",
58946
+ "phantom-ethereum": "phantom",
58947
+ coinbase: "coinbase",
58948
+ trust: "trust",
58949
+ rainbow: "rainbow",
58950
+ rabby: "rabby",
58951
+ okx: "okx"
58952
+ };
58953
+ var EIP6963_WALLET_ID_TO_INFO = {
58954
+ metamask: { walletType: "metamask", name: "MetaMask", icon: "metamask" },
58955
+ phantom: { walletType: "phantom-ethereum", name: "Phantom", icon: "phantom" },
58956
+ coinbase: { walletType: "coinbase", name: "Coinbase Wallet", icon: "coinbase" },
58957
+ trust: { walletType: "trust", name: "Trust Wallet", icon: "trust" },
58958
+ rainbow: { walletType: "rainbow", name: "Rainbow", icon: "rainbow" },
58959
+ rabby: { walletType: "rabby", name: "Rabby", icon: "rabby" },
58960
+ okx: { walletType: "okx", name: "OKX Wallet", icon: "okx" }
58961
+ };
58962
+ var WALLET_ID_TO_WALLET_TYPE = {
58963
+ phantom: "phantom-ethereum",
58964
+ coinbase: "coinbase",
58965
+ trust: "trust",
58966
+ rainbow: "rainbow",
58967
+ rabby: "rabby",
58968
+ okx: "okx",
58969
+ metamask: "metamask"
58970
+ };
58971
+ var WALLET_TYPE_TO_WALLET_ID = {
58972
+ "phantom-ethereum": "phantom",
58973
+ coinbase: "coinbase",
58974
+ trust: "trust",
58975
+ okx: "okx",
58976
+ rainbow: "rainbow",
58977
+ rabby: "rabby",
58978
+ metamask: "metamask"
58979
+ };
58980
+ function isWalletType(value) {
58981
+ 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";
58982
+ }
58983
+ function walletIdToWalletType(walletId) {
58984
+ return WALLET_ID_TO_WALLET_TYPE[walletId] || "metamask";
58985
+ }
58986
+ function walletTypeToWalletId(walletType) {
58987
+ return WALLET_TYPE_TO_WALLET_ID[walletType] || walletType;
58988
+ }
58989
+ function getLegacyEvmProviders(win) {
58990
+ if (!win) return {};
58991
+ const anyWin = win;
58992
+ return {
58993
+ ethereum: anyWin.ethereum,
58994
+ phantomEthereum: anyWin.phantom?.ethereum,
58995
+ coinbaseEthereum: anyWin.coinbaseWalletExtension,
58996
+ trustEthereum: anyWin.trustwallet?.ethereum,
58997
+ okxEthereum: anyWin.okxwallet
58998
+ };
58999
+ }
59000
+ function getInjectedSolanaProviders(win) {
59001
+ if (!win) return {};
59002
+ const anyWin = win;
59003
+ return {
59004
+ phantomSolana: anyWin.phantom?.solana,
59005
+ solflare: anyWin.solflare,
59006
+ backpack: anyWin.backpack,
59007
+ glow: anyWin.glow,
59008
+ coinbaseSolana: anyWin.coinbaseSolana || anyWin.coinbaseWalletExtension?.solana,
59009
+ trustSolana: anyWin.trustwallet?.solana
59010
+ };
59011
+ }
59012
+ function describeEip6963Provider(wp) {
59013
+ const mapped = EIP6963_WALLET_ID_TO_INFO[wp.walletId];
59014
+ return {
59015
+ provider: wp.provider,
59016
+ walletType: mapped?.walletType ?? "metamask",
59017
+ name: mapped?.name ?? wp.info.name,
59018
+ icon: mapped?.icon ?? wp.info.icon
59019
+ };
59020
+ }
59021
+ function resolveQuickConnectEvmProvider(win) {
59022
+ const eip6963Providers = getEip6963Providers();
59023
+ if (eip6963Providers.length > 0) {
59024
+ const stored = getStoredWalletState();
59025
+ const preferredWalletId = stored?.walletType && isWalletType(stored.walletType) ? STORED_TYPE_TO_EIP6963_WALLET_ID[stored.walletType] : void 0;
59026
+ if (preferredWalletId) {
59027
+ const preferred = findProviderByWalletId(preferredWalletId);
59028
+ if (preferred) return describeEip6963Provider(preferred);
59029
+ }
59030
+ if (eip6963Providers.length === 1) {
59031
+ return describeEip6963Provider(eip6963Providers[0]);
59032
+ }
59033
+ return void 0;
59034
+ }
59035
+ const anyWin = win;
59036
+ const legacy = anyWin.phantom?.ethereum || anyWin.ethereum;
59037
+ if (!legacy) return void 0;
59038
+ const isPhantom = legacy.isPhantom;
59039
+ return {
59040
+ provider: legacy,
59041
+ walletType: isPhantom ? "phantom-ethereum" : "metamask",
59042
+ name: isPhantom ? "Phantom" : "MetaMask",
59043
+ icon: isPhantom ? "phantom" : "metamask"
59044
+ };
59045
+ }
59046
+ function resolveSolanaPublicKey(provider, response) {
59047
+ if (response?.publicKey) return { publicKey: response.publicKey };
59048
+ if (provider.publicKey) return { publicKey: provider.publicKey };
59049
+ return null;
59050
+ }
59051
+ function isUserRejectedSolanaConnectError(error) {
59052
+ if (!error || typeof error !== "object") return false;
59053
+ const maybeCode = "code" in error ? error.code : void 0;
59054
+ if (maybeCode === 4001) return true;
59055
+ const msg = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
59056
+ return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("rejected the request") || msg.includes("declined");
59057
+ }
59058
+ function isSolanaConnectTimeoutError(error) {
59059
+ return error instanceof Error && error.message.toLowerCase().includes("did not respond to the connection request");
59060
+ }
59061
+ async function connectSolanaProviderWithRecovery(provider, walletId, walletName) {
59062
+ if (provider.isConnected && provider.publicKey) {
59063
+ return { publicKey: provider.publicKey };
59064
+ }
59065
+ const connectOnce = () => provider.connect(walletId === "solflare" ? { onlyIfTrusted: false } : void 0);
59066
+ const withTimeout = async (ms = 2e4) => await Promise.race([
59067
+ connectOnce(),
59068
+ new Promise(
59069
+ (resolve, reject) => setTimeout(() => {
59070
+ const connected = resolveSolanaPublicKey(provider);
59071
+ if (connected) {
59072
+ resolve(connected);
59073
+ return;
59074
+ }
59075
+ reject(
59076
+ new Error(
59077
+ `${walletName} did not respond to the connection request. Please unlock the wallet and try again.`
59078
+ )
59079
+ );
59080
+ }, ms)
59081
+ )
59082
+ ]);
59083
+ if (walletId === "solflare") {
59084
+ await provider.disconnect?.().catch(() => {
59085
+ });
59086
+ }
59087
+ const connectAndResolve = async () => {
59088
+ try {
59089
+ const response = await withTimeout();
59090
+ const resolved = resolveSolanaPublicKey(provider, response);
59091
+ if (resolved) return resolved;
59092
+ await new Promise((resolve) => setTimeout(resolve, 120));
59093
+ const delayedResolved = resolveSolanaPublicKey(provider);
59094
+ if (delayedResolved) return delayedResolved;
59095
+ throw new Error(`${walletName} connected but did not expose a public key.`);
59096
+ } catch (error) {
59097
+ const connected = resolveSolanaPublicKey(provider);
59098
+ if (connected) return connected;
59099
+ throw error;
59100
+ }
59101
+ };
59102
+ try {
59103
+ return await connectAndResolve();
59104
+ } catch (err) {
59105
+ if (isUserRejectedSolanaConnectError(err)) throw err;
59106
+ if (isSolanaConnectTimeoutError(err)) throw err;
59107
+ if (walletId === "solflare") {
59108
+ await provider.disconnect?.().catch(() => {
59109
+ });
59110
+ await new Promise((resolve) => setTimeout(resolve, 150));
59111
+ return await connectAndResolve();
59112
+ }
59113
+ throw err;
59114
+ }
59115
+ }
58810
59116
  function MetamaskIcon({ size: size4 = 24, className, variant = "color" }) {
58811
59117
  const id = React172.useId();
58812
59118
  if (variant === "light" || variant === "dark") {
@@ -60666,21 +60972,19 @@ function BrowserWalletButton({
60666
60972
  }
60667
60973
  }
60668
60974
  if (!chainType || chainType === "ethereum") {
60669
- const ethProvider = window.phantom?.ethereum || window.ethereum;
60670
- if (ethProvider) {
60671
- const accounts = await ethProvider.request({
60975
+ const resolved = resolveQuickConnectEvmProvider(window);
60976
+ if (resolved) {
60977
+ const accounts = await resolved.provider.request({
60672
60978
  method: "eth_requestAccounts"
60673
60979
  });
60674
60980
  if (accounts && accounts.length > 0) {
60675
60981
  setUserDisconnectedWallet(false);
60676
- const isPhantom = ethProvider.isPhantom;
60677
- const walletType = isPhantom ? "phantom-ethereum" : "metamask";
60678
- setStoredWalletState(walletType);
60982
+ setStoredWalletState(resolved.walletType);
60679
60983
  setWallet({
60680
- type: walletType,
60681
- name: isPhantom ? "Phantom" : "MetaMask",
60984
+ type: resolved.walletType,
60985
+ name: resolved.name,
60682
60986
  address: accounts[0],
60683
- icon: isPhantom ? "phantom" : "metamask"
60987
+ icon: resolved.icon
60684
60988
  });
60685
60989
  }
60686
60990
  }
@@ -60714,7 +61018,10 @@ function BrowserWalletButton({
60714
61018
  if (isLoading) {
60715
61019
  return null;
60716
61020
  }
60717
- 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);
61021
+ const eip6963EvmProviderCount = getEip6963Providers().length;
61022
+ const legacyEvmProviders = getLegacyEvmProviders(window);
61023
+ const hasLegacyEvmProvider = eip6963EvmProviderCount === 0 && !!(legacyEvmProviders.ethereum || legacyEvmProviders.phantomEthereum || legacyEvmProviders.coinbaseEthereum || legacyEvmProviders.trustEthereum || legacyEvmProviders.okxEthereum);
61024
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && eip6963EvmProviderCount > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && hasLegacyEvmProvider;
60718
61025
  if (!onConnectClick && !wallet && !hasWalletExtension) {
60719
61026
  return null;
60720
61027
  }
@@ -60724,11 +61031,25 @@ function BrowserWalletButton({
60724
61031
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
60725
61032
  };
60726
61033
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
61034
+ const isImageIcon = !!wallet && (wallet.icon.startsWith("data:") || wallet.icon.startsWith("http"));
60727
61035
  const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React292.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
60728
61036
  size: 36,
60729
61037
  className: "uf-rounded-lg",
60730
61038
  variant: "color"
60731
- }) : /* @__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 } }) });
61039
+ }) : isImageIcon ? (
61040
+ // Wallet announced via EIP-6963 with no internal icon component: render its
61041
+ // own advertised icon (`info.icon`) rather than a generic placeholder.
61042
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
61043
+ "img",
61044
+ {
61045
+ src: wallet.icon,
61046
+ alt: wallet.name,
61047
+ width: 36,
61048
+ height: 36,
61049
+ className: "uf-rounded-lg uf-w-9 uf-h-9"
61050
+ }
61051
+ )
61052
+ ) : /* @__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 } }) });
60732
61053
  const titleSubtitleBlock = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "uf-text-left uf-min-w-0", children: [
60733
61054
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
60734
61055
  "div",
@@ -66686,6 +67007,24 @@ function useExchanges({
66686
67007
  });
66687
67008
  return { exchanges, isLoading };
66688
67009
  }
67010
+ function usePublicIncident({
67011
+ publishableKey,
67012
+ enabled = true
67013
+ }) {
67014
+ const {
67015
+ data: incident,
67016
+ isLoading,
67017
+ error
67018
+ } = useQuery({
67019
+ queryKey: ["unifold", "publicIncident", publishableKey],
67020
+ queryFn: () => getPublicIncident(publishableKey),
67021
+ enabled,
67022
+ staleTime: 1e3 * 30,
67023
+ refetchInterval: 1e3 * 30,
67024
+ refetchOnWindowFocus: true
67025
+ });
67026
+ return { incident, isLoading, error: error ?? null };
67027
+ }
66689
67028
  function useApplePayProviders({
66690
67029
  publishableKey,
66691
67030
  enabled = true
@@ -66781,6 +67120,7 @@ function useAddressValidation({
66781
67120
  return {
66782
67121
  isValid: null,
66783
67122
  failureCode: null,
67123
+ message: null,
66784
67124
  metadata: null,
66785
67125
  isLoading: false,
66786
67126
  error: null
@@ -66789,6 +67129,7 @@ function useAddressValidation({
66789
67129
  return {
66790
67130
  isValid: data?.valid ?? null,
66791
67131
  failureCode: data?.failure_code ?? null,
67132
+ message: data?.message ?? null,
66792
67133
  metadata: data?.metadata ?? null,
66793
67134
  isLoading,
66794
67135
  error: error ?? null
@@ -67614,6 +67955,37 @@ function TokenSelectorSheet({
67614
67955
  var getChainKey = (chainId, chainType) => {
67615
67956
  return `${chainType}:${chainId}`;
67616
67957
  };
67958
+ function getStoredSelection(key) {
67959
+ if (typeof window === "undefined") return null;
67960
+ try {
67961
+ const raw = localStorage.getItem(key);
67962
+ if (!raw) return null;
67963
+ const parsed = JSON.parse(raw);
67964
+ if (parsed && typeof parsed.symbol === "string" && typeof parsed.chainType === "string" && typeof parsed.chainId === "string") {
67965
+ return parsed;
67966
+ }
67967
+ } catch {
67968
+ }
67969
+ return null;
67970
+ }
67971
+ function saveStoredSelection(key, symbol, chainType, chainId) {
67972
+ if (typeof window === "undefined") return;
67973
+ try {
67974
+ localStorage.setItem(key, JSON.stringify({ symbol, chainType, chainId }));
67975
+ } catch {
67976
+ }
67977
+ }
67978
+ function resolveFromStorage(tokens, stored) {
67979
+ for (const t13 of tokens) {
67980
+ if (t13.symbol !== stored.symbol) continue;
67981
+ const matchedChain = t13.chains.find(
67982
+ (c) => c.chain_type === stored.chainType && c.chain_id === stored.chainId
67983
+ );
67984
+ if (matchedChain) return { token: t13, chain: matchedChain };
67985
+ if (t13.chains.length > 0) return { token: t13, chain: t13.chains[0] };
67986
+ }
67987
+ return null;
67988
+ }
67617
67989
  function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
67618
67990
  if (!tokens.length) return null;
67619
67991
  let selectedToken;
@@ -67663,27 +68035,73 @@ function useDefaultToken({
67663
68035
  defaultChainType,
67664
68036
  defaultChainId,
67665
68037
  defaultTokenAddress,
67666
- defaultSymbol
68038
+ defaultSymbol,
68039
+ storageKey: storageKey2
67667
68040
  }) {
67668
- const [token, setToken] = (0, import_react28.useState)(null);
67669
- const [chain, setChain] = (0, import_react28.useState)(null);
68041
+ const [token, setTokenState] = (0, import_react28.useState)(null);
68042
+ const [chain, setChainState] = (0, import_react28.useState)(null);
67670
68043
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react28.useState)(false);
67671
68044
  const appliedDefaultsRef = (0, import_react28.useRef)("");
68045
+ const tokenRef = (0, import_react28.useRef)(null);
68046
+ const chainRef = (0, import_react28.useRef)(null);
68047
+ tokenRef.current = token;
68048
+ chainRef.current = chain;
68049
+ const setToken = (0, import_react28.useCallback)(
68050
+ (newToken) => {
68051
+ tokenRef.current = newToken;
68052
+ setTokenState(newToken);
68053
+ if (storageKey2 && chainRef.current) {
68054
+ const [chainType, chainId] = chainRef.current.split(":");
68055
+ saveStoredSelection(storageKey2, newToken, chainType, chainId);
68056
+ }
68057
+ },
68058
+ [storageKey2]
68059
+ );
68060
+ const setChain = (0, import_react28.useCallback)(
68061
+ (newChain) => {
68062
+ chainRef.current = newChain;
68063
+ setChainState(newChain);
68064
+ if (storageKey2 && tokenRef.current) {
68065
+ const [chainType, chainId] = newChain.split(":");
68066
+ saveStoredSelection(storageKey2, tokenRef.current, chainType, chainId);
68067
+ }
68068
+ },
68069
+ [storageKey2]
68070
+ );
67672
68071
  (0, import_react28.useEffect)(() => {
67673
68072
  if (!tokens.length) return;
67674
68073
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
67675
68074
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
67676
68075
  if (initialSelectionDone && !defaultsChanged) return;
67677
- const result = resolveToken(
67678
- tokens,
67679
- defaultChainType,
67680
- defaultChainId,
67681
- defaultTokenAddress,
67682
- defaultSymbol
67683
- );
68076
+ const hasExplicitDefaults = defaultTokenAddress && defaultChainType && defaultChainId || defaultSymbol && defaultChainType && defaultChainId;
68077
+ let result = null;
68078
+ if (hasExplicitDefaults) {
68079
+ result = resolveToken(
68080
+ tokens,
68081
+ defaultChainType,
68082
+ defaultChainId,
68083
+ defaultTokenAddress,
68084
+ defaultSymbol
68085
+ );
68086
+ if (result) {
68087
+ 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;
68088
+ if (!matched) {
68089
+ result = null;
68090
+ }
68091
+ }
68092
+ }
68093
+ if (!result && storageKey2) {
68094
+ const stored = getStoredSelection(storageKey2);
68095
+ if (stored) {
68096
+ result = resolveFromStorage(tokens, stored);
68097
+ }
68098
+ }
68099
+ if (!result) {
68100
+ result = resolveToken(tokens);
68101
+ }
67684
68102
  if (result) {
67685
- setToken(result.token.symbol);
67686
- setChain(getChainKey(result.chain.chain_id, result.chain.chain_type));
68103
+ setTokenState(result.token.symbol);
68104
+ setChainState(getChainKey(result.chain.chain_id, result.chain.chain_type));
67687
68105
  appliedDefaultsRef.current = defaultsKey;
67688
68106
  setInitialSelectionDone(true);
67689
68107
  }
@@ -67693,7 +68111,8 @@ function useDefaultToken({
67693
68111
  defaultSymbol,
67694
68112
  defaultChainType,
67695
68113
  defaultChainId,
67696
- initialSelectionDone
68114
+ initialSelectionDone,
68115
+ storageKey2
67697
68116
  ]);
67698
68117
  (0, import_react28.useEffect)(() => {
67699
68118
  if (!tokens.length || !token) return;
@@ -67704,11 +68123,12 @@ function useDefaultToken({
67704
68123
  });
67705
68124
  if (!isChainAvailable) {
67706
68125
  const firstChain = currentToken.chains[0];
67707
- setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
68126
+ setChainState(getChainKey(firstChain.chain_id, firstChain.chain_type));
67708
68127
  }
67709
68128
  }, [token, tokens, chain]);
67710
68129
  return { token, chain, setToken, setChain, initialSelectionDone };
67711
68130
  }
68131
+ var STORAGE_KEY2 = "unifold_last_deposit_from_token";
67712
68132
  function useDefaultSourceToken({
67713
68133
  supportedTokens,
67714
68134
  defaultSourceChainType,
@@ -67721,7 +68141,8 @@ function useDefaultSourceToken({
67721
68141
  defaultChainType: defaultSourceChainType,
67722
68142
  defaultChainId: defaultSourceChainId,
67723
68143
  defaultTokenAddress: defaultSourceTokenAddress,
67724
- defaultSymbol: defaultSourceSymbol
68144
+ defaultSymbol: defaultSourceSymbol,
68145
+ storageKey: STORAGE_KEY2
67725
68146
  });
67726
68147
  }
67727
68148
  function DepositFooterLinks({ onGlossaryClick, leftElement }) {
@@ -70733,33 +71154,11 @@ function balancesRepresentSameToken(a, b) {
70733
71154
  if (!tokenA || !tokenB) return false;
70734
71155
  return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
70735
71156
  }
70736
- function getSolanaProviders() {
70737
- if (typeof window === "undefined") return {};
70738
- const win = window;
70739
- return {
70740
- phantomSolana: win.phantom?.solana,
70741
- solflare: win.solflare,
70742
- backpack: win.backpack,
70743
- glow: win.glow,
70744
- coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
70745
- };
70746
- }
70747
- function getLegacyEvmProviders() {
70748
- if (typeof window === "undefined") return {};
70749
- const win = window;
70750
- return {
70751
- ethereum: win.ethereum,
70752
- phantomEthereum: win.phantom?.ethereum,
70753
- coinbaseEthereum: win.coinbaseWalletExtension,
70754
- trustEthereum: win.trustwallet?.ethereum,
70755
- okxEthereum: win.okxwallet
70756
- };
70757
- }
70758
71157
  function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
70759
- const solProviders = getSolanaProviders();
70760
- const legacyEvm = getLegacyEvmProviders();
70761
- const eip6963List = getEip6963Providers();
70762
71158
  const win = typeof window !== "undefined" ? window : null;
71159
+ const solProviders = getInjectedSolanaProviders(win);
71160
+ const legacyEvm = getLegacyEvmProviders(win);
71161
+ const eip6963List = getEip6963Providers();
70763
71162
  const hasEip6963 = (walletId) => eip6963List.some((d) => {
70764
71163
  const rdns = d.info?.rdns || "";
70765
71164
  switch (walletId) {
@@ -71028,10 +71427,13 @@ function WalletConnect({
71028
71427
  };
71029
71428
  const openMobileWalletBrowse = async (wallet, depositAddresses) => {
71030
71429
  try {
71430
+ const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
71431
+ const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
71031
71432
  const res = await getWalletMobileDeepLink(
71032
71433
  wallet.id,
71033
71434
  depositAddresses,
71034
- publishableKey
71435
+ publishableKey,
71436
+ forwardedAmountUsd
71035
71437
  );
71036
71438
  if (res.deeplink) {
71037
71439
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
@@ -71120,7 +71522,7 @@ function WalletConnect({
71120
71522
  const eip6963Match = findProviderByWalletId(wallet.id);
71121
71523
  let provider = eip6963Match?.provider;
71122
71524
  if (!provider) {
71123
- const legacyEvm = getLegacyEvmProviders();
71525
+ const legacyEvm = getLegacyEvmProviders(win);
71124
71526
  switch (wallet.id) {
71125
71527
  case "metamask":
71126
71528
  if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom)
@@ -71152,16 +71554,7 @@ function WalletConnect({
71152
71554
  const accounts = await provider.request({ method: "eth_requestAccounts" });
71153
71555
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
71154
71556
  setUserDisconnectedWallet(false);
71155
- const walletIdToType = {
71156
- phantom: "phantom-ethereum",
71157
- coinbase: "coinbase",
71158
- trust: "trust",
71159
- rainbow: "rainbow",
71160
- rabby: "rabby",
71161
- okx: "okx",
71162
- metamask: "metamask"
71163
- };
71164
- const walletType = walletIdToType[wallet.id] || "metamask";
71557
+ const walletType = walletIdToWalletType(wallet.id);
71165
71558
  setStoredWalletState(walletType);
71166
71559
  connectedInfo = {
71167
71560
  type: walletType,
@@ -71170,7 +71563,7 @@ function WalletConnect({
71170
71563
  icon: wallet.id
71171
71564
  };
71172
71565
  } else {
71173
- const solProviders = getSolanaProviders();
71566
+ const solProviders = getInjectedSolanaProviders(win);
71174
71567
  let provider;
71175
71568
  switch (wallet.id) {
71176
71569
  case "phantom":
@@ -71189,11 +71582,11 @@ function WalletConnect({
71189
71582
  provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
71190
71583
  break;
71191
71584
  case "trust":
71192
- provider = win?.trustwallet?.solana;
71585
+ provider = solProviders.trustSolana;
71193
71586
  break;
71194
71587
  }
71195
71588
  if (!provider) throw new Error(`${wallet.name} Solana wallet not found.`);
71196
- const response = await provider.connect();
71589
+ const response = await connectSolanaProviderWithRecovery(provider, wallet.id, wallet.name);
71197
71590
  setUserDisconnectedWallet(false);
71198
71591
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
71199
71592
  setStoredWalletState(walletType);
@@ -71544,16 +71937,7 @@ function WalletConnect({
71544
71937
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
71545
71938
  };
71546
71939
  const resolveEvmProvider = () => {
71547
- const walletIdMap = {
71548
- "phantom-ethereum": "phantom",
71549
- coinbase: "coinbase",
71550
- trust: "trust",
71551
- okx: "okx",
71552
- rainbow: "rainbow",
71553
- rabby: "rabby",
71554
- metamask: "metamask"
71555
- };
71556
- const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
71940
+ const lookupId = walletTypeToWalletId(walletInfo.type);
71557
71941
  const eip6963Match = findProviderByWalletId(lookupId);
71558
71942
  let provider = eip6963Match?.provider;
71559
71943
  if (!provider) {
@@ -72282,6 +72666,7 @@ function DepositModal({
72282
72666
  applePayTitle = "Pay with Apple Pay",
72283
72667
  applePaySubTitle = "Instant",
72284
72668
  enableBankTransfer,
72669
+ enableIncidentBanner = false,
72285
72670
  // No default: left undefined so the backend `stripe_link.enabled` can govern
72286
72671
  // (via the `??` chain in showStripeLink) once a dashboard toggle exists.
72287
72672
  enableStripeLink,
@@ -72327,7 +72712,7 @@ function DepositModal({
72327
72712
  const s = initialScreen ?? "main";
72328
72713
  if (s === "tracker" && hideDepositTracker === true) return "main";
72329
72714
  if (s === "cashapp" && enableCashApp === false) return "main";
72330
- if (s === "stripe_link" && !enableStripeLink) return "main";
72715
+ if (s === "stripe_link" && enableStripeLink === false) return "main";
72331
72716
  if (s === "apple_pay" && enableApplePay === false) return "main";
72332
72717
  if (s === "card" && enableFiatOnramp === false) return "main";
72333
72718
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
@@ -72386,6 +72771,16 @@ function DepositModal({
72386
72771
  const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
72387
72772
  const showBankTransfer = enableBankTransfer ?? projectConfig?.bank_transfer?.enabled ?? true;
72388
72773
  const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
72774
+ const { incident: publicIncident } = usePublicIncident({
72775
+ publishableKey,
72776
+ enabled: open && enableIncidentBanner
72777
+ });
72778
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
72779
+ enabled: true,
72780
+ messages: publicIncident.messages,
72781
+ severity: publicIncident.severity,
72782
+ statusPageUrl: publicIncident.status_page_url
72783
+ } : void 0;
72389
72784
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react3.useState)([]);
72390
72785
  (0, import_react3.useEffect)(() => {
72391
72786
  if (!showConnectExchange || !open) return;
@@ -72452,7 +72847,11 @@ function DepositModal({
72452
72847
  setConnectedExchange((prev) => prev ? { ...prev, iconUrl } : prev);
72453
72848
  }
72454
72849
  }, [integrationExchanges, connectedExchange]);
72455
- const { data: depositAddressResponse, isLoading: walletsLoading } = useDepositAddress({
72850
+ const {
72851
+ data: depositAddressResponse,
72852
+ isLoading: walletsLoading,
72853
+ error: walletsError
72854
+ } = useDepositAddress({
72456
72855
  userId,
72457
72856
  publishableKey,
72458
72857
  recipientAddress,
@@ -72585,6 +72984,7 @@ function DepositModal({
72585
72984
  const {
72586
72985
  isValid: isAddressValid,
72587
72986
  failureCode: addressFailureCode,
72987
+ message: addressFailureMessage,
72588
72988
  metadata: addressFailureMetadata,
72589
72989
  isLoading: isAddressValidationLoading
72590
72990
  } = useAddressValidation({
@@ -72598,17 +72998,31 @@ function DepositModal({
72598
72998
  refetchOnMount: "always"
72599
72999
  });
72600
73000
  const addressValidationMessages = i18n2.transferCrypto.addressValidation;
72601
- const getAddressValidationErrorMessage = (code, metadata) => {
73001
+ const getAddressValidationErrorMessage = (message, code, metadata) => {
73002
+ if (message && message.trim().length > 0) return message;
72602
73003
  if (!code) return addressValidationMessages.defaultError;
72603
73004
  const errors = addressValidationMessages.errors;
72604
73005
  const template = errors[code] ?? addressValidationMessages.defaultError;
72605
73006
  return interpolate(template, metadata);
72606
73007
  };
73008
+ const walletsRecipientError = isDepositAddressValidationError(walletsError) ? walletsError.message : null;
73009
+ const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
73010
+ const recipientInvalidMessage = getAddressValidationErrorMessage(
73011
+ addressFailureMessage ?? walletsRecipientError,
73012
+ addressFailureCode,
73013
+ addressFailureMetadata
73014
+ );
72607
73015
  const openingScreen = effectiveInitialScreen;
72608
73016
  const sessionOpenedFromMenu = openingScreen === "main";
72609
73017
  const standaloneNeedsDepositPrereq = openingScreen !== "main" && (view === "transfer" || view === "card");
72610
73018
  let depositPrerequisiteBody;
72611
- if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
73019
+ if (isRecipientAddressInvalid) {
73020
+ 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: [
73021
+ /* @__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" }) }),
73022
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
73023
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: recipientInvalidMessage })
73024
+ ] });
73025
+ } else if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
72612
73026
  // fetch — block the menu on it so the row never flashes in or out.
72613
73027
  showBankTransfer && bankTransferProvidersLoading || // Same for Apple Pay: row visibility depends on the geo/platform-gated
72614
73028
  // providers fetch — block the menu so the row doesn't pop in or out.
@@ -72630,12 +73044,6 @@ function DepositModal({
72630
73044
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
72631
73045
  /* @__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." })
72632
73046
  ] });
72633
- } else if (isAddressValid === false) {
72634
- 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: [
72635
- /* @__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" }) }),
72636
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
72637
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(addressFailureCode, addressFailureMetadata) })
72638
- ] });
72639
73047
  } else {
72640
73048
  depositPrerequisiteBody = null;
72641
73049
  }
@@ -73129,6 +73537,7 @@ function DepositModal({
73129
73537
  title: modalTitle || "Deposit",
73130
73538
  showClose: !hideOverlay,
73131
73539
  onClose: handleClose,
73540
+ incident: activeIncident,
73132
73541
  showBalance: showBalanceHeader,
73133
73542
  balanceAddress: recipientAddress,
73134
73543
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -73148,6 +73557,7 @@ function DepositModal({
73148
73557
  showBack: showBackTransfer,
73149
73558
  onBack: handleBack,
73150
73559
  onClose: handleClose,
73560
+ incident: activeIncident,
73151
73561
  showBalance: showBalanceHeader,
73152
73562
  balanceAddress: recipientAddress,
73153
73563
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
@@ -73208,7 +73618,8 @@ function DepositModal({
73208
73618
  title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
73209
73619
  showBack: showBackTracker,
73210
73620
  onBack: handleBack,
73211
- onClose: handleClose
73621
+ onClose: handleClose,
73622
+ incident: activeIncident
73212
73623
  }
73213
73624
  ),
73214
73625
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73240,6 +73651,7 @@ function DepositModal({
73240
73651
  showBack: showBackCard,
73241
73652
  onBack: handleBack,
73242
73653
  onClose: handleClose,
73654
+ incident: activeIncident,
73243
73655
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
73244
73656
  showBalance: showBalanceHeader,
73245
73657
  balanceAddress: recipientAddress,
@@ -73289,7 +73701,8 @@ function DepositModal({
73289
73701
  title: payWithExchangeTitle,
73290
73702
  showBack: exchangeView === "pending" || sessionOpenedFromMenu,
73291
73703
  onBack: handleBack,
73292
- onClose: handleClose
73704
+ onClose: handleClose,
73705
+ incident: activeIncident
73293
73706
  }
73294
73707
  ),
73295
73708
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73403,7 +73816,8 @@ function DepositModal({
73403
73816
  title: t8.bankTransfer.title,
73404
73817
  showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
73405
73818
  onBack: handleBack,
73406
- onClose: handleClose
73819
+ onClose: handleClose,
73820
+ incident: activeIncident
73407
73821
  }
73408
73822
  ),
73409
73823
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73437,26 +73851,24 @@ function DepositModal({
73437
73851
  title: "Deposit with Link",
73438
73852
  showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
73439
73853
  onBack: handleBack,
73854
+ incident: activeIncident,
73440
73855
  showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
73441
73856
  onClose: handleClose
73442
73857
  }
73443
73858
  ),
73444
73859
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
73445
73860
  isLoadingIp ? (
73446
- // Hold the geo decision until IP resolves so we don't mount
73447
- // PayWithStripeLink (which kicks off config/OAuth work) for a
73448
- // deep-link user who turns out to be outside the US.
73861
+ // Wait for location so the first config fetch is region-aware.
73449
73862
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(SkeletonButton, { variant: "with-icons" })
73450
73863
  ) : !showStripeLink ? (
73451
- // Stripe Link's crypto on-ramp is US-only. On a direct open
73452
- // (initialScreen="stripe_link") the row isn't in a menu to
73453
- // fall back to, so show a geo-restriction screen rather than
73454
- // the Link UI.
73864
+ // Direct opens (initialScreen="stripe_link") have no menu row
73865
+ // to fall back to, so render an unavailable state when backend
73866
+ // config resolves Stripe Link disabled/hidden.
73455
73867
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
73456
73868
  GeoRestrictionScreen,
73457
73869
  {
73458
73870
  methodName: t8.stripeLink.title,
73459
- message: "Pay with Link is only available in the US."
73871
+ message: t8.stripeLink.unavailableInRegionMessage
73460
73872
  }
73461
73873
  )
73462
73874
  ) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
@@ -73489,7 +73901,8 @@ function DepositModal({
73489
73901
  title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
73490
73902
  showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
73491
73903
  onBack: handleBack,
73492
- onClose: handleClose
73904
+ onClose: handleClose,
73905
+ incident: activeIncident
73493
73906
  }
73494
73907
  ),
73495
73908
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73525,7 +73938,8 @@ function DepositModal({
73525
73938
  const handled = applePayHandleRef.current?.requestBack() ?? false;
73526
73939
  if (!handled) handleBack();
73527
73940
  },
73528
- onClose: handleClose
73941
+ onClose: handleClose,
73942
+ incident: activeIncident
73529
73943
  }
73530
73944
  ),
73531
73945
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -73640,6 +74054,7 @@ function CheckoutModal({
73640
74054
  modalTitle,
73641
74055
  enableTransferCrypto,
73642
74056
  enableConnectWallet,
74057
+ enableIncidentBanner = false,
73643
74058
  defaultSourceChainType,
73644
74059
  defaultSourceChainId,
73645
74060
  defaultSourceTokenAddress,
@@ -73711,6 +74126,16 @@ function CheckoutModal({
73711
74126
  });
73712
74127
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
73713
74128
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
74129
+ const { incident: publicIncident } = usePublicIncident({
74130
+ publishableKey,
74131
+ enabled: open && enableIncidentBanner
74132
+ });
74133
+ const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
74134
+ enabled: true,
74135
+ messages: publicIncident.messages,
74136
+ severity: publicIncident.severity,
74137
+ statusPageUrl: publicIncident.status_page_url
74138
+ } : void 0;
73714
74139
  (0, import_react35.useEffect)(() => {
73715
74140
  if (view === "transfer" && !showTransferCrypto) {
73716
74141
  setView("main");
@@ -74012,7 +74437,15 @@ function CheckoutModal({
74012
74437
  {
74013
74438
  className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
74014
74439
  children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
74015
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
74440
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
74441
+ DepositHeader,
74442
+ {
74443
+ title: modalTitle || "Checkout",
74444
+ showClose: true,
74445
+ onClose: handleClose,
74446
+ incident: activeIncident
74447
+ }
74448
+ ),
74016
74449
  /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
74017
74450
  piLoading ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-space-y-3", children: [
74018
74451
  /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
@@ -74110,7 +74543,8 @@ function CheckoutModal({
74110
74543
  title: modalTitle || "Checkout",
74111
74544
  showBack: true,
74112
74545
  onBack: handleBack,
74113
- onClose: handleClose
74546
+ onClose: handleClose,
74547
+ incident: activeIncident
74114
74548
  }
74115
74549
  ),
74116
74550
  /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
@@ -74280,6 +74714,7 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
74280
74714
  enabled
74281
74715
  });
74282
74716
  }
74717
+ var STORAGE_KEY3 = "unifold_last_withdraw_to_token";
74283
74718
  function useDefaultDestinationToken({
74284
74719
  destinationTokens,
74285
74720
  defaultDestinationChainType,
@@ -74292,7 +74727,8 @@ function useDefaultDestinationToken({
74292
74727
  defaultChainType: defaultDestinationChainType,
74293
74728
  defaultChainId: defaultDestinationChainId,
74294
74729
  defaultTokenAddress: defaultDestinationTokenAddress,
74295
- defaultSymbol: defaultDestinationSymbol
74730
+ defaultSymbol: defaultDestinationSymbol,
74731
+ storageKey: STORAGE_KEY3
74296
74732
  });
74297
74733
  }
74298
74734
  function useSourceTokenValidation(params) {
@@ -74966,6 +75402,9 @@ function WithdrawForm({
74966
75402
  if (isDebouncing || isVerifyingAddress) return null;
74967
75403
  if (verifyError) return t10.invalidAddress;
74968
75404
  if (addressVerification && !addressVerification.valid) {
75405
+ if (addressVerification.message && addressVerification.message.trim().length > 0) {
75406
+ return addressVerification.message;
75407
+ }
74969
75408
  if (addressVerification.failure_code === "account_not_found")
74970
75409
  return `Account not found on ${selectedChain?.chain_name}`;
74971
75410
  if (addressVerification.failure_code === "not_opted_in")
@@ -76222,6 +76661,7 @@ function UnifoldProvider2({
76222
76661
  const [isWithdrawOpen, setIsWithdrawOpen] = (0, import_react.useState)(false);
76223
76662
  const [withdrawConfig, setWithdrawConfig] = (0, import_react.useState)(null);
76224
76663
  const [resolvedTheme, setResolvedTheme] = import_react.default.useState("dark");
76664
+ const incidentBannerEnabled = config?.notifications?.incidentBanner;
76225
76665
  (0, import_react.useEffect)(() => {
76226
76666
  if (publishableKey) {
76227
76667
  setApiConfig({ publishableKey });
@@ -76519,6 +76959,7 @@ function UnifoldProvider2({
76519
76959
  publishableKey,
76520
76960
  enableTransferCrypto: config?.enableTransferCrypto,
76521
76961
  enableConnectWallet: config?.enableConnectWallet,
76962
+ enableIncidentBanner: incidentBannerEnabled,
76522
76963
  defaultSourceChainType: checkoutConfig.defaultSourceChainType,
76523
76964
  defaultSourceChainId: checkoutConfig.defaultSourceChainId,
76524
76965
  defaultSourceTokenAddress: checkoutConfig.defaultSourceTokenAddress,
@@ -76586,6 +77027,7 @@ function UnifoldProvider2({
76586
77027
  enableConnectExchange: config?.enableConnectExchange,
76587
77028
  enableCashApp: config?.enableCashApp,
76588
77029
  enableStripeLink: config?.enableStripeLink,
77030
+ enableIncidentBanner: incidentBannerEnabled,
76589
77031
  enableApplePay: config?.enableApplePay,
76590
77032
  applePayTitle: config?.applePayTitle,
76591
77033
  applePaySubTitle: config?.applePaySubTitle,