tiwiflix-wallet-connector 1.6.8 → 1.6.9

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
@@ -418,8 +418,6 @@ declare class WalletConnector {
418
418
  * Get TWC token balance for EVM wallets
419
419
  * TWC is ONLY available on BSC (chainId 56)
420
420
  */
421
- private twcBalanceCache;
422
- private readonly TWC_CACHE_TTL;
423
421
  private balanceFetchErrors;
424
422
  getTWCBalance(): Promise<{
425
423
  amount: string;
@@ -492,10 +490,6 @@ declare class WalletConnector {
492
490
  * Can optionally filter by collection addresses
493
491
  */
494
492
  private queryAllTONNFTs;
495
- /**
496
- * Query TON API for NFTs owned by an address in a specific collection
497
- */
498
- private queryTONNFTs;
499
493
  }
500
494
 
501
495
  /**
package/dist/index.esm.js CHANGED
@@ -1907,7 +1907,7 @@ const defaultMultiChainConfig = {
1907
1907
  {
1908
1908
  chainId: 56,
1909
1909
  name: 'BNB Smart Chain',
1910
- rpcUrl: 'https://bsc-dataseed.binance.org',
1910
+ rpcUrl: 'https://bsc.publicnode.com',
1911
1911
  blockExplorerUrl: 'https://bscscan.com',
1912
1912
  nativeCurrency: {
1913
1913
  name: 'BNB',
@@ -2312,6 +2312,7 @@ class WalletConnector {
2312
2312
  error: null,
2313
2313
  twcBalance: null,
2314
2314
  usdValue: null,
2315
+ chainId: null,
2315
2316
  };
2316
2317
  // Performance monitoring
2317
2318
  this.performanceMetrics = {
@@ -2325,8 +2326,6 @@ class WalletConnector {
2325
2326
  * TWC is ONLY available on BSC (chainId 56)
2326
2327
  */
2327
2328
  // Cache for TWC balance to avoid redundant fetches
2328
- this.twcBalanceCache = null;
2329
- this.TWC_CACHE_TTL = 30000; // 30 seconds cache
2330
2329
  // Error tracking for balance fetching
2331
2330
  this.balanceFetchErrors = [];
2332
2331
  this.config = config;
@@ -2693,7 +2692,7 @@ class WalletConnector {
2693
2692
  clearTimeout(safetyTimeout);
2694
2693
  clearTimeout(connectionTimeout);
2695
2694
  document.removeEventListener('visibilitychange', handleVisibilityChange);
2696
- error instanceof Error ? error.message : 'Connection failed';
2695
+ // removed unused errorMsg
2697
2696
  this.debugTools.error('WALLET_CONNECTOR', 'Connection error caught', error);
2698
2697
  // Reset state on connection error
2699
2698
  this.updateState({
@@ -2775,7 +2774,7 @@ class WalletConnector {
2775
2774
  }
2776
2775
  else {
2777
2776
  // Connection failed - reset state properly
2778
- result.error?.message || 'Failed to connect';
2777
+ // removed unused errorMsg
2779
2778
  this.debugTools.error('WALLET_CONNECTOR', 'Connection failed', result.error);
2780
2779
  this.updateState({
2781
2780
  status: ConnectionStatus.DISCONNECTED,
@@ -3151,154 +3150,29 @@ class WalletConnector {
3151
3150
  this.sdkLoader.clearCache();
3152
3151
  }
3153
3152
  async getTWCBalance() {
3154
- if (!this.state.account) {
3155
- if (typeof window !== 'undefined')
3156
- window.showDebugLog?.('[getTWCBalance] No wallet connected');
3157
- throw new Error('No wallet connected');
3153
+ if (!this.state.account || this.state.account.chainType !== 'evm') {
3154
+ throw new Error('No EVM account connected');
3158
3155
  }
3159
3156
  const accountAddress = this.state.account.address;
3160
- const chainId = this.state.chainId;
3161
- performance.now();
3162
- if (typeof window !== 'undefined')
3163
- window.showDebugLog?.(`[getTWCBalance] Called for account=${accountAddress}, chainId=${chainId}`);
3164
- // Check cache first
3165
- if (this.twcBalanceCache &&
3166
- this.twcBalanceCache.address === accountAddress &&
3167
- Date.now() - this.twcBalanceCache.timestamp < this.TWC_CACHE_TTL) {
3168
- if (typeof window !== 'undefined')
3169
- window.showDebugLog?.(`[getTWCBalance] Using cache for ${accountAddress}: ${JSON.stringify(this.twcBalanceCache)}`);
3170
- return {
3171
- amount: this.twcBalanceCache.balance,
3172
- symbol: 'TWC',
3173
- usdValue: this.twcBalanceCache.usdValue,
3174
- usdFormatted: priceService.formatUSDValue(this.twcBalanceCache.usdValue)
3175
- };
3176
- }
3177
- // TWC contract on BSC
3178
3157
  const TWC_CONTRACT = '0xDA1060158F7D593667cCE0a15DB346BB3FfB3596';
3179
3158
  const TWC_DECIMALS = 9;
3180
3159
  const TWC_SYMBOL = 'TWC';
3181
- try {
3182
- // Get balance directly from wallet provider via EVM adapter
3183
- // Use the currently connected wallet's adapter
3184
- const currentWallet = this.state.wallet;
3185
- if (!currentWallet) {
3186
- if (typeof window !== 'undefined')
3187
- window.showDebugLog?.('[getTWCBalance] No wallet connected (no currentWallet)');
3188
- throw new Error('No wallet connected');
3189
- }
3190
- const adapter = this.adapters.get(currentWallet);
3191
- if (!adapter || adapter.chainType !== ChainType.EVM) {
3192
- if (typeof window !== 'undefined')
3193
- window.showDebugLog?.('[getTWCBalance] No EVM adapter available');
3194
- throw new Error('No EVM adapter available');
3195
- }
3196
- // Debug: log adapter type and available methods
3197
- if (typeof window !== 'undefined') {
3198
- window.showDebugLog?.(`[getTWCBalance] Using adapter: ${adapter.constructor?.name || typeof adapter}`);
3199
- window.showDebugLog?.(`[getTWCBalance] Adapter keys: ${Object.keys(adapter).join(', ')}`);
3200
- window.showDebugLog?.(`[getTWCBalance] typeof getTokenBalance: ${typeof adapter.getTokenBalance}`);
3201
- }
3202
- let balance;
3203
- // Always use ethers fallback if EVM is connected, regardless of chainId
3204
- if (this.state.chainId !== 56) {
3205
- if (typeof window !== 'undefined')
3206
- window.showDebugLog?.(`[getTWCBalance] Warning: Not on BSC (chainId=${this.state.chainId}), but fetching TWC balance using ethers fallback.`);
3207
- // Fallback: use ethers.js to fetch balance from chain
3208
- let provider = adapter.provider || this.getProvider();
3209
- if (!provider) {
3210
- if (typeof window !== 'undefined')
3211
- window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3212
- throw new Error('No provider available for ethers fallback');
3213
- }
3214
- // Use ethers.BrowserProvider for ethers v6 compatibility
3215
- if (!provider._isProvider) {
3216
- provider = new ethers.BrowserProvider(provider);
3217
- }
3218
- const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3219
- const contract = new ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3220
- const rawBalance = await contract.balanceOf(accountAddress);
3221
- if (typeof window !== 'undefined')
3222
- window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3223
- balance = ethers.formatUnits(rawBalance, TWC_DECIMALS);
3224
- if (typeof window !== 'undefined')
3225
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3226
- }
3227
- else if (typeof adapter.getTokenBalance === 'function') {
3228
- // Use adapter method if available and on BSC
3229
- const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3230
- const timeoutPromise = new Promise((_, reject) => {
3231
- setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3232
- });
3233
- balance = await Promise.race([balancePromise, timeoutPromise]);
3234
- if (typeof window !== 'undefined')
3235
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (adapter): ${balance}`);
3236
- }
3237
- else {
3238
- // Fallback: use ethers.js to fetch balance from chain (should not happen, but for safety)
3239
- if (typeof window !== 'undefined')
3240
- window.showDebugLog?.('[getTWCBalance] Fallback to ethers.js for TWC balance (on BSC)');
3241
- let provider = adapter.provider || this.getProvider();
3242
- if (!provider) {
3243
- if (typeof window !== 'undefined')
3244
- window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3245
- throw new Error('No provider available for ethers fallback');
3246
- }
3247
- if (!provider._isProvider) {
3248
- provider = new ethers.BrowserProvider(provider);
3249
- }
3250
- const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3251
- const contract = new ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3252
- const rawBalance = await contract.balanceOf(accountAddress);
3253
- if (typeof window !== 'undefined')
3254
- window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3255
- balance = ethers.formatUnits(rawBalance, TWC_DECIMALS);
3256
- if (typeof window !== 'undefined')
3257
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3258
- }
3259
- // Calculate USD value with 5 second timeout
3260
- const usdPromise = priceService.calculateTWCValue(balance);
3261
- const usdTimeoutPromise = new Promise((resolve) => {
3262
- setTimeout(() => resolve(0), 5000); // Default to 0 on timeout
3263
- });
3264
- const usdValue = await Promise.race([usdPromise, usdTimeoutPromise]);
3265
- if (typeof window !== 'undefined')
3266
- window.showDebugLog?.(`[getTWCBalance] USD value for ${accountAddress}: ${usdValue}`);
3267
- // Update cache
3268
- this.twcBalanceCache = {
3269
- balance,
3270
- usdValue,
3271
- timestamp: Date.now(),
3272
- address: accountAddress
3273
- };
3274
- const result = {
3275
- amount: balance,
3276
- symbol: TWC_SYMBOL,
3277
- usdValue,
3278
- usdFormatted: priceService.formatUSDValue(usdValue)
3279
- };
3280
- // Keep state in sync
3281
- this.updateState({ twcBalance: result.amount, usdValue: result.usdValue ?? null });
3282
- if (typeof window !== 'undefined')
3283
- window.showDebugLog?.(`[getTWCBalance] Final result for ${accountAddress}: ${JSON.stringify(result)}`);
3284
- return result;
3285
- }
3286
- catch (error) {
3287
- const errorMsg = error instanceof Error ? error.message : String(error);
3288
- if (typeof window !== 'undefined')
3289
- window.showDebugLog?.(`[getTWCBalance] ERROR: ${errorMsg}`);
3290
- // Track error
3291
- this.balanceFetchErrors.push({
3292
- endpoint: 'wallet-provider',
3293
- error: errorMsg,
3294
- timestamp: Date.now()
3295
- });
3296
- // Keep only last 10 errors
3297
- if (this.balanceFetchErrors.length > 10) {
3298
- this.balanceFetchErrors = this.balanceFetchErrors.slice(-10);
3299
- }
3300
- throw error;
3301
- }
3160
+ let provider = this.getProvider();
3161
+ // If provider is missing or not a valid ethers.js provider, use a public BSC provider
3162
+ if (!provider || typeof provider.call !== 'function') {
3163
+ provider = new ethers.JsonRpcProvider('https://bsc.publicnode.com', 56);
3164
+ }
3165
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3166
+ const contract = new ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3167
+ const rawBalance = await contract.balanceOf(accountAddress);
3168
+ const balance = ethers.formatUnits(rawBalance, TWC_DECIMALS);
3169
+ const usdValue = await priceService.calculateTWCValue(balance);
3170
+ return {
3171
+ amount: balance,
3172
+ symbol: TWC_SYMBOL,
3173
+ usdValue,
3174
+ usdFormatted: priceService.formatUSDValue(usdValue)
3175
+ };
3302
3176
  }
3303
3177
  /**
3304
3178
  * Get balance fetch error history (for debugging)
@@ -3560,73 +3434,6 @@ class WalletConnector {
3560
3434
  return [];
3561
3435
  }
3562
3436
  }
3563
- /**
3564
- * Query TON API for NFTs owned by an address in a specific collection
3565
- */
3566
- async queryTONNFTs(ownerAddress, collectionAddress) {
3567
- // TON API endpoints to try
3568
- const endpoints = [
3569
- 'https://tonapi.io/v1',
3570
- 'https://testnet.tonapi.io/v1'
3571
- ];
3572
- for (const baseUrl of endpoints) {
3573
- try {
3574
- // First, get NFT items for the collection
3575
- const collectionResponse = await fetch(`${baseUrl}/nft/getItems?collection=${collectionAddress}&limit=1000`, {
3576
- method: 'GET',
3577
- headers: {
3578
- 'Accept': 'application/json'
3579
- }
3580
- });
3581
- if (!collectionResponse.ok) {
3582
- continue; // Try next endpoint
3583
- }
3584
- const collectionData = await collectionResponse.json();
3585
- const nftItems = collectionData.nft_items || [];
3586
- // Filter NFTs owned by the specified address
3587
- const ownedNFTs = [];
3588
- for (const nft of nftItems) {
3589
- if (nft.owner?.address === ownerAddress) {
3590
- ownedNFTs.push({
3591
- collection: collectionAddress,
3592
- nftAddress: nft.address,
3593
- name: nft.metadata?.name,
3594
- description: nft.metadata?.description
3595
- });
3596
- }
3597
- }
3598
- return ownedNFTs;
3599
- }
3600
- catch (error) {
3601
- this.debugTools.warn('WALLET_CONNECTOR', `TON API call failed for ${baseUrl}`, error);
3602
- continue; // Try next endpoint
3603
- }
3604
- }
3605
- // If all endpoints fail, try a simpler approach using getAccountNftItems
3606
- try {
3607
- const accountResponse = await fetch(`${endpoints[0]}/account/getNftItems?account=${ownerAddress}&collection=${collectionAddress}&limit=100`, {
3608
- method: 'GET',
3609
- headers: {
3610
- 'Accept': 'application/json'
3611
- }
3612
- });
3613
- if (accountResponse.ok) {
3614
- const accountData = await accountResponse.json();
3615
- const nftItems = accountData.nft_items || [];
3616
- return nftItems.map((nft) => ({
3617
- collection: collectionAddress,
3618
- nftAddress: nft.address,
3619
- name: nft.metadata?.name,
3620
- description: nft.metadata?.description
3621
- }));
3622
- }
3623
- }
3624
- catch (error) {
3625
- this.debugTools.warn('WALLET_CONNECTOR', 'Fallback NFT query also failed', error);
3626
- }
3627
- // Return empty array if all queries fail
3628
- return [];
3629
- }
3630
3437
  }
3631
3438
 
3632
3439
  /**
@@ -7677,8 +7484,41 @@ function showDebugLog(msg) {
7677
7484
  const tonApiCache = new Map();
7678
7485
  const CACHE_DURATION = 30000; // 30 seconds
7679
7486
  const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet', getExplorerUrl, }) => {
7487
+ // Move all state hooks that are referenced early to the top to avoid use-before-init errors
7488
+ const [isInitializing, setIsInitializing] = useState(true);
7489
+ const [isConnecting, setIsConnecting] = useState(false);
7490
+ const [balanceLoading, setBalanceLoading] = useState(false);
7680
7491
  // Always fetch balance automatically when wallet is connected
7681
7492
  // Balance is always fetched automatically from the chain
7493
+ // Helper: get the best available TWC balance (cached or real)
7494
+ const getDisplayBalance = () => {
7495
+ // Prefer real fetched balance if available and non-zero
7496
+ if (twcBalance && twcBalance !== '0' && twcBalance !== '0.00')
7497
+ return twcBalance;
7498
+ // Fallback to cached balance if available and non-zero
7499
+ if (account?.address) {
7500
+ const cached = loadTWCBalanceFromCache(account.address);
7501
+ if (cached?.balance && cached.balance !== '0' && cached.balance !== '0.00')
7502
+ return cached.balance;
7503
+ }
7504
+ // If loading, keep showing last known value (even if zero)
7505
+ if (isInitializing || isConnecting) {
7506
+ if (twcBalance)
7507
+ return twcBalance;
7508
+ if (account?.address) {
7509
+ const cached = loadTWCBalanceFromCache(account.address);
7510
+ if (cached?.balance)
7511
+ return cached.balance;
7512
+ }
7513
+ }
7514
+ // Otherwise, show 0
7515
+ return '0';
7516
+ };
7517
+ // ...existing code...
7518
+ // ...existing code...
7519
+ // Helper: show spinner if loading/connecting
7520
+ // Show spinner if initializing, connecting, or balance is loading
7521
+ const showSpinner = Boolean(isInitializing || isConnecting || balanceLoading);
7682
7522
  // Detect dark mode
7683
7523
  const [isDarkMode, setIsDarkMode] = useState(false);
7684
7524
  useEffect(() => {
@@ -7696,7 +7536,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7696
7536
  }, [theme]);
7697
7537
  const [account, setAccount] = useState(null);
7698
7538
  const [status, setStatus] = useState(ConnectionStatus.DISCONNECTED);
7699
- const [isInitializing, setIsInitializing] = useState(true);
7700
7539
  const [showModal, setShowModal] = useState(false);
7701
7540
  // Preload Reown SDK when modal opens for faster connection
7702
7541
  React.useEffect(() => {
@@ -7718,7 +7557,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7718
7557
  const [showActivityModal, setShowActivityModal] = useState(false);
7719
7558
  const [showTWCBalanceModal, setShowTWCBalanceModal] = useState(false);
7720
7559
  const [availableWallets, setAvailableWallets] = useState([]);
7721
- const [isConnecting, setIsConnecting] = useState(false);
7722
7560
  const [error, setError] = useState(null);
7723
7561
  const [nftCount, setNftCount] = useState(0);
7724
7562
  const [nftLoading, setNftLoading] = useState(false);
@@ -7729,7 +7567,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7729
7567
  const [txsLoading, setTxsLoading] = useState(false);
7730
7568
  const [txsError, setTxsError] = useState(null);
7731
7569
  const [balance, setBalance] = useState({ amount: '', symbol: '' });
7732
- const [balanceLoading, setBalanceLoading] = useState(false);
7733
7570
  const [currentChainId, setCurrentChainId] = useState(null);
7734
7571
  const [isWrongNetwork, setIsWrongNetwork] = useState(false);
7735
7572
  // TWC Balance cache key prefix
@@ -8907,8 +8744,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8907
8744
  }, [connector, account]);
8908
8745
  // Render button based on connection status
8909
8746
  const renderButton = () => {
8910
- // Only show connect button if we are fully initialized and truly disconnected (no account and status is DISCONNECTED)
8911
- if (!isInitializing && (!account && status === ConnectionStatus.DISCONNECTED)) {
8747
+ // Always show connect button for first-time visitors or when not connected
8748
+ if (!account && status === ConnectionStatus.DISCONNECTED) {
8912
8749
  // Wallet icon SVG component
8913
8750
  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" })] }));
8914
8751
  return (jsxs("button", { onClick: () => handleOpenModal(), style: {
@@ -9082,34 +8919,75 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
9082
8919
  }
9083
8920
  // Wallet icon SVG component
9084
8921
  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" })] }));
9085
- // Only show connect button if not connected
9086
- if (!account || status !== ConnectionStatus.CONNECTED) {
9087
- return (jsxs("button", { onClick: () => handleOpenModal(), style: {
9088
- display: 'flex',
9089
- alignItems: 'center',
9090
- gap: '10px',
9091
- padding: '12px 12px',
9092
- borderRadius: '12px',
9093
- border: 'none',
9094
- backgroundColor: '#FF9814', // Warm golden-orange
9095
- color: '#000000', // Black text
9096
- fontWeight: '700',
9097
- fontSize: '15px',
9098
- cursor: 'pointer',
9099
- transition: 'all 0.15s ease',
9100
- fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
9101
- boxShadow: '0 2px 8px rgba(255, 152, 20, 0.3)',
9102
- ...style,
9103
- }, className: className, onMouseEnter: (e) => {
9104
- e.currentTarget.style.backgroundColor = '#E8870F';
9105
- e.currentTarget.style.transform = 'translateY(-1px)';
9106
- e.currentTarget.style.boxShadow = '0 4px 12px rgba(255, 152, 20, 0.4)';
9107
- }, onMouseLeave: (e) => {
9108
- e.currentTarget.style.backgroundColor = '#FF9814';
9109
- e.currentTarget.style.transform = 'translateY(0)';
9110
- e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
9111
- }, children: [jsx("span", { style: { color: '#000000', display: 'flex', alignItems: 'center' }, children: jsx(WalletIcon, {}) }), jsx("span", { style: { color: '#000000', fontWeight: '500', fontSize: '14px' }, children: buttonText })] }));
9112
- }
8922
+ // Always show the button, but change content based on connection state
8923
+ const displayBalance = getDisplayBalance();
8924
+ const isConnected = !!account && status === ConnectionStatus.CONNECTED;
8925
+ // Helper for details modal open
8926
+ const handleOpenDetailsModal = () => setShowDetailsModal(true);
8927
+ // Wallet icon for display
8928
+ const walletIcon = account ? getWalletIcon(connector.getState().wallet || '') : jsx("span", { children: "\uD83D\uDCBC" });
8929
+ // Current wallet type
8930
+ const currentWalletType = connector.getState().wallet;
8931
+ return (jsxs(React.Fragment, { children: [jsx("style", { children: `
8932
+ @import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap');
8933
+ .tiwiflix-scrollbar-hide::-webkit-scrollbar {
8934
+ display: none;
8935
+ }
8936
+ .twc-balance-spinner {
8937
+ display: inline-block;
8938
+ width: 16px;
8939
+ height: 16px;
8940
+ border: 2px solid #FF9814;
8941
+ border-top: 2px solid #fff;
8942
+ border-radius: 50%;
8943
+ animation: spin 0.7s linear infinite;
8944
+ margin-left: 6px;
8945
+ vertical-align: middle;
8946
+ }
8947
+ @keyframes spin {
8948
+ 0% { transform: rotate(0deg); }
8949
+ 100% { transform: rotate(360deg); }
8950
+ }
8951
+ ` }), jsxs("button", { onClick: () => (isConnected ? handleOpenDetailsModal() : handleOpenModal()), style: {
8952
+ display: 'flex',
8953
+ alignItems: 'center',
8954
+ gap: '10px',
8955
+ padding: '12px 12px',
8956
+ borderRadius: '12px',
8957
+ border: 'none',
8958
+ backgroundColor: isConnected ? '#0A0A0A' : '#FF9814',
8959
+ color: isConnected ? '#FF9814' : '#000000',
8960
+ fontWeight: '700',
8961
+ fontSize: '15px',
8962
+ cursor: showSpinner ? 'wait' : 'pointer',
8963
+ transition: 'all 0.15s ease',
8964
+ fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
8965
+ boxShadow: isConnected ? '0 2px 8px rgba(10,10,10,0.3)' : '0 2px 8px rgba(255, 152, 20, 0.3)',
8966
+ opacity: showSpinner ? 0.85 : 1,
8967
+ pointerEvents: showSpinner ? 'none' : 'auto',
8968
+ ...style,
8969
+ }, className: className, disabled: showSpinner, onMouseEnter: (e) => {
8970
+ if (!isConnected) {
8971
+ e.currentTarget.style.backgroundColor = '#E8870F';
8972
+ e.currentTarget.style.transform = 'translateY(-1px)';
8973
+ e.currentTarget.style.boxShadow = '0 4px 12px rgba(255, 152, 20, 0.4)';
8974
+ }
8975
+ }, onMouseLeave: (e) => {
8976
+ if (!isConnected) {
8977
+ e.currentTarget.style.backgroundColor = '#FF9814';
8978
+ e.currentTarget.style.transform = 'translateY(0)';
8979
+ e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
8980
+ }
8981
+ }, children: [jsx("span", { style: { color: isConnected ? '#FF9814' : '#000000', display: 'flex', alignItems: 'center' }, children: jsx(WalletIcon, {}) }), jsx("span", { style: { color: isConnected ? '#FF9814' : '#000000', fontWeight: '500', fontSize: '14px' }, children: isConnected ? (jsxs(Fragment, { children: [twcIconMemoized, jsx("span", { style: { marginLeft: 6, fontWeight: 600, fontFamily: 'SF Mono, Monaco, Inconsolata, Roboto Mono, monospace' }, children: displayBalance }), showSpinner && jsx("span", { className: "twc-balance-spinner" })] })) : (jsxs(Fragment, { children: [buttonText, showSpinner && jsx("span", { className: "twc-balance-spinner" })] })) })] }), jsx(AccountDetailsModal, { isOpen: showDetailsModal, onClose: () => setShowDetailsModal(false), account: account, onDisconnect: handleDisconnect, onCopyAddress: handleCopyAddress, onOpenSwap: () => setShowSwapModal(true), onOpenSend: () => setShowSendModal(true), onOpenActivity: () => setShowActivityModal(true), balance: balance, balanceLoading: balanceLoading, twcBalance: twcBalance, usdValue: usdValue, nftCount: nftCount, nftLoading: nftLoading, tonBalance: balance.amount || tonBalance, tonUsdValue: balance.usdValue ?? tonUsdValue, walletIcon: walletIcon, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition,
8982
+ // Add a Switch Wallet button to allow explicit wallet switching
8983
+ onSwitchWallet: () => handleOpenModal(true) }), jsx(ActivityModal, { isOpen: showActivityModal, onClose: () => setShowActivityModal(false), transactions: txs, loading: txsLoading, error: txsError, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition }), jsx(SwapModal, { isOpen: showSwapModal && account?.chainType !== 'ton', onClose: () => setShowSwapModal(false), colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition }), jsx(SendModal, { isOpen: showSendModal, onClose: () => setShowSendModal(false), balance: balance, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition, onSend: async () => {
8984
+ alert('Send functionality coming soon');
8985
+ setShowSendModal(false);
8986
+ } }), jsx(TWCBalanceModal, { isOpen: showTWCBalanceModal, onClose: () => setShowTWCBalanceModal(false), twcBalance: twcBalance, usdValue: usdValue, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition, onBuyTWC: () => {
8987
+ // Handle Buy TWC action
8988
+ }, onLearnMore: () => {
8989
+ // Handle Learn More action
8990
+ } }), jsx(WalletSelectModal, { isOpen: showModal, onClose: () => setShowModal(false), onSelectWallet: handleConnect, availableWallets: availableWallets, currentWalletType: currentWalletType, isConnecting: isConnecting, error: error, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition })] }));
9113
8991
  };
9114
8992
  // Group wallets by chain
9115
8993
  availableWallets.reduce((acc, wallet) => {
package/dist/index.js CHANGED
@@ -1909,7 +1909,7 @@ const defaultMultiChainConfig = {
1909
1909
  {
1910
1910
  chainId: 56,
1911
1911
  name: 'BNB Smart Chain',
1912
- rpcUrl: 'https://bsc-dataseed.binance.org',
1912
+ rpcUrl: 'https://bsc.publicnode.com',
1913
1913
  blockExplorerUrl: 'https://bscscan.com',
1914
1914
  nativeCurrency: {
1915
1915
  name: 'BNB',
@@ -2314,6 +2314,7 @@ class WalletConnector {
2314
2314
  error: null,
2315
2315
  twcBalance: null,
2316
2316
  usdValue: null,
2317
+ chainId: null,
2317
2318
  };
2318
2319
  // Performance monitoring
2319
2320
  this.performanceMetrics = {
@@ -2327,8 +2328,6 @@ class WalletConnector {
2327
2328
  * TWC is ONLY available on BSC (chainId 56)
2328
2329
  */
2329
2330
  // Cache for TWC balance to avoid redundant fetches
2330
- this.twcBalanceCache = null;
2331
- this.TWC_CACHE_TTL = 30000; // 30 seconds cache
2332
2331
  // Error tracking for balance fetching
2333
2332
  this.balanceFetchErrors = [];
2334
2333
  this.config = config;
@@ -2695,7 +2694,7 @@ class WalletConnector {
2695
2694
  clearTimeout(safetyTimeout);
2696
2695
  clearTimeout(connectionTimeout);
2697
2696
  document.removeEventListener('visibilitychange', handleVisibilityChange);
2698
- error instanceof Error ? error.message : 'Connection failed';
2697
+ // removed unused errorMsg
2699
2698
  this.debugTools.error('WALLET_CONNECTOR', 'Connection error caught', error);
2700
2699
  // Reset state on connection error
2701
2700
  this.updateState({
@@ -2777,7 +2776,7 @@ class WalletConnector {
2777
2776
  }
2778
2777
  else {
2779
2778
  // Connection failed - reset state properly
2780
- result.error?.message || 'Failed to connect';
2779
+ // removed unused errorMsg
2781
2780
  this.debugTools.error('WALLET_CONNECTOR', 'Connection failed', result.error);
2782
2781
  this.updateState({
2783
2782
  status: exports.ConnectionStatus.DISCONNECTED,
@@ -3153,154 +3152,29 @@ class WalletConnector {
3153
3152
  this.sdkLoader.clearCache();
3154
3153
  }
3155
3154
  async getTWCBalance() {
3156
- if (!this.state.account) {
3157
- if (typeof window !== 'undefined')
3158
- window.showDebugLog?.('[getTWCBalance] No wallet connected');
3159
- throw new Error('No wallet connected');
3155
+ if (!this.state.account || this.state.account.chainType !== 'evm') {
3156
+ throw new Error('No EVM account connected');
3160
3157
  }
3161
3158
  const accountAddress = this.state.account.address;
3162
- const chainId = this.state.chainId;
3163
- performance.now();
3164
- if (typeof window !== 'undefined')
3165
- window.showDebugLog?.(`[getTWCBalance] Called for account=${accountAddress}, chainId=${chainId}`);
3166
- // Check cache first
3167
- if (this.twcBalanceCache &&
3168
- this.twcBalanceCache.address === accountAddress &&
3169
- Date.now() - this.twcBalanceCache.timestamp < this.TWC_CACHE_TTL) {
3170
- if (typeof window !== 'undefined')
3171
- window.showDebugLog?.(`[getTWCBalance] Using cache for ${accountAddress}: ${JSON.stringify(this.twcBalanceCache)}`);
3172
- return {
3173
- amount: this.twcBalanceCache.balance,
3174
- symbol: 'TWC',
3175
- usdValue: this.twcBalanceCache.usdValue,
3176
- usdFormatted: priceService.formatUSDValue(this.twcBalanceCache.usdValue)
3177
- };
3178
- }
3179
- // TWC contract on BSC
3180
3159
  const TWC_CONTRACT = '0xDA1060158F7D593667cCE0a15DB346BB3FfB3596';
3181
3160
  const TWC_DECIMALS = 9;
3182
3161
  const TWC_SYMBOL = 'TWC';
3183
- try {
3184
- // Get balance directly from wallet provider via EVM adapter
3185
- // Use the currently connected wallet's adapter
3186
- const currentWallet = this.state.wallet;
3187
- if (!currentWallet) {
3188
- if (typeof window !== 'undefined')
3189
- window.showDebugLog?.('[getTWCBalance] No wallet connected (no currentWallet)');
3190
- throw new Error('No wallet connected');
3191
- }
3192
- const adapter = this.adapters.get(currentWallet);
3193
- if (!adapter || adapter.chainType !== exports.ChainType.EVM) {
3194
- if (typeof window !== 'undefined')
3195
- window.showDebugLog?.('[getTWCBalance] No EVM adapter available');
3196
- throw new Error('No EVM adapter available');
3197
- }
3198
- // Debug: log adapter type and available methods
3199
- if (typeof window !== 'undefined') {
3200
- window.showDebugLog?.(`[getTWCBalance] Using adapter: ${adapter.constructor?.name || typeof adapter}`);
3201
- window.showDebugLog?.(`[getTWCBalance] Adapter keys: ${Object.keys(adapter).join(', ')}`);
3202
- window.showDebugLog?.(`[getTWCBalance] typeof getTokenBalance: ${typeof adapter.getTokenBalance}`);
3203
- }
3204
- let balance;
3205
- // Always use ethers fallback if EVM is connected, regardless of chainId
3206
- if (this.state.chainId !== 56) {
3207
- if (typeof window !== 'undefined')
3208
- window.showDebugLog?.(`[getTWCBalance] Warning: Not on BSC (chainId=${this.state.chainId}), but fetching TWC balance using ethers fallback.`);
3209
- // Fallback: use ethers.js to fetch balance from chain
3210
- let provider = adapter.provider || this.getProvider();
3211
- if (!provider) {
3212
- if (typeof window !== 'undefined')
3213
- window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3214
- throw new Error('No provider available for ethers fallback');
3215
- }
3216
- // Use ethers.BrowserProvider for ethers v6 compatibility
3217
- if (!provider._isProvider) {
3218
- provider = new ethers.ethers.BrowserProvider(provider);
3219
- }
3220
- const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3221
- const contract = new ethers.ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3222
- const rawBalance = await contract.balanceOf(accountAddress);
3223
- if (typeof window !== 'undefined')
3224
- window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3225
- balance = ethers.ethers.formatUnits(rawBalance, TWC_DECIMALS);
3226
- if (typeof window !== 'undefined')
3227
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3228
- }
3229
- else if (typeof adapter.getTokenBalance === 'function') {
3230
- // Use adapter method if available and on BSC
3231
- const balancePromise = adapter.getTokenBalance(TWC_CONTRACT, TWC_DECIMALS, true);
3232
- const timeoutPromise = new Promise((_, reject) => {
3233
- setTimeout(() => reject(new Error('Balance fetch timeout after 10 seconds')), 10000);
3234
- });
3235
- balance = await Promise.race([balancePromise, timeoutPromise]);
3236
- if (typeof window !== 'undefined')
3237
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (adapter): ${balance}`);
3238
- }
3239
- else {
3240
- // Fallback: use ethers.js to fetch balance from chain (should not happen, but for safety)
3241
- if (typeof window !== 'undefined')
3242
- window.showDebugLog?.('[getTWCBalance] Fallback to ethers.js for TWC balance (on BSC)');
3243
- let provider = adapter.provider || this.getProvider();
3244
- if (!provider) {
3245
- if (typeof window !== 'undefined')
3246
- window.showDebugLog?.('[getTWCBalance] No provider available for ethers fallback');
3247
- throw new Error('No provider available for ethers fallback');
3248
- }
3249
- if (!provider._isProvider) {
3250
- provider = new ethers.ethers.BrowserProvider(provider);
3251
- }
3252
- const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3253
- const contract = new ethers.ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3254
- const rawBalance = await contract.balanceOf(accountAddress);
3255
- if (typeof window !== 'undefined')
3256
- window.showDebugLog?.(`[getTWCBalance] [ethers fallback] rawBalance (BigInt) for ${accountAddress}: ${rawBalance?.toString?.()}`);
3257
- balance = ethers.ethers.formatUnits(rawBalance, TWC_DECIMALS);
3258
- if (typeof window !== 'undefined')
3259
- window.showDebugLog?.(`[getTWCBalance] Raw balance for ${accountAddress} (ethers): ${balance}`);
3260
- }
3261
- // Calculate USD value with 5 second timeout
3262
- const usdPromise = priceService.calculateTWCValue(balance);
3263
- const usdTimeoutPromise = new Promise((resolve) => {
3264
- setTimeout(() => resolve(0), 5000); // Default to 0 on timeout
3265
- });
3266
- const usdValue = await Promise.race([usdPromise, usdTimeoutPromise]);
3267
- if (typeof window !== 'undefined')
3268
- window.showDebugLog?.(`[getTWCBalance] USD value for ${accountAddress}: ${usdValue}`);
3269
- // Update cache
3270
- this.twcBalanceCache = {
3271
- balance,
3272
- usdValue,
3273
- timestamp: Date.now(),
3274
- address: accountAddress
3275
- };
3276
- const result = {
3277
- amount: balance,
3278
- symbol: TWC_SYMBOL,
3279
- usdValue,
3280
- usdFormatted: priceService.formatUSDValue(usdValue)
3281
- };
3282
- // Keep state in sync
3283
- this.updateState({ twcBalance: result.amount, usdValue: result.usdValue ?? null });
3284
- if (typeof window !== 'undefined')
3285
- window.showDebugLog?.(`[getTWCBalance] Final result for ${accountAddress}: ${JSON.stringify(result)}`);
3286
- return result;
3287
- }
3288
- catch (error) {
3289
- const errorMsg = error instanceof Error ? error.message : String(error);
3290
- if (typeof window !== 'undefined')
3291
- window.showDebugLog?.(`[getTWCBalance] ERROR: ${errorMsg}`);
3292
- // Track error
3293
- this.balanceFetchErrors.push({
3294
- endpoint: 'wallet-provider',
3295
- error: errorMsg,
3296
- timestamp: Date.now()
3297
- });
3298
- // Keep only last 10 errors
3299
- if (this.balanceFetchErrors.length > 10) {
3300
- this.balanceFetchErrors = this.balanceFetchErrors.slice(-10);
3301
- }
3302
- throw error;
3303
- }
3162
+ let provider = this.getProvider();
3163
+ // If provider is missing or not a valid ethers.js provider, use a public BSC provider
3164
+ if (!provider || typeof provider.call !== 'function') {
3165
+ provider = new ethers.ethers.JsonRpcProvider('https://bsc.publicnode.com', 56);
3166
+ }
3167
+ const erc20Abi = ["function balanceOf(address) view returns (uint256)"];
3168
+ const contract = new ethers.ethers.Contract(TWC_CONTRACT, erc20Abi, provider);
3169
+ const rawBalance = await contract.balanceOf(accountAddress);
3170
+ const balance = ethers.ethers.formatUnits(rawBalance, TWC_DECIMALS);
3171
+ const usdValue = await priceService.calculateTWCValue(balance);
3172
+ return {
3173
+ amount: balance,
3174
+ symbol: TWC_SYMBOL,
3175
+ usdValue,
3176
+ usdFormatted: priceService.formatUSDValue(usdValue)
3177
+ };
3304
3178
  }
3305
3179
  /**
3306
3180
  * Get balance fetch error history (for debugging)
@@ -3562,73 +3436,6 @@ class WalletConnector {
3562
3436
  return [];
3563
3437
  }
3564
3438
  }
3565
- /**
3566
- * Query TON API for NFTs owned by an address in a specific collection
3567
- */
3568
- async queryTONNFTs(ownerAddress, collectionAddress) {
3569
- // TON API endpoints to try
3570
- const endpoints = [
3571
- 'https://tonapi.io/v1',
3572
- 'https://testnet.tonapi.io/v1'
3573
- ];
3574
- for (const baseUrl of endpoints) {
3575
- try {
3576
- // First, get NFT items for the collection
3577
- const collectionResponse = await fetch(`${baseUrl}/nft/getItems?collection=${collectionAddress}&limit=1000`, {
3578
- method: 'GET',
3579
- headers: {
3580
- 'Accept': 'application/json'
3581
- }
3582
- });
3583
- if (!collectionResponse.ok) {
3584
- continue; // Try next endpoint
3585
- }
3586
- const collectionData = await collectionResponse.json();
3587
- const nftItems = collectionData.nft_items || [];
3588
- // Filter NFTs owned by the specified address
3589
- const ownedNFTs = [];
3590
- for (const nft of nftItems) {
3591
- if (nft.owner?.address === ownerAddress) {
3592
- ownedNFTs.push({
3593
- collection: collectionAddress,
3594
- nftAddress: nft.address,
3595
- name: nft.metadata?.name,
3596
- description: nft.metadata?.description
3597
- });
3598
- }
3599
- }
3600
- return ownedNFTs;
3601
- }
3602
- catch (error) {
3603
- this.debugTools.warn('WALLET_CONNECTOR', `TON API call failed for ${baseUrl}`, error);
3604
- continue; // Try next endpoint
3605
- }
3606
- }
3607
- // If all endpoints fail, try a simpler approach using getAccountNftItems
3608
- try {
3609
- const accountResponse = await fetch(`${endpoints[0]}/account/getNftItems?account=${ownerAddress}&collection=${collectionAddress}&limit=100`, {
3610
- method: 'GET',
3611
- headers: {
3612
- 'Accept': 'application/json'
3613
- }
3614
- });
3615
- if (accountResponse.ok) {
3616
- const accountData = await accountResponse.json();
3617
- const nftItems = accountData.nft_items || [];
3618
- return nftItems.map((nft) => ({
3619
- collection: collectionAddress,
3620
- nftAddress: nft.address,
3621
- name: nft.metadata?.name,
3622
- description: nft.metadata?.description
3623
- }));
3624
- }
3625
- }
3626
- catch (error) {
3627
- this.debugTools.warn('WALLET_CONNECTOR', 'Fallback NFT query also failed', error);
3628
- }
3629
- // Return empty array if all queries fail
3630
- return [];
3631
- }
3632
3439
  }
3633
3440
 
3634
3441
  /**
@@ -7679,8 +7486,41 @@ function showDebugLog(msg) {
7679
7486
  const tonApiCache = new Map();
7680
7487
  const CACHE_DURATION = 30000; // 30 seconds
7681
7488
  const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet', getExplorerUrl, }) => {
7489
+ // Move all state hooks that are referenced early to the top to avoid use-before-init errors
7490
+ const [isInitializing, setIsInitializing] = React.useState(true);
7491
+ const [isConnecting, setIsConnecting] = React.useState(false);
7492
+ const [balanceLoading, setBalanceLoading] = React.useState(false);
7682
7493
  // Always fetch balance automatically when wallet is connected
7683
7494
  // Balance is always fetched automatically from the chain
7495
+ // Helper: get the best available TWC balance (cached or real)
7496
+ const getDisplayBalance = () => {
7497
+ // Prefer real fetched balance if available and non-zero
7498
+ if (twcBalance && twcBalance !== '0' && twcBalance !== '0.00')
7499
+ return twcBalance;
7500
+ // Fallback to cached balance if available and non-zero
7501
+ if (account?.address) {
7502
+ const cached = loadTWCBalanceFromCache(account.address);
7503
+ if (cached?.balance && cached.balance !== '0' && cached.balance !== '0.00')
7504
+ return cached.balance;
7505
+ }
7506
+ // If loading, keep showing last known value (even if zero)
7507
+ if (isInitializing || isConnecting) {
7508
+ if (twcBalance)
7509
+ return twcBalance;
7510
+ if (account?.address) {
7511
+ const cached = loadTWCBalanceFromCache(account.address);
7512
+ if (cached?.balance)
7513
+ return cached.balance;
7514
+ }
7515
+ }
7516
+ // Otherwise, show 0
7517
+ return '0';
7518
+ };
7519
+ // ...existing code...
7520
+ // ...existing code...
7521
+ // Helper: show spinner if loading/connecting
7522
+ // Show spinner if initializing, connecting, or balance is loading
7523
+ const showSpinner = Boolean(isInitializing || isConnecting || balanceLoading);
7684
7524
  // Detect dark mode
7685
7525
  const [isDarkMode, setIsDarkMode] = React.useState(false);
7686
7526
  React.useEffect(() => {
@@ -7698,7 +7538,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7698
7538
  }, [theme]);
7699
7539
  const [account, setAccount] = React.useState(null);
7700
7540
  const [status, setStatus] = React.useState(exports.ConnectionStatus.DISCONNECTED);
7701
- const [isInitializing, setIsInitializing] = React.useState(true);
7702
7541
  const [showModal, setShowModal] = React.useState(false);
7703
7542
  // Preload Reown SDK when modal opens for faster connection
7704
7543
  React.useEffect(() => {
@@ -7720,7 +7559,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7720
7559
  const [showActivityModal, setShowActivityModal] = React.useState(false);
7721
7560
  const [showTWCBalanceModal, setShowTWCBalanceModal] = React.useState(false);
7722
7561
  const [availableWallets, setAvailableWallets] = React.useState([]);
7723
- const [isConnecting, setIsConnecting] = React.useState(false);
7724
7562
  const [error, setError] = React.useState(null);
7725
7563
  const [nftCount, setNftCount] = React.useState(0);
7726
7564
  const [nftLoading, setNftLoading] = React.useState(false);
@@ -7731,7 +7569,6 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
7731
7569
  const [txsLoading, setTxsLoading] = React.useState(false);
7732
7570
  const [txsError, setTxsError] = React.useState(null);
7733
7571
  const [balance, setBalance] = React.useState({ amount: '', symbol: '' });
7734
- const [balanceLoading, setBalanceLoading] = React.useState(false);
7735
7572
  const [currentChainId, setCurrentChainId] = React.useState(null);
7736
7573
  const [isWrongNetwork, setIsWrongNetwork] = React.useState(false);
7737
7574
  // TWC Balance cache key prefix
@@ -8909,8 +8746,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
8909
8746
  }, [connector, account]);
8910
8747
  // Render button based on connection status
8911
8748
  const renderButton = () => {
8912
- // Only show connect button if we are fully initialized and truly disconnected (no account and status is DISCONNECTED)
8913
- if (!isInitializing && (!account && status === exports.ConnectionStatus.DISCONNECTED)) {
8749
+ // Always show connect button for first-time visitors or when not connected
8750
+ if (!account && status === exports.ConnectionStatus.DISCONNECTED) {
8914
8751
  // Wallet icon SVG component
8915
8752
  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" })] }));
8916
8753
  return (jsxRuntime.jsxs("button", { onClick: () => handleOpenModal(), style: {
@@ -9084,34 +8921,75 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
9084
8921
  }
9085
8922
  // Wallet icon SVG component
9086
8923
  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" })] }));
9087
- // Only show connect button if not connected
9088
- if (!account || status !== exports.ConnectionStatus.CONNECTED) {
9089
- return (jsxRuntime.jsxs("button", { onClick: () => handleOpenModal(), style: {
9090
- display: 'flex',
9091
- alignItems: 'center',
9092
- gap: '10px',
9093
- padding: '12px 12px',
9094
- borderRadius: '12px',
9095
- border: 'none',
9096
- backgroundColor: '#FF9814', // Warm golden-orange
9097
- color: '#000000', // Black text
9098
- fontWeight: '700',
9099
- fontSize: '15px',
9100
- cursor: 'pointer',
9101
- transition: 'all 0.15s ease',
9102
- fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
9103
- boxShadow: '0 2px 8px rgba(255, 152, 20, 0.3)',
9104
- ...style,
9105
- }, className: className, onMouseEnter: (e) => {
9106
- e.currentTarget.style.backgroundColor = '#E8870F';
9107
- e.currentTarget.style.transform = 'translateY(-1px)';
9108
- e.currentTarget.style.boxShadow = '0 4px 12px rgba(255, 152, 20, 0.4)';
9109
- }, onMouseLeave: (e) => {
9110
- e.currentTarget.style.backgroundColor = '#FF9814';
9111
- e.currentTarget.style.transform = 'translateY(0)';
9112
- e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
9113
- }, 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 })] }));
9114
- }
8924
+ // Always show the button, but change content based on connection state
8925
+ const displayBalance = getDisplayBalance();
8926
+ const isConnected = !!account && status === exports.ConnectionStatus.CONNECTED;
8927
+ // Helper for details modal open
8928
+ const handleOpenDetailsModal = () => setShowDetailsModal(true);
8929
+ // Wallet icon for display
8930
+ const walletIcon = account ? getWalletIcon(connector.getState().wallet || '') : jsxRuntime.jsx("span", { children: "\uD83D\uDCBC" });
8931
+ // Current wallet type
8932
+ const currentWalletType = connector.getState().wallet;
8933
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("style", { children: `
8934
+ @import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap');
8935
+ .tiwiflix-scrollbar-hide::-webkit-scrollbar {
8936
+ display: none;
8937
+ }
8938
+ .twc-balance-spinner {
8939
+ display: inline-block;
8940
+ width: 16px;
8941
+ height: 16px;
8942
+ border: 2px solid #FF9814;
8943
+ border-top: 2px solid #fff;
8944
+ border-radius: 50%;
8945
+ animation: spin 0.7s linear infinite;
8946
+ margin-left: 6px;
8947
+ vertical-align: middle;
8948
+ }
8949
+ @keyframes spin {
8950
+ 0% { transform: rotate(0deg); }
8951
+ 100% { transform: rotate(360deg); }
8952
+ }
8953
+ ` }), jsxRuntime.jsxs("button", { onClick: () => (isConnected ? handleOpenDetailsModal() : handleOpenModal()), style: {
8954
+ display: 'flex',
8955
+ alignItems: 'center',
8956
+ gap: '10px',
8957
+ padding: '12px 12px',
8958
+ borderRadius: '12px',
8959
+ border: 'none',
8960
+ backgroundColor: isConnected ? '#0A0A0A' : '#FF9814',
8961
+ color: isConnected ? '#FF9814' : '#000000',
8962
+ fontWeight: '700',
8963
+ fontSize: '15px',
8964
+ cursor: showSpinner ? 'wait' : 'pointer',
8965
+ transition: 'all 0.15s ease',
8966
+ fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
8967
+ boxShadow: isConnected ? '0 2px 8px rgba(10,10,10,0.3)' : '0 2px 8px rgba(255, 152, 20, 0.3)',
8968
+ opacity: showSpinner ? 0.85 : 1,
8969
+ pointerEvents: showSpinner ? 'none' : 'auto',
8970
+ ...style,
8971
+ }, className: className, disabled: showSpinner, onMouseEnter: (e) => {
8972
+ if (!isConnected) {
8973
+ e.currentTarget.style.backgroundColor = '#E8870F';
8974
+ e.currentTarget.style.transform = 'translateY(-1px)';
8975
+ e.currentTarget.style.boxShadow = '0 4px 12px rgba(255, 152, 20, 0.4)';
8976
+ }
8977
+ }, onMouseLeave: (e) => {
8978
+ if (!isConnected) {
8979
+ e.currentTarget.style.backgroundColor = '#FF9814';
8980
+ e.currentTarget.style.transform = 'translateY(0)';
8981
+ e.currentTarget.style.boxShadow = '0 2px 8px rgba(255, 152, 20, 0.3)';
8982
+ }
8983
+ }, children: [jsxRuntime.jsx("span", { style: { color: isConnected ? '#FF9814' : '#000000', display: 'flex', alignItems: 'center' }, children: jsxRuntime.jsx(WalletIcon, {}) }), jsxRuntime.jsx("span", { style: { color: isConnected ? '#FF9814' : '#000000', fontWeight: '500', fontSize: '14px' }, children: isConnected ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [twcIconMemoized, jsxRuntime.jsx("span", { style: { marginLeft: 6, fontWeight: 600, fontFamily: 'SF Mono, Monaco, Inconsolata, Roboto Mono, monospace' }, children: displayBalance }), showSpinner && jsxRuntime.jsx("span", { className: "twc-balance-spinner" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [buttonText, showSpinner && jsxRuntime.jsx("span", { className: "twc-balance-spinner" })] })) })] }), jsxRuntime.jsx(AccountDetailsModal, { isOpen: showDetailsModal, onClose: () => setShowDetailsModal(false), account: account, onDisconnect: handleDisconnect, onCopyAddress: handleCopyAddress, onOpenSwap: () => setShowSwapModal(true), onOpenSend: () => setShowSendModal(true), onOpenActivity: () => setShowActivityModal(true), balance: balance, balanceLoading: balanceLoading, twcBalance: twcBalance, usdValue: usdValue, nftCount: nftCount, nftLoading: nftLoading, tonBalance: balance.amount || tonBalance, tonUsdValue: balance.usdValue ?? tonUsdValue, walletIcon: walletIcon, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition,
8984
+ // Add a Switch Wallet button to allow explicit wallet switching
8985
+ onSwitchWallet: () => handleOpenModal(true) }), jsxRuntime.jsx(ActivityModal, { isOpen: showActivityModal, onClose: () => setShowActivityModal(false), transactions: txs, loading: txsLoading, error: txsError, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition }), jsxRuntime.jsx(SwapModal, { isOpen: showSwapModal && account?.chainType !== 'ton', onClose: () => setShowSwapModal(false), colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition }), jsxRuntime.jsx(SendModal, { isOpen: showSendModal, onClose: () => setShowSendModal(false), balance: balance, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition, onSend: async () => {
8986
+ alert('Send functionality coming soon');
8987
+ setShowSendModal(false);
8988
+ } }), jsxRuntime.jsx(TWCBalanceModal, { isOpen: showTWCBalanceModal, onClose: () => setShowTWCBalanceModal(false), twcBalance: twcBalance, usdValue: usdValue, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition, onBuyTWC: () => {
8989
+ // Handle Buy TWC action
8990
+ }, onLearnMore: () => {
8991
+ // Handle Learn More action
8992
+ } }), jsxRuntime.jsx(WalletSelectModal, { isOpen: showModal, onClose: () => setShowModal(false), onSelectWallet: handleConnect, availableWallets: availableWallets, currentWalletType: currentWalletType, isConnecting: isConnecting, error: error, colors: colors, isDarkMode: isDarkMode, modalPosition: modalPosition })] }));
9115
8993
  };
9116
8994
  // Group wallets by chain
9117
8995
  availableWallets.reduce((acc, wallet) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiwiflix-wallet-connector",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
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",