tiwiflix-wallet-connector 1.6.6 → 1.6.7

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.esm.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ethers } from 'ethers';
1
2
  import React, { useMemo, useState, useEffect, useRef, useCallback } from 'react';
2
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
4
  import ReactDOM from 'react-dom';
@@ -2552,13 +2553,9 @@ class WalletConnector {
2552
2553
  if (account && adapter.chainType === ChainType.TON) {
2553
2554
  try {
2554
2555
  const nftResult = await this.checkNFTOwnership([
2555
- // New collection - user-friendly format
2556
2556
  'EQDVaDCso_2LRTkc8WrT9A4bVO5BG_PZ8313BC_lOO8XW1T8',
2557
- // New collection - raw format
2558
2557
  '0:d56830aca3fd8b45391cf16ad3f40e1b54ee411bf3d9f37d77042fe538ef175b',
2559
- // Legacy collection - user-friendly format
2560
2558
  'EQDKfA87JVnBJXsBVfzjIfbhr3bmTTdouUP31Szgm_Lw0v-J',
2561
- // Legacy collection - raw format
2562
2559
  '0:ca7c0f3b2559c1257b0155fce321f6e1af76e64d3768b943f7d52ce09bf2f0d2'
2563
2560
  ]);
2564
2561
  accountWithNFTs = {
@@ -2569,7 +2566,6 @@ class WalletConnector {
2569
2566
  hasRequiredNFTs: nftResult.hasNFTs,
2570
2567
  ownedCount: nftResult.ownedNFTs.length
2571
2568
  });
2572
- // Update state with NFT count and data
2573
2569
  this.updateState({
2574
2570
  account: accountWithNFTs,
2575
2571
  nftCount: nftResult.ownedNFTs.length,
@@ -2578,36 +2574,40 @@ class WalletConnector {
2578
2574
  }
2579
2575
  catch (nftError) {
2580
2576
  this.debugTools.warn('WALLET_CONNECTOR', 'NFT check failed during account change', nftError);
2581
- // Continue with account change even if NFT check fails
2582
2577
  this.updateState({ account: accountWithNFTs });
2583
2578
  }
2584
2579
  }
2585
2580
  else {
2586
2581
  this.updateState({ account: accountWithNFTs });
2587
2582
  }
2583
+ // Always update chainId in state after account change (for EVM wallets)
2584
+ if (account && adapter.chainType === ChainType.EVM && typeof adapter.getChainId === 'function') {
2585
+ try {
2586
+ const chainId = await adapter.getChainId();
2587
+ this.updateState({ chainId });
2588
+ }
2589
+ catch (e) {
2590
+ this.updateState({ chainId: null });
2591
+ }
2592
+ }
2588
2593
  this.eventEmitter.emit(WalletEvent.ACCOUNT_CHANGED, accountWithNFTs);
2589
2594
  if (account) {
2590
2595
  this.eventEmitter.emit(WalletEvent.CONNECTED, account);
2591
- // Automatically fetch new balance and price when account changes
2592
2596
  try {
2593
2597
  this.debugTools.info('WALLET_CONNECTOR', 'Account changed, fetching new balance and price', {
2594
2598
  account: account.address,
2595
2599
  wallet: walletType
2596
2600
  });
2597
- // Clear price cache for new account
2598
2601
  priceService.clearCache();
2599
- // Fetch TWC balance and price
2600
2602
  if (adapter.chainType === ChainType.EVM) {
2601
2603
  try {
2602
2604
  const twcBalance = await this.getTWCBalance();
2603
- // Persist in state for exportability
2604
2605
  this.updateState({ twcBalance: twcBalance.amount, usdValue: twcBalance.usdValue ?? null });
2605
2606
  this.debugTools.info('WALLET_CONNECTOR', 'TWC balance updated for new account', {
2606
2607
  balance: twcBalance.amount,
2607
2608
  usdValue: twcBalance.usdValue,
2608
2609
  account: account.address
2609
2610
  });
2610
- // Emit balance update event
2611
2611
  this.eventEmitter.emit(WalletEvent.BALANCE_UPDATED, {
2612
2612
  type: 'TWC',
2613
2613
  balance: twcBalance.amount,
@@ -2619,7 +2619,6 @@ class WalletConnector {
2619
2619
  }
2620
2620
  catch (twcError) {
2621
2621
  this.debugTools.warn('WALLET_CONNECTOR', 'Failed to fetch TWC balance for new account', twcError);
2622
- // Fallback to native balance
2623
2622
  try {
2624
2623
  const nativeBalance = await this.getNativeBalance();
2625
2624
  this.debugTools.info('WALLET_CONNECTOR', 'Native balance updated for new account', {
@@ -2627,7 +2626,6 @@ class WalletConnector {
2627
2626
  symbol: nativeBalance.symbol,
2628
2627
  account: account.address
2629
2628
  });
2630
- // Emit balance update event
2631
2629
  this.eventEmitter.emit(WalletEvent.BALANCE_UPDATED, {
2632
2630
  type: 'NATIVE',
2633
2631
  balance: nativeBalance.amount,
@@ -2646,7 +2644,6 @@ class WalletConnector {
2646
2644
  }
2647
2645
  }
2648
2646
  else if (this.state.wallet) {
2649
- // Account removed/disconnected from wallet app
2650
2647
  this.storage.clearWallet();
2651
2648
  this.updateState({ wallet: null, account: null, status: ConnectionStatus.DISCONNECTED, twcBalance: null, usdValue: null, nftCount: 0, nftData: null });
2652
2649
  this.eventEmitter.emit(WalletEvent.DISCONNECTED, undefined);
@@ -2692,13 +2689,9 @@ class WalletConnector {
2692
2689
  if (adapter.chainType === ChainType.TON) {
2693
2690
  try {
2694
2691
  const nftResult = await this.checkNFTOwnership([
2695
- // New collection - user-friendly format
2696
2692
  'EQDVaDCso_2LRTkc8WrT9A4bVO5BG_PZ8313BC_lOO8XW1T8',
2697
- // New collection - raw format
2698
2693
  '0:d56830aca3fd8b45391cf16ad3f40e1b54ee411bf3d9f37d77042fe538ef175b',
2699
- // Legacy collection - user-friendly format
2700
2694
  'EQDKfA87JVnBJXsBVfzjIfbhr3bmTTdouUP31Szgm_Lw0v-J',
2701
- // Legacy collection - raw format
2702
2695
  '0:ca7c0f3b2559c1257b0155fce321f6e1af76e64d3768b943f7d52ce09bf2f0d2'
2703
2696
  ]);
2704
2697
  accountWithNFTs = {
@@ -2712,7 +2705,6 @@ class WalletConnector {
2712
2705
  }
2713
2706
  catch (nftError) {
2714
2707
  this.debugTools.warn('WALLET_CONNECTOR', 'NFT check failed, proceeding without NFT info', nftError);
2715
- // Continue with connection even if NFT check fails
2716
2708
  }
2717
2709
  }
2718
2710
  this.storage.saveWallet(walletType);
@@ -2722,6 +2714,39 @@ class WalletConnector {
2722
2714
  error: null,
2723
2715
  });
2724
2716
  this.eventEmitter.emit(WalletEvent.CONNECTED, accountWithNFTs);
2717
+ // Immediately fetch TWC balance after initial connection (not just on reconnect or refresh)
2718
+ if (adapter.chainType === ChainType.EVM) {
2719
+ try {
2720
+ // Update chainId in state if possible
2721
+ if (typeof adapter.getChainId === 'function') {
2722
+ try {
2723
+ const chainId = await adapter.getChainId();
2724
+ this.updateState({ chainId });
2725
+ }
2726
+ catch (e) {
2727
+ this.updateState({ chainId: null });
2728
+ }
2729
+ }
2730
+ const twcBalance = await this.getTWCBalance();
2731
+ this.updateState({ twcBalance: twcBalance.amount, usdValue: twcBalance.usdValue ?? null });
2732
+ this.debugTools.info('WALLET_CONNECTOR', 'TWC balance updated after initial connect', {
2733
+ balance: twcBalance.amount,
2734
+ usdValue: twcBalance.usdValue,
2735
+ account: accountWithNFTs.address
2736
+ });
2737
+ this.eventEmitter.emit(WalletEvent.BALANCE_UPDATED, {
2738
+ type: 'TWC',
2739
+ balance: twcBalance.amount,
2740
+ symbol: twcBalance.symbol,
2741
+ usdValue: twcBalance.usdValue,
2742
+ usdFormatted: twcBalance.usdFormatted,
2743
+ account: accountWithNFTs.address
2744
+ });
2745
+ }
2746
+ catch (twcError) {
2747
+ this.debugTools.warn('WALLET_CONNECTOR', 'Failed to fetch TWC balance after initial connect', twcError);
2748
+ }
2749
+ }
2725
2750
  }
2726
2751
  else {
2727
2752
  // Connection failed - reset state properly
@@ -3102,14 +3127,21 @@ class WalletConnector {
3102
3127
  }
3103
3128
  async getTWCBalance() {
3104
3129
  if (!this.state.account) {
3130
+ if (typeof window !== 'undefined')
3131
+ window.showDebugLog?.('[getTWCBalance] No wallet connected');
3105
3132
  throw new Error('No wallet connected');
3106
3133
  }
3107
3134
  const accountAddress = this.state.account.address;
3135
+ const chainId = this.state.chainId;
3108
3136
  performance.now();
3137
+ if (typeof window !== 'undefined')
3138
+ window.showDebugLog?.(`[getTWCBalance] Called for account=${accountAddress}, chainId=${chainId}`);
3109
3139
  // Check cache first
3110
3140
  if (this.twcBalanceCache &&
3111
3141
  this.twcBalanceCache.address === accountAddress &&
3112
3142
  Date.now() - this.twcBalanceCache.timestamp < this.TWC_CACHE_TTL) {
3143
+ if (typeof window !== 'undefined')
3144
+ window.showDebugLog?.(`[getTWCBalance] Using cache for ${accountAddress}: ${JSON.stringify(this.twcBalanceCache)}`);
3113
3145
  return {
3114
3146
  amount: this.twcBalanceCache.balance,
3115
3147
  symbol: 'TWC',
@@ -3126,26 +3158,86 @@ class WalletConnector {
3126
3158
  // Use the currently connected wallet's adapter
3127
3159
  const currentWallet = this.state.wallet;
3128
3160
  if (!currentWallet) {
3161
+ if (typeof window !== 'undefined')
3162
+ window.showDebugLog?.('[getTWCBalance] No wallet connected (no currentWallet)');
3129
3163
  throw new Error('No wallet connected');
3130
3164
  }
3131
3165
  const adapter = this.adapters.get(currentWallet);
3132
3166
  if (!adapter || adapter.chainType !== ChainType.EVM) {
3167
+ if (typeof window !== 'undefined')
3168
+ window.showDebugLog?.('[getTWCBalance] No EVM adapter available');
3133
3169
  throw new Error('No EVM adapter available');
3134
3170
  }
3135
- // Call balanceOf directly on the TWC contract using the wallet's provider
3136
- // Skip existence check for known TWC contract (faster)
3137
- // Add 10 second timeout for mobile networks
3138
- const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3139
- const timeoutPromise = new Promise((_, reject) => {
3140
- setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3141
- });
3142
- const balance = await Promise.race([balancePromise, timeoutPromise]);
3171
+ // Debug: log adapter type and available methods
3172
+ if (typeof window !== 'undefined') {
3173
+ window.showDebugLog?.(`[getTWCBalance] Using adapter: ${adapter.constructor?.name || typeof adapter}`);
3174
+ window.showDebugLog?.(`[getTWCBalance] Adapter keys: ${Object.keys(adapter).join(', ')}`);
3175
+ window.showDebugLog?.(`[getTWCBalance] typeof getTokenBalance: ${typeof adapter.getTokenBalance}`);
3176
+ }
3177
+ let balance;
3178
+ // Always use ethers fallback if EVM is connected, regardless of chainId
3179
+ if (this.state.chainId !== 56) {
3180
+ if (typeof window !== 'undefined')
3181
+ window.showDebugLog?.(`[getTWCBalance] Warning: Not on BSC (chainId=${this.state.chainId}), but fetching TWC balance using ethers fallback.`);
3182
+ // Fallback: use ethers.js to fetch balance from chain
3183
+ let provider = adapter.provider || this.getProvider();
3184
+ if (!provider) {
3185
+ if (typeof window !== 'undefined')
3186
+ window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3187
+ throw new Error('No provider available for ethers fallback');
3188
+ }
3189
+ if (!provider._isProvider) {
3190
+ provider = new ethers.BrowserProvider(provider);
3191
+ }
3192
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3193
+ const contract = new ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3194
+ const rawBalance = await contract.balanceOf(accountAddress);
3195
+ if (typeof window !== 'undefined')
3196
+ window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3197
+ balance = ethers.formatUnits(rawBalance, TWC_DECIMALS);
3198
+ if (typeof window !== 'undefined')
3199
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3200
+ }
3201
+ else if (typeof adapter.getTokenBalance === 'function') {
3202
+ // Use adapter method if available and on BSC
3203
+ const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3204
+ const timeoutPromise = new Promise((_, reject) => {
3205
+ setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3206
+ });
3207
+ balance = await Promise.race([balancePromise, timeoutPromise]);
3208
+ if (typeof window !== 'undefined')
3209
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (adapter): ${balance}`);
3210
+ }
3211
+ else {
3212
+ // Fallback: use ethers.js to fetch balance from chain (should not happen, but for safety)
3213
+ if (typeof window !== 'undefined')
3214
+ window.showDebugLog?.('[getTWCBalance] Fallback to ethers.js for TWC balance (on BSC)');
3215
+ let provider = adapter.provider || this.getProvider();
3216
+ if (!provider) {
3217
+ if (typeof window !== 'undefined')
3218
+ window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3219
+ throw new Error('No provider available for ethers fallback');
3220
+ }
3221
+ if (!provider._isProvider) {
3222
+ provider = new ethers.BrowserProvider(provider);
3223
+ }
3224
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3225
+ const contract = new ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3226
+ const rawBalance = await contract.balanceOf(accountAddress);
3227
+ if (typeof window !== 'undefined')
3228
+ window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3229
+ balance = ethers.formatUnits(rawBalance, TWC_DECIMALS);
3230
+ if (typeof window !== 'undefined')
3231
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3232
+ }
3143
3233
  // Calculate USD value with 5 second timeout
3144
3234
  const usdPromise = priceService.calculateTWCValue(balance);
3145
3235
  const usdTimeoutPromise = new Promise((resolve) => {
3146
3236
  setTimeout(() => resolve(0), 5000); // Default to 0 on timeout
3147
3237
  });
3148
3238
  const usdValue = await Promise.race([usdPromise, usdTimeoutPromise]);
3239
+ if (typeof window !== 'undefined')
3240
+ window.showDebugLog?.(`[getTWCBalance] USD value for ${accountAddress}: ${usdValue}`);
3149
3241
  // Update cache
3150
3242
  this.twcBalanceCache = {
3151
3243
  balance,
@@ -3161,10 +3253,14 @@ class WalletConnector {
3161
3253
  };
3162
3254
  // Keep state in sync
3163
3255
  this.updateState({ twcBalance: result.amount, usdValue: result.usdValue ?? null });
3256
+ if (typeof window !== 'undefined')
3257
+ window.showDebugLog?.(`[getTWCBalance] Final result for ${accountAddress}: ${JSON.stringify(result)}`);
3164
3258
  return result;
3165
3259
  }
3166
3260
  catch (error) {
3167
3261
  const errorMsg = error instanceof Error ? error.message : String(error);
3262
+ if (typeof window !== 'undefined')
3263
+ window.showDebugLog?.(`[getTWCBalance] ERROR: ${errorMsg}`);
3168
3264
  // Track error
3169
3265
  this.balanceFetchErrors.push({
3170
3266
  endpoint: 'wallet-provider',
@@ -7857,12 +7953,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7857
7953
  return;
7858
7954
  }
7859
7955
  try {
7860
- const chainId = await connector.getCurrentChain();
7956
+ let chainId = await connector.getCurrentChain();
7861
7957
  setCurrentChainId(chainId);
7862
7958
  if (chainId !== 56) {
7863
7959
  // Automatically switch to BSC
7864
7960
  try {
7865
7961
  await connector.switchChain(56);
7962
+ // After switching, re-fetch chainId and update state
7963
+ chainId = await connector.getCurrentChain();
7964
+ setCurrentChainId(chainId);
7965
+ // Optionally, trigger TWC balance fetch here if needed
7966
+ if (chainId === 56) {
7967
+ // Force a state update to trigger TWC balance fetch effect
7968
+ setTimeout(() => setCurrentChainId(56), 100); // small delay to ensure state update
7969
+ }
7866
7970
  }
7867
7971
  catch (err) {
7868
7972
  // Optionally handle error (user rejected, etc.)
@@ -8424,13 +8528,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8424
8528
  }
8425
8529
  }, [account]);
8426
8530
  const fetchTWCBalanceWithRetry = useCallback(async (maxRetries = 3, initialDelay = 200) => {
8427
- // Only fetch TWC balance if wallet is on BSC (chainId 56)
8531
+ // Fetch TWC balance for all EVM chains (for debugging)
8428
8532
  try {
8429
8533
  const state = connector.getState();
8430
- if (state.account?.chainType !== 'evm' || state.chainId !== 56) {
8431
- // Not on BSC, do not fetch TWC balance
8534
+ if (state.account?.chainType !== 'evm') {
8535
+ // Not EVM, do not fetch TWC balance
8432
8536
  return null;
8433
8537
  }
8538
+ // Log chainId for debug
8539
+ showDebugLog?.(`[fetchTWCBalanceWithRetry] Fetching TWC for chainId=${state.chainId}`);
8434
8540
  const twcBalance = await connector.getTWCBalance();
8435
8541
  return {
8436
8542
  balance: twcBalance.amount || '0',
@@ -8772,8 +8878,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8772
8878
  }, [connector, account]);
8773
8879
  // Render button based on connection status
8774
8880
  const renderButton = () => {
8775
- // Only show connect button if we are fully initialized and truly disconnected
8776
- if (!isInitializing && (!account || status === ConnectionStatus.DISCONNECTED)) {
8881
+ // Only show connect button if we are fully initialized and truly disconnected (no account and status is DISCONNECTED)
8882
+ if (!isInitializing && (!account && status === ConnectionStatus.DISCONNECTED)) {
8777
8883
  // Wallet icon SVG component
8778
8884
  const WalletIcon = () => (jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { display: 'block' }, children: [jsx("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }), jsx("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })] }));
8779
8885
  return (jsxs("button", { onClick: () => handleOpenModal(), style: {
@@ -8802,16 +8908,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8802
8908
  e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
8803
8909
  }, children: [jsx("span", { style: { color: '#000000', display: 'flex', alignItems: 'center' }, children: jsx(WalletIcon, {}) }), jsx("span", { style: { color: '#000000', fontWeight: '500', fontSize: '14px' }, children: buttonText })] }));
8804
8910
  }
8805
- // ...existing code...
8806
8911
  // All other states (including loading, connecting, connected) should only show the connected button or loading spinner if account is present or initializing is true
8807
8912
  // If initializing, show nothing (or a spinner if desired)
8808
8913
  if (isInitializing) {
8809
8914
  // Optionally, you can show a spinner or skeleton here, but do not show connect/disconnect buttons
8810
8915
  return null;
8811
8916
  }
8812
- // ...existing code...
8813
- // The rest of the renderButton logic (wrong network, connected, etc.) remains unchanged
8814
- if (account) {
8917
+ // Show connected button for any state where account is present and status is not DISCONNECTED or CONNECTING
8918
+ if (account && status !== ConnectionStatus.DISCONNECTED && status !== ConnectionStatus.CONNECTING) {
8815
8919
  // ...existing code...
8816
8920
  // Show normal connected button - styled to match design
8817
8921
  // Parse balance amount and symbol separately
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var ethers = require('ethers');
3
4
  var React = require('react');
4
5
  var jsxRuntime = require('react/jsx-runtime');
5
6
  var ReactDOM = require('react-dom');
@@ -2554,13 +2555,9 @@ class WalletConnector {
2554
2555
  if (account && adapter.chainType === exports.ChainType.TON) {
2555
2556
  try {
2556
2557
  const nftResult = await this.checkNFTOwnership([
2557
- // New collection - user-friendly format
2558
2558
  'EQDVaDCso_2LRTkc8WrT9A4bVO5BG_PZ8313BC_lOO8XW1T8',
2559
- // New collection - raw format
2560
2559
  '0:d56830aca3fd8b45391cf16ad3f40e1b54ee411bf3d9f37d77042fe538ef175b',
2561
- // Legacy collection - user-friendly format
2562
2560
  'EQDKfA87JVnBJXsBVfzjIfbhr3bmTTdouUP31Szgm_Lw0v-J',
2563
- // Legacy collection - raw format
2564
2561
  '0:ca7c0f3b2559c1257b0155fce321f6e1af76e64d3768b943f7d52ce09bf2f0d2'
2565
2562
  ]);
2566
2563
  accountWithNFTs = {
@@ -2571,7 +2568,6 @@ class WalletConnector {
2571
2568
  hasRequiredNFTs: nftResult.hasNFTs,
2572
2569
  ownedCount: nftResult.ownedNFTs.length
2573
2570
  });
2574
- // Update state with NFT count and data
2575
2571
  this.updateState({
2576
2572
  account: accountWithNFTs,
2577
2573
  nftCount: nftResult.ownedNFTs.length,
@@ -2580,36 +2576,40 @@ class WalletConnector {
2580
2576
  }
2581
2577
  catch (nftError) {
2582
2578
  this.debugTools.warn('WALLET_CONNECTOR', 'NFT check failed during account change', nftError);
2583
- // Continue with account change even if NFT check fails
2584
2579
  this.updateState({ account: accountWithNFTs });
2585
2580
  }
2586
2581
  }
2587
2582
  else {
2588
2583
  this.updateState({ account: accountWithNFTs });
2589
2584
  }
2585
+ // Always update chainId in state after account change (for EVM wallets)
2586
+ if (account && adapter.chainType === exports.ChainType.EVM && typeof adapter.getChainId === 'function') {
2587
+ try {
2588
+ const chainId = await adapter.getChainId();
2589
+ this.updateState({ chainId });
2590
+ }
2591
+ catch (e) {
2592
+ this.updateState({ chainId: null });
2593
+ }
2594
+ }
2590
2595
  this.eventEmitter.emit(exports.WalletEvent.ACCOUNT_CHANGED, accountWithNFTs);
2591
2596
  if (account) {
2592
2597
  this.eventEmitter.emit(exports.WalletEvent.CONNECTED, account);
2593
- // Automatically fetch new balance and price when account changes
2594
2598
  try {
2595
2599
  this.debugTools.info('WALLET_CONNECTOR', 'Account changed, fetching new balance and price', {
2596
2600
  account: account.address,
2597
2601
  wallet: walletType
2598
2602
  });
2599
- // Clear price cache for new account
2600
2603
  priceService.clearCache();
2601
- // Fetch TWC balance and price
2602
2604
  if (adapter.chainType === exports.ChainType.EVM) {
2603
2605
  try {
2604
2606
  const twcBalance = await this.getTWCBalance();
2605
- // Persist in state for exportability
2606
2607
  this.updateState({ twcBalance: twcBalance.amount, usdValue: twcBalance.usdValue ?? null });
2607
2608
  this.debugTools.info('WALLET_CONNECTOR', 'TWC balance updated for new account', {
2608
2609
  balance: twcBalance.amount,
2609
2610
  usdValue: twcBalance.usdValue,
2610
2611
  account: account.address
2611
2612
  });
2612
- // Emit balance update event
2613
2613
  this.eventEmitter.emit(exports.WalletEvent.BALANCE_UPDATED, {
2614
2614
  type: 'TWC',
2615
2615
  balance: twcBalance.amount,
@@ -2621,7 +2621,6 @@ class WalletConnector {
2621
2621
  }
2622
2622
  catch (twcError) {
2623
2623
  this.debugTools.warn('WALLET_CONNECTOR', 'Failed to fetch TWC balance for new account', twcError);
2624
- // Fallback to native balance
2625
2624
  try {
2626
2625
  const nativeBalance = await this.getNativeBalance();
2627
2626
  this.debugTools.info('WALLET_CONNECTOR', 'Native balance updated for new account', {
@@ -2629,7 +2628,6 @@ class WalletConnector {
2629
2628
  symbol: nativeBalance.symbol,
2630
2629
  account: account.address
2631
2630
  });
2632
- // Emit balance update event
2633
2631
  this.eventEmitter.emit(exports.WalletEvent.BALANCE_UPDATED, {
2634
2632
  type: 'NATIVE',
2635
2633
  balance: nativeBalance.amount,
@@ -2648,7 +2646,6 @@ class WalletConnector {
2648
2646
  }
2649
2647
  }
2650
2648
  else if (this.state.wallet) {
2651
- // Account removed/disconnected from wallet app
2652
2649
  this.storage.clearWallet();
2653
2650
  this.updateState({ wallet: null, account: null, status: exports.ConnectionStatus.DISCONNECTED, twcBalance: null, usdValue: null, nftCount: 0, nftData: null });
2654
2651
  this.eventEmitter.emit(exports.WalletEvent.DISCONNECTED, undefined);
@@ -2694,13 +2691,9 @@ class WalletConnector {
2694
2691
  if (adapter.chainType === exports.ChainType.TON) {
2695
2692
  try {
2696
2693
  const nftResult = await this.checkNFTOwnership([
2697
- // New collection - user-friendly format
2698
2694
  'EQDVaDCso_2LRTkc8WrT9A4bVO5BG_PZ8313BC_lOO8XW1T8',
2699
- // New collection - raw format
2700
2695
  '0:d56830aca3fd8b45391cf16ad3f40e1b54ee411bf3d9f37d77042fe538ef175b',
2701
- // Legacy collection - user-friendly format
2702
2696
  'EQDKfA87JVnBJXsBVfzjIfbhr3bmTTdouUP31Szgm_Lw0v-J',
2703
- // Legacy collection - raw format
2704
2697
  '0:ca7c0f3b2559c1257b0155fce321f6e1af76e64d3768b943f7d52ce09bf2f0d2'
2705
2698
  ]);
2706
2699
  accountWithNFTs = {
@@ -2714,7 +2707,6 @@ class WalletConnector {
2714
2707
  }
2715
2708
  catch (nftError) {
2716
2709
  this.debugTools.warn('WALLET_CONNECTOR', 'NFT check failed, proceeding without NFT info', nftError);
2717
- // Continue with connection even if NFT check fails
2718
2710
  }
2719
2711
  }
2720
2712
  this.storage.saveWallet(walletType);
@@ -2724,6 +2716,39 @@ class WalletConnector {
2724
2716
  error: null,
2725
2717
  });
2726
2718
  this.eventEmitter.emit(exports.WalletEvent.CONNECTED, accountWithNFTs);
2719
+ // Immediately fetch TWC balance after initial connection (not just on reconnect or refresh)
2720
+ if (adapter.chainType === exports.ChainType.EVM) {
2721
+ try {
2722
+ // Update chainId in state if possible
2723
+ if (typeof adapter.getChainId === 'function') {
2724
+ try {
2725
+ const chainId = await adapter.getChainId();
2726
+ this.updateState({ chainId });
2727
+ }
2728
+ catch (e) {
2729
+ this.updateState({ chainId: null });
2730
+ }
2731
+ }
2732
+ const twcBalance = await this.getTWCBalance();
2733
+ this.updateState({ twcBalance: twcBalance.amount, usdValue: twcBalance.usdValue ?? null });
2734
+ this.debugTools.info('WALLET_CONNECTOR', 'TWC balance updated after initial connect', {
2735
+ balance: twcBalance.amount,
2736
+ usdValue: twcBalance.usdValue,
2737
+ account: accountWithNFTs.address
2738
+ });
2739
+ this.eventEmitter.emit(exports.WalletEvent.BALANCE_UPDATED, {
2740
+ type: 'TWC',
2741
+ balance: twcBalance.amount,
2742
+ symbol: twcBalance.symbol,
2743
+ usdValue: twcBalance.usdValue,
2744
+ usdFormatted: twcBalance.usdFormatted,
2745
+ account: accountWithNFTs.address
2746
+ });
2747
+ }
2748
+ catch (twcError) {
2749
+ this.debugTools.warn('WALLET_CONNECTOR', 'Failed to fetch TWC balance after initial connect', twcError);
2750
+ }
2751
+ }
2727
2752
  }
2728
2753
  else {
2729
2754
  // Connection failed - reset state properly
@@ -3104,14 +3129,21 @@ class WalletConnector {
3104
3129
  }
3105
3130
  async getTWCBalance() {
3106
3131
  if (!this.state.account) {
3132
+ if (typeof window !== 'undefined')
3133
+ window.showDebugLog?.('[getTWCBalance] No wallet connected');
3107
3134
  throw new Error('No wallet connected');
3108
3135
  }
3109
3136
  const accountAddress = this.state.account.address;
3137
+ const chainId = this.state.chainId;
3110
3138
  performance.now();
3139
+ if (typeof window !== 'undefined')
3140
+ window.showDebugLog?.(`[getTWCBalance] Called for account=${accountAddress}, chainId=${chainId}`);
3111
3141
  // Check cache first
3112
3142
  if (this.twcBalanceCache &&
3113
3143
  this.twcBalanceCache.address === accountAddress &&
3114
3144
  Date.now() - this.twcBalanceCache.timestamp < this.TWC_CACHE_TTL) {
3145
+ if (typeof window !== 'undefined')
3146
+ window.showDebugLog?.(`[getTWCBalance] Using cache for ${accountAddress}: ${JSON.stringify(this.twcBalanceCache)}`);
3115
3147
  return {
3116
3148
  amount: this.twcBalanceCache.balance,
3117
3149
  symbol: 'TWC',
@@ -3128,26 +3160,86 @@ class WalletConnector {
3128
3160
  // Use the currently connected wallet's adapter
3129
3161
  const currentWallet = this.state.wallet;
3130
3162
  if (!currentWallet) {
3163
+ if (typeof window !== 'undefined')
3164
+ window.showDebugLog?.('[getTWCBalance] No wallet connected (no currentWallet)');
3131
3165
  throw new Error('No wallet connected');
3132
3166
  }
3133
3167
  const adapter = this.adapters.get(currentWallet);
3134
3168
  if (!adapter || adapter.chainType !== exports.ChainType.EVM) {
3169
+ if (typeof window !== 'undefined')
3170
+ window.showDebugLog?.('[getTWCBalance] No EVM adapter available');
3135
3171
  throw new Error('No EVM adapter available');
3136
3172
  }
3137
- // Call balanceOf directly on the TWC contract using the wallet's provider
3138
- // Skip existence check for known TWC contract (faster)
3139
- // Add 10 second timeout for mobile networks
3140
- const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3141
- const timeoutPromise = new Promise((_, reject) => {
3142
- setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3143
- });
3144
- const balance = await Promise.race([balancePromise, timeoutPromise]);
3173
+ // Debug: log adapter type and available methods
3174
+ if (typeof window !== 'undefined') {
3175
+ window.showDebugLog?.(`[getTWCBalance] Using adapter: ${adapter.constructor?.name || typeof adapter}`);
3176
+ window.showDebugLog?.(`[getTWCBalance] Adapter keys: ${Object.keys(adapter).join(', ')}`);
3177
+ window.showDebugLog?.(`[getTWCBalance] typeof getTokenBalance: ${typeof adapter.getTokenBalance}`);
3178
+ }
3179
+ let balance;
3180
+ // Always use ethers fallback if EVM is connected, regardless of chainId
3181
+ if (this.state.chainId !== 56) {
3182
+ if (typeof window !== 'undefined')
3183
+ window.showDebugLog?.(`[getTWCBalance] Warning: Not on BSC (chainId=${this.state.chainId}), but fetching TWC balance using ethers fallback.`);
3184
+ // Fallback: use ethers.js to fetch balance from chain
3185
+ let provider = adapter.provider || this.getProvider();
3186
+ if (!provider) {
3187
+ if (typeof window !== 'undefined')
3188
+ window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3189
+ throw new Error('No provider available for ethers fallback');
3190
+ }
3191
+ if (!provider._isProvider) {
3192
+ provider = new ethers.ethers.BrowserProvider(provider);
3193
+ }
3194
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3195
+ const contract = new ethers.ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3196
+ const rawBalance = await contract.balanceOf(accountAddress);
3197
+ if (typeof window !== 'undefined')
3198
+ window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3199
+ balance = ethers.ethers.formatUnits(rawBalance, TWC_DECIMALS);
3200
+ if (typeof window !== 'undefined')
3201
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3202
+ }
3203
+ else if (typeof adapter.getTokenBalance === 'function') {
3204
+ // Use adapter method if available and on BSC
3205
+ const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3206
+ const timeoutPromise = new Promise((_, reject) => {
3207
+ setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3208
+ });
3209
+ balance = await Promise.race([balancePromise, timeoutPromise]);
3210
+ if (typeof window !== 'undefined')
3211
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (adapter): ${balance}`);
3212
+ }
3213
+ else {
3214
+ // Fallback: use ethers.js to fetch balance from chain (should not happen, but for safety)
3215
+ if (typeof window !== 'undefined')
3216
+ window.showDebugLog?.('[getTWCBalance] Fallback to ethers.js for TWC balance (on BSC)');
3217
+ let provider = adapter.provider || this.getProvider();
3218
+ if (!provider) {
3219
+ if (typeof window !== 'undefined')
3220
+ window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3221
+ throw new Error('No provider available for ethers fallback');
3222
+ }
3223
+ if (!provider._isProvider) {
3224
+ provider = new ethers.ethers.BrowserProvider(provider);
3225
+ }
3226
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3227
+ const contract = new ethers.ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3228
+ const rawBalance = await contract.balanceOf(accountAddress);
3229
+ if (typeof window !== 'undefined')
3230
+ window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3231
+ balance = ethers.ethers.formatUnits(rawBalance, TWC_DECIMALS);
3232
+ if (typeof window !== 'undefined')
3233
+ window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3234
+ }
3145
3235
  // Calculate USD value with 5 second timeout
3146
3236
  const usdPromise = priceService.calculateTWCValue(balance);
3147
3237
  const usdTimeoutPromise = new Promise((resolve) => {
3148
3238
  setTimeout(() => resolve(0), 5000); // Default to 0 on timeout
3149
3239
  });
3150
3240
  const usdValue = await Promise.race([usdPromise, usdTimeoutPromise]);
3241
+ if (typeof window !== 'undefined')
3242
+ window.showDebugLog?.(`[getTWCBalance] USD value for ${accountAddress}: ${usdValue}`);
3151
3243
  // Update cache
3152
3244
  this.twcBalanceCache = {
3153
3245
  balance,
@@ -3163,10 +3255,14 @@ class WalletConnector {
3163
3255
  };
3164
3256
  // Keep state in sync
3165
3257
  this.updateState({ twcBalance: result.amount, usdValue: result.usdValue ?? null });
3258
+ if (typeof window !== 'undefined')
3259
+ window.showDebugLog?.(`[getTWCBalance] Final result for ${accountAddress}: ${JSON.stringify(result)}`);
3166
3260
  return result;
3167
3261
  }
3168
3262
  catch (error) {
3169
3263
  const errorMsg = error instanceof Error ? error.message : String(error);
3264
+ if (typeof window !== 'undefined')
3265
+ window.showDebugLog?.(`[getTWCBalance] ERROR: ${errorMsg}`);
3170
3266
  // Track error
3171
3267
  this.balanceFetchErrors.push({
3172
3268
  endpoint: 'wallet-provider',
@@ -7859,12 +7955,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7859
7955
  return;
7860
7956
  }
7861
7957
  try {
7862
- const chainId = await connector.getCurrentChain();
7958
+ let chainId = await connector.getCurrentChain();
7863
7959
  setCurrentChainId(chainId);
7864
7960
  if (chainId !== 56) {
7865
7961
  // Automatically switch to BSC
7866
7962
  try {
7867
7963
  await connector.switchChain(56);
7964
+ // After switching, re-fetch chainId and update state
7965
+ chainId = await connector.getCurrentChain();
7966
+ setCurrentChainId(chainId);
7967
+ // Optionally, trigger TWC balance fetch here if needed
7968
+ if (chainId === 56) {
7969
+ // Force a state update to trigger TWC balance fetch effect
7970
+ setTimeout(() => setCurrentChainId(56), 100); // small delay to ensure state update
7971
+ }
7868
7972
  }
7869
7973
  catch (err) {
7870
7974
  // Optionally handle error (user rejected, etc.)
@@ -8426,13 +8530,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8426
8530
  }
8427
8531
  }, [account]);
8428
8532
  const fetchTWCBalanceWithRetry = React.useCallback(async (maxRetries = 3, initialDelay = 200) => {
8429
- // Only fetch TWC balance if wallet is on BSC (chainId 56)
8533
+ // Fetch TWC balance for all EVM chains (for debugging)
8430
8534
  try {
8431
8535
  const state = connector.getState();
8432
- if (state.account?.chainType !== 'evm' || state.chainId !== 56) {
8433
- // Not on BSC, do not fetch TWC balance
8536
+ if (state.account?.chainType !== 'evm') {
8537
+ // Not EVM, do not fetch TWC balance
8434
8538
  return null;
8435
8539
  }
8540
+ // Log chainId for debug
8541
+ showDebugLog?.(`[fetchTWCBalanceWithRetry] Fetching TWC for chainId=${state.chainId}`);
8436
8542
  const twcBalance = await connector.getTWCBalance();
8437
8543
  return {
8438
8544
  balance: twcBalance.amount || '0',
@@ -8774,8 +8880,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8774
8880
  }, [connector, account]);
8775
8881
  // Render button based on connection status
8776
8882
  const renderButton = () => {
8777
- // Only show connect button if we are fully initialized and truly disconnected
8778
- if (!isInitializing && (!account || status === exports.ConnectionStatus.DISCONNECTED)) {
8883
+ // Only show connect button if we are fully initialized and truly disconnected (no account and status is DISCONNECTED)
8884
+ if (!isInitializing && (!account && status === exports.ConnectionStatus.DISCONNECTED)) {
8779
8885
  // Wallet icon SVG component
8780
8886
  const WalletIcon = () => (jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { display: 'block' }, children: [jsxRuntime.jsx("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }), jsxRuntime.jsx("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })] }));
8781
8887
  return (jsxRuntime.jsxs("button", { onClick: () => handleOpenModal(), style: {
@@ -8804,16 +8910,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8804
8910
  e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
8805
8911
  }, children: [jsxRuntime.jsx("span", { style: { color: '#000000', display: 'flex', alignItems: 'center' }, children: jsxRuntime.jsx(WalletIcon, {}) }), jsxRuntime.jsx("span", { style: { color: '#000000', fontWeight: '500', fontSize: '14px' }, children: buttonText })] }));
8806
8912
  }
8807
- // ...existing code...
8808
8913
  // All other states (including loading, connecting, connected) should only show the connected button or loading spinner if account is present or initializing is true
8809
8914
  // If initializing, show nothing (or a spinner if desired)
8810
8915
  if (isInitializing) {
8811
8916
  // Optionally, you can show a spinner or skeleton here, but do not show connect/disconnect buttons
8812
8917
  return null;
8813
8918
  }
8814
- // ...existing code...
8815
- // The rest of the renderButton logic (wrong network, connected, etc.) remains unchanged
8816
- if (account) {
8919
+ // Show connected button for any state where account is present and status is not DISCONNECTED or CONNECTING
8920
+ if (account && status !== exports.ConnectionStatus.DISCONNECTED && status !== exports.ConnectionStatus.CONNECTING) {
8817
8921
  // ...existing code...
8818
8922
  // Show normal connected button - styled to match design
8819
8923
  // Parse balance amount and symbol separately
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiwiflix-wallet-connector",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
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",