@unifold/ui-react 0.1.62 → 0.1.63

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
@@ -128,8 +128,32 @@ var import_tailwind_merge = require("tailwind-merge");
128
128
  function cn(...inputs) {
129
129
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
130
130
  }
131
- var WALLET_CHAIN_TYPE_STORAGE_KEY = "unifold_last_wallet_type";
131
+ var WALLET_STATE_STORAGE_KEY = "unifold_wallet_state";
132
+ var LEGACY_WALLET_KEYS = [
133
+ "unifold_last_wallet_type",
134
+ "unifold_last_connected_wallet"
135
+ ];
132
136
  var WALLET_USER_DISCONNECTED_KEY = "unifold_wallet_user_disconnected";
137
+ var SOLANA_WALLET_TYPES = /* @__PURE__ */ new Set([
138
+ "phantom-solana",
139
+ "solflare",
140
+ "backpack",
141
+ "glow"
142
+ ]);
143
+ var ETHEREUM_WALLET_TYPES = /* @__PURE__ */ new Set([
144
+ "metamask",
145
+ "phantom-ethereum",
146
+ "coinbase",
147
+ "trust",
148
+ "rainbow",
149
+ "rabby",
150
+ "okx"
151
+ ]);
152
+ function walletTypeToChain(t12) {
153
+ if (SOLANA_WALLET_TYPES.has(t12)) return "solana";
154
+ if (ETHEREUM_WALLET_TYPES.has(t12)) return "ethereum";
155
+ return void 0;
156
+ }
133
157
  function getUserDisconnectedWallet() {
134
158
  if (typeof window === "undefined") return false;
135
159
  try {
@@ -149,26 +173,35 @@ function setUserDisconnectedWallet(disconnected) {
149
173
  } catch {
150
174
  }
151
175
  }
152
- function getStoredWalletChainType() {
176
+ function getStoredWalletState() {
153
177
  if (typeof window === "undefined") return void 0;
154
178
  try {
155
- const stored = localStorage.getItem(WALLET_CHAIN_TYPE_STORAGE_KEY);
156
- if (stored === "ethereum" || stored === "solana") return stored;
179
+ const raw = localStorage.getItem(WALLET_STATE_STORAGE_KEY);
180
+ if (!raw) return void 0;
181
+ const chainType = walletTypeToChain(raw);
182
+ if (!chainType) {
183
+ localStorage.removeItem(WALLET_STATE_STORAGE_KEY);
184
+ return void 0;
185
+ }
186
+ return { walletType: raw, chainType };
157
187
  } catch {
188
+ return void 0;
158
189
  }
159
- return void 0;
160
190
  }
161
- function setStoredWalletChainType(chainType) {
191
+ function setStoredWalletState(walletType) {
162
192
  if (typeof window === "undefined") return;
193
+ if (!walletTypeToChain(walletType)) return;
163
194
  try {
164
- localStorage.setItem(WALLET_CHAIN_TYPE_STORAGE_KEY, chainType);
195
+ localStorage.setItem(WALLET_STATE_STORAGE_KEY, walletType);
196
+ for (const key of LEGACY_WALLET_KEYS) localStorage.removeItem(key);
165
197
  } catch {
166
198
  }
167
199
  }
168
- function clearStoredWalletChainType() {
200
+ function clearStoredWalletState() {
169
201
  if (typeof window === "undefined") return;
170
202
  try {
171
- localStorage.removeItem(WALLET_CHAIN_TYPE_STORAGE_KEY);
203
+ localStorage.removeItem(WALLET_STATE_STORAGE_KEY);
204
+ for (const key of LEGACY_WALLET_KEYS) localStorage.removeItem(key);
172
205
  } catch {
173
206
  }
174
207
  }
@@ -770,6 +803,60 @@ var import_core3 = require("@unifold/core");
770
803
 
771
804
  // src/components/deposits/browser-wallets/utils.ts
772
805
  var import_core2 = require("@unifold/core");
806
+ var normalize = (value) => value?.toLowerCase();
807
+ function sourceTokenMatchesDefaultSource(token, defaultSource) {
808
+ if (!token || !defaultSource.defaultSourceChainType || !defaultSource.defaultSourceChainId) {
809
+ return false;
810
+ }
811
+ if (token.chain_type !== defaultSource.defaultSourceChainType || token.chain_id !== defaultSource.defaultSourceChainId) {
812
+ return false;
813
+ }
814
+ if (defaultSource.defaultSourceTokenAddress && normalize(token.token_address) === normalize(defaultSource.defaultSourceTokenAddress)) {
815
+ return true;
816
+ }
817
+ if (defaultSource.defaultSourceTokenAddress) {
818
+ return false;
819
+ }
820
+ return !!defaultSource.defaultSourceSymbol && normalize(token.symbol) === normalize(defaultSource.defaultSourceSymbol);
821
+ }
822
+ function isDefaultSourceBalance(balance, defaultSource) {
823
+ return isBalanceEligible(balance) && sourceTokenMatchesDefaultSource(getTokenFromBalance(balance), defaultSource);
824
+ }
825
+ function compareBalancesWithDefaultSource(a, b, defaultSource) {
826
+ const aDefault = isDefaultSourceBalance(a, defaultSource);
827
+ const bDefault = isDefaultSourceBalance(b, defaultSource);
828
+ if (aDefault && !bDefault) return -1;
829
+ if (!aDefault && bDefault) return 1;
830
+ const aEligible = isBalanceEligible(a);
831
+ const bEligible = isBalanceEligible(b);
832
+ if (aEligible && !bEligible) return -1;
833
+ if (!aEligible && bEligible) return 1;
834
+ return 0;
835
+ }
836
+ function resolveDefaultSourceSymbol(supportedTokens, defaultSource) {
837
+ if (!supportedTokens?.length || !defaultSource.defaultSourceChainType || !defaultSource.defaultSourceChainId) {
838
+ return null;
839
+ }
840
+ if (defaultSource.defaultSourceTokenAddress) {
841
+ for (const token of supportedTokens) {
842
+ const matchingChain = token.chains.find(
843
+ (chain) => chain.chain_type === defaultSource.defaultSourceChainType && chain.chain_id === defaultSource.defaultSourceChainId && normalize(chain.token_address) === normalize(defaultSource.defaultSourceTokenAddress)
844
+ );
845
+ if (matchingChain) return token.symbol;
846
+ }
847
+ }
848
+ if (!defaultSource.defaultSourceSymbol) return null;
849
+ for (const token of supportedTokens) {
850
+ if (normalize(token.symbol) !== normalize(defaultSource.defaultSourceSymbol)) {
851
+ continue;
852
+ }
853
+ const matchingChain = token.chains.find(
854
+ (chain) => chain.chain_type === defaultSource.defaultSourceChainType && chain.chain_id === defaultSource.defaultSourceChainId
855
+ );
856
+ if (matchingChain) return token.symbol;
857
+ }
858
+ return null;
859
+ }
773
860
  function formatUsdFromBalancePercent(maxUsdAmount, percent) {
774
861
  if (maxUsdAmount <= 0 || percent < 0) return "";
775
862
  const raw = maxUsdAmount * percent / 100;
@@ -5419,70 +5506,106 @@ function identifyEthWallet(provider, hint) {
5419
5506
  }
5420
5507
  return { type: "metamask", name: "Wallet", icon: "metamask" };
5421
5508
  }
5509
+ var EIP6963_ID_TO_WALLET_TYPE = {
5510
+ metamask: "metamask",
5511
+ phantom: "phantom-ethereum",
5512
+ coinbase: "coinbase",
5513
+ trust: "trust",
5514
+ rainbow: "rainbow",
5515
+ rabby: "rabby",
5516
+ okx: "okx"
5517
+ };
5518
+ function inferEthWalletType(provider, walletId) {
5519
+ if (EIP6963_ID_TO_WALLET_TYPE[walletId]) return EIP6963_ID_TO_WALLET_TYPE[walletId];
5520
+ const any = provider;
5521
+ if (provider.isPhantom) return "phantom-ethereum";
5522
+ if (any.isCoinbaseWallet) return "coinbase";
5523
+ if (any.isRabby) return "rabby";
5524
+ if (any.isTrust) return "trust";
5525
+ if (any.isRainbow) return "rainbow";
5526
+ if (any.isOkxWallet) return "okx";
5527
+ if (provider.isMetaMask && !provider.isPhantom) return "metamask";
5528
+ return null;
5529
+ }
5530
+ function solanaCandidate(provider, type, name, icon) {
5531
+ return {
5532
+ walletType: type,
5533
+ detect: async () => {
5534
+ if (!provider) return null;
5535
+ if (provider.isConnected && provider.publicKey) {
5536
+ return { type, name, address: provider.publicKey.toString(), icon };
5537
+ }
5538
+ try {
5539
+ const resp = await provider.connect({ onlyIfTrusted: true });
5540
+ if (resp.publicKey) {
5541
+ return { type, name, address: resp.publicKey.toString(), icon };
5542
+ }
5543
+ } catch {
5544
+ }
5545
+ return null;
5546
+ }
5547
+ };
5548
+ }
5549
+ function ethereumCandidate(provider, walletId) {
5550
+ return {
5551
+ walletType: inferEthWalletType(provider, walletId),
5552
+ detect: async () => {
5553
+ try {
5554
+ const accounts = await provider.request({ method: "eth_accounts" });
5555
+ if (!accounts?.length) return null;
5556
+ const resolved = identifyEthWallet(provider, walletId);
5557
+ return { ...resolved, address: accounts[0] };
5558
+ } catch {
5559
+ return null;
5560
+ }
5561
+ }
5562
+ };
5563
+ }
5564
+ function buildCandidates(win, chainType) {
5565
+ const candidates = [];
5566
+ if (!chainType || chainType === "solana") {
5567
+ candidates.push(
5568
+ solanaCandidate(win.phantom?.solana, "phantom-solana", "Phantom", "phantom"),
5569
+ solanaCandidate(win.solflare, "solflare", "Solflare", "solflare"),
5570
+ solanaCandidate(win.backpack, "backpack", "Backpack", "backpack"),
5571
+ solanaCandidate(win.glow, "glow", "Glow", "glow")
5572
+ );
5573
+ }
5574
+ if (!chainType || chainType === "ethereum") {
5575
+ const seen = /* @__PURE__ */ new Set();
5576
+ const addEth = (provider, walletId) => {
5577
+ if (!provider || seen.has(provider)) return;
5578
+ seen.add(provider);
5579
+ candidates.push(ethereumCandidate(provider, walletId));
5580
+ };
5581
+ for (const { provider, walletId } of getEip6963Providers()) {
5582
+ addEth(
5583
+ provider,
5584
+ walletId === "unknown" ? "default" : walletId
5585
+ );
5586
+ }
5587
+ addEth(win.phantom?.ethereum, "phantom");
5588
+ addEth(win.coinbaseWalletExtension, "coinbase");
5589
+ addEth(win.okxwallet, "okx");
5590
+ addEth(win.trustwallet?.ethereum, "trust");
5591
+ addEth(win.ethereum, "default");
5592
+ }
5593
+ return candidates;
5594
+ }
5422
5595
  async function detectConnectedBrowserWallet(chainType) {
5423
5596
  if (typeof window === "undefined") return null;
5424
5597
  if (getUserDisconnectedWallet()) return null;
5425
5598
  try {
5426
5599
  const win = window;
5427
- if (!chainType || chainType === "solana") {
5428
- const trySilentSolana = async (provider, type, name, icon) => {
5429
- if (!provider) return null;
5430
- if (provider.isConnected && provider.publicKey) {
5431
- return { type, name, address: provider.publicKey.toString(), icon };
5432
- }
5433
- try {
5434
- const resp = await provider.connect({ onlyIfTrusted: true });
5435
- if (resp.publicKey) {
5436
- return { type, name, address: resp.publicKey.toString(), icon };
5437
- }
5438
- } catch {
5439
- }
5440
- return null;
5441
- };
5442
- const solanaCandidates = [
5443
- [win.phantom?.solana, "phantom-solana", "Phantom", "phantom"],
5444
- [win.solflare, "solflare", "Solflare", "solflare"],
5445
- [win.backpack, "backpack", "Backpack", "backpack"],
5446
- [win.glow, "glow", "Glow", "glow"]
5447
- ];
5448
- for (const [provider, type, name, icon] of solanaCandidates) {
5449
- const found = await trySilentSolana(provider, type, name, icon);
5450
- if (found) return found;
5451
- }
5600
+ const candidates = buildCandidates(win, chainType);
5601
+ const preferred = getStoredWalletState();
5602
+ if (preferred && (!chainType || preferred.chainType === chainType)) {
5603
+ const idx = candidates.findIndex((c) => c.walletType === preferred.walletType);
5604
+ if (idx > 0) candidates.unshift(...candidates.splice(idx, 1));
5452
5605
  }
5453
- if (!chainType || chainType === "ethereum") {
5454
- const allProviders = [];
5455
- const eip6963 = getEip6963Providers();
5456
- for (const { provider, walletId } of eip6963) {
5457
- allProviders.push({
5458
- provider,
5459
- walletId: walletId === "unknown" ? "default" : walletId
5460
- });
5461
- }
5462
- if (allProviders.length === 0) {
5463
- if (win.phantom?.ethereum) {
5464
- allProviders.push({ provider: win.phantom.ethereum, walletId: "phantom" });
5465
- }
5466
- if (win.okxwallet) {
5467
- allProviders.push({ provider: win.okxwallet, walletId: "okx" });
5468
- }
5469
- if (win.coinbaseWalletExtension) {
5470
- allProviders.push({ provider: win.coinbaseWalletExtension, walletId: "coinbase" });
5471
- }
5472
- if (win.ethereum && !allProviders.some((p) => p.provider === win.ethereum)) {
5473
- allProviders.push({ provider: win.ethereum, walletId: "default" });
5474
- }
5475
- }
5476
- for (const { provider, walletId } of allProviders) {
5477
- if (!provider) continue;
5478
- try {
5479
- const accounts = await provider.request({ method: "eth_accounts" });
5480
- if (!accounts || accounts.length === 0) continue;
5481
- const resolved = identifyEthWallet(provider, walletId);
5482
- return { ...resolved, address: accounts[0] };
5483
- } catch {
5484
- }
5485
- }
5606
+ for (const c of candidates) {
5607
+ const found = await c.detect();
5608
+ if (found) return found;
5486
5609
  }
5487
5610
  } catch (error) {
5488
5611
  console.error("[detectConnectedBrowserWallet] detection error:", error);
@@ -7686,6 +7809,7 @@ function BrowserWalletButton({
7686
7809
  if (solanaProvider?.isPhantom) {
7687
7810
  const { publicKey } = await solanaProvider.connect();
7688
7811
  setUserDisconnectedWallet(false);
7812
+ setStoredWalletState("phantom-solana");
7689
7813
  setWallet({
7690
7814
  type: "phantom-solana",
7691
7815
  name: "Phantom",
@@ -7705,8 +7829,10 @@ function BrowserWalletButton({
7705
7829
  if (accounts && accounts.length > 0) {
7706
7830
  setUserDisconnectedWallet(false);
7707
7831
  const isPhantom = ethProvider.isPhantom;
7832
+ const walletType = isPhantom ? "phantom-ethereum" : "metamask";
7833
+ setStoredWalletState(walletType);
7708
7834
  setWallet({
7709
- type: isPhantom ? "phantom-ethereum" : "metamask",
7835
+ type: walletType,
7710
7836
  name: isPhantom ? "Phantom" : "MetaMask",
7711
7837
  address: accounts[0],
7712
7838
  icon: isPhantom ? "phantom" : "metamask"
@@ -8038,7 +8164,11 @@ function CoinbaseConnect({
8038
8164
  onDisconnect,
8039
8165
  skipToHoldings,
8040
8166
  canGoBack = true,
8041
- onExecutionsChange
8167
+ onExecutionsChange,
8168
+ defaultSourceChainType,
8169
+ defaultSourceChainId,
8170
+ defaultSourceTokenAddress,
8171
+ defaultSourceSymbol
8042
8172
  }) {
8043
8173
  const { colors: colors2, fonts, components } = useTheme();
8044
8174
  const { projectConfig } = useProjectConfig({ publishableKey });
@@ -8103,6 +8233,21 @@ function CoinbaseConnect({
8103
8233
  params: defaultTokenParams,
8104
8234
  publishableKey
8105
8235
  });
8236
+ const defaultSourceCurrency = (0, import_react12.useMemo)(
8237
+ () => resolveDefaultSourceSymbol(supportedTokensData?.data, {
8238
+ defaultSourceChainType,
8239
+ defaultSourceChainId,
8240
+ defaultSourceTokenAddress,
8241
+ defaultSourceSymbol
8242
+ })?.toLowerCase() ?? null,
8243
+ [
8244
+ supportedTokensData,
8245
+ defaultSourceChainType,
8246
+ defaultSourceChainId,
8247
+ defaultSourceTokenAddress,
8248
+ defaultSourceSymbol
8249
+ ]
8250
+ );
8106
8251
  const sortedHoldings = (0, import_react12.useMemo)(() => {
8107
8252
  const supported = [];
8108
8253
  const unsupported = [];
@@ -8112,13 +8257,42 @@ function CoinbaseConnect({
8112
8257
  if (isSupported) supported.push(account);
8113
8258
  else unsupported.push(account);
8114
8259
  });
8260
+ if (defaultSourceCurrency) {
8261
+ const defaultIndex = supported.findIndex(
8262
+ (account) => account.currency.toLowerCase() === defaultSourceCurrency
8263
+ );
8264
+ if (defaultIndex > 0) {
8265
+ const [defaultHolding] = supported.splice(defaultIndex, 1);
8266
+ supported.unshift(defaultHolding);
8267
+ }
8268
+ }
8115
8269
  return [...supported, ...unsupported];
8116
- }, [holdings, supportedSymbols, exchangeSupportedCurrencies]);
8270
+ }, [
8271
+ holdings,
8272
+ supportedSymbols,
8273
+ exchangeSupportedCurrencies,
8274
+ defaultSourceCurrency
8275
+ ]);
8117
8276
  const selectedHoldingIsSupported = (0, import_react12.useMemo)(() => {
8118
8277
  if (!selectedHolding) return false;
8119
8278
  const currencyLower = selectedHolding.currency.toLowerCase();
8120
8279
  return (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
8121
8280
  }, [selectedHolding, supportedSymbols, exchangeSupportedCurrencies]);
8281
+ (0, import_react12.useEffect)(() => {
8282
+ if (!defaultSourceCurrency || selectedHolding) return;
8283
+ const defaultHolding = sortedHoldings.find((account) => {
8284
+ const currencyLower = account.currency.toLowerCase();
8285
+ return currencyLower === defaultSourceCurrency && (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
8286
+ });
8287
+ if (!defaultHolding) return;
8288
+ setSelectedHolding(defaultHolding);
8289
+ }, [
8290
+ defaultSourceCurrency,
8291
+ selectedHolding,
8292
+ sortedHoldings,
8293
+ supportedSymbols,
8294
+ exchangeSupportedCurrencies
8295
+ ]);
8122
8296
  const exchangeName = selectedExchange?.service_provider_display_name || "Exchange";
8123
8297
  const {
8124
8298
  executions: depositExecutions,
@@ -13437,6 +13611,19 @@ var WALLET_DEFINITIONS = [
13437
13611
  { id: "backpack", name: "Backpack", networks: ["solana"], installUrl: "https://backpack.app/" },
13438
13612
  { id: "glow", name: "Glow", networks: ["solana"], installUrl: "https://glow.app/" }
13439
13613
  ];
13614
+ function normalizeTokenAddress(address) {
13615
+ const normalized = (address ?? "").toLowerCase();
13616
+ if (normalized === "" || normalized === "native" || normalized === "0x0000000000000000000000000000000000000000") {
13617
+ return "native";
13618
+ }
13619
+ return normalized;
13620
+ }
13621
+ function balancesRepresentSameToken(a, b) {
13622
+ const tokenA = getTokenFromBalance(a);
13623
+ const tokenB = getTokenFromBalance(b);
13624
+ if (!tokenA || !tokenB) return false;
13625
+ return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
13626
+ }
13440
13627
  function getSolanaProviders() {
13441
13628
  if (typeof window === "undefined") return {};
13442
13629
  const win = window;
@@ -13579,6 +13766,10 @@ function WalletConnect({
13579
13766
  checkoutRemainingBaseUnits,
13580
13767
  stablecoinParity = false,
13581
13768
  productType,
13769
+ defaultSourceChainType,
13770
+ defaultSourceChainId,
13771
+ defaultSourceTokenAddress,
13772
+ defaultSourceSymbol,
13582
13773
  onBack: parentOnBack,
13583
13774
  onClose,
13584
13775
  canGoBack = true,
@@ -13739,6 +13930,7 @@ function WalletConnect({
13739
13930
  metamask: "metamask"
13740
13931
  };
13741
13932
  const walletType = walletIdToType[wallet.id] || "metamask";
13933
+ setStoredWalletState(walletType);
13742
13934
  connectedInfo = { type: walletType, name: wallet.name, address: accounts[0], icon: wallet.id };
13743
13935
  } else {
13744
13936
  const solProviders = getSolanaProviders();
@@ -13767,6 +13959,7 @@ function WalletConnect({
13767
13959
  const response = await provider.connect();
13768
13960
  setUserDisconnectedWallet(false);
13769
13961
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
13962
+ setStoredWalletState(walletType);
13770
13963
  connectedInfo = { type: walletType, name: wallet.name, address: response.publicKey.toString(), icon: wallet.id };
13771
13964
  }
13772
13965
  const walletChainType = network === "solana" ? "solana" : "ethereum";
@@ -13881,18 +14074,33 @@ function WalletConnect({
13881
14074
  (0, import_core28.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
13882
14075
  if (cancelled) return;
13883
14076
  const nonZero = response.balances.filter((b) => b.amount !== "0");
13884
- const sorted = [...nonZero].sort((a, b) => {
13885
- const ae = isBalanceEligible(a);
13886
- const be = isBalanceEligible(b);
13887
- if (ae && !be) return -1;
13888
- if (!ae && be) return 1;
13889
- return 0;
13890
- });
14077
+ const defaultSource = {
14078
+ defaultSourceChainType,
14079
+ defaultSourceChainId,
14080
+ defaultSourceTokenAddress,
14081
+ defaultSourceSymbol
14082
+ };
14083
+ const sorted = [...nonZero].sort(
14084
+ (a, b) => compareBalancesWithDefaultSource(a, b, defaultSource)
14085
+ );
13891
14086
  setBalances(sorted);
13892
14087
  const totalUsd = nonZero.reduce((sum, b) => b.amount_usd ? sum + parseFloat(b.amount_usd) : sum, 0);
13893
14088
  if (totalUsd > 0) setTotalBalanceUsd(totalUsd.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
13894
14089
  const eligible = sorted.filter(isBalanceEligible);
13895
- if (eligible.length === 1) setSelectedBalance(eligible[0]);
14090
+ const defaultBalance = sorted.find(
14091
+ (balance) => isDefaultSourceBalance(balance, defaultSource)
14092
+ );
14093
+ setSelectedBalance((current) => {
14094
+ if (current) {
14095
+ const currentInNewBalances = sorted.find(
14096
+ (balance) => balancesRepresentSameToken(balance, current)
14097
+ );
14098
+ if (currentInNewBalances) return currentInNewBalances;
14099
+ }
14100
+ if (defaultBalance) return defaultBalance;
14101
+ if (eligible.length === 1) return eligible[0];
14102
+ return null;
14103
+ });
13896
14104
  }).catch((err) => {
13897
14105
  if (!cancelled) {
13898
14106
  console.error("[WalletConnect] Error fetching balances:", err);
@@ -13904,7 +14112,15 @@ function WalletConnect({
13904
14112
  return () => {
13905
14113
  cancelled = true;
13906
14114
  };
13907
- }, [activeWalletInfo?.address, activeDepositWallet?.chain_type, publishableKey]);
14115
+ }, [
14116
+ activeWalletInfo?.address,
14117
+ activeDepositWallet?.chain_type,
14118
+ publishableKey,
14119
+ defaultSourceChainType,
14120
+ defaultSourceChainId,
14121
+ defaultSourceTokenAddress,
14122
+ defaultSourceSymbol
14123
+ ]);
13908
14124
  const usdToTokenRate = React30.useMemo(() => {
13909
14125
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken) return 0;
13910
14126
  const balanceAmount = Number(selectedBalance.amount) / 10 ** selectedToken.decimals;
@@ -14262,16 +14478,17 @@ function DepositModal({
14262
14478
  defaultSourceChainId,
14263
14479
  defaultSourceTokenAddress,
14264
14480
  defaultSourceSymbol,
14265
- hideDepositTracker = false,
14481
+ hideDepositTracker,
14266
14482
  showBalanceHeader = false,
14267
14483
  transferInputVariant = "double_input",
14268
14484
  depositConfirmationMode = "auto_ui",
14269
- enableConnectWallet = false,
14485
+ enableTransferCrypto,
14486
+ enableConnectWallet,
14270
14487
  browserWalletAmountQuickSelect = "percentage",
14271
14488
  enablePayWithExchange,
14272
14489
  enableFiatOnramp,
14273
- enableConnectExchange = false,
14274
- enableCashApp = false,
14490
+ enableConnectExchange,
14491
+ enableCashApp,
14275
14492
  hideDepositFlowInfo = false,
14276
14493
  hideDisplayDescription = false,
14277
14494
  onDepositSuccess,
@@ -14289,12 +14506,13 @@ function DepositModal({
14289
14506
  const { colors: colors2, fonts, components } = useTheme();
14290
14507
  const effectiveInitialScreen = (0, import_react20.useMemo)(() => {
14291
14508
  const s = initialScreen ?? "main";
14292
- if (s === "tracker" && hideDepositTracker) return "main";
14293
- if (s === "cashapp" && !enableCashApp) return "main";
14509
+ if (s === "tracker" && hideDepositTracker === true) return "main";
14510
+ if (s === "cashapp" && enableCashApp === false) return "main";
14294
14511
  if (s === "card" && enableFiatOnramp === false) return "main";
14295
14512
  if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
14296
- if (s === "exchange_connect") return enableConnectExchange ? "coinbase_connect" : "main";
14297
- if (s === "wallet_connect") return enableConnectWallet ? "wallet_connect" : "main";
14513
+ if (s === "exchange_connect")
14514
+ return enableConnectExchange === false ? "main" : "coinbase_connect";
14515
+ if (s === "wallet_connect") return enableConnectWallet === false ? "main" : "wallet_connect";
14298
14516
  return s;
14299
14517
  }, [
14300
14518
  initialScreen,
@@ -14323,26 +14541,37 @@ function DepositModal({
14323
14541
  const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0, import_react20.useState)(false);
14324
14542
  const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react20.useState)(null);
14325
14543
  const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0, import_react20.useState)(false);
14326
- const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react20.useState)(() => getStoredWalletChainType());
14544
+ const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react20.useState)(() => getStoredWalletState()?.chainType);
14327
14545
  const [quotesCount, setQuotesCount] = (0, import_react20.useState)(0);
14328
14546
  const [allExecutions, setAllExecutions] = (0, import_react20.useState)([]);
14329
14547
  const [selectedExecution, setSelectedExecution] = (0, import_react20.useState)(null);
14330
14548
  const [depositExecutions, setDepositExecutions] = (0, import_react20.useState)([]);
14331
14549
  const isMobileView = useIsMobileViewport();
14550
+ const { projectConfig } = useProjectConfig({
14551
+ publishableKey,
14552
+ enabled: open
14553
+ });
14554
+ const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
14555
+ const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
14556
+ const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
14557
+ const showFiatOnramp = enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true;
14558
+ const showConnectExchange = enableConnectExchange ?? projectConfig?.connect_exchange?.enabled ?? true;
14559
+ const showCashApp = enableCashApp ?? projectConfig?.cash_app?.enabled ?? true;
14560
+ const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
14332
14561
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react20.useState)([]);
14333
14562
  (0, import_react20.useEffect)(() => {
14334
- if (!enableConnectExchange || !open) return;
14563
+ if (!showConnectExchange || !open) return;
14335
14564
  (0, import_core29.getIntegrationExchanges)(publishableKey).then((res) => setIntegrationExchanges(res.data)).catch(() => {
14336
14565
  });
14337
- }, [enableConnectExchange, open, publishableKey]);
14566
+ }, [showConnectExchange, open, publishableKey]);
14338
14567
  const [connectedExchange, setConnectedExchange] = (0, import_react20.useState)(() => {
14339
- if (!enableConnectExchange) return null;
14568
+ if (!showConnectExchange) return null;
14340
14569
  const stored = getStoredIntegrationToken(import_core29.IntegrationProvider.COINBASE);
14341
14570
  if (!stored) return null;
14342
14571
  return { name: "Coinbase", iconUrl: void 0, balanceUsd: null, isLoading: true };
14343
14572
  });
14344
14573
  (0, import_react20.useEffect)(() => {
14345
- if (!enableConnectExchange || !open || view !== "main") return;
14574
+ if (!showConnectExchange || !open || view !== "main") return;
14346
14575
  const stored = getStoredIntegrationToken(import_core29.IntegrationProvider.COINBASE);
14347
14576
  if (!stored) {
14348
14577
  setConnectedExchange(null);
@@ -14377,7 +14606,7 @@ function DepositModal({
14377
14606
  setConnectedExchange(null);
14378
14607
  }
14379
14608
  });
14380
- }, [enableConnectExchange, open, view, publishableKey]);
14609
+ }, [showConnectExchange, open, view, publishableKey]);
14381
14610
  (0, import_react20.useEffect)(() => {
14382
14611
  if (!connectedExchange || integrationExchanges.length === 0) return;
14383
14612
  const cbExchange = integrationExchanges.find(
@@ -14416,18 +14645,33 @@ function DepositModal({
14416
14645
  setResolvedTheme(theme);
14417
14646
  }
14418
14647
  }, [theme]);
14419
- const { projectConfig } = useProjectConfig({
14420
- publishableKey,
14421
- enabled: open
14422
- });
14423
- const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
14424
- const showFiatOnramp = enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true;
14425
14648
  (0, import_react20.useEffect)(() => {
14426
14649
  if (view === "card" && !showFiatOnramp) {
14427
14650
  setView("main");
14428
14651
  setCardView("amount");
14652
+ } else if (view === "transfer" && !showTransferCrypto) {
14653
+ setView("main");
14654
+ } else if (view === "exchange" && !showPayWithExchange) {
14655
+ setView("main");
14656
+ } else if (view === "cashapp" && !showCashApp) {
14657
+ setView("main");
14658
+ } else if (view === "tracker" && !showDepositTracker) {
14659
+ setView("main");
14660
+ } else if (view === "coinbase_connect" && !showConnectExchange) {
14661
+ setView("main");
14662
+ } else if (view === "wallet_connect" && !showConnectWallet) {
14663
+ setView("main");
14429
14664
  }
14430
- }, [view, showFiatOnramp]);
14665
+ }, [
14666
+ view,
14667
+ showFiatOnramp,
14668
+ showTransferCrypto,
14669
+ showPayWithExchange,
14670
+ showCashApp,
14671
+ showDepositTracker,
14672
+ showConnectExchange,
14673
+ showConnectWallet
14674
+ ]);
14431
14675
  (0, import_react20.useEffect)(() => {
14432
14676
  if (view === "exchange" && !showPayWithExchange) {
14433
14677
  setView("main");
@@ -14517,7 +14761,7 @@ function DepositModal({
14517
14761
  depositPrerequisiteBody = standaloneNeedsDepositPrereq ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(SkeletonButton, { variant: "with-icons" }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
14518
14762
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(SkeletonButton, { variant: "with-icons" }),
14519
14763
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(SkeletonButton, { variant: "with-icons" }),
14520
- !hideDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(SkeletonButton, {})
14764
+ showDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(SkeletonButton, {})
14521
14765
  ] });
14522
14766
  } else if (countryError) {
14523
14767
  depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
@@ -14549,7 +14793,7 @@ function DepositModal({
14549
14793
  const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
14550
14794
  const handleWalletDisconnect = () => {
14551
14795
  setUserDisconnectedWallet(true);
14552
- clearStoredWalletChainType();
14796
+ clearStoredWalletState();
14553
14797
  setBrowserWalletChainType(void 0);
14554
14798
  setBrowserWalletInfo(null);
14555
14799
  setBrowserWalletModalOpen(false);
@@ -14627,7 +14871,7 @@ function DepositModal({
14627
14871
  };
14628
14872
  const handleBrowserWalletClick = (walletInfo) => {
14629
14873
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
14630
- setStoredWalletChainType(walletChainType);
14874
+ setStoredWalletState(walletInfo.type);
14631
14875
  setBrowserWalletChainType(walletChainType);
14632
14876
  const matchingDepositWallet = wallets.find(
14633
14877
  (w) => w.chain_type === walletChainType
@@ -14658,7 +14902,7 @@ function DepositModal({
14658
14902
  };
14659
14903
  const handleWalletConnected = (walletInfo) => {
14660
14904
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
14661
- setStoredWalletChainType(walletChainType);
14905
+ setStoredWalletState(walletInfo.type);
14662
14906
  setBrowserWalletChainType(walletChainType);
14663
14907
  const matchingDepositWallet = wallets.find(
14664
14908
  (w) => w.chain_type === walletChainType
@@ -14725,7 +14969,7 @@ function DepositModal({
14725
14969
  ),
14726
14970
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
14727
14971
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uf-space-y-3", children: depositPrerequisiteBody ?? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
14728
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14972
+ showTransferCrypto && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14729
14973
  TransferCryptoButton,
14730
14974
  {
14731
14975
  onClick: () => setView("transfer"),
@@ -14734,7 +14978,7 @@ function DepositModal({
14734
14978
  featuredTokens: projectConfig?.transfer_crypto.networks
14735
14979
  }
14736
14980
  ),
14737
- enableConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14981
+ showConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14738
14982
  BrowserWalletButton,
14739
14983
  {
14740
14984
  onClick: handleBrowserWalletClick,
@@ -14764,7 +15008,7 @@ function DepositModal({
14764
15008
  loading: exchangesLoading
14765
15009
  }
14766
15010
  ),
14767
- enableConnectExchange && connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
15011
+ showConnectExchange && connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14768
15012
  ConnectExchangeButton,
14769
15013
  {
14770
15014
  onClick: () => {
@@ -14778,7 +15022,7 @@ function DepositModal({
14778
15022
  connectedExchange
14779
15023
  }
14780
15024
  ),
14781
- enableConnectExchange && !connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
15025
+ showConnectExchange && !connectedExchange && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14782
15026
  ConnectExchangeButton,
14783
15027
  {
14784
15028
  onClick: () => {
@@ -14790,7 +15034,7 @@ function DepositModal({
14790
15034
  exchanges: integrationExchanges
14791
15035
  }
14792
15036
  ),
14793
- enableCashApp && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
15037
+ showCashApp && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14794
15038
  CashAppButton,
14795
15039
  {
14796
15040
  onClick: () => setView("cashapp"),
@@ -14799,7 +15043,7 @@ function DepositModal({
14799
15043
  iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
14800
15044
  }
14801
15045
  ),
14802
- !hideDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
15046
+ showDepositTracker && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14803
15047
  DepositTrackerButton,
14804
15048
  {
14805
15049
  onClick: () => {
@@ -15004,7 +15248,11 @@ function DepositModal({
15004
15248
  onDisconnect: handleExchangeDisconnect,
15005
15249
  skipToHoldings: coinbaseSkipToHoldings,
15006
15250
  canGoBack: sessionOpenedFromMenu,
15007
- onExecutionsChange: setDepositExecutions
15251
+ onExecutionsChange: setDepositExecutions,
15252
+ defaultSourceChainType,
15253
+ defaultSourceChainId,
15254
+ defaultSourceTokenAddress,
15255
+ defaultSourceSymbol
15008
15256
  }
15009
15257
  ),
15010
15258
  depositPoweredByFooter
@@ -15037,11 +15285,15 @@ function DepositModal({
15037
15285
  onWalletDisconnect: handleWalletDisconnect,
15038
15286
  onWalletConnected: (info, dw) => {
15039
15287
  setBrowserWalletInfo({ ...info, depositWallet: dw });
15040
- setStoredWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
15288
+ setStoredWalletState(info.type);
15041
15289
  setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
15042
15290
  },
15043
15291
  onBack: handleBack,
15044
15292
  onClose: handleClose,
15293
+ defaultSourceChainType,
15294
+ defaultSourceChainId,
15295
+ defaultSourceTokenAddress,
15296
+ defaultSourceSymbol,
15045
15297
  canGoBack: sessionOpenedFromMenu,
15046
15298
  depositWalletsLoading: walletsLoading
15047
15299
  }
@@ -15155,7 +15407,8 @@ function CheckoutModal({
15155
15407
  clientSecret,
15156
15408
  publishableKey,
15157
15409
  modalTitle,
15158
- enableConnectWallet = false,
15410
+ enableTransferCrypto,
15411
+ enableConnectWallet,
15159
15412
  defaultSourceChainType,
15160
15413
  defaultSourceChainId,
15161
15414
  defaultSourceTokenAddress,
@@ -15172,7 +15425,7 @@ function CheckoutModal({
15172
15425
  const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0, import_react21.useState)(false);
15173
15426
  const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react21.useState)(null);
15174
15427
  const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0, import_react21.useState)(false);
15175
- const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react21.useState)(() => getStoredWalletChainType());
15428
+ const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react21.useState)(() => getStoredWalletState()?.chainType);
15176
15429
  const isMobileView = useIsMobileViewport();
15177
15430
  const [resolvedTheme, setResolvedTheme] = (0, import_react21.useState)(
15178
15431
  theme === "auto" ? "dark" : theme
@@ -15205,6 +15458,15 @@ function CheckoutModal({
15205
15458
  publishableKey,
15206
15459
  enabled: open
15207
15460
  });
15461
+ const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
15462
+ const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
15463
+ (0, import_react21.useEffect)(() => {
15464
+ if (view === "transfer" && !showTransferCrypto) {
15465
+ setView("main");
15466
+ } else if (view === "wallet_connect" && !showConnectWallet) {
15467
+ setView("main");
15468
+ }
15469
+ }, [showConnectWallet, showTransferCrypto, view]);
15208
15470
  const prevStatusRef = (0, import_react21.useRef)(null);
15209
15471
  (0, import_react21.useEffect)(() => {
15210
15472
  if (!paymentIntent) return;
@@ -15295,7 +15557,7 @@ function CheckoutModal({
15295
15557
  const handleBrowserWalletClick = (0, import_react21.useCallback)(
15296
15558
  (walletInfo) => {
15297
15559
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
15298
- setStoredWalletChainType(walletChainType);
15560
+ setStoredWalletState(walletInfo.type);
15299
15561
  setBrowserWalletChainType(walletChainType);
15300
15562
  const matchingDepositWallet = wallets.find(
15301
15563
  (w) => w.chain_type === walletChainType
@@ -15322,7 +15584,7 @@ function CheckoutModal({
15322
15584
  const handleWalletConnected = (0, import_react21.useCallback)(
15323
15585
  (walletInfo) => {
15324
15586
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
15325
- setStoredWalletChainType(walletChainType);
15587
+ setStoredWalletState(walletInfo.type);
15326
15588
  setBrowserWalletChainType(walletChainType);
15327
15589
  const matchingDepositWallet = wallets.find(
15328
15590
  (w) => w.chain_type === walletChainType
@@ -15346,7 +15608,7 @@ function CheckoutModal({
15346
15608
  );
15347
15609
  const handleWalletDisconnect = (0, import_react21.useCallback)(() => {
15348
15610
  setUserDisconnectedWallet(true);
15349
- clearStoredWalletChainType();
15611
+ clearStoredWalletState();
15350
15612
  setBrowserWalletChainType(void 0);
15351
15613
  setBrowserWalletInfo(null);
15352
15614
  setBrowserWalletModalOpen(false);
@@ -15581,7 +15843,7 @@ function CheckoutModal({
15581
15843
  ] }) : paymentIntent ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uf-space-y-3", children: [
15582
15844
  progressSection,
15583
15845
  (paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
15584
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
15846
+ showTransferCrypto && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
15585
15847
  TransferCryptoButton,
15586
15848
  {
15587
15849
  onClick: () => setView("transfer"),
@@ -15590,7 +15852,7 @@ function CheckoutModal({
15590
15852
  featuredTokens: projectConfig?.transfer_crypto.networks
15591
15853
  }
15592
15854
  ),
15593
- enableConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
15855
+ showConnectWallet && !isMobileView && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
15594
15856
  BrowserWalletButton,
15595
15857
  {
15596
15858
  onClick: handleBrowserWalletClick,
@@ -15731,14 +15993,18 @@ function CheckoutModal({
15731
15993
  onWalletDisconnect: handleWalletDisconnect,
15732
15994
  onWalletConnected: (info, dw) => {
15733
15995
  setBrowserWalletInfo({ ...info, depositWallet: dw });
15734
- setStoredWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
15996
+ setStoredWalletState(info.type);
15735
15997
  setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
15736
15998
  },
15737
15999
  onNewDeposit: () => setView("main"),
15738
16000
  onDone: () => setView("main"),
15739
16001
  paymentIntentStatus: paymentIntent.status,
15740
16002
  onBack: handleBack,
15741
- onClose: handleClose
16003
+ onClose: handleClose,
16004
+ defaultSourceChainType,
16005
+ defaultSourceChainId,
16006
+ defaultSourceTokenAddress,
16007
+ defaultSourceSymbol
15742
16008
  }
15743
16009
  ),
15744
16010
  poweredByFooter