@unifold/connect-react 0.1.62 → 0.1.64

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
@@ -6151,6 +6151,42 @@ var import_react9 = require("react");
6151
6151
 
6152
6152
  // ../core/dist/index.mjs
6153
6153
  var import_react_query2 = require("@tanstack/react-query");
6154
+ function formatStablecoinAmount(baseUnits, decimals) {
6155
+ const raw = Number(baseUnits) / 10 ** decimals;
6156
+ const floored = Math.floor(raw * 100) / 100;
6157
+ const ceiled = raw > floored ? floored + 0.01 : raw;
6158
+ return ceiled.toFixed(2);
6159
+ }
6160
+ function generateKSUID() {
6161
+ const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
6162
+ const KSUID_EPOCH = 14e8;
6163
+ const timestampSeconds = Math.floor(Date.now() / 1e3) - KSUID_EPOCH;
6164
+ const payload = new Uint8Array(20);
6165
+ payload[0] = timestampSeconds >>> 24 & 255;
6166
+ payload[1] = timestampSeconds >>> 16 & 255;
6167
+ payload[2] = timestampSeconds >>> 8 & 255;
6168
+ payload[3] = timestampSeconds & 255;
6169
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
6170
+ crypto.getRandomValues(payload.subarray(4));
6171
+ } else {
6172
+ for (let i = 4; i < 20; i++) {
6173
+ payload[i] = Math.floor(Math.random() * 256);
6174
+ }
6175
+ }
6176
+ let value = 0n;
6177
+ for (const byte of payload) {
6178
+ value = value << 8n | BigInt(byte);
6179
+ }
6180
+ let encoded = "";
6181
+ while (value > 0n) {
6182
+ encoded = BASE62[Number(value % 62n)] + encoded;
6183
+ value = value / 62n;
6184
+ }
6185
+ return encoded.padStart(27, "0");
6186
+ }
6187
+ function generatePrefixedKSUID(prefix) {
6188
+ return `${prefix}_${generateKSUID()}`;
6189
+ }
6154
6190
  var API_BASE_URL = (() => {
6155
6191
  try {
6156
6192
  return process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.unifold.io";
@@ -6477,9 +6513,7 @@ function getOnrampSessionStartUrl(request, publishableKey) {
6477
6513
  if (request.subdivision_code) {
6478
6514
  params.append("subdivision_code", request.subdivision_code);
6479
6515
  }
6480
- if (request.external_id) {
6481
- params.append("external_id", request.external_id);
6482
- }
6516
+ params.append("external_id", request.external_id ?? generatePrefixedKSUID("ors"));
6483
6517
  if (request.email) {
6484
6518
  params.append("email", request.email);
6485
6519
  }
@@ -6590,6 +6624,40 @@ async function getAddressBalances(address, chainType, publishableKey) {
6590
6624
  const data = await response.json();
6591
6625
  return data;
6592
6626
  }
6627
+ async function getExternalWallets(publishableKey) {
6628
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6629
+ validatePublishableKey(pk);
6630
+ const response = await fetch(`${API_BASE_URL}/v1/public/external_wallets`, {
6631
+ method: "GET",
6632
+ headers: {
6633
+ accept: "application/json",
6634
+ "x-publishable-key": pk
6635
+ }
6636
+ });
6637
+ if (!response.ok) {
6638
+ throw new Error(`Failed to fetch external wallets: ${response.statusText}`);
6639
+ }
6640
+ const data = await response.json();
6641
+ return data;
6642
+ }
6643
+ async function getWalletMobileDeepLink(wallet, depositAddresses, publishableKey) {
6644
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6645
+ validatePublishableKey(pk);
6646
+ const response = await fetch(`${API_BASE_URL}/v1/public/external_wallets/mobile_deeplink`, {
6647
+ method: "POST",
6648
+ headers: {
6649
+ "Content-Type": "application/json",
6650
+ accept: "application/json",
6651
+ "x-publishable-key": pk
6652
+ },
6653
+ body: JSON.stringify({ wallet, deposit_addresses: depositAddresses })
6654
+ });
6655
+ if (!response.ok) {
6656
+ throw new Error(`Failed to generate wallet deep link: ${response.statusText}`);
6657
+ }
6658
+ const data = await response.json();
6659
+ return data;
6660
+ }
6593
6661
  async function getAddressBalance(address, chainType, chainId, tokenAddress, publishableKey) {
6594
6662
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6595
6663
  validatePublishableKey(pk);
@@ -6694,9 +6762,7 @@ function getExchangeSessionStartUrl(request, publishableKey) {
6694
6762
  if (request.source_amount) {
6695
6763
  params.append("source_amount", request.source_amount);
6696
6764
  }
6697
- if (request.external_id) {
6698
- params.append("external_id", request.external_id);
6699
- }
6765
+ params.append("external_id", request.external_id ?? generatePrefixedKSUID("exc"));
6700
6766
  return `${API_BASE_URL}/v1/public/onramps/exchanges/sessions/start?${params.toString()}`;
6701
6767
  }
6702
6768
  async function getIntegrationExchanges(publishableKey) {
@@ -7030,40 +7096,6 @@ async function getCashAppSessionStatus(externalId, publishableKey) {
7030
7096
  }
7031
7097
  return response.json();
7032
7098
  }
7033
- function formatStablecoinAmount(baseUnits, decimals) {
7034
- const raw = Number(baseUnits) / 10 ** decimals;
7035
- const floored = Math.floor(raw * 100) / 100;
7036
- const ceiled = raw > floored ? floored + 0.01 : raw;
7037
- return ceiled.toFixed(2);
7038
- }
7039
- function generatePrefixedKSUID(prefix) {
7040
- const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
7041
- const KSUID_EPOCH = 14e8;
7042
- const timestampSeconds = Math.floor(Date.now() / 1e3) - KSUID_EPOCH;
7043
- const payload = new Uint8Array(20);
7044
- payload[0] = timestampSeconds >>> 24 & 255;
7045
- payload[1] = timestampSeconds >>> 16 & 255;
7046
- payload[2] = timestampSeconds >>> 8 & 255;
7047
- payload[3] = timestampSeconds & 255;
7048
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
7049
- crypto.getRandomValues(payload.subarray(4));
7050
- } else {
7051
- for (let i = 4; i < 20; i++) {
7052
- payload[i] = Math.floor(Math.random() * 256);
7053
- }
7054
- }
7055
- let value = 0n;
7056
- for (const byte of payload) {
7057
- value = value << 8n | BigInt(byte);
7058
- }
7059
- let encoded = "";
7060
- while (value > 0n) {
7061
- encoded = BASE62[Number(value % 62n)] + encoded;
7062
- value = value / 62n;
7063
- }
7064
- encoded = encoded.padStart(27, "0");
7065
- return `${prefix}_${encoded}`;
7066
- }
7067
7099
  var DepositEventType = /* @__PURE__ */ ((DepositEventType2) => {
7068
7100
  DepositEventType2["ONRAMP_SESSION_CREATED"] = "onramp_session.created";
7069
7101
  return DepositEventType2;
@@ -13468,6 +13500,7 @@ var import_jsx_runtime64 = require("react/jsx-runtime");
13468
13500
  var import_jsx_runtime65 = require("react/jsx-runtime");
13469
13501
  var React302 = __toESM(require("react"), 1);
13470
13502
  var import_react_query14 = require("@tanstack/react-query");
13503
+ var import_react_query15 = require("@tanstack/react-query");
13471
13504
  var import_jsx_runtime66 = require("react/jsx-runtime");
13472
13505
  var import_jsx_runtime67 = require("react/jsx-runtime");
13473
13506
  var import_jsx_runtime68 = require("react/jsx-runtime");
@@ -13477,19 +13510,19 @@ var import_jsx_runtime70 = require("react/jsx-runtime");
13477
13510
  var import_jsx_runtime71 = require("react/jsx-runtime");
13478
13511
  var import_jsx_runtime72 = require("react/jsx-runtime");
13479
13512
  var import_react28 = require("react");
13480
- var import_react_query15 = require("@tanstack/react-query");
13513
+ var import_react_query16 = require("@tanstack/react-query");
13481
13514
  var import_jsx_runtime73 = require("react/jsx-runtime");
13482
13515
  var import_react29 = require("react");
13483
- var import_react_query16 = require("@tanstack/react-query");
13484
13516
  var import_react_query17 = require("@tanstack/react-query");
13485
13517
  var import_react_query18 = require("@tanstack/react-query");
13486
13518
  var import_react_query19 = require("@tanstack/react-query");
13519
+ var import_react_query20 = require("@tanstack/react-query");
13487
13520
  var import_react30 = require("react");
13488
13521
  var import_jsx_runtime74 = require("react/jsx-runtime");
13489
13522
  var import_react31 = require("react");
13490
- var import_react_query20 = require("@tanstack/react-query");
13491
- var import_react32 = require("react");
13492
13523
  var import_react_query21 = require("@tanstack/react-query");
13524
+ var import_react32 = require("react");
13525
+ var import_react_query22 = require("@tanstack/react-query");
13493
13526
  var import_jsx_runtime75 = require("react/jsx-runtime");
13494
13527
  var import_jsx_runtime76 = require("react/jsx-runtime");
13495
13528
  var import_react33 = require("react");
@@ -13500,8 +13533,32 @@ var import_jsx_runtime79 = require("react/jsx-runtime");
13500
13533
  function cn(...inputs) {
13501
13534
  return twMerge(clsx(inputs));
13502
13535
  }
13503
- var WALLET_CHAIN_TYPE_STORAGE_KEY = "unifold_last_wallet_type";
13536
+ var WALLET_STATE_STORAGE_KEY = "unifold_wallet_state";
13537
+ var LEGACY_WALLET_KEYS = [
13538
+ "unifold_last_wallet_type",
13539
+ "unifold_last_connected_wallet"
13540
+ ];
13504
13541
  var WALLET_USER_DISCONNECTED_KEY = "unifold_wallet_user_disconnected";
13542
+ var SOLANA_WALLET_TYPES = /* @__PURE__ */ new Set([
13543
+ "phantom-solana",
13544
+ "solflare",
13545
+ "backpack",
13546
+ "glow"
13547
+ ]);
13548
+ var ETHEREUM_WALLET_TYPES = /* @__PURE__ */ new Set([
13549
+ "metamask",
13550
+ "phantom-ethereum",
13551
+ "coinbase",
13552
+ "trust",
13553
+ "rainbow",
13554
+ "rabby",
13555
+ "okx"
13556
+ ]);
13557
+ function walletTypeToChain(t12) {
13558
+ if (SOLANA_WALLET_TYPES.has(t12)) return "solana";
13559
+ if (ETHEREUM_WALLET_TYPES.has(t12)) return "ethereum";
13560
+ return void 0;
13561
+ }
13505
13562
  function getUserDisconnectedWallet() {
13506
13563
  if (typeof window === "undefined") return false;
13507
13564
  try {
@@ -13521,26 +13578,35 @@ function setUserDisconnectedWallet(disconnected) {
13521
13578
  } catch {
13522
13579
  }
13523
13580
  }
13524
- function getStoredWalletChainType() {
13581
+ function getStoredWalletState() {
13525
13582
  if (typeof window === "undefined") return void 0;
13526
13583
  try {
13527
- const stored = localStorage.getItem(WALLET_CHAIN_TYPE_STORAGE_KEY);
13528
- if (stored === "ethereum" || stored === "solana") return stored;
13584
+ const raw = localStorage.getItem(WALLET_STATE_STORAGE_KEY);
13585
+ if (!raw) return void 0;
13586
+ const chainType = walletTypeToChain(raw);
13587
+ if (!chainType) {
13588
+ localStorage.removeItem(WALLET_STATE_STORAGE_KEY);
13589
+ return void 0;
13590
+ }
13591
+ return { walletType: raw, chainType };
13529
13592
  } catch {
13593
+ return void 0;
13530
13594
  }
13531
- return void 0;
13532
13595
  }
13533
- function setStoredWalletChainType(chainType) {
13596
+ function setStoredWalletState(walletType) {
13534
13597
  if (typeof window === "undefined") return;
13598
+ if (!walletTypeToChain(walletType)) return;
13535
13599
  try {
13536
- localStorage.setItem(WALLET_CHAIN_TYPE_STORAGE_KEY, chainType);
13600
+ localStorage.setItem(WALLET_STATE_STORAGE_KEY, walletType);
13601
+ for (const key of LEGACY_WALLET_KEYS) localStorage.removeItem(key);
13537
13602
  } catch {
13538
13603
  }
13539
13604
  }
13540
- function clearStoredWalletChainType() {
13605
+ function clearStoredWalletState() {
13541
13606
  if (typeof window === "undefined") return;
13542
13607
  try {
13543
- localStorage.removeItem(WALLET_CHAIN_TYPE_STORAGE_KEY);
13608
+ localStorage.removeItem(WALLET_STATE_STORAGE_KEY);
13609
+ for (const key of LEGACY_WALLET_KEYS) localStorage.removeItem(key);
13544
13610
  } catch {
13545
13611
  }
13546
13612
  }
@@ -13900,6 +13966,36 @@ function ThemeProvider({
13900
13966
  );
13901
13967
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ThemeContext.Provider, { value: contextValue, children });
13902
13968
  }
13969
+ function AccentColorOverride({
13970
+ accentColor,
13971
+ accentForeground,
13972
+ children
13973
+ }) {
13974
+ const parent = useTheme();
13975
+ const value = React37.useMemo(() => {
13976
+ if (!accentColor) return parent;
13977
+ const foreground = accentForeground ?? parent.colors.primaryForeground;
13978
+ const nextColors = {
13979
+ ...parent.colors,
13980
+ primary: accentColor,
13981
+ primaryForeground: foreground
13982
+ };
13983
+ const nextComponents = {
13984
+ ...parent.components,
13985
+ button: {
13986
+ ...parent.components.button,
13987
+ primaryBackground: accentColor,
13988
+ primaryText: foreground
13989
+ },
13990
+ card: {
13991
+ ...parent.components.card,
13992
+ iconBackgroundColor: `${accentColor}26`
13993
+ }
13994
+ };
13995
+ return { ...parent, colors: nextColors, components: nextComponents };
13996
+ }, [parent, accentColor, accentForeground]);
13997
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ThemeContext.Provider, { value, children });
13998
+ }
13903
13999
  function useTheme() {
13904
14000
  const context = React37.useContext(ThemeContext);
13905
14001
  if (!context) {
@@ -14103,6 +14199,60 @@ function useDepositAddress(params) {
14103
14199
  // 1s, 2s, 4s (max 10s)
14104
14200
  });
14105
14201
  }
14202
+ var normalize = (value) => value?.toLowerCase();
14203
+ function sourceTokenMatchesDefaultSource(token, defaultSource) {
14204
+ if (!token || !defaultSource.defaultSourceChainType || !defaultSource.defaultSourceChainId) {
14205
+ return false;
14206
+ }
14207
+ if (token.chain_type !== defaultSource.defaultSourceChainType || token.chain_id !== defaultSource.defaultSourceChainId) {
14208
+ return false;
14209
+ }
14210
+ if (defaultSource.defaultSourceTokenAddress && normalize(token.token_address) === normalize(defaultSource.defaultSourceTokenAddress)) {
14211
+ return true;
14212
+ }
14213
+ if (defaultSource.defaultSourceTokenAddress) {
14214
+ return false;
14215
+ }
14216
+ return !!defaultSource.defaultSourceSymbol && normalize(token.symbol) === normalize(defaultSource.defaultSourceSymbol);
14217
+ }
14218
+ function isDefaultSourceBalance(balance, defaultSource) {
14219
+ return isBalanceEligible(balance) && sourceTokenMatchesDefaultSource(getTokenFromBalance(balance), defaultSource);
14220
+ }
14221
+ function compareBalancesWithDefaultSource(a, b, defaultSource) {
14222
+ const aDefault = isDefaultSourceBalance(a, defaultSource);
14223
+ const bDefault = isDefaultSourceBalance(b, defaultSource);
14224
+ if (aDefault && !bDefault) return -1;
14225
+ if (!aDefault && bDefault) return 1;
14226
+ const aEligible = isBalanceEligible(a);
14227
+ const bEligible = isBalanceEligible(b);
14228
+ if (aEligible && !bEligible) return -1;
14229
+ if (!aEligible && bEligible) return 1;
14230
+ return 0;
14231
+ }
14232
+ function resolveDefaultSourceSymbol(supportedTokens, defaultSource) {
14233
+ if (!supportedTokens?.length || !defaultSource.defaultSourceChainType || !defaultSource.defaultSourceChainId) {
14234
+ return null;
14235
+ }
14236
+ if (defaultSource.defaultSourceTokenAddress) {
14237
+ for (const token of supportedTokens) {
14238
+ const matchingChain = token.chains.find(
14239
+ (chain) => chain.chain_type === defaultSource.defaultSourceChainType && chain.chain_id === defaultSource.defaultSourceChainId && normalize(chain.token_address) === normalize(defaultSource.defaultSourceTokenAddress)
14240
+ );
14241
+ if (matchingChain) return token.symbol;
14242
+ }
14243
+ }
14244
+ if (!defaultSource.defaultSourceSymbol) return null;
14245
+ for (const token of supportedTokens) {
14246
+ if (normalize(token.symbol) !== normalize(defaultSource.defaultSourceSymbol)) {
14247
+ continue;
14248
+ }
14249
+ const matchingChain = token.chains.find(
14250
+ (chain) => chain.chain_type === defaultSource.defaultSourceChainType && chain.chain_id === defaultSource.defaultSourceChainId
14251
+ );
14252
+ if (matchingChain) return token.symbol;
14253
+ }
14254
+ return null;
14255
+ }
14106
14256
  function formatUsdFromBalancePercent(maxUsdAmount, percent) {
14107
14257
  if (maxUsdAmount <= 0 || percent < 0) return "";
14108
14258
  const raw = maxUsdAmount * percent / 100;
@@ -14897,6 +15047,7 @@ function useDepositPolling({
14897
15047
  clientSecret,
14898
15048
  depositConfirmationMode = "auto_ui",
14899
15049
  depositWalletId,
15050
+ depositWalletIds,
14900
15051
  enabled = true,
14901
15052
  immediateDirectPolling = false,
14902
15053
  onDepositSuccess,
@@ -15042,21 +15193,25 @@ function useDepositPolling({
15042
15193
  setIsPolling(false);
15043
15194
  };
15044
15195
  }, [userId, publishableKey, clientSecret, enabled]);
15196
+ const pollWalletIdsKey = depositWalletIds && depositWalletIds.length > 0 ? Array.from(new Set(depositWalletIds.filter(Boolean))).join(",") : depositWalletId || "";
15045
15197
  (0, import_react12.useEffect)(() => {
15046
- if (!pollingEnabled || !depositWalletId) return;
15198
+ if (!pollingEnabled || !pollWalletIdsKey) return;
15199
+ const ids = pollWalletIdsKey.split(",").filter(Boolean);
15047
15200
  const triggerPoll = async () => {
15048
- try {
15049
- await pollDirectExecutions(
15050
- { deposit_wallet_id: depositWalletId },
15051
- publishableKey
15052
- );
15053
- } catch {
15054
- }
15201
+ await Promise.all(
15202
+ ids.map(
15203
+ (id) => pollDirectExecutions(
15204
+ { deposit_wallet_id: id },
15205
+ publishableKey
15206
+ ).catch(() => {
15207
+ })
15208
+ )
15209
+ );
15055
15210
  };
15056
15211
  triggerPoll();
15057
15212
  const interval = setInterval(triggerPoll, POLL_ENDPOINT_INTERVAL_MS);
15058
15213
  return () => clearInterval(interval);
15059
- }, [pollingEnabled, depositWalletId, publishableKey]);
15214
+ }, [pollingEnabled, pollWalletIdsKey, publishableKey]);
15060
15215
  const handleIveDeposited = () => {
15061
15216
  setPollingEnabled(true);
15062
15217
  setShowWaitingUi(true);
@@ -16245,6 +16400,7 @@ function BuyWithCard({
16245
16400
  if (!selectedProvider) return "0.000000";
16246
16401
  return selectedProvider.destination_amount.toFixed(6);
16247
16402
  };
16403
+ const canOpenProviderSelector = !quotesLoading && quotes.length > 1;
16248
16404
  const selectedCurrencyData = fiatCurrencies.find(
16249
16405
  (c) => c.currency_code.toLowerCase() === currency.toLowerCase()
16250
16406
  );
@@ -16430,9 +16586,12 @@ function BuyWithCard({
16430
16586
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
16431
16587
  "button",
16432
16588
  {
16433
- onClick: () => handleViewChange("quotes"),
16589
+ onClick: () => {
16590
+ if (canOpenProviderSelector) handleViewChange("quotes");
16591
+ },
16434
16592
  disabled: quotesLoading || quotes.length === 0,
16435
- className: "uf-w-full hover:uf-bg-accent uf-transition-colors uf-p-4 uf-group disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
16593
+ "aria-disabled": !canOpenProviderSelector,
16594
+ className: `uf-w-full uf-transition-colors uf-p-4 uf-group disabled:uf-opacity-50 disabled:uf-cursor-not-allowed ${canOpenProviderSelector ? "hover:uf-bg-accent uf-cursor-pointer" : "uf-cursor-default"}`,
16436
16595
  style: { backgroundColor: components.card.backgroundColor, borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` },
16437
16596
  children: quotesLoading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "uf-text-left uf-w-full uf-animate-pulse", children: [
16438
16597
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -16459,7 +16618,7 @@ function BuyWithCard({
16459
16618
  )
16460
16619
  ] })
16461
16620
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "uf-w-full uf-text-left", children: [
16462
- isAutoSelected && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
16621
+ isAutoSelected && canOpenProviderSelector && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
16463
16622
  "div",
16464
16623
  {
16465
16624
  className: "uf-text-xs uf-font-normal uf-mb-2",
@@ -16495,7 +16654,7 @@ function BuyWithCard({
16495
16654
  ),
16496
16655
  selectedProvider.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" }) })
16497
16656
  ] }),
16498
- quotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
16657
+ canOpenProviderSelector && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
16499
16658
  ChevronRight,
16500
16659
  {
16501
16660
  className: "uf-w-4 uf-h-4 group-hover:uf-text-foreground uf-transition-colors uf-flex-shrink-0",
@@ -18616,70 +18775,106 @@ function identifyEthWallet(provider, hint) {
18616
18775
  }
18617
18776
  return { type: "metamask", name: "Wallet", icon: "metamask" };
18618
18777
  }
18778
+ var EIP6963_ID_TO_WALLET_TYPE = {
18779
+ metamask: "metamask",
18780
+ phantom: "phantom-ethereum",
18781
+ coinbase: "coinbase",
18782
+ trust: "trust",
18783
+ rainbow: "rainbow",
18784
+ rabby: "rabby",
18785
+ okx: "okx"
18786
+ };
18787
+ function inferEthWalletType(provider, walletId) {
18788
+ if (EIP6963_ID_TO_WALLET_TYPE[walletId]) return EIP6963_ID_TO_WALLET_TYPE[walletId];
18789
+ const any = provider;
18790
+ if (provider.isPhantom) return "phantom-ethereum";
18791
+ if (any.isCoinbaseWallet) return "coinbase";
18792
+ if (any.isRabby) return "rabby";
18793
+ if (any.isTrust) return "trust";
18794
+ if (any.isRainbow) return "rainbow";
18795
+ if (any.isOkxWallet) return "okx";
18796
+ if (provider.isMetaMask && !provider.isPhantom) return "metamask";
18797
+ return null;
18798
+ }
18799
+ function solanaCandidate(provider, type, name, icon) {
18800
+ return {
18801
+ walletType: type,
18802
+ detect: async () => {
18803
+ if (!provider) return null;
18804
+ if (provider.isConnected && provider.publicKey) {
18805
+ return { type, name, address: provider.publicKey.toString(), icon };
18806
+ }
18807
+ try {
18808
+ const resp = await provider.connect({ onlyIfTrusted: true });
18809
+ if (resp.publicKey) {
18810
+ return { type, name, address: resp.publicKey.toString(), icon };
18811
+ }
18812
+ } catch {
18813
+ }
18814
+ return null;
18815
+ }
18816
+ };
18817
+ }
18818
+ function ethereumCandidate(provider, walletId) {
18819
+ return {
18820
+ walletType: inferEthWalletType(provider, walletId),
18821
+ detect: async () => {
18822
+ try {
18823
+ const accounts = await provider.request({ method: "eth_accounts" });
18824
+ if (!accounts?.length) return null;
18825
+ const resolved = identifyEthWallet(provider, walletId);
18826
+ return { ...resolved, address: accounts[0] };
18827
+ } catch {
18828
+ return null;
18829
+ }
18830
+ }
18831
+ };
18832
+ }
18833
+ function buildCandidates(win, chainType) {
18834
+ const candidates = [];
18835
+ if (!chainType || chainType === "solana") {
18836
+ candidates.push(
18837
+ solanaCandidate(win.phantom?.solana, "phantom-solana", "Phantom", "phantom"),
18838
+ solanaCandidate(win.solflare, "solflare", "Solflare", "solflare"),
18839
+ solanaCandidate(win.backpack, "backpack", "Backpack", "backpack"),
18840
+ solanaCandidate(win.glow, "glow", "Glow", "glow")
18841
+ );
18842
+ }
18843
+ if (!chainType || chainType === "ethereum") {
18844
+ const seen = /* @__PURE__ */ new Set();
18845
+ const addEth = (provider, walletId) => {
18846
+ if (!provider || seen.has(provider)) return;
18847
+ seen.add(provider);
18848
+ candidates.push(ethereumCandidate(provider, walletId));
18849
+ };
18850
+ for (const { provider, walletId } of getEip6963Providers()) {
18851
+ addEth(
18852
+ provider,
18853
+ walletId === "unknown" ? "default" : walletId
18854
+ );
18855
+ }
18856
+ addEth(win.phantom?.ethereum, "phantom");
18857
+ addEth(win.coinbaseWalletExtension, "coinbase");
18858
+ addEth(win.okxwallet, "okx");
18859
+ addEth(win.trustwallet?.ethereum, "trust");
18860
+ addEth(win.ethereum, "default");
18861
+ }
18862
+ return candidates;
18863
+ }
18619
18864
  async function detectConnectedBrowserWallet(chainType) {
18620
18865
  if (typeof window === "undefined") return null;
18621
18866
  if (getUserDisconnectedWallet()) return null;
18622
18867
  try {
18623
18868
  const win = window;
18624
- if (!chainType || chainType === "solana") {
18625
- const trySilentSolana = async (provider, type, name, icon) => {
18626
- if (!provider) return null;
18627
- if (provider.isConnected && provider.publicKey) {
18628
- return { type, name, address: provider.publicKey.toString(), icon };
18629
- }
18630
- try {
18631
- const resp = await provider.connect({ onlyIfTrusted: true });
18632
- if (resp.publicKey) {
18633
- return { type, name, address: resp.publicKey.toString(), icon };
18634
- }
18635
- } catch {
18636
- }
18637
- return null;
18638
- };
18639
- const solanaCandidates = [
18640
- [win.phantom?.solana, "phantom-solana", "Phantom", "phantom"],
18641
- [win.solflare, "solflare", "Solflare", "solflare"],
18642
- [win.backpack, "backpack", "Backpack", "backpack"],
18643
- [win.glow, "glow", "Glow", "glow"]
18644
- ];
18645
- for (const [provider, type, name, icon] of solanaCandidates) {
18646
- const found = await trySilentSolana(provider, type, name, icon);
18647
- if (found) return found;
18648
- }
18649
- }
18650
- if (!chainType || chainType === "ethereum") {
18651
- const allProviders = [];
18652
- const eip6963 = getEip6963Providers();
18653
- for (const { provider, walletId } of eip6963) {
18654
- allProviders.push({
18655
- provider,
18656
- walletId: walletId === "unknown" ? "default" : walletId
18657
- });
18658
- }
18659
- if (allProviders.length === 0) {
18660
- if (win.phantom?.ethereum) {
18661
- allProviders.push({ provider: win.phantom.ethereum, walletId: "phantom" });
18662
- }
18663
- if (win.okxwallet) {
18664
- allProviders.push({ provider: win.okxwallet, walletId: "okx" });
18665
- }
18666
- if (win.coinbaseWalletExtension) {
18667
- allProviders.push({ provider: win.coinbaseWalletExtension, walletId: "coinbase" });
18668
- }
18669
- if (win.ethereum && !allProviders.some((p) => p.provider === win.ethereum)) {
18670
- allProviders.push({ provider: win.ethereum, walletId: "default" });
18671
- }
18672
- }
18673
- for (const { provider, walletId } of allProviders) {
18674
- if (!provider) continue;
18675
- try {
18676
- const accounts = await provider.request({ method: "eth_accounts" });
18677
- if (!accounts || accounts.length === 0) continue;
18678
- const resolved = identifyEthWallet(provider, walletId);
18679
- return { ...resolved, address: accounts[0] };
18680
- } catch {
18681
- }
18682
- }
18869
+ const candidates = buildCandidates(win, chainType);
18870
+ const preferred = getStoredWalletState();
18871
+ if (preferred && (!chainType || preferred.chainType === chainType)) {
18872
+ const idx = candidates.findIndex((c) => c.walletType === preferred.walletType);
18873
+ if (idx > 0) candidates.unshift(...candidates.splice(idx, 1));
18874
+ }
18875
+ for (const c of candidates) {
18876
+ const found = await c.detect();
18877
+ if (found) return found;
18683
18878
  }
18684
18879
  } catch (error) {
18685
18880
  console.error("[detectConnectedBrowserWallet] detection error:", error);
@@ -20825,6 +21020,7 @@ function BrowserWalletButton({
20825
21020
  if (solanaProvider?.isPhantom) {
20826
21021
  const { publicKey } = await solanaProvider.connect();
20827
21022
  setUserDisconnectedWallet(false);
21023
+ setStoredWalletState("phantom-solana");
20828
21024
  setWallet({
20829
21025
  type: "phantom-solana",
20830
21026
  name: "Phantom",
@@ -20844,8 +21040,10 @@ function BrowserWalletButton({
20844
21040
  if (accounts && accounts.length > 0) {
20845
21041
  setUserDisconnectedWallet(false);
20846
21042
  const isPhantom = ethProvider.isPhantom;
21043
+ const walletType = isPhantom ? "phantom-ethereum" : "metamask";
21044
+ setStoredWalletState(walletType);
20847
21045
  setWallet({
20848
- type: isPhantom ? "phantom-ethereum" : "metamask",
21046
+ type: walletType,
20849
21047
  name: isPhantom ? "Phantom" : "MetaMask",
20850
21048
  address: accounts[0],
20851
21049
  icon: isPhantom ? "phantom" : "metamask"
@@ -21155,7 +21353,11 @@ function CoinbaseConnect({
21155
21353
  onDisconnect,
21156
21354
  skipToHoldings,
21157
21355
  canGoBack = true,
21158
- onExecutionsChange
21356
+ onExecutionsChange,
21357
+ defaultSourceChainType,
21358
+ defaultSourceChainId,
21359
+ defaultSourceTokenAddress,
21360
+ defaultSourceSymbol
21159
21361
  }) {
21160
21362
  const { colors: colors2, fonts, components } = useTheme();
21161
21363
  const { projectConfig } = useProjectConfig({ publishableKey });
@@ -21220,6 +21422,21 @@ function CoinbaseConnect({
21220
21422
  params: defaultTokenParams,
21221
21423
  publishableKey
21222
21424
  });
21425
+ const defaultSourceCurrency = (0, import_react20.useMemo)(
21426
+ () => resolveDefaultSourceSymbol(supportedTokensData?.data, {
21427
+ defaultSourceChainType,
21428
+ defaultSourceChainId,
21429
+ defaultSourceTokenAddress,
21430
+ defaultSourceSymbol
21431
+ })?.toLowerCase() ?? null,
21432
+ [
21433
+ supportedTokensData,
21434
+ defaultSourceChainType,
21435
+ defaultSourceChainId,
21436
+ defaultSourceTokenAddress,
21437
+ defaultSourceSymbol
21438
+ ]
21439
+ );
21223
21440
  const sortedHoldings = (0, import_react20.useMemo)(() => {
21224
21441
  const supported = [];
21225
21442
  const unsupported = [];
@@ -21229,13 +21446,42 @@ function CoinbaseConnect({
21229
21446
  if (isSupported) supported.push(account);
21230
21447
  else unsupported.push(account);
21231
21448
  });
21449
+ if (defaultSourceCurrency) {
21450
+ const defaultIndex = supported.findIndex(
21451
+ (account) => account.currency.toLowerCase() === defaultSourceCurrency
21452
+ );
21453
+ if (defaultIndex > 0) {
21454
+ const [defaultHolding] = supported.splice(defaultIndex, 1);
21455
+ supported.unshift(defaultHolding);
21456
+ }
21457
+ }
21232
21458
  return [...supported, ...unsupported];
21233
- }, [holdings, supportedSymbols, exchangeSupportedCurrencies]);
21459
+ }, [
21460
+ holdings,
21461
+ supportedSymbols,
21462
+ exchangeSupportedCurrencies,
21463
+ defaultSourceCurrency
21464
+ ]);
21234
21465
  const selectedHoldingIsSupported = (0, import_react20.useMemo)(() => {
21235
21466
  if (!selectedHolding) return false;
21236
21467
  const currencyLower = selectedHolding.currency.toLowerCase();
21237
21468
  return (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
21238
21469
  }, [selectedHolding, supportedSymbols, exchangeSupportedCurrencies]);
21470
+ (0, import_react20.useEffect)(() => {
21471
+ if (!defaultSourceCurrency || selectedHolding) return;
21472
+ const defaultHolding = sortedHoldings.find((account) => {
21473
+ const currencyLower = account.currency.toLowerCase();
21474
+ return currencyLower === defaultSourceCurrency && (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
21475
+ });
21476
+ if (!defaultHolding) return;
21477
+ setSelectedHolding(defaultHolding);
21478
+ }, [
21479
+ defaultSourceCurrency,
21480
+ selectedHolding,
21481
+ sortedHoldings,
21482
+ supportedSymbols,
21483
+ exchangeSupportedCurrencies
21484
+ ]);
21239
21485
  const exchangeName = selectedExchange?.service_provider_display_name || "Exchange";
21240
21486
  const {
21241
21487
  executions: depositExecutions,
@@ -25384,6 +25630,60 @@ function useDepositQuote(params) {
25384
25630
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
25385
25631
  });
25386
25632
  }
25633
+ function useExternalWallets({
25634
+ publishableKey,
25635
+ enabled = true
25636
+ }) {
25637
+ const { data: wallets = [], isLoading } = (0, import_react_query15.useQuery)({
25638
+ queryKey: ["unifold", "external-wallets", publishableKey],
25639
+ queryFn: () => getExternalWallets(publishableKey).then((res) => res.data),
25640
+ enabled: enabled && !!publishableKey,
25641
+ staleTime: 1e3 * 60 * 30,
25642
+ refetchOnMount: false,
25643
+ refetchOnWindowFocus: false
25644
+ });
25645
+ return { wallets, isLoading };
25646
+ }
25647
+ var WALLET_BRAND_COLORS = {
25648
+ phantom: "#AB9FF2",
25649
+ metamask: "#F6851B",
25650
+ coinbase: "#0052FF",
25651
+ trust: "#3375BB",
25652
+ rainbow: "#5B6CFF",
25653
+ rabby: "#7084FF",
25654
+ okx: "#000000"
25655
+ };
25656
+ function normalizeWalletId(type) {
25657
+ return type.replace(/-(ethereum|solana)$/i, "").toLowerCase();
25658
+ }
25659
+ function getWalletBrandColor(type, mode = "dark") {
25660
+ if (!type) return void 0;
25661
+ const id = normalizeWalletId(type);
25662
+ const color = WALLET_BRAND_COLORS[id];
25663
+ if (!color) return void 0;
25664
+ if (id === "okx") return mode === "dark" ? "#FFFFFF" : "#111111";
25665
+ return color;
25666
+ }
25667
+ function getContrastingTextColor(hex) {
25668
+ const c = hex.replace("#", "");
25669
+ if (c.length !== 6) return "#FFFFFF";
25670
+ const r2 = parseInt(c.slice(0, 2), 16);
25671
+ const g = parseInt(c.slice(2, 4), 16);
25672
+ const b = parseInt(c.slice(4, 6), 16);
25673
+ const luminance = (0.299 * r2 + 0.587 * g + 0.114 * b) / 255;
25674
+ return luminance > 0.6 ? "#13111C" : "#FFFFFF";
25675
+ }
25676
+ function isMobileDevice() {
25677
+ if (typeof navigator === "undefined") return false;
25678
+ return /android|iphone|ipad|ipod|mobile/i.test(navigator.userAgent);
25679
+ }
25680
+ function getMobilePlatform() {
25681
+ if (typeof navigator === "undefined") return null;
25682
+ const ua = navigator.userAgent;
25683
+ if (/iphone|ipad|ipod/i.test(ua)) return "ios";
25684
+ if (/android/i.test(ua)) return "android";
25685
+ return null;
25686
+ }
25387
25687
  var WALLET_ICONS = {
25388
25688
  metamask: MetamaskIcon,
25389
25689
  phantom: PhantomIcon,
@@ -26389,18 +26689,46 @@ var WALLET_ICONS3 = {
26389
26689
  backpack: BackpackIcon,
26390
26690
  glow: GlowIcon
26391
26691
  };
26392
- var WALLET_DEFINITIONS = [
26393
- { id: "phantom", name: "Phantom", networks: ["ethereum", "solana"], installUrl: "https://phantom.app/" },
26394
- { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum", "solana"], installUrl: "https://www.coinbase.com/wallet" },
26395
- { id: "trust", name: "Trust Wallet", networks: ["ethereum", "solana"], installUrl: "https://trustwallet.com/" },
26396
- { id: "metamask", name: "MetaMask", networks: ["ethereum"], installUrl: "https://metamask.io/download/" },
26397
- { id: "rainbow", name: "Rainbow", networks: ["ethereum"], installUrl: "https://rainbow.me/" },
26398
- { id: "rabby", name: "Rabby", networks: ["ethereum"], installUrl: "https://rabby.io/" },
26399
- { id: "okx", name: "OKX Wallet", networks: ["ethereum"], installUrl: "https://www.okx.com/web3" },
26400
- { id: "solflare", name: "Solflare", networks: ["solana"], installUrl: "https://solflare.com/" },
26401
- { id: "backpack", name: "Backpack", networks: ["solana"], installUrl: "https://backpack.app/" },
26402
- { id: "glow", name: "Glow", networks: ["solana"], installUrl: "https://glow.app/" }
26692
+ var FALLBACK_WALLET_DEFINITIONS = [
26693
+ { id: "phantom", name: "Phantom", networks: ["ethereum", "solana"], installUrl: "https://phantom.app/", supportsMobileBrowse: true },
26694
+ { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum", "solana"], installUrl: "https://www.coinbase.com/wallet", supportsMobileBrowse: true },
26695
+ { id: "trust", name: "Trust Wallet", networks: ["ethereum", "solana"], installUrl: "https://trustwallet.com/", supportsMobileBrowse: true },
26696
+ { id: "metamask", name: "MetaMask", networks: ["ethereum"], installUrl: "https://metamask.io/download/", supportsMobileBrowse: true },
26697
+ { id: "rainbow", name: "Rainbow", networks: ["ethereum"], installUrl: "https://rainbow.me/", supportsMobileBrowse: true },
26698
+ { id: "rabby", name: "Rabby", networks: ["ethereum"], installUrl: "https://apps.apple.com/app/rabby-wallet/id6450663781", supportsMobileBrowse: true },
26699
+ { id: "okx", name: "OKX Wallet", networks: ["ethereum"], installUrl: "https://www.okx.com/web3", supportsMobileBrowse: true, mobileBrowsePlatforms: ["ios"] }
26403
26700
  ];
26701
+ function getMobileInstallUrl(walletId, defaultUrl) {
26702
+ if (!isMobileDevice()) return defaultUrl;
26703
+ const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
26704
+ const isIOS = /iPhone|iPad|iPod/i.test(ua);
26705
+ const stores = {
26706
+ rabby: {
26707
+ ios: "https://apps.apple.com/app/rabby-wallet/id6450663781",
26708
+ android: "https://play.google.com/store/apps/details?id=com.debank.rabbymobile"
26709
+ },
26710
+ glow: {
26711
+ ios: "https://apps.apple.com/us/app/glow-solana-wallet/id1599584512",
26712
+ android: "https://play.google.com/store/apps/details?id=com.luma.wallet.prod"
26713
+ }
26714
+ };
26715
+ const entry = stores[walletId];
26716
+ if (!entry) return defaultUrl;
26717
+ return isIOS ? entry.ios : entry.android;
26718
+ }
26719
+ function normalizeTokenAddress(address) {
26720
+ const normalized = (address ?? "").toLowerCase();
26721
+ if (normalized === "" || normalized === "native" || normalized === "0x0000000000000000000000000000000000000000") {
26722
+ return "native";
26723
+ }
26724
+ return normalized;
26725
+ }
26726
+ function balancesRepresentSameToken(a, b) {
26727
+ const tokenA = getTokenFromBalance(a);
26728
+ const tokenB = getTokenFromBalance(b);
26729
+ if (!tokenA || !tokenB) return false;
26730
+ return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
26731
+ }
26404
26732
  function getSolanaProviders() {
26405
26733
  if (typeof window === "undefined") return {};
26406
26734
  const win = window;
@@ -26423,7 +26751,7 @@ function getLegacyEvmProviders() {
26423
26751
  okxEthereum: win.okxwallet
26424
26752
  };
26425
26753
  }
26426
- function detectAvailableWallets(filterChainType) {
26754
+ function detectAvailableWallets(definitions, filterChainType) {
26427
26755
  const solProviders = getSolanaProviders();
26428
26756
  const legacyEvm = getLegacyEvmProviders();
26429
26757
  const eip6963List = getEip6963Providers();
@@ -26449,7 +26777,7 @@ function detectAvailableWallets(filterChainType) {
26449
26777
  return false;
26450
26778
  }
26451
26779
  });
26452
- return WALLET_DEFINITIONS.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
26780
+ return definitions.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
26453
26781
  let isInstalled = false;
26454
26782
  const detectedNetworks = [];
26455
26783
  switch (wallet.id) {
@@ -26543,13 +26871,17 @@ function WalletConnect({
26543
26871
  checkoutRemainingBaseUnits,
26544
26872
  stablecoinParity = false,
26545
26873
  productType,
26874
+ defaultSourceChainType,
26875
+ defaultSourceChainId,
26876
+ defaultSourceTokenAddress,
26877
+ defaultSourceSymbol,
26546
26878
  onBack: parentOnBack,
26547
26879
  onClose,
26548
26880
  canGoBack = true,
26549
26881
  depositWalletsLoading = false,
26550
26882
  onExecutionsChange
26551
26883
  }) {
26552
- const { colors: colors2, fonts, components } = useTheme();
26884
+ const { colors: colors2, fonts, components, mode } = useTheme();
26553
26885
  const walletProvidedAtMount = React302.useRef(!!initialWalletInfo && !!initialDepositWallet);
26554
26886
  const [activeWalletInfo, setActiveWalletInfo] = React302.useState(initialWalletInfo ?? null);
26555
26887
  const [activeDepositWallet, setActiveDepositWallet] = React302.useState(initialDepositWallet ?? null);
@@ -26573,7 +26905,37 @@ function WalletConnect({
26573
26905
  setEip6963ProviderCount(providers.length);
26574
26906
  });
26575
26907
  }, []);
26576
- const availableWallets = React302.useMemo(() => detectAvailableWallets(), [eip6963ProviderCount]);
26908
+ const { wallets: backendWallets } = useExternalWallets({ publishableKey });
26909
+ const walletDefinitions = React302.useMemo(
26910
+ () => backendWallets.length > 0 ? backendWallets.map((w) => ({
26911
+ id: w.id,
26912
+ name: w.name,
26913
+ networks: w.chain_types,
26914
+ installUrl: w.install_url,
26915
+ supportsMobileBrowse: w.supports_mobile_browse,
26916
+ mobileBrowsePlatforms: w.mobile_browse_platforms ?? null
26917
+ })) : FALLBACK_WALLET_DEFINITIONS,
26918
+ [backendWallets]
26919
+ );
26920
+ const availableWallets = React302.useMemo(
26921
+ () => detectAvailableWallets(walletDefinitions),
26922
+ [walletDefinitions, eip6963ProviderCount]
26923
+ );
26924
+ const [isMobile, setIsMobile] = React302.useState(false);
26925
+ React302.useEffect(() => {
26926
+ setIsMobile(isMobileDevice());
26927
+ }, []);
26928
+ const mobileDepositAddresses = React302.useMemo(
26929
+ () => (depositWallets ?? []).map((w) => ({ chain_type: w.chain_type, address: w.address })),
26930
+ [depositWallets]
26931
+ );
26932
+ const mobileDepositWalletIds = React302.useMemo(
26933
+ () => (depositWallets ?? []).filter((w) => w.chain_type === "ethereum" || w.chain_type === "solana").map((w) => w.id),
26934
+ [depositWallets]
26935
+ );
26936
+ const [mobileRedirect, setMobileRedirect] = React302.useState(null);
26937
+ const [pendingMobileWallet, setPendingMobileWallet] = React302.useState(null);
26938
+ const [awaitingMobileDeposit, setAwaitingMobileDeposit] = React302.useState(false);
26577
26939
  React302.useEffect(() => {
26578
26940
  if (!standalone || autoResolved || detectingWallet) return;
26579
26941
  if (!detectedWallet) {
@@ -26632,10 +26994,37 @@ function WalletConnect({
26632
26994
  transform: isTransitioning ? "translateY(4px)" : "translateY(0)",
26633
26995
  transition: "opacity 150ms ease, transform 150ms ease"
26634
26996
  };
26635
- const handleWalletClick = (wallet) => {
26636
- if (!wallet.isInstalled) {
26637
- window.open(wallet.installUrl, "_blank", "noopener,noreferrer");
26638
- return;
26997
+ const openMobileWalletBrowse = async (wallet, depositAddresses) => {
26998
+ try {
26999
+ const res = await getWalletMobileDeepLink(
27000
+ wallet.id,
27001
+ depositAddresses,
27002
+ publishableKey
27003
+ );
27004
+ if (res.deeplink) {
27005
+ setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
27006
+ setAwaitingMobileDeposit(true);
27007
+ transitionTo("mobile_redirect");
27008
+ window.location.href = res.deeplink;
27009
+ return true;
27010
+ }
27011
+ } catch {
27012
+ }
27013
+ return false;
27014
+ };
27015
+ const handleWalletClick = async (wallet) => {
27016
+ if (!wallet.isInstalled) {
27017
+ const platform2 = getMobilePlatform();
27018
+ const platformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(platform2 ?? "");
27019
+ if (isMobileDevice() && wallet.supportsMobileBrowse !== false && platformAllowed) {
27020
+ if (mobileDepositAddresses.length === 0) {
27021
+ setPendingMobileWallet(wallet);
27022
+ return;
27023
+ }
27024
+ if (await openMobileWalletBrowse(wallet, mobileDepositAddresses)) return;
27025
+ }
27026
+ window.open(getMobileInstallUrl(wallet.id, wallet.installUrl), "_blank", "noopener,noreferrer");
27027
+ return;
26639
27028
  }
26640
27029
  setSelectedWalletDef(wallet);
26641
27030
  setWalletError(null);
@@ -26650,6 +27039,27 @@ function WalletConnect({
26650
27039
  if (!selectedWalletDef) return;
26651
27040
  handleConnectWallet(selectedWalletDef, network);
26652
27041
  };
27042
+ React302.useEffect(() => {
27043
+ if (!pendingMobileWallet) return;
27044
+ if (mobileDepositAddresses.length > 0) {
27045
+ const wallet = pendingMobileWallet;
27046
+ setPendingMobileWallet(null);
27047
+ void (async () => {
27048
+ if (!await openMobileWalletBrowse(wallet, mobileDepositAddresses)) {
27049
+ window.open(getMobileInstallUrl(wallet.id, wallet.installUrl), "_blank", "noopener,noreferrer");
27050
+ }
27051
+ })();
27052
+ return;
27053
+ }
27054
+ const timeout = setTimeout(() => {
27055
+ setPendingMobileWallet((current) => {
27056
+ if (!current) return null;
27057
+ window.open(getMobileInstallUrl(current.id, current.installUrl), "_blank", "noopener,noreferrer");
27058
+ return null;
27059
+ });
27060
+ }, 8e3);
27061
+ return () => clearTimeout(timeout);
27062
+ }, [pendingMobileWallet, mobileDepositAddresses]);
26653
27063
  const handleConnectWallet = async (wallet, network) => {
26654
27064
  setConnectingNetwork(network);
26655
27065
  transitionTo("connecting");
@@ -26703,6 +27113,7 @@ function WalletConnect({
26703
27113
  metamask: "metamask"
26704
27114
  };
26705
27115
  const walletType = walletIdToType[wallet.id] || "metamask";
27116
+ setStoredWalletState(walletType);
26706
27117
  connectedInfo = { type: walletType, name: wallet.name, address: accounts[0], icon: wallet.id };
26707
27118
  } else {
26708
27119
  const solProviders = getSolanaProviders();
@@ -26731,6 +27142,7 @@ function WalletConnect({
26731
27142
  const response = await provider.connect();
26732
27143
  setUserDisconnectedWallet(false);
26733
27144
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
27145
+ setStoredWalletState(walletType);
26734
27146
  connectedInfo = { type: walletType, name: wallet.name, address: response.publicKey.toString(), icon: wallet.id };
26735
27147
  }
26736
27148
  const walletChainType = network === "solana" ? "solana" : "ethereum";
@@ -26792,14 +27204,32 @@ function WalletConnect({
26792
27204
  userId,
26793
27205
  publishableKey,
26794
27206
  clientSecret,
27207
+ // In-tab flow: poll the single connected deposit wallet.
26795
27208
  depositWalletId: activeDepositWallet?.id ?? "",
26796
- enabled: hasSignedTransaction && !!activeDepositWallet,
27209
+ // Mobile redirect flow: the deposit chain isn't known up front, so /poll every
27210
+ // chain's deposit wallet. Detection still happens via the single /query by
27211
+ // external_user_id, which already spans all chains.
27212
+ depositWalletIds: awaitingMobileDeposit ? mobileDepositWalletIds : void 0,
27213
+ enabled: hasSignedTransaction && !!activeDepositWallet || awaitingMobileDeposit,
26797
27214
  onDepositSuccess,
26798
27215
  onDepositError
26799
27216
  });
26800
27217
  React302.useEffect(() => {
26801
27218
  onExecutionsChange?.(depositExecutions);
26802
27219
  }, [depositExecutions, onExecutionsChange]);
27220
+ const latestDepositExecution = React302.useMemo(() => {
27221
+ if (depositExecutions.length === 0) return null;
27222
+ return [...depositExecutions].sort((a, b) => {
27223
+ const ta = a.created_at ? new Date(a.created_at).getTime() : 0;
27224
+ const tb = b.created_at ? new Date(b.created_at).getTime() : 0;
27225
+ return tb - ta;
27226
+ })[0];
27227
+ }, [depositExecutions]);
27228
+ React302.useEffect(() => {
27229
+ if (awaitingMobileDeposit && latestDepositExecution && (viewRef.current === "mobile_redirect" || viewRef.current === "connecting")) {
27230
+ transitionTo("mobile_deposit_status");
27231
+ }
27232
+ }, [awaitingMobileDeposit, latestDepositExecution, transitionTo]);
26803
27233
  React302.useEffect(() => {
26804
27234
  if (!prefillAmountUsd || !tokenChainDetails || view !== "enter_amount") return;
26805
27235
  const minDeposit = tokenChainDetails.minimum_deposit_amount_usd || 0;
@@ -26845,18 +27275,33 @@ function WalletConnect({
26845
27275
  getAddressBalances(activeWalletInfo.address, sct, publishableKey).then((response) => {
26846
27276
  if (cancelled) return;
26847
27277
  const nonZero = response.balances.filter((b) => b.amount !== "0");
26848
- const sorted = [...nonZero].sort((a, b) => {
26849
- const ae = isBalanceEligible(a);
26850
- const be = isBalanceEligible(b);
26851
- if (ae && !be) return -1;
26852
- if (!ae && be) return 1;
26853
- return 0;
26854
- });
27278
+ const defaultSource = {
27279
+ defaultSourceChainType,
27280
+ defaultSourceChainId,
27281
+ defaultSourceTokenAddress,
27282
+ defaultSourceSymbol
27283
+ };
27284
+ const sorted = [...nonZero].sort(
27285
+ (a, b) => compareBalancesWithDefaultSource(a, b, defaultSource)
27286
+ );
26855
27287
  setBalances(sorted);
26856
27288
  const totalUsd = nonZero.reduce((sum, b) => b.amount_usd ? sum + parseFloat(b.amount_usd) : sum, 0);
26857
27289
  if (totalUsd > 0) setTotalBalanceUsd(totalUsd.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
26858
27290
  const eligible = sorted.filter(isBalanceEligible);
26859
- if (eligible.length === 1) setSelectedBalance(eligible[0]);
27291
+ const defaultBalance = sorted.find(
27292
+ (balance) => isDefaultSourceBalance(balance, defaultSource)
27293
+ );
27294
+ setSelectedBalance((current) => {
27295
+ if (current) {
27296
+ const currentInNewBalances = sorted.find(
27297
+ (balance) => balancesRepresentSameToken(balance, current)
27298
+ );
27299
+ if (currentInNewBalances) return currentInNewBalances;
27300
+ }
27301
+ if (defaultBalance) return defaultBalance;
27302
+ if (eligible.length === 1) return eligible[0];
27303
+ return null;
27304
+ });
26860
27305
  }).catch((err) => {
26861
27306
  if (!cancelled) {
26862
27307
  console.error("[WalletConnect] Error fetching balances:", err);
@@ -26868,7 +27313,15 @@ function WalletConnect({
26868
27313
  return () => {
26869
27314
  cancelled = true;
26870
27315
  };
26871
- }, [activeWalletInfo?.address, activeDepositWallet?.chain_type, publishableKey]);
27316
+ }, [
27317
+ activeWalletInfo?.address,
27318
+ activeDepositWallet?.chain_type,
27319
+ publishableKey,
27320
+ defaultSourceChainType,
27321
+ defaultSourceChainId,
27322
+ defaultSourceTokenAddress,
27323
+ defaultSourceSymbol
27324
+ ]);
26872
27325
  const usdToTokenRate = React302.useMemo(() => {
26873
27326
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken) return 0;
26874
27327
  const balanceAmount = Number(selectedBalance.amount) / 10 ** selectedToken.decimals;
@@ -26907,6 +27360,16 @@ function WalletConnect({
26907
27360
  setSelectedWalletDef(null);
26908
27361
  setConnectingNetwork(null);
26909
27362
  break;
27363
+ case "mobile_redirect":
27364
+ transitionTo("select_wallet");
27365
+ setMobileRedirect(null);
27366
+ setAwaitingMobileDeposit(false);
27367
+ break;
27368
+ case "mobile_deposit_status":
27369
+ transitionTo("select_wallet");
27370
+ setMobileRedirect(null);
27371
+ setAwaitingMobileDeposit(false);
27372
+ break;
26910
27373
  case "select_token":
26911
27374
  if (walletProvidedAtMount.current) parentOnBack?.();
26912
27375
  else transitionTo("select_wallet");
@@ -27092,33 +27555,40 @@ function WalletConnect({
27092
27555
  return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27093
27556
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DepositHeader, { title: "Connect Wallet", showBack: canGoBack, onBack: handleBack, onClose }),
27094
27557
  /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-pb-4", children: [
27095
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("p", { className: "uf-text-sm uf-text-center uf-pb-4", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "Select a wallet to connect" }),
27096
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-space-y-2", style: { maxHeight: 330, overflowY: "auto" }, children: availableWallets.map((wallet) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
27097
- "button",
27098
- {
27099
- onClick: () => handleWalletClick(wallet),
27100
- disabled: isWalletConnecting,
27101
- className: "uf-w-full uf-transition-colors uf-p-3 uf-flex uf-items-center uf-justify-between hover:uf-opacity-90 disabled:uf-opacity-50",
27102
- style: { backgroundColor: components.card.backgroundColor, borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` },
27103
- children: [
27104
- /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
27105
- WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(WalletIconWithNetwork, { WalletIcon: WALLET_ICONS3[wallet.id], networks: wallet.networks, size: 40, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
27106
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-text-sm uf-font-medium", style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: wallet.name })
27107
- ] }),
27108
- wallet.isInstalled ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full", style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium }, children: "Detected" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
27109
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "Install" }),
27110
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ExternalLink, { className: "uf-w-3 uf-h-3", style: { color: colors2.foregroundMuted } })
27111
- ] })
27112
- ]
27113
- },
27114
- wallet.id
27115
- )) }),
27558
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("p", { className: "uf-text-sm uf-text-center uf-pb-4", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: isMobile ? "Open this page in your wallet's app to connect" : "Select a wallet to connect" }),
27559
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-space-y-2", style: { maxHeight: 330, overflowY: "auto" }, children: availableWallets.map((wallet) => {
27560
+ const walletPlatformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
27561
+ const showOpenInApp = isMobile && !wallet.isInstalled && wallet.supportsMobileBrowse !== false && walletPlatformAllowed;
27562
+ const isPending = pendingMobileWallet?.id === wallet.id;
27563
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
27564
+ "button",
27565
+ {
27566
+ onClick: () => void handleWalletClick(wallet),
27567
+ disabled: isWalletConnecting || !!pendingMobileWallet,
27568
+ className: "uf-w-full uf-transition-colors uf-p-3 uf-flex uf-items-center uf-justify-between hover:uf-opacity-90 disabled:uf-opacity-50",
27569
+ style: { backgroundColor: components.card.backgroundColor, borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` },
27570
+ children: [
27571
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
27572
+ WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(WalletIconWithNetwork, { WalletIcon: WALLET_ICONS3[wallet.id], networks: wallet.networks, size: 40, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
27573
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-text-sm uf-font-medium", style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: wallet.name })
27574
+ ] }),
27575
+ isPending ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin", style: { color: colors2.primary } }) : wallet.isInstalled ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full", style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium }, children: "Detected" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
27576
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: showOpenInApp ? "Open" : "Install" }),
27577
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ExternalLink, { className: "uf-w-3 uf-h-3", style: { color: colors2.foregroundMuted } })
27578
+ ] })
27579
+ ]
27580
+ },
27581
+ wallet.id
27582
+ );
27583
+ }) }),
27116
27584
  walletError && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-text-center uf-text-sm uf-mt-4 uf-px-4", style: { color: "#ef4444" }, children: walletError })
27117
27585
  ] })
27118
27586
  ] });
27119
27587
  }
27588
+ const preConnectAccent = selectedWalletDef ? getWalletBrandColor(selectedWalletDef.id, mode) : void 0;
27589
+ const preConnectFg = preConnectAccent ? getContrastingTextColor(preConnectAccent) : void 0;
27120
27590
  if (view === "select_network" && selectedWalletDef) {
27121
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27591
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27122
27592
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DepositHeader, { title: "Select Network", showBack: true, onBack: handleBack, onClose }),
27123
27593
  /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-pb-4", children: [
27124
27594
  /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-pb-4", children: [
@@ -27148,10 +27618,10 @@ function WalletConnect({
27148
27618
  )) }),
27149
27619
  walletError && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-text-center uf-text-sm uf-mt-4 uf-px-4", style: { color: "#ef4444" }, children: walletError })
27150
27620
  ] })
27151
- ] });
27621
+ ] }) });
27152
27622
  }
27153
27623
  if (view === "connecting") {
27154
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27624
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27155
27625
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DepositHeader, { title: "Connecting...", showBack: true, onBack: handleBack, onClose }),
27156
27626
  /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16", children: [
27157
27627
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(LoaderCircle, { className: "uf-w-12 uf-h-12 uf-animate-spin uf-mb-4", style: { color: colors2.primary } }),
@@ -27162,24 +27632,132 @@ function WalletConnect({
27162
27632
  ] }),
27163
27633
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-text-sm uf-mt-2", style: { color: colors2.foregroundMuted }, children: "Please approve the connection in your wallet" })
27164
27634
  ] })
27165
- ] });
27635
+ ] }) });
27636
+ }
27637
+ if (view === "mobile_redirect" && mobileRedirect) {
27638
+ const Icon22 = WALLET_ICONS3[mobileRedirect.walletId];
27639
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27640
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DepositHeader, { title: mobileRedirect.walletName, showBack: true, onBack: handleBack, onClose }),
27641
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-px-6 uf-py-10", children: [
27642
+ Icon22 ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(Icon22, { size: 64, className: "uf-rounded-2xl uf-mb-5" }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-w-16 uf-h-16 uf-rounded-2xl uf-bg-gray-500 uf-mb-5" }),
27643
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
27644
+ "div",
27645
+ {
27646
+ className: "uf-text-base uf-font-medium uf-text-center uf-mb-1",
27647
+ style: { color: colors2.foreground, fontFamily: fonts.medium },
27648
+ children: [
27649
+ "Continue in ",
27650
+ mobileRedirect.walletName
27651
+ ]
27652
+ }
27653
+ ),
27654
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
27655
+ "div",
27656
+ {
27657
+ className: "uf-text-sm uf-text-center uf-mb-6",
27658
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
27659
+ children: [
27660
+ "Complete your deposit in the ",
27661
+ mobileRedirect.walletName,
27662
+ " app"
27663
+ ]
27664
+ }
27665
+ ),
27666
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
27667
+ "button",
27668
+ {
27669
+ type: "button",
27670
+ onClick: () => {
27671
+ window.location.href = mobileRedirect.deeplink;
27672
+ },
27673
+ className: "uf-w-full uf-transition-colors uf-p-3.5 uf-flex uf-items-center uf-justify-center uf-gap-2 hover:uf-opacity-90",
27674
+ style: {
27675
+ backgroundColor: components.card.backgroundColor,
27676
+ borderRadius: components.card.borderRadius,
27677
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`,
27678
+ color: components.card.titleColor,
27679
+ fontFamily: fonts.medium
27680
+ },
27681
+ children: [
27682
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ExternalLink, { className: "uf-w-4 uf-h-4", style: { color: components.card.iconColor } }),
27683
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { className: "uf-text-sm uf-font-medium", children: [
27684
+ "Open in ",
27685
+ mobileRedirect.walletName
27686
+ ] })
27687
+ ]
27688
+ }
27689
+ ),
27690
+ awaitingMobileDeposit && /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2 uf-mt-6", children: [
27691
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
27692
+ LoaderCircle,
27693
+ {
27694
+ className: "uf-w-4 uf-h-4 uf-animate-spin",
27695
+ style: { color: colors2.foregroundMuted }
27696
+ }
27697
+ ),
27698
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
27699
+ "span",
27700
+ {
27701
+ className: "uf-text-sm",
27702
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
27703
+ children: "Checking for deposit..."
27704
+ }
27705
+ )
27706
+ ] })
27707
+ ] })
27708
+ ] }) });
27709
+ }
27710
+ if (view === "mobile_deposit_status" && latestDepositExecution) {
27711
+ const isComplete = latestDepositExecution.status === ExecutionStatus.SUCCEEDED;
27712
+ const isFailed = latestDepositExecution.status === ExecutionStatus.FAILED;
27713
+ const title = isComplete ? "Payment Complete" : isFailed ? "Payment Failed" : "Payment Processing";
27714
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { style: viewTransitionStyle, children: [
27715
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
27716
+ DepositHeader,
27717
+ {
27718
+ title,
27719
+ showBack: false,
27720
+ onClose: isComplete && onDone ? onDone : onClose
27721
+ }
27722
+ ),
27723
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DepositDetailContent, { execution: latestDepositExecution }),
27724
+ isComplete && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uf-flex uf-gap-2 uf-px-2 uf-pt-4 uf-pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
27725
+ "button",
27726
+ {
27727
+ type: "button",
27728
+ onClick: onDone ? onDone : onNewDeposit ? onNewDeposit : onClose ?? (() => {
27729
+ }),
27730
+ className: "uf-flex-1 uf-py-4 uf-text-sm uf-font-medium uf-transition-opacity hover:uf-opacity-80",
27731
+ style: {
27732
+ backgroundColor: colors2.primary,
27733
+ color: colors2.primaryForeground,
27734
+ fontFamily: fonts.medium,
27735
+ borderRadius: components.button.borderRadius,
27736
+ border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
27737
+ },
27738
+ children: "Done"
27739
+ }
27740
+ ) })
27741
+ ] }) });
27166
27742
  }
27167
27743
  if (!hasWallet) return null;
27744
+ const walletAccent = getWalletBrandColor(walletInfo.type, mode);
27745
+ const walletAccentForeground = walletAccent ? getContrastingTextColor(walletAccent) : void 0;
27168
27746
  if (view === "select_token") {
27169
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(SelectTokenView, { walletInfo, projectName, assetCdnUrl, balances, isLoading, error, selectedBalance, totalBalanceUsd, onTokenSelect: handleTokenSelect, onContinue: handleContinueToAmount, onBack: handleBack, onClose: onClose ?? (() => {
27170
- }), onDisconnectWallet: onWalletDisconnect ? () => void handleDisconnect() : void 0, isDisconnectingWallet, checkoutAmountUsd, checkoutReceivedUsd }) });
27747
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(SelectTokenView, { walletInfo, projectName, assetCdnUrl, balances, isLoading, error, selectedBalance, totalBalanceUsd, onTokenSelect: handleTokenSelect, onContinue: handleContinueToAmount, onBack: handleBack, onClose: onClose ?? (() => {
27748
+ }), onDisconnectWallet: onWalletDisconnect ? () => void handleDisconnect() : void 0, isDisconnectingWallet, checkoutAmountUsd, checkoutReceivedUsd }) }) });
27171
27749
  }
27172
27750
  if (view === "enter_amount" && selectedToken && selectedBalance) {
27173
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(EnterAmountView, { walletInfo, selectedBalance, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, inputUsdNum, maxUsdAmount, isValidAmount, error, onAmountChange: setAmountUsd, onMaxClick: handleMaxClick, onReview: handleReview, onBack: handleBack, onClose: onClose ?? (() => {
27174
- }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd }) });
27751
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(EnterAmountView, { walletInfo, selectedBalance, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, inputUsdNum, maxUsdAmount, isValidAmount, error, onAmountChange: setAmountUsd, onMaxClick: handleMaxClick, onReview: handleReview, onBack: handleBack, onClose: onClose ?? (() => {
27752
+ }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd }) }) });
27175
27753
  }
27176
27754
  if (view === "review" && selectedToken) {
27177
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ReviewView, { walletInfo, recipientAddress, assetCdnUrl, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, loadingTokenDetails, showTransactionDetails, isConfirming, error, onToggleDetails: () => setShowTransactionDetails(!showTransactionDetails), onConfirm: handleConfirm, onBack: handleBack, onClose: onClose ?? (() => {
27178
- }) }) });
27755
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ReviewView, { walletInfo, recipientAddress, assetCdnUrl, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, loadingTokenDetails, showTransactionDetails, isConfirming, error, onToggleDetails: () => setShowTransactionDetails(!showTransactionDetails), onConfirm: handleConfirm, onBack: handleBack, onClose: onClose ?? (() => {
27756
+ }) }) }) });
27179
27757
  }
27180
27758
  if (view === "confirming") {
27181
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ConfirmingView, { isConfirming, onClose: onClose ?? (() => {
27182
- }), executions: depositExecutions, isPolling, onNewDeposit, onDone, paymentIntentStatus, amountReceivedUsd: checkoutReceivedUsd, amountReceivedUsdAtSubmission: receivedUsdAtSubmission }) });
27759
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { style: viewTransitionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ConfirmingView, { isConfirming, onClose: onClose ?? (() => {
27760
+ }), executions: depositExecutions, isPolling, onNewDeposit, onDone, paymentIntentStatus, amountReceivedUsd: checkoutReceivedUsd, amountReceivedUsdAtSubmission: receivedUsdAtSubmission }) }) });
27183
27761
  }
27184
27762
  return null;
27185
27763
  }
@@ -27223,16 +27801,17 @@ function DepositModal({
27223
27801
  defaultSourceChainId,
27224
27802
  defaultSourceTokenAddress,
27225
27803
  defaultSourceSymbol,
27226
- hideDepositTracker = false,
27804
+ hideDepositTracker,
27227
27805
  showBalanceHeader = false,
27228
27806
  transferInputVariant = "double_input",
27229
27807
  depositConfirmationMode = "auto_ui",
27230
- enableConnectWallet = false,
27808
+ enableTransferCrypto,
27809
+ enableConnectWallet,
27231
27810
  browserWalletAmountQuickSelect = "percentage",
27232
27811
  enablePayWithExchange,
27233
27812
  enableFiatOnramp,
27234
- enableConnectExchange = false,
27235
- enableCashApp = false,
27813
+ enableConnectExchange,
27814
+ enableCashApp,
27236
27815
  hideDepositFlowInfo = false,
27237
27816
  hideDisplayDescription = false,
27238
27817
  onDepositSuccess,
@@ -27250,12 +27829,13 @@ function DepositModal({
27250
27829
  const { colors: colors2, fonts, components } = useTheme();
27251
27830
  const effectiveInitialScreen = (0, import_react8.useMemo)(() => {
27252
27831
  const s = initialScreen ?? "main";
27253
- if (s === "tracker" && hideDepositTracker) return "main";
27254
- if (s === "cashapp" && !enableCashApp) return "main";
27832
+ if (s === "tracker" && hideDepositTracker === true) return "main";
27833
+ if (s === "cashapp" && enableCashApp === false) return "main";
27255
27834
  if (s === "card" && enableFiatOnramp === false) return "main";
27256
27835
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
27257
- if (s === "exchange_connect") return enableConnectExchange ? "coinbase_connect" : "main";
27258
- if (s === "wallet_connect") return enableConnectWallet ? "wallet_connect" : "main";
27836
+ if (s === "exchange_connect")
27837
+ return enableConnectExchange === false ? "main" : "coinbase_connect";
27838
+ if (s === "wallet_connect") return enableConnectWallet === false ? "main" : "wallet_connect";
27259
27839
  return s;
27260
27840
  }, [
27261
27841
  initialScreen,
@@ -27284,26 +27864,36 @@ function DepositModal({
27284
27864
  const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0, import_react8.useState)(false);
27285
27865
  const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react8.useState)(null);
27286
27866
  const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0, import_react8.useState)(false);
27287
- const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react8.useState)(() => getStoredWalletChainType());
27867
+ const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react8.useState)(() => getStoredWalletState()?.chainType);
27288
27868
  const [quotesCount, setQuotesCount] = (0, import_react8.useState)(0);
27289
27869
  const [allExecutions, setAllExecutions] = (0, import_react8.useState)([]);
27290
27870
  const [selectedExecution, setSelectedExecution] = (0, import_react8.useState)(null);
27291
27871
  const [depositExecutions, setDepositExecutions] = (0, import_react8.useState)([]);
27292
- const isMobileView = useIsMobileViewport();
27872
+ const { projectConfig } = useProjectConfig({
27873
+ publishableKey,
27874
+ enabled: open
27875
+ });
27876
+ const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
27877
+ const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
27878
+ const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
27879
+ const showFiatOnramp = enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true;
27880
+ const showConnectExchange = enableConnectExchange ?? projectConfig?.connect_exchange?.enabled ?? true;
27881
+ const showCashApp = enableCashApp ?? projectConfig?.cash_app?.enabled ?? true;
27882
+ const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
27293
27883
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react8.useState)([]);
27294
27884
  (0, import_react8.useEffect)(() => {
27295
- if (!enableConnectExchange || !open) return;
27885
+ if (!showConnectExchange || !open) return;
27296
27886
  getIntegrationExchanges(publishableKey).then((res) => setIntegrationExchanges(res.data)).catch(() => {
27297
27887
  });
27298
- }, [enableConnectExchange, open, publishableKey]);
27888
+ }, [showConnectExchange, open, publishableKey]);
27299
27889
  const [connectedExchange, setConnectedExchange] = (0, import_react8.useState)(() => {
27300
- if (!enableConnectExchange) return null;
27890
+ if (!showConnectExchange) return null;
27301
27891
  const stored = getStoredIntegrationToken(IntegrationProvider.COINBASE);
27302
27892
  if (!stored) return null;
27303
27893
  return { name: "Coinbase", iconUrl: void 0, balanceUsd: null, isLoading: true };
27304
27894
  });
27305
27895
  (0, import_react8.useEffect)(() => {
27306
- if (!enableConnectExchange || !open || view !== "main") return;
27896
+ if (!showConnectExchange || !open || view !== "main") return;
27307
27897
  const stored = getStoredIntegrationToken(IntegrationProvider.COINBASE);
27308
27898
  if (!stored) {
27309
27899
  setConnectedExchange(null);
@@ -27338,7 +27928,7 @@ function DepositModal({
27338
27928
  setConnectedExchange(null);
27339
27929
  }
27340
27930
  });
27341
- }, [enableConnectExchange, open, view, publishableKey]);
27931
+ }, [showConnectExchange, open, view, publishableKey]);
27342
27932
  (0, import_react8.useEffect)(() => {
27343
27933
  if (!connectedExchange || integrationExchanges.length === 0) return;
27344
27934
  const cbExchange = integrationExchanges.find(
@@ -27377,18 +27967,33 @@ function DepositModal({
27377
27967
  setResolvedTheme(theme);
27378
27968
  }
27379
27969
  }, [theme]);
27380
- const { projectConfig } = useProjectConfig({
27381
- publishableKey,
27382
- enabled: open
27383
- });
27384
- const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
27385
- const showFiatOnramp = enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true;
27386
27970
  (0, import_react8.useEffect)(() => {
27387
27971
  if (view === "card" && !showFiatOnramp) {
27388
27972
  setView("main");
27389
27973
  setCardView("amount");
27974
+ } else if (view === "transfer" && !showTransferCrypto) {
27975
+ setView("main");
27976
+ } else if (view === "exchange" && !showPayWithExchange) {
27977
+ setView("main");
27978
+ } else if (view === "cashapp" && !showCashApp) {
27979
+ setView("main");
27980
+ } else if (view === "tracker" && !showDepositTracker) {
27981
+ setView("main");
27982
+ } else if (view === "coinbase_connect" && !showConnectExchange) {
27983
+ setView("main");
27984
+ } else if (view === "wallet_connect" && !showConnectWallet) {
27985
+ setView("main");
27390
27986
  }
27391
- }, [view, showFiatOnramp]);
27987
+ }, [
27988
+ view,
27989
+ showFiatOnramp,
27990
+ showTransferCrypto,
27991
+ showPayWithExchange,
27992
+ showCashApp,
27993
+ showDepositTracker,
27994
+ showConnectExchange,
27995
+ showConnectWallet
27996
+ ]);
27392
27997
  (0, import_react8.useEffect)(() => {
27393
27998
  if (view === "exchange" && !showPayWithExchange) {
27394
27999
  setView("main");
@@ -27478,7 +28083,7 @@ function DepositModal({
27478
28083
  depositPrerequisiteBody = standaloneNeedsDepositPrereq ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SkeletonButton, { variant: "with-icons" }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27479
28084
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SkeletonButton, { variant: "with-icons" }),
27480
28085
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SkeletonButton, { variant: "with-icons" }),
27481
- !hideDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SkeletonButton, {})
28086
+ showDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SkeletonButton, {})
27482
28087
  ] });
27483
28088
  } else if (countryError) {
27484
28089
  depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
@@ -27510,7 +28115,7 @@ function DepositModal({
27510
28115
  const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
27511
28116
  const handleWalletDisconnect = () => {
27512
28117
  setUserDisconnectedWallet(true);
27513
- clearStoredWalletChainType();
28118
+ clearStoredWalletState();
27514
28119
  setBrowserWalletChainType(void 0);
27515
28120
  setBrowserWalletInfo(null);
27516
28121
  setBrowserWalletModalOpen(false);
@@ -27588,7 +28193,7 @@ function DepositModal({
27588
28193
  };
27589
28194
  const handleBrowserWalletClick = (walletInfo) => {
27590
28195
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
27591
- setStoredWalletChainType(walletChainType);
28196
+ setStoredWalletState(walletInfo.type);
27592
28197
  setBrowserWalletChainType(walletChainType);
27593
28198
  const matchingDepositWallet = wallets.find(
27594
28199
  (w) => w.chain_type === walletChainType
@@ -27619,7 +28224,7 @@ function DepositModal({
27619
28224
  };
27620
28225
  const handleWalletConnected = (walletInfo) => {
27621
28226
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
27622
- setStoredWalletChainType(walletChainType);
28227
+ setStoredWalletState(walletInfo.type);
27623
28228
  setBrowserWalletChainType(walletChainType);
27624
28229
  const matchingDepositWallet = wallets.find(
27625
28230
  (w) => w.chain_type === walletChainType
@@ -27659,7 +28264,7 @@ function DepositModal({
27659
28264
  open: hideOverlay || open,
27660
28265
  onOpenChange: hideOverlay ? void 0 : handleClose,
27661
28266
  modal: !hideOverlay,
27662
- children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28267
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
27663
28268
  DialogContent2,
27664
28269
  {
27665
28270
  ref: hideOverlay ? containerCallbackRef : void 0,
@@ -27668,378 +28273,389 @@ function DepositModal({
27668
28273
  style: { backgroundColor: colors2.background },
27669
28274
  onPointerDownOutside: (e) => e.preventDefault(),
27670
28275
  onInteractOutside: (e) => e.preventDefault(),
27671
- children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ThemeStyleInjector, { children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27672
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27673
- DepositHeader,
27674
- {
27675
- title: modalTitle || "Deposit",
27676
- showClose: !hideOverlay,
27677
- onClose: handleClose,
27678
- showBalance: showBalanceHeader,
27679
- balanceAddress: recipientAddress,
27680
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
27681
- balanceChainId: destinationChainId,
27682
- balanceTokenAddress: destinationTokenAddress,
27683
- projectName: projectConfig?.project_name,
27684
- publishableKey
27685
- }
27686
- ),
27687
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27688
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-space-y-3", children: depositPrerequisiteBody ?? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27689
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27690
- TransferCryptoButton,
27691
- {
27692
- onClick: () => setView("transfer"),
27693
- title: transferCryptoTitle,
27694
- subtitle: t7.transferCrypto.subtitle,
27695
- featuredTokens: projectConfig?.transfer_crypto.networks
27696
- }
27697
- ),
27698
- enableConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27699
- BrowserWalletButton,
28276
+ children: [
28277
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(DialogTitle2, { className: "uf-sr-only", children: modalTitle || "Deposit" }),
28278
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ThemeStyleInjector, { children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28279
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28280
+ DepositHeader,
28281
+ {
28282
+ title: modalTitle || "Deposit",
28283
+ showClose: !hideOverlay,
28284
+ onClose: handleClose,
28285
+ showBalance: showBalanceHeader,
28286
+ balanceAddress: recipientAddress,
28287
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28288
+ balanceChainId: destinationChainId,
28289
+ balanceTokenAddress: destinationTokenAddress,
28290
+ projectName: projectConfig?.project_name,
28291
+ publishableKey
28292
+ }
28293
+ ),
28294
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28295
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-space-y-3", children: depositPrerequisiteBody ?? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28296
+ showTransferCrypto && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28297
+ TransferCryptoButton,
28298
+ {
28299
+ onClick: () => setView("transfer"),
28300
+ title: transferCryptoTitle,
28301
+ subtitle: t7.transferCrypto.subtitle,
28302
+ featuredTokens: projectConfig?.transfer_crypto.networks
28303
+ }
28304
+ ),
28305
+ showConnectWallet && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28306
+ BrowserWalletButton,
28307
+ {
28308
+ onClick: handleBrowserWalletClick,
28309
+ onConnectClick: handleWalletConnectClick,
28310
+ onDisconnect: handleWalletDisconnect,
28311
+ chainType: browserWalletChainType,
28312
+ publishableKey,
28313
+ featuredWallets: projectConfig?.connect_wallet?.wallets
28314
+ }
28315
+ ),
28316
+ showFiatOnramp && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28317
+ DepositWithCardButton,
28318
+ {
28319
+ onClick: () => setView("card"),
28320
+ title: depositWithCardTitle,
28321
+ subtitle: t7.depositWithCard.subtitle,
28322
+ paymentNetworks: projectConfig?.payment_networks.networks
28323
+ }
28324
+ ),
28325
+ showPayWithExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28326
+ PayWithExchangeButton,
28327
+ {
28328
+ onClick: () => setView("exchange"),
28329
+ title: payWithExchangeTitle,
28330
+ subtitle: t7.payWithExchange.subtitle,
28331
+ exchanges,
28332
+ loading: exchangesLoading
28333
+ }
28334
+ ),
28335
+ showConnectExchange && connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28336
+ ConnectExchangeButton,
28337
+ {
28338
+ onClick: () => {
28339
+ setCoinbaseSkipToHoldings(true);
28340
+ setView("coinbase_connect");
28341
+ },
28342
+ onDisconnect: handleExchangeDisconnect,
28343
+ title: i18n2.connectExchange.title,
28344
+ subtitle: i18n2.connectExchange.subtitle,
28345
+ exchanges: integrationExchanges,
28346
+ connectedExchange
28347
+ }
28348
+ ),
28349
+ showConnectExchange && !connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28350
+ ConnectExchangeButton,
28351
+ {
28352
+ onClick: () => {
28353
+ setCoinbaseSkipToHoldings(false);
28354
+ setView("coinbase_connect");
28355
+ },
28356
+ title: i18n2.connectExchange.title,
28357
+ subtitle: i18n2.connectExchange.subtitle,
28358
+ exchanges: integrationExchanges
28359
+ }
28360
+ ),
28361
+ showCashApp && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28362
+ CashAppButton,
28363
+ {
28364
+ onClick: () => setView("cashapp"),
28365
+ title: "Pay with Cash App",
28366
+ subtitle: "Deposit via Cash App",
28367
+ iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
28368
+ }
28369
+ ),
28370
+ showDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28371
+ DepositTrackerButton,
28372
+ {
28373
+ onClick: () => {
28374
+ setAllExecutions(depositExecutions);
28375
+ setView("tracker");
28376
+ },
28377
+ title: depositTrackerTitle,
28378
+ subtitle: depositTrackerSubTitle,
28379
+ badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
28380
+ }
28381
+ )
28382
+ ] }) }),
28383
+ depositPoweredByFooter
28384
+ ] })
28385
+ ] }) : view === "transfer" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28386
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28387
+ DepositHeader,
28388
+ {
28389
+ title: transferCryptoTitle,
28390
+ showBack: showBackTransfer,
28391
+ onBack: handleBack,
28392
+ onClose: handleClose,
28393
+ showBalance: showBalanceHeader,
28394
+ balanceAddress: recipientAddress,
28395
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28396
+ balanceChainId: destinationChainId,
28397
+ balanceTokenAddress: destinationTokenAddress,
28398
+ projectName: projectConfig?.project_name,
28399
+ publishableKey
28400
+ }
28401
+ ),
28402
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28403
+ standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : transferInputVariant === "single_input" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28404
+ TransferCryptoSingleInput,
27700
28405
  {
27701
- onClick: handleBrowserWalletClick,
27702
- onConnectClick: handleWalletConnectClick,
27703
- onDisconnect: handleWalletDisconnect,
27704
- chainType: browserWalletChainType,
28406
+ userId,
27705
28407
  publishableKey,
27706
- featuredWallets: projectConfig?.connect_wallet?.wallets
28408
+ recipientAddress,
28409
+ destinationChainType,
28410
+ destinationChainId,
28411
+ destinationTokenAddress,
28412
+ defaultSourceChainType,
28413
+ defaultSourceChainId,
28414
+ defaultSourceTokenAddress,
28415
+ defaultSourceSymbol,
28416
+ depositConfirmationMode,
28417
+ onExecutionsChange: setDepositExecutions,
28418
+ onDepositSuccess,
28419
+ onDepositError,
28420
+ wallets
27707
28421
  }
27708
- ),
27709
- showFiatOnramp && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27710
- DepositWithCardButton,
28422
+ ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28423
+ TransferCryptoDoubleInput,
27711
28424
  {
27712
- onClick: () => setView("card"),
27713
- title: depositWithCardTitle,
27714
- subtitle: t7.depositWithCard.subtitle,
27715
- paymentNetworks: projectConfig?.payment_networks.networks
28425
+ userId,
28426
+ publishableKey,
28427
+ recipientAddress,
28428
+ destinationChainType,
28429
+ destinationChainId,
28430
+ destinationTokenAddress,
28431
+ defaultSourceChainType,
28432
+ defaultSourceChainId,
28433
+ defaultSourceTokenAddress,
28434
+ defaultSourceSymbol,
28435
+ depositConfirmationMode,
28436
+ onExecutionsChange: setDepositExecutions,
28437
+ onDepositSuccess,
28438
+ onDepositError,
28439
+ wallets
27716
28440
  }
27717
28441
  ),
27718
- showPayWithExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27719
- PayWithExchangeButton,
28442
+ depositPoweredByFooter
28443
+ ] })
28444
+ ] }) : view === "tracker" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28445
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28446
+ DepositHeader,
28447
+ {
28448
+ title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
28449
+ showBack: showBackTracker,
28450
+ onBack: handleBack,
28451
+ onClose: handleClose
28452
+ }
28453
+ ),
28454
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28455
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28456
+ "div",
27720
28457
  {
27721
- onClick: () => setView("exchange"),
27722
- title: payWithExchangeTitle,
27723
- subtitle: t7.payWithExchange.subtitle,
27724
- exchanges,
27725
- loading: exchangesLoading
28458
+ className: "uf-text-sm",
28459
+ style: { color: components.container.subtitleColor, fontFamily: fonts.regular },
28460
+ children: "No deposits yet"
27726
28461
  }
27727
- ),
27728
- enableConnectExchange && connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27729
- ConnectExchangeButton,
28462
+ ) }) : allExecutions.map((execution) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28463
+ DepositExecutionItem,
27730
28464
  {
27731
- onClick: () => {
27732
- setCoinbaseSkipToHoldings(true);
27733
- setView("coinbase_connect");
27734
- },
27735
- onDisconnect: handleExchangeDisconnect,
27736
- title: i18n2.connectExchange.title,
27737
- subtitle: i18n2.connectExchange.subtitle,
27738
- exchanges: integrationExchanges,
27739
- connectedExchange
27740
- }
27741
- ),
27742
- enableConnectExchange && !connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27743
- ConnectExchangeButton,
28465
+ execution,
28466
+ onClick: () => setSelectedExecution(execution)
28467
+ },
28468
+ execution.id
28469
+ )) }) }),
28470
+ depositPoweredByFooter
28471
+ ] })
28472
+ ] }) : view === "card" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28473
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28474
+ DepositHeader,
28475
+ {
28476
+ title: cardView === "quotes" ? t7.quotes : depositWithCardTitle,
28477
+ showBack: showBackCard,
28478
+ onBack: handleBack,
28479
+ onClose: handleClose,
28480
+ badge: cardView === "quotes" ? { count: quotesCount } : void 0,
28481
+ showBalance: showBalanceHeader,
28482
+ balanceAddress: recipientAddress,
28483
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28484
+ balanceChainId: destinationChainId,
28485
+ balanceTokenAddress: destinationTokenAddress,
28486
+ projectName: projectConfig?.project_name,
28487
+ publishableKey
28488
+ }
28489
+ ),
28490
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28491
+ standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28492
+ BuyWithCard,
27744
28493
  {
27745
- onClick: () => {
27746
- setCoinbaseSkipToHoldings(false);
27747
- setView("coinbase_connect");
27748
- },
27749
- title: i18n2.connectExchange.title,
27750
- subtitle: i18n2.connectExchange.subtitle,
27751
- exchanges: integrationExchanges
28494
+ userId,
28495
+ publishableKey,
28496
+ view: cardView,
28497
+ onViewChange: handleCardViewChange,
28498
+ destinationTokenSymbol,
28499
+ recipientAddress,
28500
+ destinationChainType,
28501
+ destinationChainId,
28502
+ destinationTokenAddress,
28503
+ onDepositSuccess,
28504
+ onDepositError,
28505
+ onEvent,
28506
+ themeClass,
28507
+ wallets,
28508
+ assetCdnUrl: projectConfig?.asset_cdn_url,
28509
+ hideDepositFlowInfo,
28510
+ hideDisplayDescription
27752
28511
  }
27753
28512
  ),
27754
- enableCashApp && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27755
- CashAppButton,
28513
+ depositPoweredByFooter
28514
+ ] })
28515
+ ] }) : view === "exchange" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28516
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28517
+ DepositHeader,
28518
+ {
28519
+ title: payWithExchangeTitle,
28520
+ showBack: exchangeView === "pending" || sessionOpenedFromMenu,
28521
+ onBack: handleBack,
28522
+ onClose: handleClose
28523
+ }
28524
+ ),
28525
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28526
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28527
+ PayWithExchange,
27756
28528
  {
27757
- onClick: () => setView("cashapp"),
27758
- title: "Pay with Cash App",
27759
- subtitle: "Deposit via Cash App",
27760
- iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
28529
+ userId,
28530
+ publishableKey,
28531
+ exchanges,
28532
+ view: exchangeView,
28533
+ onViewChange: setExchangeView,
28534
+ destinationTokenSymbol,
28535
+ recipientAddress,
28536
+ destinationChainType,
28537
+ destinationChainId,
28538
+ destinationTokenAddress,
28539
+ onDepositSuccess,
28540
+ onDepositError,
28541
+ wallets,
28542
+ defaultToken: defaultToken ?? null
27761
28543
  }
27762
28544
  ),
27763
- !hideDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27764
- DepositTrackerButton,
27765
- {
27766
- onClick: () => {
27767
- setAllExecutions(depositExecutions);
27768
- setView("tracker");
27769
- },
27770
- title: depositTrackerTitle,
27771
- subtitle: depositTrackerSubTitle,
27772
- badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
27773
- }
27774
- )
27775
- ] }) }),
27776
- depositPoweredByFooter
27777
- ] })
27778
- ] }) : view === "transfer" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27779
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27780
- DepositHeader,
27781
- {
27782
- title: transferCryptoTitle,
27783
- showBack: showBackTransfer,
27784
- onBack: handleBack,
27785
- onClose: handleClose,
27786
- showBalance: showBalanceHeader,
27787
- balanceAddress: recipientAddress,
27788
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
27789
- balanceChainId: destinationChainId,
27790
- balanceTokenAddress: destinationTokenAddress,
27791
- projectName: projectConfig?.project_name,
27792
- publishableKey
27793
- }
27794
- ),
27795
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27796
- standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : transferInputVariant === "single_input" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27797
- TransferCryptoSingleInput,
28545
+ depositPoweredByFooter
28546
+ ] })
28547
+ ] }) : view === "coinbase_connect" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28548
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28549
+ CoinbaseConnect,
27798
28550
  {
27799
- userId,
27800
28551
  publishableKey,
27801
- recipientAddress,
27802
- destinationChainType,
27803
- destinationChainId,
27804
- destinationTokenAddress,
27805
- defaultSourceChainType,
27806
- defaultSourceChainId,
27807
- defaultSourceTokenAddress,
27808
- defaultSourceSymbol,
27809
- depositConfirmationMode,
27810
- onExecutionsChange: setDepositExecutions,
27811
- onDepositSuccess,
27812
- onDepositError,
27813
- wallets
27814
- }
27815
- ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27816
- TransferCryptoDoubleInput,
27817
- {
27818
28552
  userId,
27819
- publishableKey,
28553
+ wallets,
27820
28554
  recipientAddress,
27821
- destinationChainType,
27822
- destinationChainId,
27823
- destinationTokenAddress,
28555
+ destinationTokenAddress: destinationTokenAddress ?? "",
28556
+ destinationChainId: destinationChainId ?? "",
28557
+ destinationChainType: destinationChainType ?? "",
28558
+ onTransferSuccess: (result) => {
28559
+ onDepositSuccess?.({
28560
+ message: "Transfer completed via Coinbase Connect",
28561
+ transaction: result
28562
+ });
28563
+ },
28564
+ onTransferError: (error) => {
28565
+ onDepositError?.({
28566
+ message: error.message,
28567
+ error
28568
+ });
28569
+ },
28570
+ onBack: handleBack,
28571
+ onClose: handleClose,
28572
+ onDisconnect: handleExchangeDisconnect,
28573
+ skipToHoldings: coinbaseSkipToHoldings,
28574
+ canGoBack: sessionOpenedFromMenu,
28575
+ onExecutionsChange: setDepositExecutions,
27824
28576
  defaultSourceChainType,
27825
28577
  defaultSourceChainId,
27826
28578
  defaultSourceTokenAddress,
27827
- defaultSourceSymbol,
27828
- depositConfirmationMode,
27829
- onExecutionsChange: setDepositExecutions,
27830
- onDepositSuccess,
27831
- onDepositError,
27832
- wallets
28579
+ defaultSourceSymbol
27833
28580
  }
27834
28581
  ),
27835
28582
  depositPoweredByFooter
27836
- ] })
27837
- ] }) : view === "tracker" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27838
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27839
- DepositHeader,
27840
- {
27841
- title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
27842
- showBack: showBackTracker,
27843
- onBack: handleBack,
27844
- onClose: handleClose
27845
- }
27846
- ),
27847
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27848
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27849
- "div",
27850
- {
27851
- className: "uf-text-sm",
27852
- style: { color: components.container.subtitleColor, fontFamily: fonts.regular },
27853
- children: "No deposits yet"
27854
- }
27855
- ) }) : allExecutions.map((execution) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27856
- DepositExecutionItem,
27857
- {
27858
- execution,
27859
- onClick: () => setSelectedExecution(execution)
27860
- },
27861
- execution.id
27862
- )) }) }),
27863
- depositPoweredByFooter
27864
- ] })
27865
- ] }) : view === "card" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27866
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27867
- DepositHeader,
27868
- {
27869
- title: cardView === "quotes" ? t7.quotes : depositWithCardTitle,
27870
- showBack: showBackCard,
27871
- onBack: handleBack,
27872
- onClose: handleClose,
27873
- badge: cardView === "quotes" ? { count: quotesCount } : void 0,
27874
- showBalance: showBalanceHeader,
27875
- balanceAddress: recipientAddress,
27876
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
27877
- balanceChainId: destinationChainId,
27878
- balanceTokenAddress: destinationTokenAddress,
27879
- projectName: projectConfig?.project_name,
27880
- publishableKey
27881
- }
27882
- ),
27883
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27884
- standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27885
- BuyWithCard,
27886
- {
27887
- userId,
27888
- publishableKey,
27889
- view: cardView,
27890
- onViewChange: handleCardViewChange,
27891
- destinationTokenSymbol,
27892
- recipientAddress,
27893
- destinationChainType,
27894
- destinationChainId,
27895
- destinationTokenAddress,
27896
- onDepositSuccess,
27897
- onDepositError,
27898
- onEvent,
27899
- themeClass,
27900
- wallets,
27901
- assetCdnUrl: projectConfig?.asset_cdn_url,
27902
- hideDepositFlowInfo,
27903
- hideDisplayDescription
27904
- }
27905
- ),
27906
- depositPoweredByFooter
27907
- ] })
27908
- ] }) : view === "exchange" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
27909
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27910
- DepositHeader,
27911
- {
27912
- title: payWithExchangeTitle,
27913
- showBack: exchangeView === "pending" || sessionOpenedFromMenu,
27914
- onBack: handleBack,
27915
- onClose: handleClose
27916
- }
27917
- ),
27918
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28583
+ ] }) : view === "wallet_connect" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27919
28584
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27920
- PayWithExchange,
28585
+ WalletConnect,
27921
28586
  {
28587
+ walletInfo: browserWalletInfo ?? void 0,
28588
+ depositWallet: browserWalletInfo?.depositWallet ?? void 0,
28589
+ wallets,
27922
28590
  userId,
27923
28591
  publishableKey,
27924
- exchanges,
27925
- view: exchangeView,
27926
- onViewChange: setExchangeView,
27927
- destinationTokenSymbol,
27928
- recipientAddress,
27929
- destinationChainType,
27930
- destinationChainId,
27931
- destinationTokenAddress,
28592
+ assetCdnUrl: projectConfig?.asset_cdn_url,
28593
+ projectName: projectConfig?.project_name,
28594
+ onSuccess: (txHash) => {
28595
+ onDepositSuccess?.({
28596
+ message: "Transaction sent successfully",
28597
+ transaction: { txHash }
28598
+ });
28599
+ },
28600
+ onError: (error) => {
28601
+ onDepositError?.({
28602
+ message: error.message,
28603
+ error
28604
+ });
28605
+ },
27932
28606
  onDepositSuccess,
27933
28607
  onDepositError,
27934
- wallets,
27935
- defaultToken: defaultToken ?? null
28608
+ amountQuickSelect: browserWalletAmountQuickSelect,
28609
+ onWalletDisconnect: handleWalletDisconnect,
28610
+ onWalletConnected: (info, dw) => {
28611
+ setBrowserWalletInfo({ ...info, depositWallet: dw });
28612
+ setStoredWalletState(info.type);
28613
+ setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
28614
+ },
28615
+ onBack: handleBack,
28616
+ onClose: handleClose,
28617
+ defaultSourceChainType,
28618
+ defaultSourceChainId,
28619
+ defaultSourceTokenAddress,
28620
+ defaultSourceSymbol,
28621
+ canGoBack: sessionOpenedFromMenu,
28622
+ depositWalletsLoading: walletsLoading
27936
28623
  }
27937
28624
  ),
27938
28625
  depositPoweredByFooter
27939
- ] })
27940
- ] }) : view === "coinbase_connect" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27941
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27942
- CoinbaseConnect,
27943
- {
27944
- publishableKey,
27945
- userId,
27946
- wallets,
27947
- recipientAddress,
27948
- destinationTokenAddress: destinationTokenAddress ?? "",
27949
- destinationChainId: destinationChainId ?? "",
27950
- destinationChainType: destinationChainType ?? "",
27951
- onTransferSuccess: (result) => {
27952
- onDepositSuccess?.({
27953
- message: "Transfer completed via Coinbase Connect",
27954
- transaction: result
27955
- });
27956
- },
27957
- onTransferError: (error) => {
27958
- onDepositError?.({
27959
- message: error.message,
27960
- error
27961
- });
27962
- },
27963
- onBack: handleBack,
27964
- onClose: handleClose,
27965
- onDisconnect: handleExchangeDisconnect,
27966
- skipToHoldings: coinbaseSkipToHoldings,
27967
- canGoBack: sessionOpenedFromMenu,
27968
- onExecutionsChange: setDepositExecutions
27969
- }
27970
- ),
27971
- depositPoweredByFooter
27972
- ] }) : view === "wallet_connect" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
27973
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
27974
- WalletConnect,
27975
- {
27976
- walletInfo: browserWalletInfo ?? void 0,
27977
- depositWallet: browserWalletInfo?.depositWallet ?? void 0,
27978
- wallets,
27979
- userId,
27980
- publishableKey,
27981
- assetCdnUrl: projectConfig?.asset_cdn_url,
27982
- projectName: projectConfig?.project_name,
27983
- onSuccess: (txHash) => {
27984
- onDepositSuccess?.({
27985
- message: "Transaction sent successfully",
27986
- transaction: { txHash }
27987
- });
27988
- },
27989
- onError: (error) => {
27990
- onDepositError?.({
27991
- message: error.message,
27992
- error
27993
- });
27994
- },
27995
- onDepositSuccess,
27996
- onDepositError,
27997
- amountQuickSelect: browserWalletAmountQuickSelect,
27998
- onWalletDisconnect: handleWalletDisconnect,
27999
- onWalletConnected: (info, dw) => {
28000
- setBrowserWalletInfo({ ...info, depositWallet: dw });
28001
- setStoredWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
28002
- setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
28003
- },
28004
- onBack: handleBack,
28005
- onClose: handleClose,
28006
- canGoBack: sessionOpenedFromMenu,
28007
- depositWalletsLoading: walletsLoading
28008
- }
28009
- ),
28010
- depositPoweredByFooter
28011
- ] }) : view === "cashapp" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28012
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28013
- DepositHeader,
28014
- {
28015
- title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
28016
- showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
28017
- onBack: handleBack,
28018
- onClose: handleClose
28019
- }
28020
- ),
28021
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28626
+ ] }) : view === "cashapp" ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(import_jsx_runtime72.Fragment, { children: [
28022
28627
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28023
- PayWithCashApp,
28628
+ DepositHeader,
28024
28629
  {
28025
- userId,
28026
- publishableKey,
28027
- recipientAddress,
28028
- destinationChainType,
28029
- destinationChainId,
28030
- destinationTokenAddress,
28031
- cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
28032
- view: cashAppView,
28033
- onViewChange: setCashAppView,
28034
- onAmountChange: setCashAppAmount,
28035
- onEvent,
28036
- onDepositSuccess,
28037
- onDepositError
28630
+ title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
28631
+ showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
28632
+ onBack: handleBack,
28633
+ onClose: handleClose
28038
28634
  }
28039
28635
  ),
28040
- depositPoweredByFooter
28041
- ] })
28042
- ] }) : null })
28636
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28637
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
28638
+ PayWithCashApp,
28639
+ {
28640
+ userId,
28641
+ publishableKey,
28642
+ recipientAddress,
28643
+ destinationChainType,
28644
+ destinationChainId,
28645
+ destinationTokenAddress,
28646
+ cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
28647
+ view: cashAppView,
28648
+ onViewChange: setCashAppView,
28649
+ onAmountChange: setCashAppAmount,
28650
+ onEvent,
28651
+ onDepositSuccess,
28652
+ onDepositError
28653
+ }
28654
+ ),
28655
+ depositPoweredByFooter
28656
+ ] })
28657
+ ] }) : null })
28658
+ ]
28043
28659
  }
28044
28660
  )
28045
28661
  }
@@ -28058,7 +28674,7 @@ function usePaymentIntent(params) {
28058
28674
  enabled = true,
28059
28675
  pollingInterval = 3e3
28060
28676
  } = params;
28061
- return (0, import_react_query15.useQuery)({
28677
+ return (0, import_react_query16.useQuery)({
28062
28678
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
28063
28679
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
28064
28680
  enabled: enabled && !!clientSecret && !!publishableKey,
@@ -28105,7 +28721,8 @@ function CheckoutModal({
28105
28721
  clientSecret,
28106
28722
  publishableKey,
28107
28723
  modalTitle,
28108
- enableConnectWallet = false,
28724
+ enableTransferCrypto,
28725
+ enableConnectWallet,
28109
28726
  defaultSourceChainType,
28110
28727
  defaultSourceChainId,
28111
28728
  defaultSourceTokenAddress,
@@ -28122,8 +28739,7 @@ function CheckoutModal({
28122
28739
  const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0, import_react28.useState)(false);
28123
28740
  const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react28.useState)(null);
28124
28741
  const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0, import_react28.useState)(false);
28125
- const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react28.useState)(() => getStoredWalletChainType());
28126
- const isMobileView = useIsMobileViewport();
28742
+ const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react28.useState)(() => getStoredWalletState()?.chainType);
28127
28743
  const [resolvedTheme, setResolvedTheme] = (0, import_react28.useState)(
28128
28744
  theme === "auto" ? "dark" : theme
28129
28745
  );
@@ -28155,6 +28771,15 @@ function CheckoutModal({
28155
28771
  publishableKey,
28156
28772
  enabled: open
28157
28773
  });
28774
+ const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
28775
+ const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
28776
+ (0, import_react28.useEffect)(() => {
28777
+ if (view === "transfer" && !showTransferCrypto) {
28778
+ setView("main");
28779
+ } else if (view === "wallet_connect" && !showConnectWallet) {
28780
+ setView("main");
28781
+ }
28782
+ }, [showConnectWallet, showTransferCrypto, view]);
28158
28783
  const prevStatusRef = (0, import_react28.useRef)(null);
28159
28784
  (0, import_react28.useEffect)(() => {
28160
28785
  if (!paymentIntent) return;
@@ -28245,7 +28870,7 @@ function CheckoutModal({
28245
28870
  const handleBrowserWalletClick = (0, import_react28.useCallback)(
28246
28871
  (walletInfo) => {
28247
28872
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
28248
- setStoredWalletChainType(walletChainType);
28873
+ setStoredWalletState(walletInfo.type);
28249
28874
  setBrowserWalletChainType(walletChainType);
28250
28875
  const matchingDepositWallet = wallets.find(
28251
28876
  (w) => w.chain_type === walletChainType
@@ -28272,7 +28897,7 @@ function CheckoutModal({
28272
28897
  const handleWalletConnected = (0, import_react28.useCallback)(
28273
28898
  (walletInfo) => {
28274
28899
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
28275
- setStoredWalletChainType(walletChainType);
28900
+ setStoredWalletState(walletInfo.type);
28276
28901
  setBrowserWalletChainType(walletChainType);
28277
28902
  const matchingDepositWallet = wallets.find(
28278
28903
  (w) => w.chain_type === walletChainType
@@ -28296,7 +28921,7 @@ function CheckoutModal({
28296
28921
  );
28297
28922
  const handleWalletDisconnect = (0, import_react28.useCallback)(() => {
28298
28923
  setUserDisconnectedWallet(true);
28299
- clearStoredWalletChainType();
28924
+ clearStoredWalletState();
28300
28925
  setBrowserWalletChainType(void 0);
28301
28926
  setBrowserWalletInfo(null);
28302
28927
  setBrowserWalletModalOpen(false);
@@ -28531,7 +29156,7 @@ function CheckoutModal({
28531
29156
  ] }) : paymentIntent ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uf-space-y-3", children: [
28532
29157
  progressSection,
28533
29158
  (paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
28534
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
29159
+ showTransferCrypto && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
28535
29160
  TransferCryptoButton,
28536
29161
  {
28537
29162
  onClick: () => setView("transfer"),
@@ -28540,7 +29165,7 @@ function CheckoutModal({
28540
29165
  featuredTokens: projectConfig?.transfer_crypto.networks
28541
29166
  }
28542
29167
  ),
28543
- enableConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
29168
+ showConnectWallet && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
28544
29169
  BrowserWalletButton,
28545
29170
  {
28546
29171
  onClick: handleBrowserWalletClick,
@@ -28681,14 +29306,18 @@ function CheckoutModal({
28681
29306
  onWalletDisconnect: handleWalletDisconnect,
28682
29307
  onWalletConnected: (info, dw) => {
28683
29308
  setBrowserWalletInfo({ ...info, depositWallet: dw });
28684
- setStoredWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
29309
+ setStoredWalletState(info.type);
28685
29310
  setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
28686
29311
  },
28687
29312
  onNewDeposit: () => setView("main"),
28688
29313
  onDone: () => setView("main"),
28689
29314
  paymentIntentStatus: paymentIntent.status,
28690
29315
  onBack: handleBack,
28691
- onClose: handleClose
29316
+ onClose: handleClose,
29317
+ defaultSourceChainType,
29318
+ defaultSourceChainId,
29319
+ defaultSourceTokenAddress,
29320
+ defaultSourceSymbol
28692
29321
  }
28693
29322
  ),
28694
29323
  poweredByFooter
@@ -28697,7 +29326,7 @@ function CheckoutModal({
28697
29326
  ) }) });
28698
29327
  }
28699
29328
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
28700
- return (0, import_react_query16.useQuery)({
29329
+ return (0, import_react_query17.useQuery)({
28701
29330
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
28702
29331
  queryFn: () => getSupportedDestinationTokens(publishableKey),
28703
29332
  staleTime: 1e3 * 60 * 5,
@@ -28732,7 +29361,7 @@ function useSourceTokenValidation(params) {
28732
29361
  enabled = true
28733
29362
  } = params;
28734
29363
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
28735
- return (0, import_react_query17.useQuery)({
29364
+ return (0, import_react_query18.useQuery)({
28736
29365
  queryKey: [
28737
29366
  "unifold",
28738
29367
  "sourceTokenValidation",
@@ -28788,7 +29417,7 @@ function useAddressBalance(params) {
28788
29417
  enabled = true
28789
29418
  } = params;
28790
29419
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
28791
- return (0, import_react_query18.useQuery)({
29420
+ return (0, import_react_query19.useQuery)({
28792
29421
  queryKey: [
28793
29422
  "unifold",
28794
29423
  "addressBalance",
@@ -28837,7 +29466,7 @@ function useAddressBalance(params) {
28837
29466
  }
28838
29467
  function useExecutions(userId, publishableKey, options) {
28839
29468
  const actionType = options?.actionType ?? ActionType.Deposit;
28840
- return (0, import_react_query19.useQuery)({
29469
+ return (0, import_react_query20.useQuery)({
28841
29470
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
28842
29471
  queryFn: () => queryExecutions(userId, publishableKey, actionType),
28843
29472
  enabled: (options?.enabled ?? true) && !!userId,
@@ -29120,7 +29749,7 @@ function useVerifyRecipientAddress(params) {
29120
29749
  } = params;
29121
29750
  const trimmedAddress = recipientAddress?.trim() || "";
29122
29751
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
29123
- return (0, import_react_query20.useQuery)({
29752
+ return (0, import_react_query21.useQuery)({
29124
29753
  queryKey: [
29125
29754
  "unifold",
29126
29755
  "verifyRecipientAddress",
@@ -29162,7 +29791,7 @@ function useGetDepositAddress(params) {
29162
29791
  enabled = true
29163
29792
  } = params;
29164
29793
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
29165
- return (0, import_react_query21.useQuery)({
29794
+ return (0, import_react_query22.useQuery)({
29166
29795
  queryKey: [
29167
29796
  "unifold",
29168
29797
  "getDepositAddress",
@@ -30445,6 +31074,16 @@ function UnifoldProvider2({
30445
31074
  });
30446
31075
  promise.catch(() => {
30447
31076
  });
31077
+ if (!config2.recipientAddress) {
31078
+ const error = {
31079
+ message: "beginDeposit requires a `recipientAddress`.",
31080
+ code: "MISSING_RECIPIENT"
31081
+ };
31082
+ console.error(`[UnifoldProvider] ${error.message}`);
31083
+ depositPromiseRef.current.reject(error);
31084
+ depositPromiseRef.current = null;
31085
+ return promise;
31086
+ }
30448
31087
  setDepositConfig(config2);
30449
31088
  setIsOpen(true);
30450
31089
  return promise;
@@ -30654,6 +31293,7 @@ function UnifoldProvider2({
30654
31293
  onOpenChange: closeCheckout,
30655
31294
  clientSecret: checkoutConfig.clientSecret,
30656
31295
  publishableKey,
31296
+ enableTransferCrypto: config?.enableTransferCrypto,
30657
31297
  enableConnectWallet: config?.enableConnectWallet,
30658
31298
  defaultSourceChainType: checkoutConfig.defaultSourceChainType,
30659
31299
  defaultSourceChainId: checkoutConfig.defaultSourceChainId,
@@ -30710,6 +31350,7 @@ function UnifoldProvider2({
30710
31350
  hideDepositTracker: config?.hideDepositTracker,
30711
31351
  showBalanceHeader: config?.showBalanceHeader,
30712
31352
  transferInputVariant: config?.transferInputVariant,
31353
+ enableTransferCrypto: config?.enableTransferCrypto,
30713
31354
  enableConnectWallet: config?.enableConnectWallet,
30714
31355
  enablePayWithExchange: config?.enablePayWithExchange,
30715
31356
  enableFiatOnramp: config?.enableFiatOnramp,