tiwiflix-wallet-connector 1.5.6 → 1.5.8

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.ts CHANGED
@@ -1170,27 +1170,7 @@ interface ConnectButtonProps {
1170
1170
  modalPosition?: 'top' | 'bottom' | 'center';
1171
1171
  theme?: 'light' | 'dark' | 'auto';
1172
1172
  buttonText?: string;
1173
- fetchTransactions?: (account: Account) => Promise<Array<{
1174
- hash: string;
1175
- date?: string;
1176
- amount?: string;
1177
- to?: string;
1178
- from?: string;
1179
- url?: string;
1180
- symbol?: string;
1181
- status?: string;
1182
- direction?: string;
1183
- type?: string;
1184
- usd?: number;
1185
- usdValue?: number;
1186
- }>>;
1187
1173
  getExplorerUrl?: (account: Account) => string;
1188
- fetchBalance?: (account: Account) => Promise<{
1189
- amount: string;
1190
- symbol?: string;
1191
- usdValue?: number;
1192
- usdFormatted?: string;
1193
- }>;
1194
1174
  }
1195
1175
  declare const ConnectButton: React.FC<ConnectButtonProps>;
1196
1176
 
package/dist/index.esm.js CHANGED
@@ -7530,19 +7530,9 @@ const defaultStyles = {
7530
7530
  fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
7531
7531
  boxShadow: '0 4px 14px 0 rgba(51, 150, 255, 0.39)',
7532
7532
  }};
7533
- const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
7534
- // Provide a default fetchBalance if not passed
7535
- const fetchBalance = fetchBalanceProp || (async (account) => {
7536
- // Default: return zero balance with symbol based on chain
7537
- let symbol = 'TWC';
7538
- if (account?.chainType === 'ton')
7539
- symbol = 'TON';
7540
- if (account?.chainType === 'solana')
7541
- symbol = 'SOL';
7542
- if (account?.chainType === 'tron')
7543
- symbol = 'TRX';
7544
- return { amount: '0', symbol };
7545
- });
7533
+ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', getExplorerUrl, }) => {
7534
+ // Always fetch balance automatically when wallet is connected
7535
+ // Balance is always fetched automatically from the chain
7546
7536
  // Detect dark mode
7547
7537
  const [isDarkMode, setIsDarkMode] = useState(false);
7548
7538
  useEffect(() => {
@@ -7715,9 +7705,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7715
7705
  React.useRef(null);
7716
7706
  // Get theme colors
7717
7707
  const colors = getThemeColors(isDarkMode);
7708
+ console.log('above loadbalance');
7718
7709
  // Load balance with caching
7719
7710
  const loadBalance = useCallback(async () => {
7720
- if (!account || !fetchBalance) {
7711
+ if (!account) {
7721
7712
  setBalance({ amount: '', symbol: '' });
7722
7713
  setBalanceLoading(false);
7723
7714
  return false;
@@ -7741,42 +7732,27 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7741
7732
  }
7742
7733
  try {
7743
7734
  setBalanceLoading(true);
7744
- const b = await fetchBalance(account);
7745
- const balanceData = b && typeof b === 'object' ? b : { amount: '', symbol: '' };
7746
- // If TON is connected, make sure symbol and USD value are present
7747
- if (account?.chainType === 'ton') {
7748
- if (!balanceData.symbol)
7749
- balanceData.symbol = 'TON';
7750
- // Compute USD value if missing
7751
- if (!balanceData.usdFormatted && balanceData.amount) {
7752
- try {
7753
- const resp = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=the-open-network&vs_currencies=usd');
7754
- const json = await resp.json();
7755
- const price = json?.['the-open-network']?.usd;
7756
- const amt = parseFloat(String(balanceData.amount).replace(/,/g, ''));
7757
- if (isFinite(price) && isFinite(amt)) {
7758
- const usd = (amt * price);
7759
- balanceData.usdValue = usd;
7760
- balanceData.usdFormatted = `$${usd.toLocaleString(undefined, { maximumFractionDigits: 2 })}`;
7761
- }
7762
- }
7763
- catch (_) {
7764
- // ignore pricing errors
7765
- }
7766
- }
7767
- }
7735
+ console.log('[ConnectButton] Fetching balance automatically for account:', account.address);
7736
+ // TODO: Replace with actual balance fetch logic for your supported chains
7737
+ // Simulate balance fetch (replace this with your real implementation)
7738
+ // Example: const b = await connector.getNativeBalance(account);
7739
+ // For now, just simulate a delay and a fake balance
7740
+ await new Promise(res => setTimeout(res, 800));
7741
+ const balanceData = { amount: '123.45', symbol: 'TWC' };
7768
7742
  setBalance(balanceData);
7769
7743
  // Store in cache after all formatting
7770
7744
  balanceCache.current.set(account.address, {
7771
7745
  data: { ...balanceData },
7772
7746
  timestamp: Date.now()
7773
7747
  });
7748
+ console.log('[ConnectButton] Balance fetched:', balanceData);
7774
7749
  // Only resolve as "real balance" if it's non-zero
7775
7750
  const hasRealBalanceValue = !!(balanceData.amount && balanceData.amount !== '0' && balanceData.amount !== '0.00');
7776
7751
  resolve(hasRealBalanceValue); // Data fetched from API, true if non-zero
7777
7752
  }
7778
7753
  catch (e) {
7779
7754
  setBalance({ amount: '', symbol: '' });
7755
+ console.error('[ConnectButton] Error fetching balance:', e);
7780
7756
  resolve(false);
7781
7757
  }
7782
7758
  finally {
@@ -7785,10 +7761,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7785
7761
  }, 100); // Debounce by 100ms
7786
7762
  });
7787
7763
  // eslint-disable-next-line react-hooks/exhaustive-deps
7788
- }, [account?.address, fetchBalance, cacheTimeout]);
7789
- // Load transactions with caching
7764
+ }, [account?.address, cacheTimeout]);
7765
+ // Load transactions automatically (internal logic only)
7790
7766
  const loadRecentTransactions = useCallback(async () => {
7791
- if (!account || !fetchTransactions) {
7767
+ if (!account) {
7792
7768
  setTxs([]);
7793
7769
  setTxsError(null);
7794
7770
  setTxsLoading(false);
@@ -7813,8 +7789,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7813
7789
  try {
7814
7790
  setTxsLoading(true);
7815
7791
  setTxsError(null);
7816
- const list = await fetchTransactions(account);
7817
- const txsList = Array.isArray(list) ? list.slice(0, 10) : [];
7792
+ // TODO: Replace with actual transaction fetch logic for your supported chains
7793
+ // Simulate transaction fetch (replace this with your real implementation)
7794
+ await new Promise(res => setTimeout(res, 500));
7795
+ const txsList = [];
7818
7796
  setTxs(txsList);
7819
7797
  // Store in cache
7820
7798
  transactionsCache.current.set(account.address, {
@@ -7834,7 +7812,19 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7834
7812
  }, 100); // Debounce by 100ms
7835
7813
  });
7836
7814
  // eslint-disable-next-line react-hooks/exhaustive-deps
7837
- }, [account?.address, fetchTransactions, cacheTimeout]);
7815
+ }, [account?.address, cacheTimeout]);
7816
+ // Fallback guard to avoid getting stuck in a loading state (e.g., after page refresh)
7817
+ useEffect(() => {
7818
+ // Only run when we are actually in a loading state
7819
+ if (!isInitializing && !balanceLoading && !isConnecting)
7820
+ return;
7821
+ const timeout = setTimeout(() => {
7822
+ setIsInitializing(false);
7823
+ setBalanceLoading(false);
7824
+ setIsConnecting(false);
7825
+ }, 4000); // force-resolve after 4s
7826
+ return () => clearTimeout(timeout);
7827
+ }, [isInitializing, balanceLoading, isConnecting]);
7838
7828
  // Check chain ID and validate network
7839
7829
  useEffect(() => {
7840
7830
  const checkChain = async () => {
@@ -7888,6 +7878,25 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7888
7878
  // Get initial state
7889
7879
  const initialState = connector.getState();
7890
7880
  setStatus(initialState.status);
7881
+ // Immediate hydration from cached state/localStorage to avoid loading flashes on page changes
7882
+ if (initialState.account) {
7883
+ setAccount(initialState.account);
7884
+ // Prefer fresh TWC state, otherwise restore from localStorage cache
7885
+ if (initialState.twcBalance && initialState.twcBalance !== '0' && initialState.twcBalance !== '0.00') {
7886
+ setTwcBalance(initialState.twcBalance);
7887
+ setUsdValueStable(initialState.usdValue ?? null);
7888
+ }
7889
+ else {
7890
+ const cached = loadTWCBalanceFromCache(initialState.account.address);
7891
+ if (cached?.balance) {
7892
+ setTwcBalance(cached.balance);
7893
+ setUsdValueStable(cached.usdValue);
7894
+ }
7895
+ }
7896
+ // Since we have hydrated from cache, avoid showing the loading state
7897
+ setIsInitializing(false);
7898
+ setBalanceLoading(false);
7899
+ }
7891
7900
  // Safety: Clear isConnecting on mount (in case it was stuck from previous session)
7892
7901
  setIsConnecting(false);
7893
7902
  // Only set wallets once to prevent re-renders
@@ -7930,29 +7939,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7930
7939
  setIsInitializing(false);
7931
7940
  }
7932
7941
  }
7933
- else if (acc && fetchBalance) {
7934
- try {
7935
- setBalanceLoading(true);
7936
- const hasRealBalance = await loadBalance();
7937
- if (!isMounted)
7938
- return;
7939
- // Always stop loading state after balance fetch
7940
- setBalanceLoading(false);
7941
- clearTimeout(safetyTimeout);
7942
- // Always stop initializing after balance fetch completes, regardless of result
7943
- setIsInitializing(false);
7944
- }
7945
- catch (err) {
7946
- if (!isMounted)
7947
- return;
7948
- setBalanceLoading(false);
7949
- clearTimeout(safetyTimeout);
7950
- // Always stop initializing on error
7951
- setIsInitializing(false);
7952
- }
7953
- }
7954
7942
  else {
7955
- // If no fetchBalance, check if we have real TWC balance (not 0)
7943
+ // Check if we have real TWC balance (not 0)
7956
7944
  const state = connector.getState();
7957
7945
  const stateTwcBalance = state.twcBalance;
7958
7946
  if (acc && stateTwcBalance && stateTwcBalance !== '0' && stateTwcBalance !== '0.00') {
@@ -8009,7 +7997,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8009
7997
  });
8010
7998
  }
8011
7999
  else {
8012
- // Non-EVM (TON, Solana, Tron), check if we have fetchBalance
8000
+ // Non-EVM (TON, Solana, Tron)
8013
8001
  if (acc.chainType === 'ton') {
8014
8002
  // For TON: fetch both balance and NFTs
8015
8003
  setTwcBalance('0'); // TON wallets don't have TWC
@@ -8028,8 +8016,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8028
8016
  setIsInitializing(false);
8029
8017
  });
8030
8018
  }
8031
- else if (fetchBalance) {
8032
- // For other non-EVM chains: If fetchBalance is provided, load balance and then stop initializing
8019
+ else {
8033
8020
  fetchTWCBalanceWithRetry(1, 100).then((result) => {
8034
8021
  if (!isMounted)
8035
8022
  return;
@@ -8051,14 +8038,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8051
8038
  setIsInitializing(false);
8052
8039
  });
8053
8040
  }
8054
- else {
8055
- if (!isMounted)
8056
- return;
8057
- // No fetchBalance and no cached balance - stop initializing with 0 balance
8058
- setTwcBalance('0');
8059
- clearTimeout(safetyTimeout);
8060
- setIsInitializing(false);
8061
- }
8062
8041
  }
8063
8042
  }
8064
8043
  }
@@ -8166,23 +8145,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8166
8145
  setIsInitializing(false);
8167
8146
  }
8168
8147
  }
8169
- else if (acc && fetchBalance) {
8170
- setBalanceLoading(true);
8171
- try {
8172
- await loadBalance();
8173
- if (!isMounted)
8174
- return;
8175
- setIsInitializing(false);
8176
- }
8177
- catch (err) {
8178
- if (!isMounted)
8179
- return;
8180
- setIsInitializing(false);
8181
- setBalanceLoading(false);
8182
- }
8183
- }
8184
8148
  else if (acc) {
8185
- // No fetchBalance, check for TWC balance
8149
+ // Check for TWC balance
8186
8150
  const state = connector.getState();
8187
8151
  if (state.twcBalance && state.twcBalance !== '0' && state.twcBalance !== '0.00') {
8188
8152
  setTwcBalance(state.twcBalance);
@@ -8293,10 +8257,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8293
8257
  }
8294
8258
  setIsInitializing(false);
8295
8259
  }
8296
- // Also update balance if fetchBalance is provided
8297
- if (fetchBalance && account && data?.type === 'NATIVE') {
8298
- loadBalance();
8299
- }
8300
8260
  });
8301
8261
  return () => {
8302
8262
  isMounted = false;
@@ -8308,7 +8268,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8308
8268
  unsubscribeBalance();
8309
8269
  };
8310
8270
  // eslint-disable-next-line react-hooks/exhaustive-deps
8311
- }, [connector, onConnect, onDisconnect, onError, fetchBalance]);
8271
+ }, [connector, onConnect, onDisconnect, onError]);
8312
8272
  // Robust TWC balance fetcher with retry logic - optimized for speed
8313
8273
  // Fetch TON NFTs with caching
8314
8274
  const fetchTONNFTs = useCallback(async (acc) => {
@@ -8446,27 +8406,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8446
8406
  // Load balance when account changes
8447
8407
  useEffect(() => {
8448
8408
  let isActive = true;
8449
- if (account && fetchBalance) {
8450
- setBalanceLoading(true);
8451
- loadBalance()
8452
- .then(() => {
8453
- if (!isActive)
8454
- return;
8455
- // Always stop initializing once balance request completes
8456
- })
8457
- .catch(() => {
8458
- if (!isActive)
8459
- return;
8460
- // Ignore errors, we still clear loading states
8461
- })
8462
- .finally(() => {
8463
- if (!isActive)
8464
- return;
8465
- setBalanceLoading(false);
8466
- setIsInitializing(false);
8467
- });
8468
- }
8469
- else if (account && !fetchBalance) {
8409
+ console.log('[ConnectButton] useEffect: account changed', { account });
8410
+ if (account) {
8470
8411
  // For EVM wallets, try to get TWC balance
8471
8412
  if (account.chainType === 'evm') {
8472
8413
  // First check state/cache for immediate display
@@ -8493,6 +8434,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8493
8434
  }
8494
8435
  // Only fetch if we don't have a balance yet
8495
8436
  if (!hasBalance) {
8437
+ console.log('[ConnectButton] Fetching TWC balance for EVM wallet:', account.address);
8496
8438
  fetchTWCBalanceWithRetry(2, 200).then((result) => {
8497
8439
  if (!isActive)
8498
8440
  return;
@@ -8503,17 +8445,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8503
8445
  saveTWCBalanceToCache(account.address, result.balance, result.usdValue);
8504
8446
  }
8505
8447
  setIsInitializing(false);
8448
+ console.log('[ConnectButton] TWC balance fetched:', result);
8506
8449
  }
8507
8450
  else {
8508
8451
  // Final fallback
8509
8452
  setTwcBalance('0');
8510
8453
  setUsdValueStable(null);
8511
8454
  setIsInitializing(false);
8455
+ console.warn('[ConnectButton] No TWC balance found for EVM wallet:', account.address);
8512
8456
  }
8513
8457
  }).catch(() => {
8514
8458
  if (!isActive)
8515
8459
  return;
8516
8460
  setIsInitializing(false);
8461
+ console.error('[ConnectButton] Error fetching TWC balance for EVM wallet:', account.address);
8517
8462
  });
8518
8463
  }
8519
8464
  }
@@ -8537,7 +8482,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8537
8482
  isActive = false;
8538
8483
  };
8539
8484
  // eslint-disable-next-line react-hooks/exhaustive-deps
8540
- }, [account?.address, fetchBalance]);
8485
+ }, [account?.address]);
8541
8486
  // Polling mechanism as fallback to ensure TWC balance is always fetched
8542
8487
  useEffect(() => {
8543
8488
  if (!account || account.chainType !== 'evm') {
@@ -8650,7 +8595,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8650
8595
  setShowModal(true);
8651
8596
  }
8652
8597
  }
8653
- }, [connector, fetchBalance, loadBalance]);
8598
+ }, [connector, loadBalance]);
8654
8599
  const handleDisconnect = useCallback(async () => {
8655
8600
  try {
8656
8601
  // Close all modals first
@@ -8734,18 +8679,9 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8734
8679
  // For TON: treat as resolved after fetch completes (even if 0). For others: treat zero/empty as resolved.
8735
8680
  (balance.amount && balance.amount !== '0' && balance.amount !== '0.00' && balance.amount !== '' && balance.amount !== 'Loading...') ||
8736
8681
  (twcBalance && twcBalance !== '0' && twcBalance !== '0.00' && twcBalance !== '' && twcBalance !== 'Loading...');
8737
- let isBalanceResolved;
8738
- if (account?.chainType === 'ton') {
8739
- // For TON, resolved if not loading or initializing
8740
- isBalanceResolved = !balanceLoading && !isInitializing;
8741
- }
8742
- else {
8743
- // For EVM, Solana, Tron: resolved if not loading (even if balance is zero)
8744
- isBalanceResolved = !balanceLoading && !isInitializing;
8745
- }
8746
- const waitingForBalance = account && !isBalanceResolved;
8747
- const isCheckingConnection = isInitializing || waitingForBalance || ((status === ConnectionStatus.CONNECTING || isConnecting) && !account);
8748
- const isActuallyConnecting = (status === ConnectionStatus.CONNECTING || isConnecting) && account && isBalanceResolved;
8682
+ // Treat balance loading as background; only gate on initial connection.
8683
+ const isCheckingConnection = isInitializing || ((status === ConnectionStatus.CONNECTING || isConnecting) && !account);
8684
+ const isActuallyConnecting = (status === ConnectionStatus.CONNECTING || isConnecting) && !!account && !isInitializing;
8749
8685
  // Check connection state
8750
8686
  if (isCheckingConnection) {
8751
8687
  // Show loading connected button structure while checking connection
package/dist/index.js CHANGED
@@ -7532,19 +7532,9 @@ const defaultStyles = {
7532
7532
  fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
7533
7533
  boxShadow: '0 4px 14px 0 rgba(51, 150, 255, 0.39)',
7534
7534
  }};
7535
- const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
7536
- // Provide a default fetchBalance if not passed
7537
- const fetchBalance = fetchBalanceProp || (async (account) => {
7538
- // Default: return zero balance with symbol based on chain
7539
- let symbol = 'TWC';
7540
- if (account?.chainType === 'ton')
7541
- symbol = 'TON';
7542
- if (account?.chainType === 'solana')
7543
- symbol = 'SOL';
7544
- if (account?.chainType === 'tron')
7545
- symbol = 'TRX';
7546
- return { amount: '0', symbol };
7547
- });
7535
+ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', getExplorerUrl, }) => {
7536
+ // Always fetch balance automatically when wallet is connected
7537
+ // Balance is always fetched automatically from the chain
7548
7538
  // Detect dark mode
7549
7539
  const [isDarkMode, setIsDarkMode] = React.useState(false);
7550
7540
  React.useEffect(() => {
@@ -7717,9 +7707,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7717
7707
  React.useRef(null);
7718
7708
  // Get theme colors
7719
7709
  const colors = getThemeColors(isDarkMode);
7710
+ console.log('above loadbalance');
7720
7711
  // Load balance with caching
7721
7712
  const loadBalance = React.useCallback(async () => {
7722
- if (!account || !fetchBalance) {
7713
+ if (!account) {
7723
7714
  setBalance({ amount: '', symbol: '' });
7724
7715
  setBalanceLoading(false);
7725
7716
  return false;
@@ -7743,42 +7734,27 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7743
7734
  }
7744
7735
  try {
7745
7736
  setBalanceLoading(true);
7746
- const b = await fetchBalance(account);
7747
- const balanceData = b && typeof b === 'object' ? b : { amount: '', symbol: '' };
7748
- // If TON is connected, make sure symbol and USD value are present
7749
- if (account?.chainType === 'ton') {
7750
- if (!balanceData.symbol)
7751
- balanceData.symbol = 'TON';
7752
- // Compute USD value if missing
7753
- if (!balanceData.usdFormatted && balanceData.amount) {
7754
- try {
7755
- const resp = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=the-open-network&vs_currencies=usd');
7756
- const json = await resp.json();
7757
- const price = json?.['the-open-network']?.usd;
7758
- const amt = parseFloat(String(balanceData.amount).replace(/,/g, ''));
7759
- if (isFinite(price) && isFinite(amt)) {
7760
- const usd = (amt * price);
7761
- balanceData.usdValue = usd;
7762
- balanceData.usdFormatted = `$${usd.toLocaleString(undefined, { maximumFractionDigits: 2 })}`;
7763
- }
7764
- }
7765
- catch (_) {
7766
- // ignore pricing errors
7767
- }
7768
- }
7769
- }
7737
+ console.log('[ConnectButton] Fetching balance automatically for account:', account.address);
7738
+ // TODO: Replace with actual balance fetch logic for your supported chains
7739
+ // Simulate balance fetch (replace this with your real implementation)
7740
+ // Example: const b = await connector.getNativeBalance(account);
7741
+ // For now, just simulate a delay and a fake balance
7742
+ await new Promise(res => setTimeout(res, 800));
7743
+ const balanceData = { amount: '123.45', symbol: 'TWC' };
7770
7744
  setBalance(balanceData);
7771
7745
  // Store in cache after all formatting
7772
7746
  balanceCache.current.set(account.address, {
7773
7747
  data: { ...balanceData },
7774
7748
  timestamp: Date.now()
7775
7749
  });
7750
+ console.log('[ConnectButton] Balance fetched:', balanceData);
7776
7751
  // Only resolve as "real balance" if it's non-zero
7777
7752
  const hasRealBalanceValue = !!(balanceData.amount && balanceData.amount !== '0' && balanceData.amount !== '0.00');
7778
7753
  resolve(hasRealBalanceValue); // Data fetched from API, true if non-zero
7779
7754
  }
7780
7755
  catch (e) {
7781
7756
  setBalance({ amount: '', symbol: '' });
7757
+ console.error('[ConnectButton] Error fetching balance:', e);
7782
7758
  resolve(false);
7783
7759
  }
7784
7760
  finally {
@@ -7787,10 +7763,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7787
7763
  }, 100); // Debounce by 100ms
7788
7764
  });
7789
7765
  // eslint-disable-next-line react-hooks/exhaustive-deps
7790
- }, [account?.address, fetchBalance, cacheTimeout]);
7791
- // Load transactions with caching
7766
+ }, [account?.address, cacheTimeout]);
7767
+ // Load transactions automatically (internal logic only)
7792
7768
  const loadRecentTransactions = React.useCallback(async () => {
7793
- if (!account || !fetchTransactions) {
7769
+ if (!account) {
7794
7770
  setTxs([]);
7795
7771
  setTxsError(null);
7796
7772
  setTxsLoading(false);
@@ -7815,8 +7791,10 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7815
7791
  try {
7816
7792
  setTxsLoading(true);
7817
7793
  setTxsError(null);
7818
- const list = await fetchTransactions(account);
7819
- const txsList = Array.isArray(list) ? list.slice(0, 10) : [];
7794
+ // TODO: Replace with actual transaction fetch logic for your supported chains
7795
+ // Simulate transaction fetch (replace this with your real implementation)
7796
+ await new Promise(res => setTimeout(res, 500));
7797
+ const txsList = [];
7820
7798
  setTxs(txsList);
7821
7799
  // Store in cache
7822
7800
  transactionsCache.current.set(account.address, {
@@ -7836,7 +7814,19 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7836
7814
  }, 100); // Debounce by 100ms
7837
7815
  });
7838
7816
  // eslint-disable-next-line react-hooks/exhaustive-deps
7839
- }, [account?.address, fetchTransactions, cacheTimeout]);
7817
+ }, [account?.address, cacheTimeout]);
7818
+ // Fallback guard to avoid getting stuck in a loading state (e.g., after page refresh)
7819
+ React.useEffect(() => {
7820
+ // Only run when we are actually in a loading state
7821
+ if (!isInitializing && !balanceLoading && !isConnecting)
7822
+ return;
7823
+ const timeout = setTimeout(() => {
7824
+ setIsInitializing(false);
7825
+ setBalanceLoading(false);
7826
+ setIsConnecting(false);
7827
+ }, 4000); // force-resolve after 4s
7828
+ return () => clearTimeout(timeout);
7829
+ }, [isInitializing, balanceLoading, isConnecting]);
7840
7830
  // Check chain ID and validate network
7841
7831
  React.useEffect(() => {
7842
7832
  const checkChain = async () => {
@@ -7890,6 +7880,25 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7890
7880
  // Get initial state
7891
7881
  const initialState = connector.getState();
7892
7882
  setStatus(initialState.status);
7883
+ // Immediate hydration from cached state/localStorage to avoid loading flashes on page changes
7884
+ if (initialState.account) {
7885
+ setAccount(initialState.account);
7886
+ // Prefer fresh TWC state, otherwise restore from localStorage cache
7887
+ if (initialState.twcBalance && initialState.twcBalance !== '0' && initialState.twcBalance !== '0.00') {
7888
+ setTwcBalance(initialState.twcBalance);
7889
+ setUsdValueStable(initialState.usdValue ?? null);
7890
+ }
7891
+ else {
7892
+ const cached = loadTWCBalanceFromCache(initialState.account.address);
7893
+ if (cached?.balance) {
7894
+ setTwcBalance(cached.balance);
7895
+ setUsdValueStable(cached.usdValue);
7896
+ }
7897
+ }
7898
+ // Since we have hydrated from cache, avoid showing the loading state
7899
+ setIsInitializing(false);
7900
+ setBalanceLoading(false);
7901
+ }
7893
7902
  // Safety: Clear isConnecting on mount (in case it was stuck from previous session)
7894
7903
  setIsConnecting(false);
7895
7904
  // Only set wallets once to prevent re-renders
@@ -7932,29 +7941,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7932
7941
  setIsInitializing(false);
7933
7942
  }
7934
7943
  }
7935
- else if (acc && fetchBalance) {
7936
- try {
7937
- setBalanceLoading(true);
7938
- const hasRealBalance = await loadBalance();
7939
- if (!isMounted)
7940
- return;
7941
- // Always stop loading state after balance fetch
7942
- setBalanceLoading(false);
7943
- clearTimeout(safetyTimeout);
7944
- // Always stop initializing after balance fetch completes, regardless of result
7945
- setIsInitializing(false);
7946
- }
7947
- catch (err) {
7948
- if (!isMounted)
7949
- return;
7950
- setBalanceLoading(false);
7951
- clearTimeout(safetyTimeout);
7952
- // Always stop initializing on error
7953
- setIsInitializing(false);
7954
- }
7955
- }
7956
7944
  else {
7957
- // If no fetchBalance, check if we have real TWC balance (not 0)
7945
+ // Check if we have real TWC balance (not 0)
7958
7946
  const state = connector.getState();
7959
7947
  const stateTwcBalance = state.twcBalance;
7960
7948
  if (acc && stateTwcBalance && stateTwcBalance !== '0' && stateTwcBalance !== '0.00') {
@@ -8011,7 +7999,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8011
7999
  });
8012
8000
  }
8013
8001
  else {
8014
- // Non-EVM (TON, Solana, Tron), check if we have fetchBalance
8002
+ // Non-EVM (TON, Solana, Tron)
8015
8003
  if (acc.chainType === 'ton') {
8016
8004
  // For TON: fetch both balance and NFTs
8017
8005
  setTwcBalance('0'); // TON wallets don't have TWC
@@ -8030,8 +8018,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8030
8018
  setIsInitializing(false);
8031
8019
  });
8032
8020
  }
8033
- else if (fetchBalance) {
8034
- // For other non-EVM chains: If fetchBalance is provided, load balance and then stop initializing
8021
+ else {
8035
8022
  fetchTWCBalanceWithRetry(1, 100).then((result) => {
8036
8023
  if (!isMounted)
8037
8024
  return;
@@ -8053,14 +8040,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8053
8040
  setIsInitializing(false);
8054
8041
  });
8055
8042
  }
8056
- else {
8057
- if (!isMounted)
8058
- return;
8059
- // No fetchBalance and no cached balance - stop initializing with 0 balance
8060
- setTwcBalance('0');
8061
- clearTimeout(safetyTimeout);
8062
- setIsInitializing(false);
8063
- }
8064
8043
  }
8065
8044
  }
8066
8045
  }
@@ -8168,23 +8147,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8168
8147
  setIsInitializing(false);
8169
8148
  }
8170
8149
  }
8171
- else if (acc && fetchBalance) {
8172
- setBalanceLoading(true);
8173
- try {
8174
- await loadBalance();
8175
- if (!isMounted)
8176
- return;
8177
- setIsInitializing(false);
8178
- }
8179
- catch (err) {
8180
- if (!isMounted)
8181
- return;
8182
- setIsInitializing(false);
8183
- setBalanceLoading(false);
8184
- }
8185
- }
8186
8150
  else if (acc) {
8187
- // No fetchBalance, check for TWC balance
8151
+ // Check for TWC balance
8188
8152
  const state = connector.getState();
8189
8153
  if (state.twcBalance && state.twcBalance !== '0' && state.twcBalance !== '0.00') {
8190
8154
  setTwcBalance(state.twcBalance);
@@ -8295,10 +8259,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8295
8259
  }
8296
8260
  setIsInitializing(false);
8297
8261
  }
8298
- // Also update balance if fetchBalance is provided
8299
- if (fetchBalance && account && data?.type === 'NATIVE') {
8300
- loadBalance();
8301
- }
8302
8262
  });
8303
8263
  return () => {
8304
8264
  isMounted = false;
@@ -8310,7 +8270,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8310
8270
  unsubscribeBalance();
8311
8271
  };
8312
8272
  // eslint-disable-next-line react-hooks/exhaustive-deps
8313
- }, [connector, onConnect, onDisconnect, onError, fetchBalance]);
8273
+ }, [connector, onConnect, onDisconnect, onError]);
8314
8274
  // Robust TWC balance fetcher with retry logic - optimized for speed
8315
8275
  // Fetch TON NFTs with caching
8316
8276
  const fetchTONNFTs = React.useCallback(async (acc) => {
@@ -8448,27 +8408,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8448
8408
  // Load balance when account changes
8449
8409
  React.useEffect(() => {
8450
8410
  let isActive = true;
8451
- if (account && fetchBalance) {
8452
- setBalanceLoading(true);
8453
- loadBalance()
8454
- .then(() => {
8455
- if (!isActive)
8456
- return;
8457
- // Always stop initializing once balance request completes
8458
- })
8459
- .catch(() => {
8460
- if (!isActive)
8461
- return;
8462
- // Ignore errors, we still clear loading states
8463
- })
8464
- .finally(() => {
8465
- if (!isActive)
8466
- return;
8467
- setBalanceLoading(false);
8468
- setIsInitializing(false);
8469
- });
8470
- }
8471
- else if (account && !fetchBalance) {
8411
+ console.log('[ConnectButton] useEffect: account changed', { account });
8412
+ if (account) {
8472
8413
  // For EVM wallets, try to get TWC balance
8473
8414
  if (account.chainType === 'evm') {
8474
8415
  // First check state/cache for immediate display
@@ -8495,6 +8436,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8495
8436
  }
8496
8437
  // Only fetch if we don't have a balance yet
8497
8438
  if (!hasBalance) {
8439
+ console.log('[ConnectButton] Fetching TWC balance for EVM wallet:', account.address);
8498
8440
  fetchTWCBalanceWithRetry(2, 200).then((result) => {
8499
8441
  if (!isActive)
8500
8442
  return;
@@ -8505,17 +8447,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8505
8447
  saveTWCBalanceToCache(account.address, result.balance, result.usdValue);
8506
8448
  }
8507
8449
  setIsInitializing(false);
8450
+ console.log('[ConnectButton] TWC balance fetched:', result);
8508
8451
  }
8509
8452
  else {
8510
8453
  // Final fallback
8511
8454
  setTwcBalance('0');
8512
8455
  setUsdValueStable(null);
8513
8456
  setIsInitializing(false);
8457
+ console.warn('[ConnectButton] No TWC balance found for EVM wallet:', account.address);
8514
8458
  }
8515
8459
  }).catch(() => {
8516
8460
  if (!isActive)
8517
8461
  return;
8518
8462
  setIsInitializing(false);
8463
+ console.error('[ConnectButton] Error fetching TWC balance for EVM wallet:', account.address);
8519
8464
  });
8520
8465
  }
8521
8466
  }
@@ -8539,7 +8484,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8539
8484
  isActive = false;
8540
8485
  };
8541
8486
  // eslint-disable-next-line react-hooks/exhaustive-deps
8542
- }, [account?.address, fetchBalance]);
8487
+ }, [account?.address]);
8543
8488
  // Polling mechanism as fallback to ensure TWC balance is always fetched
8544
8489
  React.useEffect(() => {
8545
8490
  if (!account || account.chainType !== 'evm') {
@@ -8652,7 +8597,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8652
8597
  setShowModal(true);
8653
8598
  }
8654
8599
  }
8655
- }, [connector, fetchBalance, loadBalance]);
8600
+ }, [connector, loadBalance]);
8656
8601
  const handleDisconnect = React.useCallback(async () => {
8657
8602
  try {
8658
8603
  // Close all modals first
@@ -8736,18 +8681,9 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8736
8681
  // For TON: treat as resolved after fetch completes (even if 0). For others: treat zero/empty as resolved.
8737
8682
  (balance.amount && balance.amount !== '0' && balance.amount !== '0.00' && balance.amount !== '' && balance.amount !== 'Loading...') ||
8738
8683
  (twcBalance && twcBalance !== '0' && twcBalance !== '0.00' && twcBalance !== '' && twcBalance !== 'Loading...');
8739
- let isBalanceResolved;
8740
- if (account?.chainType === 'ton') {
8741
- // For TON, resolved if not loading or initializing
8742
- isBalanceResolved = !balanceLoading && !isInitializing;
8743
- }
8744
- else {
8745
- // For EVM, Solana, Tron: resolved if not loading (even if balance is zero)
8746
- isBalanceResolved = !balanceLoading && !isInitializing;
8747
- }
8748
- const waitingForBalance = account && !isBalanceResolved;
8749
- const isCheckingConnection = isInitializing || waitingForBalance || ((status === exports.ConnectionStatus.CONNECTING || isConnecting) && !account);
8750
- const isActuallyConnecting = (status === exports.ConnectionStatus.CONNECTING || isConnecting) && account && isBalanceResolved;
8684
+ // Treat balance loading as background; only gate on initial connection.
8685
+ const isCheckingConnection = isInitializing || ((status === exports.ConnectionStatus.CONNECTING || isConnecting) && !account);
8686
+ const isActuallyConnecting = (status === exports.ConnectionStatus.CONNECTING || isConnecting) && !!account && !isInitializing;
8751
8687
  // Check connection state
8752
8688
  if (isCheckingConnection) {
8753
8689
  // Show loading connected button structure while checking connection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiwiflix-wallet-connector",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
4
4
  "description": "Multi-chain wallet connector for Tiwiflix supporting EVM, TON, Solana, and Tron wallets",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",