@unifold/ui-react 0.1.59 → 0.1.61

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.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AutoSwapResponse, ChainType, DepositEvent, Wallet, ProductType, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, ConfirmIntegrationTransferResult, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
2
+ import { AutoSwapResponse, ChainType, EvmContractCall, DepositEvent, Wallet, ProductType, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, ConfirmIntegrationTransferResult, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
3
3
  export { ChainType } from '@unifold/core';
4
4
  import * as _tanstack_react_query from '@tanstack/react-query';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -153,6 +153,12 @@ interface DepositModalProps {
153
153
  destinationChainType?: ChainType;
154
154
  destinationChainId?: string;
155
155
  destinationTokenAddress?: string;
156
+ /**
157
+ * Array of contract calls to execute on the destination chain when delivering funds.
158
+ * Only supported when destinationChainType is "ethereum" and
159
+ * destinationChainId is one of: "1", "8453", "42161", "4326".
160
+ */
161
+ contractCalls?: EvmContractCall[];
156
162
  /**
157
163
  * Pre-select source token/chain in the Transfer Crypto view.
158
164
  * All four props are optional. To match, provide `chainType` + `chainId` + (`symbol` OR `tokenAddress`).
@@ -212,7 +218,7 @@ interface DepositModalProps {
212
218
  /** First screen when the modal opens. Default `main` (deposit menu). */
213
219
  initialScreen?: DepositModalInitialScreen;
214
220
  }
215
- declare function DepositModal({ open, onOpenChange, userId, publishableKey, modalTitle, destinationTokenSymbol, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, hideDepositTracker, showBalanceHeader, transferInputVariant, depositConfirmationMode, enableConnectWallet, browserWalletAmountQuickSelect, enablePayWithExchange, enableFiatOnramp, enableConnectExchange, enableCashApp, hideDepositFlowInfo, hideDisplayDescription, onDepositSuccess, onDepositError, onEvent, theme, hideOverlay, initialScreen, transferCryptoTitle, depositWithCardTitle, payWithExchangeTitle, depositTrackerTitle, depositTrackerSubTitle, }: DepositModalProps): react_jsx_runtime.JSX.Element;
221
+ declare function DepositModal({ open, onOpenChange, userId, publishableKey, modalTitle, destinationTokenSymbol, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, contractCalls, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, hideDepositTracker, showBalanceHeader, transferInputVariant, depositConfirmationMode, enableConnectWallet, browserWalletAmountQuickSelect, enablePayWithExchange, enableFiatOnramp, enableConnectExchange, enableCashApp, hideDepositFlowInfo, hideDisplayDescription, onDepositSuccess, onDepositError, onEvent, theme, hideOverlay, initialScreen, transferCryptoTitle, depositWithCardTitle, payWithExchangeTitle, depositTrackerTitle, depositTrackerSubTitle, }: DepositModalProps): react_jsx_runtime.JSX.Element;
216
222
 
217
223
  interface DepositHeaderProps {
218
224
  title: string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AutoSwapResponse, ChainType, DepositEvent, Wallet, ProductType, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, ConfirmIntegrationTransferResult, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
2
+ import { AutoSwapResponse, ChainType, EvmContractCall, DepositEvent, Wallet, ProductType, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, ConfirmIntegrationTransferResult, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
3
3
  export { ChainType } from '@unifold/core';
4
4
  import * as _tanstack_react_query from '@tanstack/react-query';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -153,6 +153,12 @@ interface DepositModalProps {
153
153
  destinationChainType?: ChainType;
154
154
  destinationChainId?: string;
155
155
  destinationTokenAddress?: string;
156
+ /**
157
+ * Array of contract calls to execute on the destination chain when delivering funds.
158
+ * Only supported when destinationChainType is "ethereum" and
159
+ * destinationChainId is one of: "1", "8453", "42161", "4326".
160
+ */
161
+ contractCalls?: EvmContractCall[];
156
162
  /**
157
163
  * Pre-select source token/chain in the Transfer Crypto view.
158
164
  * All four props are optional. To match, provide `chainType` + `chainId` + (`symbol` OR `tokenAddress`).
@@ -212,7 +218,7 @@ interface DepositModalProps {
212
218
  /** First screen when the modal opens. Default `main` (deposit menu). */
213
219
  initialScreen?: DepositModalInitialScreen;
214
220
  }
215
- declare function DepositModal({ open, onOpenChange, userId, publishableKey, modalTitle, destinationTokenSymbol, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, hideDepositTracker, showBalanceHeader, transferInputVariant, depositConfirmationMode, enableConnectWallet, browserWalletAmountQuickSelect, enablePayWithExchange, enableFiatOnramp, enableConnectExchange, enableCashApp, hideDepositFlowInfo, hideDisplayDescription, onDepositSuccess, onDepositError, onEvent, theme, hideOverlay, initialScreen, transferCryptoTitle, depositWithCardTitle, payWithExchangeTitle, depositTrackerTitle, depositTrackerSubTitle, }: DepositModalProps): react_jsx_runtime.JSX.Element;
221
+ declare function DepositModal({ open, onOpenChange, userId, publishableKey, modalTitle, destinationTokenSymbol, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, contractCalls, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, hideDepositTracker, showBalanceHeader, transferInputVariant, depositConfirmationMode, enableConnectWallet, browserWalletAmountQuickSelect, enablePayWithExchange, enableFiatOnramp, enableConnectExchange, enableCashApp, hideDepositFlowInfo, hideDisplayDescription, onDepositSuccess, onDepositError, onEvent, theme, hideOverlay, initialScreen, transferCryptoTitle, depositWithCardTitle, payWithExchangeTitle, depositTrackerTitle, depositTrackerSubTitle, }: DepositModalProps): react_jsx_runtime.JSX.Element;
216
222
 
217
223
  interface DepositHeaderProps {
218
224
  title: string;
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
  ),
@@ -1580,7 +1583,7 @@ var import_react3 = require("react");
1580
1583
  var import_core6 = require("@unifold/core");
1581
1584
  var DEPOSIT_CONFIRM_DELAY_MS = 5e3;
1582
1585
  var POLL_INTERVAL_MS = 2500;
1583
- var POLL_ENDPOINT_INTERVAL_MS = 3e3;
1586
+ var POLL_ENDPOINT_INTERVAL_MS = 5e3;
1584
1587
  var CUTOFF_BUFFER_MS = 6e4;
1585
1588
  function useDepositPolling({
1586
1589
  userId,
@@ -5324,6 +5327,56 @@ var React24 = __toESM(require("react"));
5324
5327
  var import_lucide_react17 = require("lucide-react");
5325
5328
  var import_core14 = require("@unifold/core");
5326
5329
 
5330
+ // src/lib/eip6963-store.ts
5331
+ var import_mipd = require("mipd");
5332
+ var _store = null;
5333
+ function getEip6963Store() {
5334
+ if (typeof window === "undefined") return null;
5335
+ if (!_store) {
5336
+ _store = (0, import_mipd.createStore)();
5337
+ }
5338
+ return _store;
5339
+ }
5340
+ var RDNS_TO_WALLET_ID = {
5341
+ "io.metamask": "metamask",
5342
+ "io.metamask.flask": "metamask",
5343
+ "io.metamask.mmi": "metamask",
5344
+ "app.phantom": "phantom",
5345
+ "com.coinbase.wallet": "coinbase",
5346
+ "com.okex.wallet": "okx",
5347
+ "io.rabby": "rabby",
5348
+ "com.trustwallet.app": "trust",
5349
+ "me.rainbow": "rainbow"
5350
+ };
5351
+ function rdnsToWalletId(rdns) {
5352
+ if (RDNS_TO_WALLET_ID[rdns]) return RDNS_TO_WALLET_ID[rdns];
5353
+ if (rdns.includes("metamask")) return "metamask";
5354
+ if (rdns.includes("phantom")) return "phantom";
5355
+ if (rdns.includes("coinbase")) return "coinbase";
5356
+ if (rdns.includes("okx") || rdns.includes("okex")) return "okx";
5357
+ if (rdns.includes("rabby")) return "rabby";
5358
+ if (rdns.includes("trust")) return "trust";
5359
+ if (rdns.includes("rainbow")) return "rainbow";
5360
+ return "unknown";
5361
+ }
5362
+ function getEip6963Providers() {
5363
+ const store = getEip6963Store();
5364
+ if (!store) return [];
5365
+ return store.getProviders().map((detail) => ({
5366
+ walletId: rdnsToWalletId(detail.info.rdns),
5367
+ provider: detail.provider,
5368
+ info: detail.info
5369
+ }));
5370
+ }
5371
+ function findProviderByWalletId(walletId) {
5372
+ return getEip6963Providers().find((p) => p.walletId === walletId);
5373
+ }
5374
+ function collectAllEip6963EthProviders() {
5375
+ const store = getEip6963Store();
5376
+ if (!store) return [];
5377
+ return store.getProviders().map((d) => d.provider);
5378
+ }
5379
+
5327
5380
  // src/components/deposits/browser-wallets/disconnectInjectedBrowserWallet.ts
5328
5381
  var SOLANA_DISCONNECT_TYPES = [
5329
5382
  "phantom-solana",
@@ -5364,8 +5417,9 @@ function collectEthereumProvidersForDisconnect(win) {
5364
5417
  out.push(p);
5365
5418
  }
5366
5419
  };
5367
- const list = anyWin.__eip6963Providers || [];
5368
- for (const d of list) add(d.provider);
5420
+ for (const p of collectAllEip6963EthProviders()) {
5421
+ add(p);
5422
+ }
5369
5423
  add(win.ethereum);
5370
5424
  add(
5371
5425
  win.phantom?.ethereum
@@ -7425,30 +7479,13 @@ function BrowserWalletButton({
7425
7479
  }, []);
7426
7480
  const [eip6963ProviderCount, setEip6963ProviderCount] = React24.useState(0);
7427
7481
  React24.useEffect(() => {
7428
- if (typeof window === "undefined") return;
7429
- const anyWin = window;
7430
- if (!anyWin.__eip6963Providers) {
7431
- anyWin.__eip6963Providers = [];
7432
- }
7433
- const handleAnnouncement = (event) => {
7434
- const { detail } = event;
7435
- if (!detail?.info || !detail?.provider) return;
7436
- const exists = anyWin.__eip6963Providers.some(
7437
- (p) => p.info.uuid === detail.info.uuid
7438
- );
7439
- if (!exists) {
7440
- anyWin.__eip6963Providers.push(detail);
7441
- setEip6963ProviderCount(anyWin.__eip6963Providers.length);
7442
- }
7443
- };
7444
- window.addEventListener("eip6963:announceProvider", handleAnnouncement);
7445
- window.dispatchEvent(new Event("eip6963:requestProvider"));
7446
- return () => {
7447
- window.removeEventListener(
7448
- "eip6963:announceProvider",
7449
- handleAnnouncement
7450
- );
7451
- };
7482
+ const store = getEip6963Store();
7483
+ if (!store) return;
7484
+ setEip6963ProviderCount(store.getProviders().length);
7485
+ const unsubscribe = store.subscribe((providers) => {
7486
+ setEip6963ProviderCount(providers.length);
7487
+ });
7488
+ return unsubscribe;
7452
7489
  }, []);
7453
7490
  React24.useEffect(() => {
7454
7491
  if (!wallet || !publishableKey) {
@@ -7507,7 +7544,7 @@ function BrowserWalletButton({
7507
7544
  return;
7508
7545
  }
7509
7546
  if (!chainType || chainType === "solana") {
7510
- const anyWin2 = win;
7547
+ const anyWin = win;
7511
7548
  const trySilentSolana = async (provider, type, name, icon) => {
7512
7549
  if (!provider) return false;
7513
7550
  if (provider.isConnected && provider.publicKey) {
@@ -7546,21 +7583,21 @@ function BrowserWalletButton({
7546
7583
  ))
7547
7584
  return;
7548
7585
  if (await trySilentSolana(
7549
- anyWin2.solflare,
7586
+ anyWin.solflare,
7550
7587
  "solflare",
7551
7588
  "Solflare",
7552
7589
  "solflare"
7553
7590
  ))
7554
7591
  return;
7555
7592
  if (await trySilentSolana(
7556
- anyWin2.backpack,
7593
+ anyWin.backpack,
7557
7594
  "backpack",
7558
7595
  "Backpack",
7559
7596
  "backpack"
7560
7597
  ))
7561
7598
  return;
7562
7599
  if (await trySilentSolana(
7563
- anyWin2.glow,
7600
+ anyWin.glow,
7564
7601
  "glow",
7565
7602
  "Glow",
7566
7603
  "glow"
@@ -7568,19 +7605,14 @@ function BrowserWalletButton({
7568
7605
  return;
7569
7606
  }
7570
7607
  if (!chainType || chainType === "ethereum") {
7571
- const anyWin2 = win;
7608
+ const anyWin = win;
7572
7609
  const allProviders = [];
7573
- const eip6963Providers = anyWin2.__eip6963Providers || [];
7574
- for (const { info, provider } of eip6963Providers) {
7575
- let walletId = "default";
7576
- if (info.rdns.includes("metamask")) walletId = "metamask";
7577
- else if (info.rdns.includes("phantom")) walletId = "phantom";
7578
- else if (info.rdns.includes("coinbase")) walletId = "coinbase";
7579
- else if (info.rdns.includes("okx")) walletId = "okx";
7580
- else if (info.rdns.includes("rabby")) walletId = "rabby";
7581
- else if (info.rdns.includes("trust")) walletId = "trust";
7582
- else if (info.rdns.includes("rainbow")) walletId = "rainbow";
7583
- allProviders.push({ provider, walletId });
7610
+ const eip6963 = getEip6963Providers();
7611
+ for (const { provider, walletId } of eip6963) {
7612
+ allProviders.push({
7613
+ provider,
7614
+ walletId: walletId === "unknown" ? "default" : walletId
7615
+ });
7584
7616
  }
7585
7617
  if (allProviders.length === 0) {
7586
7618
  if (win.phantom?.ethereum) {
@@ -7589,15 +7621,15 @@ function BrowserWalletButton({
7589
7621
  walletId: "phantom"
7590
7622
  });
7591
7623
  }
7592
- if (anyWin2.okxwallet) {
7624
+ if (anyWin.okxwallet) {
7593
7625
  allProviders.push({
7594
- provider: anyWin2.okxwallet,
7626
+ provider: anyWin.okxwallet,
7595
7627
  walletId: "okx"
7596
7628
  });
7597
7629
  }
7598
- if (anyWin2.coinbaseWalletExtension) {
7630
+ if (anyWin.coinbaseWalletExtension) {
7599
7631
  allProviders.push({
7600
- provider: anyWin2.coinbaseWalletExtension,
7632
+ provider: anyWin.coinbaseWalletExtension,
7601
7633
  walletId: "coinbase"
7602
7634
  });
7603
7635
  }
@@ -7621,7 +7653,7 @@ function BrowserWalletButton({
7621
7653
  });
7622
7654
  if (!accounts || accounts.length === 0) continue;
7623
7655
  const address = accounts[0];
7624
- const resolved = identifyEthWallet(provider, anyWin2, walletId);
7656
+ const resolved = identifyEthWallet(provider, anyWin, walletId);
7625
7657
  if (mounted) {
7626
7658
  setWallet({ ...resolved, address });
7627
7659
  setIsLoading(false);
@@ -7663,15 +7695,11 @@ function BrowserWalletButton({
7663
7695
  solanaProvider.on("disconnect", handleDisconnect);
7664
7696
  solanaProvider.on("accountChanged", handleAccountsChanged);
7665
7697
  }
7666
- const anyWin = window;
7667
7698
  const ethProviders = [];
7668
- if (anyWin.__eip6963Providers) {
7669
- for (const {
7670
- provider
7671
- } of anyWin.__eip6963Providers) {
7672
- if (provider && !ethProviders.includes(provider)) {
7673
- ethProviders.push(provider);
7674
- }
7699
+ for (const { provider } of getEip6963Providers()) {
7700
+ const p = provider;
7701
+ if (p && !ethProviders.includes(p)) {
7702
+ ethProviders.push(p);
7675
7703
  }
7676
7704
  }
7677
7705
  if (window.ethereum && !ethProviders.includes(window.ethereum)) {
@@ -7773,7 +7801,7 @@ function BrowserWalletButton({
7773
7801
  if (isLoading) {
7774
7802
  return null;
7775
7803
  }
7776
- const hasWalletExtension = (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) ? true : (!chainType || chainType === "ethereum") && (window.phantom?.ethereum || window.ethereum) ? true : false;
7804
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && getEip6963Providers().length > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && (window.phantom?.ethereum || window.ethereum);
7777
7805
  if (!onConnectClick && !wallet && !hasWalletExtension) {
7778
7806
  return null;
7779
7807
  }
@@ -13456,15 +13484,10 @@ var WALLET_DEFINITIONS = [
13456
13484
  { id: "backpack", name: "Backpack", networks: ["solana"], installUrl: "https://backpack.app/" },
13457
13485
  { id: "glow", name: "Glow", networks: ["solana"], installUrl: "https://glow.app/" }
13458
13486
  ];
13459
- function getWalletProviders() {
13487
+ function getSolanaProviders() {
13460
13488
  if (typeof window === "undefined") return {};
13461
13489
  const win = window;
13462
13490
  return {
13463
- ethereum: win.ethereum,
13464
- phantomEthereum: win.phantom?.ethereum,
13465
- coinbaseEthereum: win.coinbaseWalletExtension,
13466
- trustEthereum: win.trustwallet?.ethereum,
13467
- okxEthereum: win.okxwallet,
13468
13491
  phantomSolana: win.phantom?.solana,
13469
13492
  solflare: win.solflare,
13470
13493
  backpack: win.backpack,
@@ -13472,37 +13495,71 @@ function getWalletProviders() {
13472
13495
  coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
13473
13496
  };
13474
13497
  }
13498
+ function getLegacyEvmProviders() {
13499
+ if (typeof window === "undefined") return {};
13500
+ const win = window;
13501
+ return {
13502
+ ethereum: win.ethereum,
13503
+ phantomEthereum: win.phantom?.ethereum,
13504
+ coinbaseEthereum: win.coinbaseWalletExtension,
13505
+ trustEthereum: win.trustwallet?.ethereum,
13506
+ okxEthereum: win.okxwallet
13507
+ };
13508
+ }
13475
13509
  function detectAvailableWallets(filterChainType) {
13476
- const providers = getWalletProviders();
13510
+ const solProviders = getSolanaProviders();
13511
+ const legacyEvm = getLegacyEvmProviders();
13512
+ const eip6963List = getEip6963Providers();
13477
13513
  const win = typeof window !== "undefined" ? window : null;
13514
+ const hasEip6963 = (walletId) => eip6963List.some((d) => {
13515
+ const rdns = d.info?.rdns || "";
13516
+ switch (walletId) {
13517
+ case "metamask":
13518
+ return rdns.includes("metamask");
13519
+ case "phantom":
13520
+ return rdns.includes("phantom");
13521
+ case "coinbase":
13522
+ return rdns.includes("coinbase");
13523
+ case "trust":
13524
+ return rdns.includes("trust");
13525
+ case "rainbow":
13526
+ return rdns.includes("rainbow");
13527
+ case "rabby":
13528
+ return rdns.includes("rabby");
13529
+ case "okx":
13530
+ return rdns.includes("okx") || rdns.includes("okex");
13531
+ default:
13532
+ return false;
13533
+ }
13534
+ });
13478
13535
  return WALLET_DEFINITIONS.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
13479
13536
  let isInstalled = false;
13480
13537
  const detectedNetworks = [];
13481
13538
  switch (wallet.id) {
13482
13539
  case "metamask":
13483
- isInstalled = !!(providers.ethereum?.isMetaMask && !providers.ethereum?.isPhantom && !providers.ethereum?.isRabby && !providers.ethereum?.isOkxWallet);
13540
+ isInstalled = hasEip6963("metamask") || !!(legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom && !legacyEvm.ethereum?.isRabby && !legacyEvm.ethereum?.isOkxWallet);
13484
13541
  if (isInstalled) detectedNetworks.push("ethereum");
13485
13542
  break;
13486
13543
  case "phantom":
13487
- if (providers.phantomSolana?.isPhantom) {
13544
+ if (solProviders.phantomSolana?.isPhantom) {
13488
13545
  isInstalled = true;
13489
13546
  detectedNetworks.push("solana");
13490
13547
  }
13491
- if (providers.phantomEthereum?.isPhantom) {
13548
+ if (hasEip6963("phantom") || legacyEvm.phantomEthereum?.isPhantom) {
13492
13549
  isInstalled = true;
13493
13550
  detectedNetworks.push("ethereum");
13494
13551
  }
13495
13552
  break;
13496
13553
  case "coinbase":
13497
- if (providers.coinbaseEthereum || providers.ethereum?.isCoinbaseWallet) {
13554
+ if (hasEip6963("coinbase") || legacyEvm.coinbaseEthereum || legacyEvm.ethereum?.isCoinbaseWallet) {
13498
13555
  isInstalled = true;
13499
13556
  detectedNetworks.push("ethereum");
13500
13557
  }
13501
- if (providers.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
13558
+ if (solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
13502
13559
  if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
13503
13560
  break;
13504
13561
  case "trust":
13505
- if (providers.trustEthereum || providers.ethereum?.isTrust || win?.trustwallet) {
13562
+ if (hasEip6963("trust") || legacyEvm.trustEthereum || legacyEvm.ethereum?.isTrust || win?.trustwallet) {
13506
13563
  isInstalled = true;
13507
13564
  detectedNetworks.push("ethereum");
13508
13565
  }
@@ -13510,27 +13567,27 @@ function detectAvailableWallets(filterChainType) {
13510
13567
  if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
13511
13568
  break;
13512
13569
  case "rainbow":
13513
- isInstalled = !!providers.ethereum?.isRainbow;
13570
+ isInstalled = hasEip6963("rainbow") || !!legacyEvm.ethereum?.isRainbow;
13514
13571
  if (isInstalled) detectedNetworks.push("ethereum");
13515
13572
  break;
13516
13573
  case "rabby":
13517
- isInstalled = !!providers.ethereum?.isRabby;
13574
+ isInstalled = hasEip6963("rabby") || !!legacyEvm.ethereum?.isRabby;
13518
13575
  if (isInstalled) detectedNetworks.push("ethereum");
13519
13576
  break;
13520
13577
  case "okx":
13521
- isInstalled = !!(providers.okxEthereum || providers.ethereum?.isOkxWallet);
13578
+ isInstalled = hasEip6963("okx") || !!(legacyEvm.okxEthereum || legacyEvm.ethereum?.isOkxWallet);
13522
13579
  if (isInstalled) detectedNetworks.push("ethereum");
13523
13580
  break;
13524
13581
  case "solflare":
13525
- isInstalled = !!providers.solflare?.isSolflare;
13582
+ isInstalled = !!solProviders.solflare?.isSolflare;
13526
13583
  if (isInstalled) detectedNetworks.push("solana");
13527
13584
  break;
13528
13585
  case "backpack":
13529
- isInstalled = !!(providers.backpack?.isBackpack || win?.backpack);
13586
+ isInstalled = !!(solProviders.backpack?.isBackpack || win?.backpack);
13530
13587
  if (isInstalled) detectedNetworks.push("solana");
13531
13588
  break;
13532
13589
  case "glow":
13533
- isInstalled = !!(providers.glow?.isGlow || win?.glow);
13590
+ isInstalled = !!(solProviders.glow?.isGlow || win?.glow);
13534
13591
  if (isInstalled) detectedNetworks.push("solana");
13535
13592
  break;
13536
13593
  }
@@ -13585,7 +13642,16 @@ function WalletConnect({
13585
13642
  const [connectingNetwork, setConnectingNetwork] = React29.useState(null);
13586
13643
  const [walletError, setWalletError] = React29.useState(null);
13587
13644
  const [isWalletConnecting, setIsWalletConnecting] = React29.useState(false);
13588
- const availableWallets = React29.useMemo(() => detectAvailableWallets(), []);
13645
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React29.useState(0);
13646
+ React29.useEffect(() => {
13647
+ const store = getEip6963Store();
13648
+ if (!store) return;
13649
+ setEip6963ProviderCount(store.getProviders().length);
13650
+ return store.subscribe((providers) => {
13651
+ setEip6963ProviderCount(providers.length);
13652
+ });
13653
+ }, []);
13654
+ const availableWallets = React29.useMemo(() => detectAvailableWallets(), [eip6963ProviderCount]);
13589
13655
  const [balances, setBalances] = React29.useState([]);
13590
13656
  const [isLoading, setIsLoading] = React29.useState(false);
13591
13657
  const [selectedBalance, setSelectedBalance] = React29.useState(null);
@@ -13644,59 +13710,72 @@ function WalletConnect({
13644
13710
  setWalletError(null);
13645
13711
  setIsWalletConnecting(true);
13646
13712
  try {
13647
- const providers = getWalletProviders();
13648
13713
  const win = typeof window !== "undefined" ? window : null;
13649
13714
  let connectedInfo;
13650
13715
  if (network === "ethereum") {
13651
- let provider;
13652
- switch (wallet.id) {
13653
- case "metamask":
13654
- if (providers.ethereum?.isMetaMask && !providers.ethereum?.isPhantom) provider = providers.ethereum;
13655
- break;
13656
- case "phantom":
13657
- provider = providers.phantomEthereum;
13658
- break;
13659
- case "coinbase":
13660
- provider = providers.coinbaseEthereum || (providers.ethereum?.isCoinbaseWallet ? providers.ethereum : void 0);
13661
- break;
13662
- case "trust":
13663
- provider = providers.trustEthereum || (providers.ethereum?.isTrust ? providers.ethereum : void 0);
13664
- break;
13665
- case "rainbow":
13666
- if (providers.ethereum?.isRainbow) provider = providers.ethereum;
13667
- break;
13668
- case "rabby":
13669
- if (providers.ethereum?.isRabby) provider = providers.ethereum;
13670
- break;
13671
- case "okx":
13672
- provider = providers.okxEthereum || (providers.ethereum?.isOkxWallet ? providers.ethereum : void 0);
13673
- break;
13674
- default:
13675
- provider = providers.ethereum;
13716
+ const eip6963Match = findProviderByWalletId(wallet.id);
13717
+ let provider = eip6963Match?.provider;
13718
+ if (!provider) {
13719
+ const legacyEvm = getLegacyEvmProviders();
13720
+ switch (wallet.id) {
13721
+ case "metamask":
13722
+ if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom) provider = legacyEvm.ethereum;
13723
+ break;
13724
+ case "phantom":
13725
+ provider = legacyEvm.phantomEthereum;
13726
+ break;
13727
+ case "coinbase":
13728
+ provider = legacyEvm.coinbaseEthereum || (legacyEvm.ethereum?.isCoinbaseWallet ? legacyEvm.ethereum : void 0);
13729
+ break;
13730
+ case "trust":
13731
+ provider = legacyEvm.trustEthereum || (legacyEvm.ethereum?.isTrust ? legacyEvm.ethereum : void 0);
13732
+ break;
13733
+ case "rainbow":
13734
+ if (legacyEvm.ethereum?.isRainbow) provider = legacyEvm.ethereum;
13735
+ break;
13736
+ case "rabby":
13737
+ if (legacyEvm.ethereum?.isRabby) provider = legacyEvm.ethereum;
13738
+ break;
13739
+ case "okx":
13740
+ provider = legacyEvm.okxEthereum || (legacyEvm.ethereum?.isOkxWallet ? legacyEvm.ethereum : void 0);
13741
+ break;
13742
+ default:
13743
+ provider = legacyEvm.ethereum;
13744
+ }
13676
13745
  }
13677
13746
  if (!provider) throw new Error(`${wallet.name} wallet not found. Please install it.`);
13678
13747
  const accounts = await provider.request({ method: "eth_requestAccounts" });
13679
13748
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
13680
13749
  setUserDisconnectedWallet(false);
13681
- const walletType = wallet.id === "phantom" ? "phantom-ethereum" : wallet.id === "coinbase" ? "coinbase" : "metamask";
13750
+ const walletIdToType = {
13751
+ phantom: "phantom-ethereum",
13752
+ coinbase: "coinbase",
13753
+ trust: "trust",
13754
+ rainbow: "rainbow",
13755
+ rabby: "rabby",
13756
+ okx: "okx",
13757
+ metamask: "metamask"
13758
+ };
13759
+ const walletType = walletIdToType[wallet.id] || "metamask";
13682
13760
  connectedInfo = { type: walletType, name: wallet.name, address: accounts[0], icon: wallet.id };
13683
13761
  } else {
13762
+ const solProviders = getSolanaProviders();
13684
13763
  let provider;
13685
13764
  switch (wallet.id) {
13686
13765
  case "phantom":
13687
- provider = providers.phantomSolana;
13766
+ provider = solProviders.phantomSolana;
13688
13767
  break;
13689
13768
  case "solflare":
13690
- provider = providers.solflare;
13769
+ provider = solProviders.solflare;
13691
13770
  break;
13692
13771
  case "backpack":
13693
- provider = providers.backpack || win?.backpack;
13772
+ provider = solProviders.backpack || win?.backpack;
13694
13773
  break;
13695
13774
  case "glow":
13696
- provider = providers.glow || win?.glow;
13775
+ provider = solProviders.glow || win?.glow;
13697
13776
  break;
13698
13777
  case "coinbase":
13699
- provider = providers.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
13778
+ provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
13700
13779
  break;
13701
13780
  case "trust":
13702
13781
  provider = win?.trustwallet?.solana;
@@ -13942,10 +14021,15 @@ function WalletConnect({
13942
14021
  };
13943
14022
  const sendEthereumTransaction = async (token, amountStr) => {
13944
14023
  if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
13945
- let provider;
13946
- if (walletInfo.type === "phantom-ethereum") provider = window.phantom?.ethereum;
13947
- else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
13948
- else provider = window.ethereum;
14024
+ const walletIdMap = { "phantom-ethereum": "phantom", coinbase: "coinbase", trust: "trust", okx: "okx", rainbow: "rainbow", rabby: "rabby", metamask: "metamask" };
14025
+ const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
14026
+ const eip6963Match = findProviderByWalletId(lookupId);
14027
+ let provider = eip6963Match?.provider;
14028
+ if (!provider) {
14029
+ if (walletInfo.type === "phantom-ethereum") provider = window.phantom?.ethereum;
14030
+ else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
14031
+ else provider = window.ethereum;
14032
+ }
13949
14033
  if (!provider) throw new Error("Ethereum wallet not found");
13950
14034
  const currentChainIdHex = await provider.request({ method: "eth_chainId", params: [] });
13951
14035
  if (parseInt(currentChainIdHex, 16).toString() !== token.chain_id) {
@@ -14176,6 +14260,7 @@ function DepositModal({
14176
14260
  destinationChainType,
14177
14261
  destinationChainId,
14178
14262
  destinationTokenAddress,
14263
+ contractCalls,
14179
14264
  defaultSourceChainType,
14180
14265
  defaultSourceChainId,
14181
14266
  defaultSourceTokenAddress,
@@ -14302,6 +14387,7 @@ function DepositModal({
14302
14387
  destinationChainType,
14303
14388
  destinationChainId,
14304
14389
  destinationTokenAddress,
14390
+ contractCalls,
14305
14391
  enabled: open
14306
14392
  // Only fetch when modal is open
14307
14393
  });
@@ -15819,7 +15905,7 @@ function useExecutions(userId, publishableKey, options) {
15819
15905
  var import_react22 = require("react");
15820
15906
  var import_core35 = require("@unifold/core");
15821
15907
  var POLL_INTERVAL_MS3 = 2500;
15822
- var POLL_ENDPOINT_INTERVAL_MS2 = 3e3;
15908
+ var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
15823
15909
  var CUTOFF_BUFFER_MS2 = 6e4;
15824
15910
  function useWithdrawPolling({
15825
15911
  userId,
@@ -16324,29 +16410,18 @@ async function detectBrowserWallet(chainType, senderAddress) {
16324
16410
  evmProviders.push({ provider: p, name });
16325
16411
  }
16326
16412
  };
16327
- if (!anyWin.__eip6963Providers) {
16328
- anyWin.__eip6963Providers = [];
16329
- }
16330
- const handleAnnouncement = (event) => {
16331
- const { detail } = event;
16332
- if (!detail?.info || !detail?.provider) return;
16333
- const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
16334
- if (!exists) anyWin.__eip6963Providers.push(detail);
16413
+ const eip6963 = getEip6963Providers();
16414
+ const walletIdToName = {
16415
+ metamask: "MetaMask",
16416
+ phantom: "Phantom",
16417
+ coinbase: "Coinbase",
16418
+ rabby: "Rabby",
16419
+ rainbow: "Rainbow",
16420
+ okx: "OKX Wallet",
16421
+ trust: "Trust Wallet"
16335
16422
  };
16336
- win.addEventListener("eip6963:announceProvider", handleAnnouncement);
16337
- win.dispatchEvent(new Event("eip6963:requestProvider"));
16338
- win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
16339
- for (const detail of anyWin.__eip6963Providers) {
16340
- const rdns = detail.info?.rdns || "";
16341
- let name = detail.info?.name || "Wallet";
16342
- if (rdns.includes("metamask")) name = "MetaMask";
16343
- else if (rdns.includes("phantom")) name = "Phantom";
16344
- else if (rdns.includes("coinbase")) name = "Coinbase";
16345
- else if (rdns.includes("rabby")) name = "Rabby";
16346
- else if (rdns.includes("rainbow")) name = "Rainbow";
16347
- else if (rdns.includes("okx")) name = "OKX Wallet";
16348
- else if (rdns.includes("trust")) name = "Trust Wallet";
16349
- add(detail.provider, name);
16423
+ for (const { provider, walletId, info } of eip6963) {
16424
+ add(provider, walletIdToName[walletId] || info.name || "Wallet");
16350
16425
  }
16351
16426
  if (evmProviders.length === 0) {
16352
16427
  add(anyWin.phantom?.ethereum, "Phantom");
package/dist/index.mjs CHANGED
@@ -624,6 +624,7 @@ function useDepositAddress(params) {
624
624
  destinationChainId,
625
625
  destinationTokenAddress,
626
626
  actionType,
627
+ contractCalls,
627
628
  enabled = true
628
629
  } = params;
629
630
  return useQuery({
@@ -636,6 +637,7 @@ function useDepositAddress(params) {
636
637
  destinationChainId ?? null,
637
638
  destinationTokenAddress ?? null,
638
639
  actionType ?? null,
640
+ contractCalls ?? null,
639
641
  publishableKey
640
642
  ],
641
643
  queryFn: () => createDepositAddress(
@@ -645,7 +647,8 @@ function useDepositAddress(params) {
645
647
  destination_chain_type: destinationChainType,
646
648
  destination_chain_id: destinationChainId,
647
649
  destination_token_address: destinationTokenAddress,
648
- action_type: actionType
650
+ action_type: actionType,
651
+ contract_calls: contractCalls
649
652
  },
650
653
  publishableKey
651
654
  ),
@@ -1491,7 +1494,7 @@ import {
1491
1494
  } from "@unifold/core";
1492
1495
  var DEPOSIT_CONFIRM_DELAY_MS = 5e3;
1493
1496
  var POLL_INTERVAL_MS = 2500;
1494
- var POLL_ENDPOINT_INTERVAL_MS = 3e3;
1497
+ var POLL_ENDPOINT_INTERVAL_MS = 5e3;
1495
1498
  var CUTOFF_BUFFER_MS = 6e4;
1496
1499
  function useDepositPolling({
1497
1500
  userId,
@@ -5253,6 +5256,56 @@ import * as React24 from "react";
5253
5256
  import { Wallet, ChevronRight as ChevronRight10, Loader2 as Loader23 } from "lucide-react";
5254
5257
  import { getAddressBalances } from "@unifold/core";
5255
5258
 
5259
+ // src/lib/eip6963-store.ts
5260
+ import { createStore } from "mipd";
5261
+ var _store = null;
5262
+ function getEip6963Store() {
5263
+ if (typeof window === "undefined") return null;
5264
+ if (!_store) {
5265
+ _store = createStore();
5266
+ }
5267
+ return _store;
5268
+ }
5269
+ var RDNS_TO_WALLET_ID = {
5270
+ "io.metamask": "metamask",
5271
+ "io.metamask.flask": "metamask",
5272
+ "io.metamask.mmi": "metamask",
5273
+ "app.phantom": "phantom",
5274
+ "com.coinbase.wallet": "coinbase",
5275
+ "com.okex.wallet": "okx",
5276
+ "io.rabby": "rabby",
5277
+ "com.trustwallet.app": "trust",
5278
+ "me.rainbow": "rainbow"
5279
+ };
5280
+ function rdnsToWalletId(rdns) {
5281
+ if (RDNS_TO_WALLET_ID[rdns]) return RDNS_TO_WALLET_ID[rdns];
5282
+ if (rdns.includes("metamask")) return "metamask";
5283
+ if (rdns.includes("phantom")) return "phantom";
5284
+ if (rdns.includes("coinbase")) return "coinbase";
5285
+ if (rdns.includes("okx") || rdns.includes("okex")) return "okx";
5286
+ if (rdns.includes("rabby")) return "rabby";
5287
+ if (rdns.includes("trust")) return "trust";
5288
+ if (rdns.includes("rainbow")) return "rainbow";
5289
+ return "unknown";
5290
+ }
5291
+ function getEip6963Providers() {
5292
+ const store = getEip6963Store();
5293
+ if (!store) return [];
5294
+ return store.getProviders().map((detail) => ({
5295
+ walletId: rdnsToWalletId(detail.info.rdns),
5296
+ provider: detail.provider,
5297
+ info: detail.info
5298
+ }));
5299
+ }
5300
+ function findProviderByWalletId(walletId) {
5301
+ return getEip6963Providers().find((p) => p.walletId === walletId);
5302
+ }
5303
+ function collectAllEip6963EthProviders() {
5304
+ const store = getEip6963Store();
5305
+ if (!store) return [];
5306
+ return store.getProviders().map((d) => d.provider);
5307
+ }
5308
+
5256
5309
  // src/components/deposits/browser-wallets/disconnectInjectedBrowserWallet.ts
5257
5310
  var SOLANA_DISCONNECT_TYPES = [
5258
5311
  "phantom-solana",
@@ -5293,8 +5346,9 @@ function collectEthereumProvidersForDisconnect(win) {
5293
5346
  out.push(p);
5294
5347
  }
5295
5348
  };
5296
- const list = anyWin.__eip6963Providers || [];
5297
- for (const d of list) add(d.provider);
5349
+ for (const p of collectAllEip6963EthProviders()) {
5350
+ add(p);
5351
+ }
5298
5352
  add(win.ethereum);
5299
5353
  add(
5300
5354
  win.phantom?.ethereum
@@ -7354,30 +7408,13 @@ function BrowserWalletButton({
7354
7408
  }, []);
7355
7409
  const [eip6963ProviderCount, setEip6963ProviderCount] = React24.useState(0);
7356
7410
  React24.useEffect(() => {
7357
- if (typeof window === "undefined") return;
7358
- const anyWin = window;
7359
- if (!anyWin.__eip6963Providers) {
7360
- anyWin.__eip6963Providers = [];
7361
- }
7362
- const handleAnnouncement = (event) => {
7363
- const { detail } = event;
7364
- if (!detail?.info || !detail?.provider) return;
7365
- const exists = anyWin.__eip6963Providers.some(
7366
- (p) => p.info.uuid === detail.info.uuid
7367
- );
7368
- if (!exists) {
7369
- anyWin.__eip6963Providers.push(detail);
7370
- setEip6963ProviderCount(anyWin.__eip6963Providers.length);
7371
- }
7372
- };
7373
- window.addEventListener("eip6963:announceProvider", handleAnnouncement);
7374
- window.dispatchEvent(new Event("eip6963:requestProvider"));
7375
- return () => {
7376
- window.removeEventListener(
7377
- "eip6963:announceProvider",
7378
- handleAnnouncement
7379
- );
7380
- };
7411
+ const store = getEip6963Store();
7412
+ if (!store) return;
7413
+ setEip6963ProviderCount(store.getProviders().length);
7414
+ const unsubscribe = store.subscribe((providers) => {
7415
+ setEip6963ProviderCount(providers.length);
7416
+ });
7417
+ return unsubscribe;
7381
7418
  }, []);
7382
7419
  React24.useEffect(() => {
7383
7420
  if (!wallet || !publishableKey) {
@@ -7436,7 +7473,7 @@ function BrowserWalletButton({
7436
7473
  return;
7437
7474
  }
7438
7475
  if (!chainType || chainType === "solana") {
7439
- const anyWin2 = win;
7476
+ const anyWin = win;
7440
7477
  const trySilentSolana = async (provider, type, name, icon) => {
7441
7478
  if (!provider) return false;
7442
7479
  if (provider.isConnected && provider.publicKey) {
@@ -7475,21 +7512,21 @@ function BrowserWalletButton({
7475
7512
  ))
7476
7513
  return;
7477
7514
  if (await trySilentSolana(
7478
- anyWin2.solflare,
7515
+ anyWin.solflare,
7479
7516
  "solflare",
7480
7517
  "Solflare",
7481
7518
  "solflare"
7482
7519
  ))
7483
7520
  return;
7484
7521
  if (await trySilentSolana(
7485
- anyWin2.backpack,
7522
+ anyWin.backpack,
7486
7523
  "backpack",
7487
7524
  "Backpack",
7488
7525
  "backpack"
7489
7526
  ))
7490
7527
  return;
7491
7528
  if (await trySilentSolana(
7492
- anyWin2.glow,
7529
+ anyWin.glow,
7493
7530
  "glow",
7494
7531
  "Glow",
7495
7532
  "glow"
@@ -7497,19 +7534,14 @@ function BrowserWalletButton({
7497
7534
  return;
7498
7535
  }
7499
7536
  if (!chainType || chainType === "ethereum") {
7500
- const anyWin2 = win;
7537
+ const anyWin = win;
7501
7538
  const allProviders = [];
7502
- const eip6963Providers = anyWin2.__eip6963Providers || [];
7503
- for (const { info, provider } of eip6963Providers) {
7504
- let walletId = "default";
7505
- if (info.rdns.includes("metamask")) walletId = "metamask";
7506
- else if (info.rdns.includes("phantom")) walletId = "phantom";
7507
- else if (info.rdns.includes("coinbase")) walletId = "coinbase";
7508
- else if (info.rdns.includes("okx")) walletId = "okx";
7509
- else if (info.rdns.includes("rabby")) walletId = "rabby";
7510
- else if (info.rdns.includes("trust")) walletId = "trust";
7511
- else if (info.rdns.includes("rainbow")) walletId = "rainbow";
7512
- allProviders.push({ provider, walletId });
7539
+ const eip6963 = getEip6963Providers();
7540
+ for (const { provider, walletId } of eip6963) {
7541
+ allProviders.push({
7542
+ provider,
7543
+ walletId: walletId === "unknown" ? "default" : walletId
7544
+ });
7513
7545
  }
7514
7546
  if (allProviders.length === 0) {
7515
7547
  if (win.phantom?.ethereum) {
@@ -7518,15 +7550,15 @@ function BrowserWalletButton({
7518
7550
  walletId: "phantom"
7519
7551
  });
7520
7552
  }
7521
- if (anyWin2.okxwallet) {
7553
+ if (anyWin.okxwallet) {
7522
7554
  allProviders.push({
7523
- provider: anyWin2.okxwallet,
7555
+ provider: anyWin.okxwallet,
7524
7556
  walletId: "okx"
7525
7557
  });
7526
7558
  }
7527
- if (anyWin2.coinbaseWalletExtension) {
7559
+ if (anyWin.coinbaseWalletExtension) {
7528
7560
  allProviders.push({
7529
- provider: anyWin2.coinbaseWalletExtension,
7561
+ provider: anyWin.coinbaseWalletExtension,
7530
7562
  walletId: "coinbase"
7531
7563
  });
7532
7564
  }
@@ -7550,7 +7582,7 @@ function BrowserWalletButton({
7550
7582
  });
7551
7583
  if (!accounts || accounts.length === 0) continue;
7552
7584
  const address = accounts[0];
7553
- const resolved = identifyEthWallet(provider, anyWin2, walletId);
7585
+ const resolved = identifyEthWallet(provider, anyWin, walletId);
7554
7586
  if (mounted) {
7555
7587
  setWallet({ ...resolved, address });
7556
7588
  setIsLoading(false);
@@ -7592,15 +7624,11 @@ function BrowserWalletButton({
7592
7624
  solanaProvider.on("disconnect", handleDisconnect);
7593
7625
  solanaProvider.on("accountChanged", handleAccountsChanged);
7594
7626
  }
7595
- const anyWin = window;
7596
7627
  const ethProviders = [];
7597
- if (anyWin.__eip6963Providers) {
7598
- for (const {
7599
- provider
7600
- } of anyWin.__eip6963Providers) {
7601
- if (provider && !ethProviders.includes(provider)) {
7602
- ethProviders.push(provider);
7603
- }
7628
+ for (const { provider } of getEip6963Providers()) {
7629
+ const p = provider;
7630
+ if (p && !ethProviders.includes(p)) {
7631
+ ethProviders.push(p);
7604
7632
  }
7605
7633
  }
7606
7634
  if (window.ethereum && !ethProviders.includes(window.ethereum)) {
@@ -7702,7 +7730,7 @@ function BrowserWalletButton({
7702
7730
  if (isLoading) {
7703
7731
  return null;
7704
7732
  }
7705
- const hasWalletExtension = (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) ? true : (!chainType || chainType === "ethereum") && (window.phantom?.ethereum || window.ethereum) ? true : false;
7733
+ const hasWalletExtension = (!chainType || chainType === "ethereum") && getEip6963Providers().length > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && (window.phantom?.ethereum || window.ethereum);
7706
7734
  if (!onConnectClick && !wallet && !hasWalletExtension) {
7707
7735
  return null;
7708
7736
  }
@@ -13458,15 +13486,10 @@ var WALLET_DEFINITIONS = [
13458
13486
  { id: "backpack", name: "Backpack", networks: ["solana"], installUrl: "https://backpack.app/" },
13459
13487
  { id: "glow", name: "Glow", networks: ["solana"], installUrl: "https://glow.app/" }
13460
13488
  ];
13461
- function getWalletProviders() {
13489
+ function getSolanaProviders() {
13462
13490
  if (typeof window === "undefined") return {};
13463
13491
  const win = window;
13464
13492
  return {
13465
- ethereum: win.ethereum,
13466
- phantomEthereum: win.phantom?.ethereum,
13467
- coinbaseEthereum: win.coinbaseWalletExtension,
13468
- trustEthereum: win.trustwallet?.ethereum,
13469
- okxEthereum: win.okxwallet,
13470
13493
  phantomSolana: win.phantom?.solana,
13471
13494
  solflare: win.solflare,
13472
13495
  backpack: win.backpack,
@@ -13474,37 +13497,71 @@ function getWalletProviders() {
13474
13497
  coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
13475
13498
  };
13476
13499
  }
13500
+ function getLegacyEvmProviders() {
13501
+ if (typeof window === "undefined") return {};
13502
+ const win = window;
13503
+ return {
13504
+ ethereum: win.ethereum,
13505
+ phantomEthereum: win.phantom?.ethereum,
13506
+ coinbaseEthereum: win.coinbaseWalletExtension,
13507
+ trustEthereum: win.trustwallet?.ethereum,
13508
+ okxEthereum: win.okxwallet
13509
+ };
13510
+ }
13477
13511
  function detectAvailableWallets(filterChainType) {
13478
- const providers = getWalletProviders();
13512
+ const solProviders = getSolanaProviders();
13513
+ const legacyEvm = getLegacyEvmProviders();
13514
+ const eip6963List = getEip6963Providers();
13479
13515
  const win = typeof window !== "undefined" ? window : null;
13516
+ const hasEip6963 = (walletId) => eip6963List.some((d) => {
13517
+ const rdns = d.info?.rdns || "";
13518
+ switch (walletId) {
13519
+ case "metamask":
13520
+ return rdns.includes("metamask");
13521
+ case "phantom":
13522
+ return rdns.includes("phantom");
13523
+ case "coinbase":
13524
+ return rdns.includes("coinbase");
13525
+ case "trust":
13526
+ return rdns.includes("trust");
13527
+ case "rainbow":
13528
+ return rdns.includes("rainbow");
13529
+ case "rabby":
13530
+ return rdns.includes("rabby");
13531
+ case "okx":
13532
+ return rdns.includes("okx") || rdns.includes("okex");
13533
+ default:
13534
+ return false;
13535
+ }
13536
+ });
13480
13537
  return WALLET_DEFINITIONS.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
13481
13538
  let isInstalled = false;
13482
13539
  const detectedNetworks = [];
13483
13540
  switch (wallet.id) {
13484
13541
  case "metamask":
13485
- isInstalled = !!(providers.ethereum?.isMetaMask && !providers.ethereum?.isPhantom && !providers.ethereum?.isRabby && !providers.ethereum?.isOkxWallet);
13542
+ isInstalled = hasEip6963("metamask") || !!(legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom && !legacyEvm.ethereum?.isRabby && !legacyEvm.ethereum?.isOkxWallet);
13486
13543
  if (isInstalled) detectedNetworks.push("ethereum");
13487
13544
  break;
13488
13545
  case "phantom":
13489
- if (providers.phantomSolana?.isPhantom) {
13546
+ if (solProviders.phantomSolana?.isPhantom) {
13490
13547
  isInstalled = true;
13491
13548
  detectedNetworks.push("solana");
13492
13549
  }
13493
- if (providers.phantomEthereum?.isPhantom) {
13550
+ if (hasEip6963("phantom") || legacyEvm.phantomEthereum?.isPhantom) {
13494
13551
  isInstalled = true;
13495
13552
  detectedNetworks.push("ethereum");
13496
13553
  }
13497
13554
  break;
13498
13555
  case "coinbase":
13499
- if (providers.coinbaseEthereum || providers.ethereum?.isCoinbaseWallet) {
13556
+ if (hasEip6963("coinbase") || legacyEvm.coinbaseEthereum || legacyEvm.ethereum?.isCoinbaseWallet) {
13500
13557
  isInstalled = true;
13501
13558
  detectedNetworks.push("ethereum");
13502
13559
  }
13503
- if (providers.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
13560
+ if (solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
13504
13561
  if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
13505
13562
  break;
13506
13563
  case "trust":
13507
- if (providers.trustEthereum || providers.ethereum?.isTrust || win?.trustwallet) {
13564
+ if (hasEip6963("trust") || legacyEvm.trustEthereum || legacyEvm.ethereum?.isTrust || win?.trustwallet) {
13508
13565
  isInstalled = true;
13509
13566
  detectedNetworks.push("ethereum");
13510
13567
  }
@@ -13512,27 +13569,27 @@ function detectAvailableWallets(filterChainType) {
13512
13569
  if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
13513
13570
  break;
13514
13571
  case "rainbow":
13515
- isInstalled = !!providers.ethereum?.isRainbow;
13572
+ isInstalled = hasEip6963("rainbow") || !!legacyEvm.ethereum?.isRainbow;
13516
13573
  if (isInstalled) detectedNetworks.push("ethereum");
13517
13574
  break;
13518
13575
  case "rabby":
13519
- isInstalled = !!providers.ethereum?.isRabby;
13576
+ isInstalled = hasEip6963("rabby") || !!legacyEvm.ethereum?.isRabby;
13520
13577
  if (isInstalled) detectedNetworks.push("ethereum");
13521
13578
  break;
13522
13579
  case "okx":
13523
- isInstalled = !!(providers.okxEthereum || providers.ethereum?.isOkxWallet);
13580
+ isInstalled = hasEip6963("okx") || !!(legacyEvm.okxEthereum || legacyEvm.ethereum?.isOkxWallet);
13524
13581
  if (isInstalled) detectedNetworks.push("ethereum");
13525
13582
  break;
13526
13583
  case "solflare":
13527
- isInstalled = !!providers.solflare?.isSolflare;
13584
+ isInstalled = !!solProviders.solflare?.isSolflare;
13528
13585
  if (isInstalled) detectedNetworks.push("solana");
13529
13586
  break;
13530
13587
  case "backpack":
13531
- isInstalled = !!(providers.backpack?.isBackpack || win?.backpack);
13588
+ isInstalled = !!(solProviders.backpack?.isBackpack || win?.backpack);
13532
13589
  if (isInstalled) detectedNetworks.push("solana");
13533
13590
  break;
13534
13591
  case "glow":
13535
- isInstalled = !!(providers.glow?.isGlow || win?.glow);
13592
+ isInstalled = !!(solProviders.glow?.isGlow || win?.glow);
13536
13593
  if (isInstalled) detectedNetworks.push("solana");
13537
13594
  break;
13538
13595
  }
@@ -13587,7 +13644,16 @@ function WalletConnect({
13587
13644
  const [connectingNetwork, setConnectingNetwork] = React29.useState(null);
13588
13645
  const [walletError, setWalletError] = React29.useState(null);
13589
13646
  const [isWalletConnecting, setIsWalletConnecting] = React29.useState(false);
13590
- const availableWallets = React29.useMemo(() => detectAvailableWallets(), []);
13647
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React29.useState(0);
13648
+ React29.useEffect(() => {
13649
+ const store = getEip6963Store();
13650
+ if (!store) return;
13651
+ setEip6963ProviderCount(store.getProviders().length);
13652
+ return store.subscribe((providers) => {
13653
+ setEip6963ProviderCount(providers.length);
13654
+ });
13655
+ }, []);
13656
+ const availableWallets = React29.useMemo(() => detectAvailableWallets(), [eip6963ProviderCount]);
13591
13657
  const [balances, setBalances] = React29.useState([]);
13592
13658
  const [isLoading, setIsLoading] = React29.useState(false);
13593
13659
  const [selectedBalance, setSelectedBalance] = React29.useState(null);
@@ -13646,59 +13712,72 @@ function WalletConnect({
13646
13712
  setWalletError(null);
13647
13713
  setIsWalletConnecting(true);
13648
13714
  try {
13649
- const providers = getWalletProviders();
13650
13715
  const win = typeof window !== "undefined" ? window : null;
13651
13716
  let connectedInfo;
13652
13717
  if (network === "ethereum") {
13653
- let provider;
13654
- switch (wallet.id) {
13655
- case "metamask":
13656
- if (providers.ethereum?.isMetaMask && !providers.ethereum?.isPhantom) provider = providers.ethereum;
13657
- break;
13658
- case "phantom":
13659
- provider = providers.phantomEthereum;
13660
- break;
13661
- case "coinbase":
13662
- provider = providers.coinbaseEthereum || (providers.ethereum?.isCoinbaseWallet ? providers.ethereum : void 0);
13663
- break;
13664
- case "trust":
13665
- provider = providers.trustEthereum || (providers.ethereum?.isTrust ? providers.ethereum : void 0);
13666
- break;
13667
- case "rainbow":
13668
- if (providers.ethereum?.isRainbow) provider = providers.ethereum;
13669
- break;
13670
- case "rabby":
13671
- if (providers.ethereum?.isRabby) provider = providers.ethereum;
13672
- break;
13673
- case "okx":
13674
- provider = providers.okxEthereum || (providers.ethereum?.isOkxWallet ? providers.ethereum : void 0);
13675
- break;
13676
- default:
13677
- provider = providers.ethereum;
13718
+ const eip6963Match = findProviderByWalletId(wallet.id);
13719
+ let provider = eip6963Match?.provider;
13720
+ if (!provider) {
13721
+ const legacyEvm = getLegacyEvmProviders();
13722
+ switch (wallet.id) {
13723
+ case "metamask":
13724
+ if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom) provider = legacyEvm.ethereum;
13725
+ break;
13726
+ case "phantom":
13727
+ provider = legacyEvm.phantomEthereum;
13728
+ break;
13729
+ case "coinbase":
13730
+ provider = legacyEvm.coinbaseEthereum || (legacyEvm.ethereum?.isCoinbaseWallet ? legacyEvm.ethereum : void 0);
13731
+ break;
13732
+ case "trust":
13733
+ provider = legacyEvm.trustEthereum || (legacyEvm.ethereum?.isTrust ? legacyEvm.ethereum : void 0);
13734
+ break;
13735
+ case "rainbow":
13736
+ if (legacyEvm.ethereum?.isRainbow) provider = legacyEvm.ethereum;
13737
+ break;
13738
+ case "rabby":
13739
+ if (legacyEvm.ethereum?.isRabby) provider = legacyEvm.ethereum;
13740
+ break;
13741
+ case "okx":
13742
+ provider = legacyEvm.okxEthereum || (legacyEvm.ethereum?.isOkxWallet ? legacyEvm.ethereum : void 0);
13743
+ break;
13744
+ default:
13745
+ provider = legacyEvm.ethereum;
13746
+ }
13678
13747
  }
13679
13748
  if (!provider) throw new Error(`${wallet.name} wallet not found. Please install it.`);
13680
13749
  const accounts = await provider.request({ method: "eth_requestAccounts" });
13681
13750
  if (!accounts?.length) throw new Error("No accounts returned from wallet");
13682
13751
  setUserDisconnectedWallet(false);
13683
- const walletType = wallet.id === "phantom" ? "phantom-ethereum" : wallet.id === "coinbase" ? "coinbase" : "metamask";
13752
+ const walletIdToType = {
13753
+ phantom: "phantom-ethereum",
13754
+ coinbase: "coinbase",
13755
+ trust: "trust",
13756
+ rainbow: "rainbow",
13757
+ rabby: "rabby",
13758
+ okx: "okx",
13759
+ metamask: "metamask"
13760
+ };
13761
+ const walletType = walletIdToType[wallet.id] || "metamask";
13684
13762
  connectedInfo = { type: walletType, name: wallet.name, address: accounts[0], icon: wallet.id };
13685
13763
  } else {
13764
+ const solProviders = getSolanaProviders();
13686
13765
  let provider;
13687
13766
  switch (wallet.id) {
13688
13767
  case "phantom":
13689
- provider = providers.phantomSolana;
13768
+ provider = solProviders.phantomSolana;
13690
13769
  break;
13691
13770
  case "solflare":
13692
- provider = providers.solflare;
13771
+ provider = solProviders.solflare;
13693
13772
  break;
13694
13773
  case "backpack":
13695
- provider = providers.backpack || win?.backpack;
13774
+ provider = solProviders.backpack || win?.backpack;
13696
13775
  break;
13697
13776
  case "glow":
13698
- provider = providers.glow || win?.glow;
13777
+ provider = solProviders.glow || win?.glow;
13699
13778
  break;
13700
13779
  case "coinbase":
13701
- provider = providers.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
13780
+ provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
13702
13781
  break;
13703
13782
  case "trust":
13704
13783
  provider = win?.trustwallet?.solana;
@@ -13944,10 +14023,15 @@ function WalletConnect({
13944
14023
  };
13945
14024
  const sendEthereumTransaction = async (token, amountStr) => {
13946
14025
  if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
13947
- let provider;
13948
- if (walletInfo.type === "phantom-ethereum") provider = window.phantom?.ethereum;
13949
- else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
13950
- else provider = window.ethereum;
14026
+ const walletIdMap = { "phantom-ethereum": "phantom", coinbase: "coinbase", trust: "trust", okx: "okx", rainbow: "rainbow", rabby: "rabby", metamask: "metamask" };
14027
+ const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
14028
+ const eip6963Match = findProviderByWalletId(lookupId);
14029
+ let provider = eip6963Match?.provider;
14030
+ if (!provider) {
14031
+ if (walletInfo.type === "phantom-ethereum") provider = window.phantom?.ethereum;
14032
+ else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
14033
+ else provider = window.ethereum;
14034
+ }
13951
14035
  if (!provider) throw new Error("Ethereum wallet not found");
13952
14036
  const currentChainIdHex = await provider.request({ method: "eth_chainId", params: [] });
13953
14037
  if (parseInt(currentChainIdHex, 16).toString() !== token.chain_id) {
@@ -14178,6 +14262,7 @@ function DepositModal({
14178
14262
  destinationChainType,
14179
14263
  destinationChainId,
14180
14264
  destinationTokenAddress,
14265
+ contractCalls,
14181
14266
  defaultSourceChainType,
14182
14267
  defaultSourceChainId,
14183
14268
  defaultSourceTokenAddress,
@@ -14304,6 +14389,7 @@ function DepositModal({
14304
14389
  destinationChainType,
14305
14390
  destinationChainId,
14306
14391
  destinationTokenAddress,
14392
+ contractCalls,
14307
14393
  enabled: open
14308
14394
  // Only fetch when modal is open
14309
14395
  });
@@ -15841,7 +15927,7 @@ import {
15841
15927
  ActionType as ActionType5
15842
15928
  } from "@unifold/core";
15843
15929
  var POLL_INTERVAL_MS3 = 2500;
15844
- var POLL_ENDPOINT_INTERVAL_MS2 = 3e3;
15930
+ var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
15845
15931
  var CUTOFF_BUFFER_MS2 = 6e4;
15846
15932
  function useWithdrawPolling({
15847
15933
  userId,
@@ -16364,29 +16450,18 @@ async function detectBrowserWallet(chainType, senderAddress) {
16364
16450
  evmProviders.push({ provider: p, name });
16365
16451
  }
16366
16452
  };
16367
- if (!anyWin.__eip6963Providers) {
16368
- anyWin.__eip6963Providers = [];
16369
- }
16370
- const handleAnnouncement = (event) => {
16371
- const { detail } = event;
16372
- if (!detail?.info || !detail?.provider) return;
16373
- const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
16374
- if (!exists) anyWin.__eip6963Providers.push(detail);
16453
+ const eip6963 = getEip6963Providers();
16454
+ const walletIdToName = {
16455
+ metamask: "MetaMask",
16456
+ phantom: "Phantom",
16457
+ coinbase: "Coinbase",
16458
+ rabby: "Rabby",
16459
+ rainbow: "Rainbow",
16460
+ okx: "OKX Wallet",
16461
+ trust: "Trust Wallet"
16375
16462
  };
16376
- win.addEventListener("eip6963:announceProvider", handleAnnouncement);
16377
- win.dispatchEvent(new Event("eip6963:requestProvider"));
16378
- win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
16379
- for (const detail of anyWin.__eip6963Providers) {
16380
- const rdns = detail.info?.rdns || "";
16381
- let name = detail.info?.name || "Wallet";
16382
- if (rdns.includes("metamask")) name = "MetaMask";
16383
- else if (rdns.includes("phantom")) name = "Phantom";
16384
- else if (rdns.includes("coinbase")) name = "Coinbase";
16385
- else if (rdns.includes("rabby")) name = "Rabby";
16386
- else if (rdns.includes("rainbow")) name = "Rainbow";
16387
- else if (rdns.includes("okx")) name = "OKX Wallet";
16388
- else if (rdns.includes("trust")) name = "Trust Wallet";
16389
- add(detail.provider, name);
16463
+ for (const { provider, walletId, info } of eip6963) {
16464
+ add(provider, walletIdToName[walletId] || info.name || "Wallet");
16390
16465
  }
16391
16466
  if (evmProviders.length === 0) {
16392
16467
  add(anyWin.phantom?.ethereum, "Phantom");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-react",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "Unifold UI React - Deposit and onramp components for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -33,9 +33,10 @@
33
33
  "clsx": "^2.0.0",
34
34
  "fuse.js": "^7.4.0",
35
35
  "lucide-react": "^0.454.0",
36
+ "mipd": "^0.0.7",
36
37
  "qr-code-styling": "^1.6.0-rc.1",
37
38
  "tailwind-merge": "^2.0.0",
38
- "@unifold/core": "0.1.59"
39
+ "@unifold/core": "0.1.61"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@solana/web3.js": "^1.87.0",