@unifold/ui-react 0.1.60 → 0.1.62

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
@@ -719,6 +719,7 @@ function useDepositAddress(params) {
719
719
  destinationChainId,
720
720
  destinationTokenAddress,
721
721
  actionType,
722
+ contractCalls,
722
723
  enabled = true
723
724
  } = params;
724
725
  return (0, import_react_query.useQuery)({
@@ -731,6 +732,7 @@ function useDepositAddress(params) {
731
732
  destinationChainId ?? null,
732
733
  destinationTokenAddress ?? null,
733
734
  actionType ?? null,
735
+ contractCalls ?? null,
734
736
  publishableKey
735
737
  ],
736
738
  queryFn: () => (0, import_core.createDepositAddress)(
@@ -740,7 +742,8 @@ function useDepositAddress(params) {
740
742
  destination_chain_type: destinationChainType,
741
743
  destination_chain_id: destinationChainId,
742
744
  destination_token_address: destinationTokenAddress,
743
- action_type: actionType
745
+ action_type: actionType,
746
+ contract_calls: contractCalls
744
747
  },
745
748
  publishableKey
746
749
  ),
@@ -5320,7 +5323,7 @@ function CashAppButton({
5320
5323
  }
5321
5324
 
5322
5325
  // src/components/deposits/buttons/BrowserWalletButton.tsx
5323
- var React24 = __toESM(require("react"));
5326
+ var React25 = __toESM(require("react"));
5324
5327
  var import_lucide_react17 = require("lucide-react");
5325
5328
  var import_core14 = require("@unifold/core");
5326
5329
 
@@ -5374,6 +5377,197 @@ function collectAllEip6963EthProviders() {
5374
5377
  return store.getProviders().map((d) => d.provider);
5375
5378
  }
5376
5379
 
5380
+ // src/components/deposits/browser-wallets/useDetectedBrowserWallet.ts
5381
+ var React12 = __toESM(require("react"));
5382
+
5383
+ // src/components/deposits/browser-wallets/detectConnectedWallet.ts
5384
+ function identifyEthWallet(provider, hint) {
5385
+ switch (hint) {
5386
+ case "metamask":
5387
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
5388
+ case "phantom":
5389
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
5390
+ case "coinbase":
5391
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
5392
+ case "okx":
5393
+ return { type: "okx", name: "OKX Wallet", icon: "okx" };
5394
+ case "rabby":
5395
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
5396
+ case "trust":
5397
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
5398
+ case "rainbow":
5399
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
5400
+ }
5401
+ const anyProvider = provider;
5402
+ if (provider.isPhantom) {
5403
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
5404
+ }
5405
+ if (anyProvider.isCoinbaseWallet) {
5406
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
5407
+ }
5408
+ if (anyProvider.isRabby) {
5409
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
5410
+ }
5411
+ if (anyProvider.isTrust) {
5412
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
5413
+ }
5414
+ if (anyProvider.isRainbow) {
5415
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
5416
+ }
5417
+ if (provider.isMetaMask && !provider.isPhantom) {
5418
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
5419
+ }
5420
+ return { type: "metamask", name: "Wallet", icon: "metamask" };
5421
+ }
5422
+ async function detectConnectedBrowserWallet(chainType) {
5423
+ if (typeof window === "undefined") return null;
5424
+ if (getUserDisconnectedWallet()) return null;
5425
+ try {
5426
+ 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
+ }
5452
+ }
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
+ }
5486
+ }
5487
+ } catch (error) {
5488
+ console.error("[detectConnectedBrowserWallet] detection error:", error);
5489
+ }
5490
+ return null;
5491
+ }
5492
+
5493
+ // src/components/deposits/browser-wallets/useDetectedBrowserWallet.ts
5494
+ function useDetectedBrowserWallet(opts = {}) {
5495
+ const { chainType, enabled = true, onDisconnect } = opts;
5496
+ const [wallet, setWallet] = React12.useState(null);
5497
+ const [isLoading, setIsLoading] = React12.useState(enabled);
5498
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React12.useState(0);
5499
+ const onDisconnectRef = React12.useRef(onDisconnect);
5500
+ onDisconnectRef.current = onDisconnect;
5501
+ React12.useEffect(() => {
5502
+ const store = getEip6963Store();
5503
+ if (!store) return;
5504
+ setEip6963ProviderCount(store.getProviders().length);
5505
+ return store.subscribe((providers) => setEip6963ProviderCount(providers.length));
5506
+ }, []);
5507
+ React12.useEffect(() => {
5508
+ if (!enabled) {
5509
+ setWallet(null);
5510
+ setIsLoading(false);
5511
+ return;
5512
+ }
5513
+ let mounted = true;
5514
+ const detect = async () => {
5515
+ if (!mounted) return;
5516
+ setIsLoading(true);
5517
+ const detected = await detectConnectedBrowserWallet(chainType);
5518
+ if (!mounted) return;
5519
+ setWallet(detected);
5520
+ setIsLoading(false);
5521
+ };
5522
+ detect();
5523
+ const onChange = () => detect();
5524
+ const onDisc = () => {
5525
+ onDisconnectRef.current?.();
5526
+ detect();
5527
+ };
5528
+ const onEthAccounts = (accounts) => {
5529
+ if (Array.isArray(accounts) && accounts.length === 0) onDisconnectRef.current?.();
5530
+ detect();
5531
+ };
5532
+ const win = typeof window !== "undefined" ? window : void 0;
5533
+ const solanaProvider = win?.phantom?.solana || win?.solana;
5534
+ if (solanaProvider) {
5535
+ solanaProvider.on("connect", onChange);
5536
+ solanaProvider.on("disconnect", onDisc);
5537
+ solanaProvider.on("accountChanged", onChange);
5538
+ }
5539
+ const ethProviders = [];
5540
+ for (const { provider } of getEip6963Providers()) {
5541
+ const p = provider;
5542
+ if (p && !ethProviders.includes(p)) ethProviders.push(p);
5543
+ }
5544
+ if (win?.ethereum && !ethProviders.includes(win.ethereum)) ethProviders.push(win.ethereum);
5545
+ if (win?.phantom?.ethereum && !ethProviders.includes(win.phantom.ethereum)) {
5546
+ ethProviders.push(win.phantom.ethereum);
5547
+ }
5548
+ for (const p of ethProviders) {
5549
+ p.on("accountsChanged", onEthAccounts);
5550
+ p.on("chainChanged", onChange);
5551
+ }
5552
+ return () => {
5553
+ mounted = false;
5554
+ if (solanaProvider) {
5555
+ solanaProvider.off?.("connect", onChange);
5556
+ solanaProvider.off?.("disconnect", onDisc);
5557
+ solanaProvider.off?.("accountChanged", onChange);
5558
+ }
5559
+ for (const p of ethProviders) {
5560
+ const off = p.off?.bind(p) ?? p.removeListener?.bind(p);
5561
+ if (off) {
5562
+ off("accountsChanged", onEthAccounts);
5563
+ off("chainChanged", onChange);
5564
+ }
5565
+ }
5566
+ };
5567
+ }, [chainType, eip6963ProviderCount, enabled]);
5568
+ return { wallet, isLoading, setWallet };
5569
+ }
5570
+
5377
5571
  // src/components/deposits/browser-wallets/disconnectInjectedBrowserWallet.ts
5378
5572
  var SOLANA_DISCONNECT_TYPES = [
5379
5573
  "phantom-solana",
@@ -5459,14 +5653,14 @@ async function disconnectInjectedBrowserWallet(wallet) {
5459
5653
  }
5460
5654
 
5461
5655
  // src/resources/icons/MetamaskIcon.tsx
5462
- var React12 = __toESM(require("react"));
5656
+ var React13 = __toESM(require("react"));
5463
5657
  var import_jsx_runtime23 = require("react/jsx-runtime");
5464
5658
  function MetamaskIcon({
5465
5659
  size = 24,
5466
5660
  className,
5467
5661
  variant = "color"
5468
5662
  }) {
5469
- const id = React12.useId();
5663
+ const id = React13.useId();
5470
5664
  if (variant === "light" || variant === "dark") {
5471
5665
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5472
5666
  "svg",
@@ -5588,14 +5782,14 @@ function MetamaskIcon({
5588
5782
  }
5589
5783
 
5590
5784
  // src/resources/icons/PhantomIcon.tsx
5591
- var React13 = __toESM(require("react"));
5785
+ var React14 = __toESM(require("react"));
5592
5786
  var import_jsx_runtime24 = require("react/jsx-runtime");
5593
5787
  function PhantomIcon({
5594
5788
  size = 24,
5595
5789
  className,
5596
5790
  variant = "color"
5597
5791
  }) {
5598
- const id = React13.useId();
5792
+ const id = React14.useId();
5599
5793
  if (variant === "light") {
5600
5794
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5601
5795
  "svg",
@@ -5663,14 +5857,14 @@ function PhantomIcon({
5663
5857
  }
5664
5858
 
5665
5859
  // src/resources/icons/CoinbaseIcon.tsx
5666
- var React14 = __toESM(require("react"));
5860
+ var React15 = __toESM(require("react"));
5667
5861
  var import_jsx_runtime25 = require("react/jsx-runtime");
5668
5862
  function CoinbaseIcon({
5669
5863
  size = 24,
5670
5864
  className,
5671
5865
  variant = "color"
5672
5866
  }) {
5673
- const id = React14.useId();
5867
+ const id = React15.useId();
5674
5868
  if (variant === "light") {
5675
5869
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5676
5870
  "svg",
@@ -5751,14 +5945,14 @@ function CoinbaseIcon({
5751
5945
  }
5752
5946
 
5753
5947
  // src/resources/icons/RabbyIcon.tsx
5754
- var React15 = __toESM(require("react"));
5948
+ var React16 = __toESM(require("react"));
5755
5949
  var import_jsx_runtime26 = require("react/jsx-runtime");
5756
5950
  function RabbyIcon({
5757
5951
  size = 24,
5758
5952
  className,
5759
5953
  variant = "color"
5760
5954
  }) {
5761
- const id = React15.useId();
5955
+ const id = React16.useId();
5762
5956
  if (variant === "light") {
5763
5957
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5764
5958
  "svg",
@@ -6106,14 +6300,14 @@ function RabbyIcon({
6106
6300
  }
6107
6301
 
6108
6302
  // src/resources/icons/RainbowIcon.tsx
6109
- var React16 = __toESM(require("react"));
6303
+ var React17 = __toESM(require("react"));
6110
6304
  var import_jsx_runtime27 = require("react/jsx-runtime");
6111
6305
  function RainbowIcon({
6112
6306
  size = 24,
6113
6307
  className,
6114
6308
  variant = "color"
6115
6309
  }) {
6116
- const id = React16.useId();
6310
+ const id = React17.useId();
6117
6311
  if (variant === "light") {
6118
6312
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6119
6313
  "svg",
@@ -6576,14 +6770,14 @@ function RainbowIcon({
6576
6770
  }
6577
6771
 
6578
6772
  // src/resources/icons/TrustIcon.tsx
6579
- var React17 = __toESM(require("react"));
6773
+ var React18 = __toESM(require("react"));
6580
6774
  var import_jsx_runtime28 = require("react/jsx-runtime");
6581
6775
  function TrustIcon({
6582
6776
  size = 24,
6583
6777
  className,
6584
6778
  variant = "color"
6585
6779
  }) {
6586
- const id = React17.useId();
6780
+ const id = React18.useId();
6587
6781
  if (variant === "light") {
6588
6782
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6589
6783
  "svg",
@@ -6673,14 +6867,14 @@ function TrustIcon({
6673
6867
  }
6674
6868
 
6675
6869
  // src/resources/icons/OkxIcon.tsx
6676
- var React18 = __toESM(require("react"));
6870
+ var React19 = __toESM(require("react"));
6677
6871
  var import_jsx_runtime29 = require("react/jsx-runtime");
6678
6872
  function OkxIcon({
6679
6873
  size = 24,
6680
6874
  className,
6681
6875
  variant = "color"
6682
6876
  }) {
6683
- const id = React18.useId();
6877
+ const id = React19.useId();
6684
6878
  if (variant === "light") {
6685
6879
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6686
6880
  "svg",
@@ -6748,14 +6942,14 @@ function OkxIcon({
6748
6942
  }
6749
6943
 
6750
6944
  // src/resources/icons/GlowIcon.tsx
6751
- var React19 = __toESM(require("react"));
6945
+ var React20 = __toESM(require("react"));
6752
6946
  var import_jsx_runtime30 = require("react/jsx-runtime");
6753
6947
  function GlowIcon({
6754
6948
  size = 24,
6755
6949
  className,
6756
6950
  variant = "color"
6757
6951
  }) {
6758
- const id = React19.useId();
6952
+ const id = React20.useId();
6759
6953
  if (variant === "light") {
6760
6954
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6761
6955
  "svg",
@@ -6857,14 +7051,14 @@ function GlowIcon({
6857
7051
  }
6858
7052
 
6859
7053
  // src/resources/icons/BackpackIcon.tsx
6860
- var React20 = __toESM(require("react"));
7054
+ var React21 = __toESM(require("react"));
6861
7055
  var import_jsx_runtime31 = require("react/jsx-runtime");
6862
7056
  function BackpackIcon({
6863
7057
  size = 24,
6864
7058
  className,
6865
7059
  variant = "color"
6866
7060
  }) {
6867
- const id = React20.useId();
7061
+ const id = React21.useId();
6868
7062
  if (variant === "light") {
6869
7063
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6870
7064
  "svg",
@@ -6938,14 +7132,14 @@ function BackpackIcon({
6938
7132
  }
6939
7133
 
6940
7134
  // src/resources/icons/SolflareIcon.tsx
6941
- var React21 = __toESM(require("react"));
7135
+ var React22 = __toESM(require("react"));
6942
7136
  var import_jsx_runtime32 = require("react/jsx-runtime");
6943
7137
  function SolflareIcon({
6944
7138
  size = 24,
6945
7139
  className,
6946
7140
  variant = "color"
6947
7141
  }) {
6948
- const id = React21.useId();
7142
+ const id = React22.useId();
6949
7143
  if (variant === "light") {
6950
7144
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6951
7145
  "svg",
@@ -7013,14 +7207,14 @@ function SolflareIcon({
7013
7207
  }
7014
7208
 
7015
7209
  // src/resources/icons/EthereumIcon.tsx
7016
- var React22 = __toESM(require("react"));
7210
+ var React23 = __toESM(require("react"));
7017
7211
  var import_jsx_runtime33 = require("react/jsx-runtime");
7018
7212
  function EthereumIcon({
7019
7213
  size = 24,
7020
7214
  className,
7021
7215
  variant = "color"
7022
7216
  }) {
7023
- const id = React22.useId();
7217
+ const id = React23.useId();
7024
7218
  if (variant === "light") {
7025
7219
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7026
7220
  "svg",
@@ -7151,14 +7345,14 @@ function EthereumIcon({
7151
7345
  }
7152
7346
 
7153
7347
  // src/resources/icons/SolanaIcon.tsx
7154
- var React23 = __toESM(require("react"));
7348
+ var React24 = __toESM(require("react"));
7155
7349
  var import_jsx_runtime34 = require("react/jsx-runtime");
7156
7350
  function SolanaIcon({
7157
7351
  size = 24,
7158
7352
  className,
7159
7353
  variant = "color"
7160
7354
  }) {
7161
- const id = React23.useId();
7355
+ const id = React24.useId();
7162
7356
  if (variant === "light") {
7163
7357
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7164
7358
  "svg",
@@ -7413,44 +7607,6 @@ function truncateAddress3(address) {
7413
7607
  if (address.length <= 10) return address;
7414
7608
  return `${address.slice(0, 4)}...${address.slice(-4)}`;
7415
7609
  }
7416
- function identifyEthWallet(provider, _win, hint) {
7417
- switch (hint) {
7418
- case "metamask":
7419
- return { type: "metamask", name: "MetaMask", icon: "metamask" };
7420
- case "phantom":
7421
- return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
7422
- case "coinbase":
7423
- return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
7424
- case "okx":
7425
- return { type: "okx", name: "OKX Wallet", icon: "okx" };
7426
- case "rabby":
7427
- return { type: "rabby", name: "Rabby", icon: "rabby" };
7428
- case "trust":
7429
- return { type: "trust", name: "Trust Wallet", icon: "trust" };
7430
- case "rainbow":
7431
- return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
7432
- }
7433
- const anyProvider = provider;
7434
- if (provider.isPhantom) {
7435
- return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
7436
- }
7437
- if (anyProvider.isCoinbaseWallet) {
7438
- return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
7439
- }
7440
- if (anyProvider.isRabby) {
7441
- return { type: "rabby", name: "Rabby", icon: "rabby" };
7442
- }
7443
- if (anyProvider.isTrust) {
7444
- return { type: "trust", name: "Trust Wallet", icon: "trust" };
7445
- }
7446
- if (anyProvider.isRainbow) {
7447
- return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
7448
- }
7449
- if (provider.isMetaMask && !provider.isPhantom) {
7450
- return { type: "metamask", name: "MetaMask", icon: "metamask" };
7451
- }
7452
- return { type: "metamask", name: "Wallet", icon: "metamask" };
7453
- }
7454
7610
  function BrowserWalletButton({
7455
7611
  onClick,
7456
7612
  onConnectClick,
@@ -7461,30 +7617,19 @@ function BrowserWalletButton({
7461
7617
  subtitle = i18n.depositModal.browserWallet.subtitle
7462
7618
  }) {
7463
7619
  const { colors: colors2, fonts, components } = useTheme();
7464
- const [isHovered, setIsHovered] = React24.useState(false);
7465
- const [isTouchDevice, setIsTouchDevice] = React24.useState(false);
7466
- const [wallet, setWallet] = React24.useState(null);
7467
- const [isLoading, setIsLoading] = React24.useState(true);
7468
- const [isConnecting, setIsConnecting] = React24.useState(false);
7469
- const [balanceText, setBalanceText] = React24.useState(null);
7470
- const [isLoadingBalance, setIsLoadingBalance] = React24.useState(false);
7471
- const [isDisconnecting, setIsDisconnecting] = React24.useState(false);
7472
- const onDisconnectRef = React24.useRef(onDisconnect);
7620
+ const [isHovered, setIsHovered] = React25.useState(false);
7621
+ const [isTouchDevice, setIsTouchDevice] = React25.useState(false);
7622
+ const { wallet, isLoading, setWallet } = useDetectedBrowserWallet({ chainType, onDisconnect });
7623
+ const [isConnecting, setIsConnecting] = React25.useState(false);
7624
+ const [balanceText, setBalanceText] = React25.useState(null);
7625
+ const [isLoadingBalance, setIsLoadingBalance] = React25.useState(false);
7626
+ const [isDisconnecting, setIsDisconnecting] = React25.useState(false);
7627
+ const onDisconnectRef = React25.useRef(onDisconnect);
7473
7628
  onDisconnectRef.current = onDisconnect;
7474
- React24.useEffect(() => {
7629
+ React25.useEffect(() => {
7475
7630
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7476
7631
  }, []);
7477
- const [eip6963ProviderCount, setEip6963ProviderCount] = React24.useState(0);
7478
- React24.useEffect(() => {
7479
- const store = getEip6963Store();
7480
- if (!store) return;
7481
- setEip6963ProviderCount(store.getProviders().length);
7482
- const unsubscribe = store.subscribe((providers) => {
7483
- setEip6963ProviderCount(providers.length);
7484
- });
7485
- return unsubscribe;
7486
- }, []);
7487
- React24.useEffect(() => {
7632
+ React25.useEffect(() => {
7488
7633
  if (!wallet || !publishableKey) {
7489
7634
  setBalanceText(null);
7490
7635
  return;
@@ -7525,206 +7670,6 @@ function BrowserWalletButton({
7525
7670
  cancelled = true;
7526
7671
  };
7527
7672
  }, [wallet, publishableKey]);
7528
- React24.useEffect(() => {
7529
- let mounted = true;
7530
- const detectWallet = async () => {
7531
- if (!mounted) return;
7532
- setIsLoading(true);
7533
- try {
7534
- const win = typeof window !== "undefined" ? window : null;
7535
- if (!win) return;
7536
- if (getUserDisconnectedWallet()) {
7537
- if (mounted) {
7538
- setWallet(null);
7539
- setIsLoading(false);
7540
- }
7541
- return;
7542
- }
7543
- if (!chainType || chainType === "solana") {
7544
- const anyWin = win;
7545
- const trySilentSolana = async (provider, type, name, icon) => {
7546
- if (!provider) return false;
7547
- if (provider.isConnected && provider.publicKey) {
7548
- if (mounted) {
7549
- setWallet({
7550
- type,
7551
- name,
7552
- address: provider.publicKey.toString(),
7553
- icon
7554
- });
7555
- setIsLoading(false);
7556
- }
7557
- return true;
7558
- }
7559
- try {
7560
- const resp = await provider.connect({ onlyIfTrusted: true });
7561
- if (mounted && resp.publicKey) {
7562
- setWallet({
7563
- type,
7564
- name,
7565
- address: resp.publicKey.toString(),
7566
- icon
7567
- });
7568
- setIsLoading(false);
7569
- return true;
7570
- }
7571
- } catch {
7572
- }
7573
- return false;
7574
- };
7575
- if (await trySilentSolana(
7576
- win.phantom?.solana,
7577
- "phantom-solana",
7578
- "Phantom",
7579
- "phantom"
7580
- ))
7581
- return;
7582
- if (await trySilentSolana(
7583
- anyWin.solflare,
7584
- "solflare",
7585
- "Solflare",
7586
- "solflare"
7587
- ))
7588
- return;
7589
- if (await trySilentSolana(
7590
- anyWin.backpack,
7591
- "backpack",
7592
- "Backpack",
7593
- "backpack"
7594
- ))
7595
- return;
7596
- if (await trySilentSolana(
7597
- anyWin.glow,
7598
- "glow",
7599
- "Glow",
7600
- "glow"
7601
- ))
7602
- return;
7603
- }
7604
- if (!chainType || chainType === "ethereum") {
7605
- const anyWin = win;
7606
- const allProviders = [];
7607
- const eip6963 = getEip6963Providers();
7608
- for (const { provider, walletId } of eip6963) {
7609
- allProviders.push({
7610
- provider,
7611
- walletId: walletId === "unknown" ? "default" : walletId
7612
- });
7613
- }
7614
- if (allProviders.length === 0) {
7615
- if (win.phantom?.ethereum) {
7616
- allProviders.push({
7617
- provider: win.phantom.ethereum,
7618
- walletId: "phantom"
7619
- });
7620
- }
7621
- if (anyWin.okxwallet) {
7622
- allProviders.push({
7623
- provider: anyWin.okxwallet,
7624
- walletId: "okx"
7625
- });
7626
- }
7627
- if (anyWin.coinbaseWalletExtension) {
7628
- allProviders.push({
7629
- provider: anyWin.coinbaseWalletExtension,
7630
- walletId: "coinbase"
7631
- });
7632
- }
7633
- if (win.ethereum) {
7634
- const isDuplicate = allProviders.some(
7635
- (p) => p.provider === win.ethereum
7636
- );
7637
- if (!isDuplicate) {
7638
- allProviders.push({
7639
- provider: win.ethereum,
7640
- walletId: "default"
7641
- });
7642
- }
7643
- }
7644
- }
7645
- for (const { provider, walletId } of allProviders) {
7646
- if (!provider) continue;
7647
- try {
7648
- const accounts = await provider.request({
7649
- method: "eth_accounts"
7650
- });
7651
- if (!accounts || accounts.length === 0) continue;
7652
- const address = accounts[0];
7653
- const resolved = identifyEthWallet(provider, anyWin, walletId);
7654
- if (mounted) {
7655
- setWallet({ ...resolved, address });
7656
- setIsLoading(false);
7657
- }
7658
- return;
7659
- } catch {
7660
- }
7661
- }
7662
- }
7663
- if (mounted) {
7664
- setWallet(null);
7665
- setIsLoading(false);
7666
- }
7667
- } catch (error) {
7668
- console.error("[BrowserWalletButton] Error detecting wallet:", error);
7669
- if (mounted) {
7670
- setWallet(null);
7671
- setIsLoading(false);
7672
- }
7673
- }
7674
- };
7675
- detectWallet();
7676
- const handleAccountsChanged = () => {
7677
- detectWallet();
7678
- };
7679
- const handleDisconnect = () => {
7680
- onDisconnectRef.current?.();
7681
- detectWallet();
7682
- };
7683
- const handleEthAccountsChanged = (accounts) => {
7684
- if (Array.isArray(accounts) && accounts.length === 0) {
7685
- onDisconnectRef.current?.();
7686
- }
7687
- detectWallet();
7688
- };
7689
- const solanaProvider = window.phantom?.solana || window.solana;
7690
- if (solanaProvider) {
7691
- solanaProvider.on("connect", handleAccountsChanged);
7692
- solanaProvider.on("disconnect", handleDisconnect);
7693
- solanaProvider.on("accountChanged", handleAccountsChanged);
7694
- }
7695
- const ethProviders = [];
7696
- for (const { provider } of getEip6963Providers()) {
7697
- const p = provider;
7698
- if (p && !ethProviders.includes(p)) {
7699
- ethProviders.push(p);
7700
- }
7701
- }
7702
- if (window.ethereum && !ethProviders.includes(window.ethereum)) {
7703
- ethProviders.push(window.ethereum);
7704
- }
7705
- if (window.phantom?.ethereum && !ethProviders.includes(window.phantom.ethereum)) {
7706
- ethProviders.push(window.phantom.ethereum);
7707
- }
7708
- for (const provider of ethProviders) {
7709
- provider.on("accountsChanged", handleEthAccountsChanged);
7710
- provider.on("chainChanged", handleAccountsChanged);
7711
- }
7712
- return () => {
7713
- mounted = false;
7714
- if (solanaProvider) {
7715
- solanaProvider.off("connect", handleAccountsChanged);
7716
- solanaProvider.off("disconnect", handleDisconnect);
7717
- solanaProvider.off("accountChanged", handleAccountsChanged);
7718
- }
7719
- for (const provider of ethProviders) {
7720
- const off = provider.off?.bind(provider) ?? provider.removeListener?.bind(provider);
7721
- if (off) {
7722
- off("accountsChanged", handleEthAccountsChanged);
7723
- off("chainChanged", handleAccountsChanged);
7724
- }
7725
- }
7726
- };
7727
- }, [chainType, eip6963ProviderCount]);
7728
7673
  const handleConnect = async () => {
7729
7674
  if (wallet) {
7730
7675
  onClick(wallet);
@@ -7808,7 +7753,7 @@ function BrowserWalletButton({
7808
7753
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
7809
7754
  };
7810
7755
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
7811
- const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React24.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
7756
+ const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React25.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
7812
7757
  size: 36,
7813
7758
  className: "uf-rounded-lg",
7814
7759
  variant: "color"
@@ -8092,6 +8037,7 @@ function CoinbaseConnect({
8092
8037
  onBack: parentOnBack,
8093
8038
  onDisconnect,
8094
8039
  skipToHoldings,
8040
+ canGoBack = true,
8095
8041
  onExecutionsChange
8096
8042
  }) {
8097
8043
  const { colors: colors2, fonts, components } = useTheme();
@@ -8479,6 +8425,16 @@ function CoinbaseConnect({
8479
8425
  setIsLoading(false);
8480
8426
  }
8481
8427
  };
8428
+ const handleDisconnect = () => {
8429
+ onDisconnect?.();
8430
+ if (!canGoBack) {
8431
+ setAccessToken(null);
8432
+ setHoldings([]);
8433
+ setSelectedHolding(null);
8434
+ setSelectedAsset(null);
8435
+ transitionTo("select_exchange");
8436
+ }
8437
+ };
8482
8438
  const handleBack = () => {
8483
8439
  switch (view) {
8484
8440
  case "select_exchange":
@@ -8539,7 +8495,7 @@ function CoinbaseConnect({
8539
8495
  DepositHeader,
8540
8496
  {
8541
8497
  title: t12.title,
8542
- showBack: true,
8498
+ showBack: canGoBack,
8543
8499
  onBack: handleBack,
8544
8500
  onClose
8545
8501
  }
@@ -8552,7 +8508,7 @@ function CoinbaseConnect({
8552
8508
  DepositHeader,
8553
8509
  {
8554
8510
  title: t12.title,
8555
- showBack: true,
8511
+ showBack: canGoBack,
8556
8512
  onBack: handleBack,
8557
8513
  onClose
8558
8514
  }
@@ -9264,7 +9220,7 @@ function CoinbaseConnect({
9264
9220
  borderRadius: components.button.borderRadius,
9265
9221
  fontFamily: fonts.medium
9266
9222
  },
9267
- onClick: onDisconnect,
9223
+ onClick: handleDisconnect,
9268
9224
  children: t12.disconnect
9269
9225
  }
9270
9226
  )
@@ -10074,14 +10030,14 @@ var import_lucide_react22 = require("lucide-react");
10074
10030
  var import_react13 = require("react");
10075
10031
 
10076
10032
  // src/components/shared/ThemeStyleInjector.tsx
10077
- var React26 = __toESM(require("react"));
10033
+ var React27 = __toESM(require("react"));
10078
10034
  var import_jsx_runtime38 = require("react/jsx-runtime");
10079
10035
  function ThemeStyleInjector({
10080
10036
  children,
10081
10037
  className
10082
10038
  }) {
10083
10039
  const { colors: colors2, fonts, mode } = useTheme();
10084
- const cssVars = React26.useMemo(() => {
10040
+ const cssVars = React27.useMemo(() => {
10085
10041
  const hexToHSL = (hex) => {
10086
10042
  hex = hex.replace("#", "");
10087
10043
  const r = parseInt(hex.slice(0, 2), 16) / 255;
@@ -10141,7 +10097,7 @@ function ThemeStyleInjector({
10141
10097
  ...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
10142
10098
  };
10143
10099
  }, [colors2, fonts.regular]);
10144
- React26.useEffect(() => {
10100
+ React27.useEffect(() => {
10145
10101
  if (typeof document === "undefined") return;
10146
10102
  if (fonts.regular) {
10147
10103
  document.documentElement.style.setProperty(
@@ -11129,7 +11085,7 @@ function useCopyAddress() {
11129
11085
  }
11130
11086
 
11131
11087
  // src/components/shared/tooltip.tsx
11132
- var React27 = __toESM(require("react"));
11088
+ var React28 = __toESM(require("react"));
11133
11089
  var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"));
11134
11090
  var import_jsx_runtime44 = require("react/jsx-runtime");
11135
11091
  var TooltipProvider = TooltipPrimitive.Provider;
@@ -11137,7 +11093,7 @@ function Tooltip({
11137
11093
  children,
11138
11094
  ...props
11139
11095
  }) {
11140
- const [open, setOpen] = React27.useState(props.defaultOpen ?? false);
11096
+ const [open, setOpen] = React28.useState(props.defaultOpen ?? false);
11141
11097
  const isControlled = props.open !== void 0;
11142
11098
  const isOpen = isControlled ? props.open : open;
11143
11099
  const onOpenChange = isControlled ? props.onOpenChange : (nextOpen) => setOpen(nextOpen);
@@ -11157,14 +11113,14 @@ function Tooltip({
11157
11113
  }
11158
11114
  );
11159
11115
  }
11160
- var TooltipContext = React27.createContext({
11116
+ var TooltipContext = React28.createContext({
11161
11117
  open: false,
11162
11118
  onOpenChange: () => {
11163
11119
  }
11164
11120
  });
11165
- var TooltipTrigger = React27.forwardRef(({ onClick, ...props }, ref) => {
11166
- const { open, onOpenChange } = React27.useContext(TooltipContext);
11167
- const handleClick = React27.useCallback(
11121
+ var TooltipTrigger = React28.forwardRef(({ onClick, ...props }, ref) => {
11122
+ const { open, onOpenChange } = React28.useContext(TooltipContext);
11123
+ const handleClick = React28.useCallback(
11168
11124
  (e) => {
11169
11125
  onOpenChange(!open);
11170
11126
  onClick?.(e);
@@ -11174,7 +11130,7 @@ var TooltipTrigger = React27.forwardRef(({ onClick, ...props }, ref) => {
11174
11130
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TooltipPrimitive.Trigger, { ref, onClick: handleClick, ...props });
11175
11131
  });
11176
11132
  TooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;
11177
- var TooltipContent = React27.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
11133
+ var TooltipContent = React28.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
11178
11134
  const { themeClass, colors: colors2 } = useTheme();
11179
11135
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11180
11136
  TooltipPrimitive.Content,
@@ -11801,14 +11757,14 @@ var import_react18 = require("react");
11801
11757
  var import_lucide_react24 = require("lucide-react");
11802
11758
 
11803
11759
  // src/components/shared/select.tsx
11804
- var React28 = __toESM(require("react"));
11760
+ var React29 = __toESM(require("react"));
11805
11761
  var SelectPrimitive = __toESM(require("@radix-ui/react-select"));
11806
11762
  var import_lucide_react23 = require("lucide-react");
11807
11763
  var import_jsx_runtime47 = require("react/jsx-runtime");
11808
11764
  var Select = SelectPrimitive.Root;
11809
11765
  var SelectGroup = SelectPrimitive.Group;
11810
11766
  var SelectValue = SelectPrimitive.Value;
11811
- var SelectTrigger = React28.forwardRef(({ className, style, children, ...props }, ref) => {
11767
+ var SelectTrigger = React29.forwardRef(({ className, style, children, ...props }, ref) => {
11812
11768
  const { components } = useTheme();
11813
11769
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
11814
11770
  SelectPrimitive.Trigger,
@@ -11832,7 +11788,7 @@ var SelectTrigger = React28.forwardRef(({ className, style, children, ...props }
11832
11788
  );
11833
11789
  });
11834
11790
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
11835
- var SelectScrollUpButton = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11791
+ var SelectScrollUpButton = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11836
11792
  SelectPrimitive.ScrollUpButton,
11837
11793
  {
11838
11794
  ref,
@@ -11845,7 +11801,7 @@ var SelectScrollUpButton = React28.forwardRef(({ className, ...props }, ref) =>
11845
11801
  }
11846
11802
  ));
11847
11803
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
11848
- var SelectScrollDownButton = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11804
+ var SelectScrollDownButton = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11849
11805
  SelectPrimitive.ScrollDownButton,
11850
11806
  {
11851
11807
  ref,
@@ -11858,7 +11814,7 @@ var SelectScrollDownButton = React28.forwardRef(({ className, ...props }, ref) =
11858
11814
  }
11859
11815
  ));
11860
11816
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
11861
- var SelectContent = React28.forwardRef(({ className, style, children, position = "popper", ...props }, ref) => {
11817
+ var SelectContent = React29.forwardRef(({ className, style, children, position = "popper", ...props }, ref) => {
11862
11818
  const { themeClass, colors: colors2, components } = useTheme();
11863
11819
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
11864
11820
  SelectPrimitive.Content,
@@ -11896,7 +11852,7 @@ var SelectContent = React28.forwardRef(({ className, style, children, position =
11896
11852
  ) });
11897
11853
  });
11898
11854
  SelectContent.displayName = SelectPrimitive.Content.displayName;
11899
- var SelectLabel = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11855
+ var SelectLabel = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11900
11856
  SelectPrimitive.Label,
11901
11857
  {
11902
11858
  ref,
@@ -11908,7 +11864,7 @@ var SelectLabel = React28.forwardRef(({ className, ...props }, ref) => /* @__PUR
11908
11864
  }
11909
11865
  ));
11910
11866
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
11911
- var SelectItem = React28.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
11867
+ var SelectItem = React29.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
11912
11868
  SelectPrimitive.Item,
11913
11869
  {
11914
11870
  ref,
@@ -11924,7 +11880,7 @@ var SelectItem = React28.forwardRef(({ className, children, ...props }, ref) =>
11924
11880
  }
11925
11881
  ));
11926
11882
  SelectItem.displayName = SelectPrimitive.Item.displayName;
11927
- var SelectSeparator = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11883
+ var SelectSeparator = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11928
11884
  SelectPrimitive.Separator,
11929
11885
  {
11930
11886
  ref,
@@ -12382,7 +12338,7 @@ function TransferCryptoDoubleInput({
12382
12338
  }
12383
12339
 
12384
12340
  // src/components/deposits/WalletConnect.tsx
12385
- var React29 = __toESM(require("react"));
12341
+ var React30 = __toESM(require("react"));
12386
12342
  var import_lucide_react28 = require("lucide-react");
12387
12343
  var import_core28 = require("@unifold/core");
12388
12344
 
@@ -13625,22 +13581,27 @@ function WalletConnect({
13625
13581
  productType,
13626
13582
  onBack: parentOnBack,
13627
13583
  onClose,
13584
+ canGoBack = true,
13585
+ depositWalletsLoading = false,
13628
13586
  onExecutionsChange
13629
13587
  }) {
13630
13588
  const { colors: colors2, fonts, components } = useTheme();
13631
- const walletProvidedAtMount = React29.useRef(!!initialWalletInfo && !!initialDepositWallet);
13632
- const [activeWalletInfo, setActiveWalletInfo] = React29.useState(initialWalletInfo ?? null);
13633
- const [activeDepositWallet, setActiveDepositWallet] = React29.useState(initialDepositWallet ?? null);
13589
+ const walletProvidedAtMount = React30.useRef(!!initialWalletInfo && !!initialDepositWallet);
13590
+ const [activeWalletInfo, setActiveWalletInfo] = React30.useState(initialWalletInfo ?? null);
13591
+ const [activeDepositWallet, setActiveDepositWallet] = React30.useState(initialDepositWallet ?? null);
13634
13592
  const initialView = initialWalletInfo && initialDepositWallet ? "select_token" : "select_wallet";
13635
- const [view, setView] = React29.useState(initialView);
13636
- const [isTransitioning, setIsTransitioning] = React29.useState(false);
13637
- const viewRef = React29.useRef(initialView);
13638
- const [selectedWalletDef, setSelectedWalletDef] = React29.useState(null);
13639
- const [connectingNetwork, setConnectingNetwork] = React29.useState(null);
13640
- const [walletError, setWalletError] = React29.useState(null);
13641
- const [isWalletConnecting, setIsWalletConnecting] = React29.useState(false);
13642
- const [eip6963ProviderCount, setEip6963ProviderCount] = React29.useState(0);
13643
- React29.useEffect(() => {
13593
+ const [view, setView] = React30.useState(initialView);
13594
+ const [isTransitioning, setIsTransitioning] = React30.useState(false);
13595
+ const viewRef = React30.useRef(initialView);
13596
+ const standalone = !canGoBack && !walletProvidedAtMount.current;
13597
+ const { wallet: detectedWallet, isLoading: detectingWallet } = useDetectedBrowserWallet({ enabled: standalone });
13598
+ const [autoResolved, setAutoResolved] = React30.useState(false);
13599
+ const [selectedWalletDef, setSelectedWalletDef] = React30.useState(null);
13600
+ const [connectingNetwork, setConnectingNetwork] = React30.useState(null);
13601
+ const [walletError, setWalletError] = React30.useState(null);
13602
+ const [isWalletConnecting, setIsWalletConnecting] = React30.useState(false);
13603
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React30.useState(0);
13604
+ React30.useEffect(() => {
13644
13605
  const store = getEip6963Store();
13645
13606
  if (!store) return;
13646
13607
  setEip6963ProviderCount(store.getProviders().length);
@@ -13648,20 +13609,44 @@ function WalletConnect({
13648
13609
  setEip6963ProviderCount(providers.length);
13649
13610
  });
13650
13611
  }, []);
13651
- const availableWallets = React29.useMemo(() => detectAvailableWallets(), [eip6963ProviderCount]);
13652
- const [balances, setBalances] = React29.useState([]);
13653
- const [isLoading, setIsLoading] = React29.useState(false);
13654
- const [selectedBalance, setSelectedBalance] = React29.useState(null);
13655
- const [totalBalanceUsd, setTotalBalanceUsd] = React29.useState(null);
13656
- const [error, setError] = React29.useState(null);
13657
- const [isDisconnectingWallet, setIsDisconnectingWallet] = React29.useState(false);
13658
- const [amountUsd, setAmountUsd] = React29.useState(prefillAmountUsd ?? "");
13659
- const [isConfirming, setIsConfirming] = React29.useState(false);
13660
- const [hasSignedTransaction, setHasSignedTransaction] = React29.useState(false);
13661
- const [tokenChainDetails, setTokenChainDetails] = React29.useState(null);
13662
- const [loadingTokenDetails, setLoadingTokenDetails] = React29.useState(false);
13663
- const [showTransactionDetails, setShowTransactionDetails] = React29.useState(false);
13664
- const [receivedUsdAtSubmission, setReceivedUsdAtSubmission] = React29.useState(null);
13612
+ const availableWallets = React30.useMemo(() => detectAvailableWallets(), [eip6963ProviderCount]);
13613
+ React30.useEffect(() => {
13614
+ if (!standalone || autoResolved || detectingWallet) return;
13615
+ if (!detectedWallet) {
13616
+ setAutoResolved(true);
13617
+ return;
13618
+ }
13619
+ const wct = detectedWallet.type === "phantom-solana" || detectedWallet.type === "solflare" || detectedWallet.type === "backpack" || detectedWallet.type === "glow" ? "solana" : "ethereum";
13620
+ const matching = depositWallets?.find((w) => w.chain_type === wct);
13621
+ if (!matching) {
13622
+ if (!depositWalletsLoading) setAutoResolved(true);
13623
+ return;
13624
+ }
13625
+ setActiveWalletInfo(detectedWallet);
13626
+ setActiveDepositWallet(matching);
13627
+ onWalletConnected?.(detectedWallet, matching);
13628
+ setView("select_token");
13629
+ viewRef.current = "select_token";
13630
+ setAutoResolved(true);
13631
+ }, [standalone, autoResolved, detectingWallet, detectedWallet, depositWallets, depositWalletsLoading]);
13632
+ React30.useEffect(() => {
13633
+ if (!standalone || autoResolved) return;
13634
+ const t12 = setTimeout(() => setAutoResolved(true), 5e3);
13635
+ return () => clearTimeout(t12);
13636
+ }, [standalone, autoResolved]);
13637
+ const [balances, setBalances] = React30.useState([]);
13638
+ const [isLoading, setIsLoading] = React30.useState(false);
13639
+ const [selectedBalance, setSelectedBalance] = React30.useState(null);
13640
+ const [totalBalanceUsd, setTotalBalanceUsd] = React30.useState(null);
13641
+ const [error, setError] = React30.useState(null);
13642
+ const [isDisconnectingWallet, setIsDisconnectingWallet] = React30.useState(false);
13643
+ const [amountUsd, setAmountUsd] = React30.useState(prefillAmountUsd ?? "");
13644
+ const [isConfirming, setIsConfirming] = React30.useState(false);
13645
+ const [hasSignedTransaction, setHasSignedTransaction] = React30.useState(false);
13646
+ const [tokenChainDetails, setTokenChainDetails] = React30.useState(null);
13647
+ const [loadingTokenDetails, setLoadingTokenDetails] = React30.useState(false);
13648
+ const [showTransactionDetails, setShowTransactionDetails] = React30.useState(false);
13649
+ const [receivedUsdAtSubmission, setReceivedUsdAtSubmission] = React30.useState(null);
13665
13650
  const walletInfo = activeWalletInfo;
13666
13651
  const depositWallet = activeDepositWallet;
13667
13652
  const hasWallet = !!activeWalletInfo && !!activeDepositWallet;
@@ -13669,7 +13654,7 @@ function WalletConnect({
13669
13654
  const recipientAddress = activeDepositWallet?.address ?? "";
13670
13655
  const isCheckoutMode = !!checkoutAmountUsd;
13671
13656
  const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
13672
- const transitionTo = React29.useCallback((nextView) => {
13657
+ const transitionTo = React30.useCallback((nextView) => {
13673
13658
  if (nextView === viewRef.current) return;
13674
13659
  setIsTransitioning(true);
13675
13660
  setTimeout(() => {
@@ -13806,7 +13791,7 @@ function WalletConnect({
13806
13791
  }
13807
13792
  };
13808
13793
  const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
13809
- const effectiveDestinationAmount = React29.useMemo(() => {
13794
+ const effectiveDestinationAmount = React30.useMemo(() => {
13810
13795
  if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
13811
13796
  if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
13812
13797
  const remaining = BigInt(checkoutRemainingBaseUnits);
@@ -13834,7 +13819,7 @@ function WalletConnect({
13834
13819
  stablecoinParity,
13835
13820
  enabled: isCheckoutMode && !!selectedToken && !!checkoutDestination && effectiveDestinationAmount !== "0"
13836
13821
  });
13837
- const activeCheckoutQuote = React29.useMemo(() => {
13822
+ const activeCheckoutQuote = React30.useMemo(() => {
13838
13823
  if (!isCheckoutMode) return null;
13839
13824
  if (walletCheckoutQuote) return { sourceAmount: walletCheckoutQuote.source_amount, sourceTokenDecimals: walletCheckoutQuote.source_token_decimals, sourceTokenSymbol: walletCheckoutQuote.source_token_symbol, sourceAmountUsd: walletCheckoutQuote.source_amount_usd, slippageBufferPercent: walletCheckoutQuote.slippage_buffer_percent ?? null };
13840
13825
  return checkoutQuote ?? null;
@@ -13848,19 +13833,19 @@ function WalletConnect({
13848
13833
  onDepositSuccess,
13849
13834
  onDepositError
13850
13835
  });
13851
- React29.useEffect(() => {
13836
+ React30.useEffect(() => {
13852
13837
  onExecutionsChange?.(depositExecutions);
13853
13838
  }, [depositExecutions, onExecutionsChange]);
13854
- React29.useEffect(() => {
13839
+ React30.useEffect(() => {
13855
13840
  if (!prefillAmountUsd || !tokenChainDetails || view !== "enter_amount") return;
13856
13841
  const minDeposit = tokenChainDetails.minimum_deposit_amount_usd || 0;
13857
13842
  const currentAmount = parseFloat(amountUsd) || 0;
13858
13843
  if (currentAmount > 0 && currentAmount < minDeposit) setAmountUsd(minDeposit.toFixed(2));
13859
13844
  }, [tokenChainDetails, view, prefillAmountUsd]);
13860
- React29.useEffect(() => {
13845
+ React30.useEffect(() => {
13861
13846
  if (view === "review") setShowTransactionDetails(false);
13862
13847
  }, [view]);
13863
- React29.useEffect(() => {
13848
+ React30.useEffect(() => {
13864
13849
  if (view !== "enter_amount" && view !== "review" || !selectedBalance || !activeDepositWallet) return;
13865
13850
  let cancelled = false;
13866
13851
  const fetchTokenDetails = async () => {
@@ -13887,7 +13872,7 @@ function WalletConnect({
13887
13872
  cancelled = true;
13888
13873
  };
13889
13874
  }, [view, selectedBalance, publishableKey, activeDepositWallet]);
13890
- React29.useEffect(() => {
13875
+ React30.useEffect(() => {
13891
13876
  if (!activeWalletInfo || !activeDepositWallet) return;
13892
13877
  let cancelled = false;
13893
13878
  setIsLoading(true);
@@ -13920,20 +13905,20 @@ function WalletConnect({
13920
13905
  cancelled = true;
13921
13906
  };
13922
13907
  }, [activeWalletInfo?.address, activeDepositWallet?.chain_type, publishableKey]);
13923
- const usdToTokenRate = React29.useMemo(() => {
13908
+ const usdToTokenRate = React30.useMemo(() => {
13924
13909
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken) return 0;
13925
13910
  const balanceAmount = Number(selectedBalance.amount) / 10 ** selectedToken.decimals;
13926
13911
  const balanceUsd = parseFloat(selectedBalance.amount_usd);
13927
13912
  if (balanceAmount === 0 || balanceUsd === 0) return 0;
13928
13913
  return balanceAmount / balanceUsd;
13929
13914
  }, [selectedBalance, selectedToken]);
13930
- const tokenAmount = React29.useMemo(() => {
13915
+ const tokenAmount = React30.useMemo(() => {
13931
13916
  if (isCheckoutMode && activeCheckoutQuote && selectedToken) return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
13932
13917
  const usdNum = parseFloat(amountUsd) || 0;
13933
13918
  if (usdNum === 0 || usdToTokenRate === 0) return 0;
13934
13919
  return usdNum * usdToTokenRate;
13935
13920
  }, [amountUsd, usdToTokenRate, isCheckoutMode, activeCheckoutQuote, selectedToken]);
13936
- React29.useEffect(() => {
13921
+ React30.useEffect(() => {
13937
13922
  if (isCheckoutMode && activeCheckoutQuote?.sourceAmountUsd && view === "enter_amount") setAmountUsd(activeCheckoutQuote.sourceAmountUsd);
13938
13923
  }, [isCheckoutMode, activeCheckoutQuote, view]);
13939
13924
  const maxTokenAmount = selectedBalance && selectedToken ? Number(selectedBalance.amount) / 10 ** selectedToken.decimals : 0;
@@ -13941,7 +13926,7 @@ function WalletConnect({
13941
13926
  const inputUsdNum = parseFloat(amountUsd) || 0;
13942
13927
  const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
13943
13928
  const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
13944
- const formattedTokenAmount = React29.useMemo(() => {
13929
+ const formattedTokenAmount = React30.useMemo(() => {
13945
13930
  if (tokenAmount === 0 || !selectedToken) return null;
13946
13931
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(/\.?0+$/, "");
13947
13932
  }, [tokenAmount, selectedToken]);
@@ -13989,16 +13974,25 @@ function WalletConnect({
13989
13974
  } catch (err) {
13990
13975
  console.warn("[WalletConnect] disconnect error:", err);
13991
13976
  } finally {
13992
- setActiveWalletInfo(null);
13993
- setActiveDepositWallet(null);
13994
- setSelectedBalance(null);
13995
- setBalances([]);
13996
- setTotalBalanceUsd(null);
13997
- setAmountUsd(prefillAmountUsd ?? "");
13998
- setError(null);
13999
13977
  setIsDisconnectingWallet(false);
14000
- if (onWalletDisconnect) onWalletDisconnect();
14001
- else parentOnBack?.();
13978
+ const clearWalletState = () => {
13979
+ setActiveWalletInfo(null);
13980
+ setActiveDepositWallet(null);
13981
+ setSelectedBalance(null);
13982
+ setBalances([]);
13983
+ setTotalBalanceUsd(null);
13984
+ setAmountUsd(prefillAmountUsd ?? "");
13985
+ setError(null);
13986
+ };
13987
+ if (standalone) {
13988
+ onWalletDisconnect?.();
13989
+ transitionTo("select_wallet");
13990
+ setTimeout(clearWalletState, 160);
13991
+ } else {
13992
+ clearWalletState();
13993
+ if (onWalletDisconnect) onWalletDisconnect();
13994
+ else parentOnBack?.();
13995
+ }
14002
13996
  }
14003
13997
  };
14004
13998
  const handleReview = () => {
@@ -14124,9 +14118,15 @@ function WalletConnect({
14124
14118
  setIsConfirming(false);
14125
14119
  }
14126
14120
  };
14121
+ if (standalone && !autoResolved) {
14122
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { style: viewTransitionStyle, children: [
14123
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DepositHeader, { title: "Connect Wallet", showBack: canGoBack, onBack: handleBack, onClose }),
14124
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react28.Loader2, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }) })
14125
+ ] });
14126
+ }
14127
14127
  if (view === "select_wallet") {
14128
14128
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { style: viewTransitionStyle, children: [
14129
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DepositHeader, { title: "Connect Wallet", showBack: true, onBack: handleBack, onClose }),
14129
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DepositHeader, { title: "Connect Wallet", showBack: canGoBack, onBack: handleBack, onClose }),
14130
14130
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "uf-pb-4", children: [
14131
14131
  /* @__PURE__ */ (0, import_jsx_runtime54.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" }),
14132
14132
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uf-space-y-2", style: { maxHeight: 330, overflowY: "auto" }, children: availableWallets.map((wallet) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
@@ -14257,6 +14257,7 @@ function DepositModal({
14257
14257
  destinationChainType,
14258
14258
  destinationChainId,
14259
14259
  destinationTokenAddress,
14260
+ contractCalls,
14260
14261
  defaultSourceChainType,
14261
14262
  defaultSourceChainId,
14262
14263
  defaultSourceTokenAddress,
@@ -14291,8 +14292,19 @@ function DepositModal({
14291
14292
  if (s === "tracker" && hideDepositTracker) return "main";
14292
14293
  if (s === "cashapp" && !enableCashApp) return "main";
14293
14294
  if (s === "card" && enableFiatOnramp === false) return "main";
14295
+ 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";
14294
14298
  return s;
14295
- }, [initialScreen, hideDepositTracker, enableCashApp, enableFiatOnramp]);
14299
+ }, [
14300
+ initialScreen,
14301
+ hideDepositTracker,
14302
+ enableCashApp,
14303
+ enableFiatOnramp,
14304
+ enablePayWithExchange,
14305
+ enableConnectExchange,
14306
+ enableConnectWallet
14307
+ ]);
14296
14308
  const [containerEl, setContainerEl] = (0, import_react20.useState)(null);
14297
14309
  const containerCallbackRef = (0, import_react20.useCallback)((el) => {
14298
14310
  setContainerEl(el);
@@ -14383,6 +14395,7 @@ function DepositModal({
14383
14395
  destinationChainType,
14384
14396
  destinationChainId,
14385
14397
  destinationTokenAddress,
14398
+ contractCalls,
14386
14399
  enabled: open
14387
14400
  // Only fetch when modal is open
14388
14401
  });
@@ -14415,6 +14428,12 @@ function DepositModal({
14415
14428
  setCardView("amount");
14416
14429
  }
14417
14430
  }, [view, showFiatOnramp]);
14431
+ (0, import_react20.useEffect)(() => {
14432
+ if (view === "exchange" && !showPayWithExchange) {
14433
+ setView("main");
14434
+ setExchangeView("providers");
14435
+ }
14436
+ }, [view, showPayWithExchange]);
14418
14437
  const { exchanges, isLoading: exchangesLoading } = useExchanges({
14419
14438
  publishableKey,
14420
14439
  enabled: open && showPayWithExchange
@@ -14534,7 +14553,7 @@ function DepositModal({
14534
14553
  setBrowserWalletChainType(void 0);
14535
14554
  setBrowserWalletInfo(null);
14536
14555
  setBrowserWalletModalOpen(false);
14537
- if (view === "wallet_connect") setView("main");
14556
+ if (view === "wallet_connect" && sessionOpenedFromMenu) setView("main");
14538
14557
  };
14539
14558
  const handleExchangeDisconnect = () => {
14540
14559
  const stored = getStoredIntegrationToken(import_core29.IntegrationProvider.COINBASE);
@@ -14543,7 +14562,7 @@ function DepositModal({
14543
14562
  }
14544
14563
  clearStoredIntegrationToken(import_core29.IntegrationProvider.COINBASE);
14545
14564
  setConnectedExchange(null);
14546
- if (view === "coinbase_connect") setView("main");
14565
+ if (view === "coinbase_connect" && sessionOpenedFromMenu) setView("main");
14547
14566
  };
14548
14567
  const handleClose = () => {
14549
14568
  onOpenChange(false);
@@ -14555,6 +14574,7 @@ function DepositModal({
14555
14574
  setCardView("amount");
14556
14575
  setExchangeView("providers");
14557
14576
  setBrowserWalletInfo(null);
14577
+ setCoinbaseSkipToHoldings(false);
14558
14578
  resetViewTimeoutRef.current = null;
14559
14579
  }, 200);
14560
14580
  };
@@ -14569,6 +14589,7 @@ function DepositModal({
14569
14589
  setExchangeView("providers");
14570
14590
  setBrowserWalletInfo(null);
14571
14591
  setSelectedExecution(null);
14592
+ setCoinbaseSkipToHoldings(false);
14572
14593
  }, [open, effectiveInitialScreen]);
14573
14594
  (0, import_react20.useEffect)(
14574
14595
  () => () => {
@@ -14928,7 +14949,7 @@ function DepositModal({
14928
14949
  DepositHeader,
14929
14950
  {
14930
14951
  title: payWithExchangeTitle,
14931
- showBack: true,
14952
+ showBack: exchangeView === "pending" || sessionOpenedFromMenu,
14932
14953
  onBack: handleBack,
14933
14954
  onClose: handleClose
14934
14955
  }
@@ -14982,6 +15003,7 @@ function DepositModal({
14982
15003
  onClose: handleClose,
14983
15004
  onDisconnect: handleExchangeDisconnect,
14984
15005
  skipToHoldings: coinbaseSkipToHoldings,
15006
+ canGoBack: sessionOpenedFromMenu,
14985
15007
  onExecutionsChange: setDepositExecutions
14986
15008
  }
14987
15009
  ),
@@ -15019,7 +15041,9 @@ function DepositModal({
15019
15041
  setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
15020
15042
  },
15021
15043
  onBack: handleBack,
15022
- onClose: handleClose
15044
+ onClose: handleClose,
15045
+ canGoBack: sessionOpenedFromMenu,
15046
+ depositWalletsLoading: walletsLoading
15023
15047
  }
15024
15048
  ),
15025
15049
  depositPoweredByFooter
@@ -15028,7 +15052,7 @@ function DepositModal({
15028
15052
  DepositHeader,
15029
15053
  {
15030
15054
  title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
15031
- showBack: true,
15055
+ showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
15032
15056
  onBack: handleBack,
15033
15057
  onClose: handleClose
15034
15058
  }