tiwiflix-wallet-connector 1.5.4 → 1.5.6
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 +140 -23
- package/dist/index.js +140 -23
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -2508,9 +2508,37 @@ class WalletConnector {
|
|
|
2508
2508
|
});
|
|
2509
2509
|
this.eventEmitter.emit(WalletEvent.CONNECTED, account);
|
|
2510
2510
|
}
|
|
2511
|
+
else {
|
|
2512
|
+
// No account found - user likely cancelled or connection failed
|
|
2513
|
+
this.debugTools.info('WALLET_CONNECTOR', 'No account found after visibility change - resetting state');
|
|
2514
|
+
clearTimeout(connectionTimeout);
|
|
2515
|
+
clearTimeout(safetyTimeout);
|
|
2516
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
2517
|
+
this.updateState({
|
|
2518
|
+
status: ConnectionStatus.DISCONNECTED,
|
|
2519
|
+
wallet: null,
|
|
2520
|
+
error: new Error('Connection cancelled or failed'),
|
|
2521
|
+
});
|
|
2522
|
+
this.eventEmitter.emit(WalletEvent.ERROR, new Error('Connection cancelled or failed'));
|
|
2523
|
+
}
|
|
2511
2524
|
}
|
|
2512
2525
|
catch (err) {
|
|
2513
2526
|
this.debugTools.warn('WALLET_CONNECTOR', 'Failed to check account on visibility change', err);
|
|
2527
|
+
// On error checking account, reset state after a longer delay
|
|
2528
|
+
setTimeout(() => {
|
|
2529
|
+
if (this.state.status === ConnectionStatus.CONNECTING) {
|
|
2530
|
+
this.debugTools.info('WALLET_CONNECTOR', 'Still connecting after visibility check error - resetting state');
|
|
2531
|
+
clearTimeout(connectionTimeout);
|
|
2532
|
+
clearTimeout(safetyTimeout);
|
|
2533
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
2534
|
+
this.updateState({
|
|
2535
|
+
status: ConnectionStatus.DISCONNECTED,
|
|
2536
|
+
wallet: null,
|
|
2537
|
+
error: new Error('Connection timeout'),
|
|
2538
|
+
});
|
|
2539
|
+
this.eventEmitter.emit(WalletEvent.ERROR, new Error('Connection timeout'));
|
|
2540
|
+
}
|
|
2541
|
+
}, 3000); // Give it 3 more seconds
|
|
2514
2542
|
}
|
|
2515
2543
|
}
|
|
2516
2544
|
}, 1000);
|
|
@@ -7502,7 +7530,7 @@ const defaultStyles = {
|
|
|
7502
7530
|
fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
7503
7531
|
boxShadow: '0 4px 14px 0 rgba(51, 150, 255, 0.39)',
|
|
7504
7532
|
}};
|
|
7505
|
-
const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
|
|
7533
|
+
const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
|
|
7506
7534
|
// Provide a default fetchBalance if not passed
|
|
7507
7535
|
const fetchBalance = fetchBalanceProp || (async (account) => {
|
|
7508
7536
|
// Default: return zero balance with symbol based on chain
|
|
@@ -7634,12 +7662,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7634
7662
|
});
|
|
7635
7663
|
// Stable USD value updater - only updates if value changes significantly
|
|
7636
7664
|
const setUsdValueStable = useCallback((newValue) => {
|
|
7637
|
-
// Set USD value immediately - only skip if value is the same
|
|
7638
7665
|
setUsdValue((prevValue) => {
|
|
7639
7666
|
// If new value is null/undefined and we have a previous value, keep it
|
|
7640
7667
|
if ((newValue === null || newValue === undefined) && prevValue !== null) {
|
|
7641
7668
|
return prevValue;
|
|
7642
7669
|
}
|
|
7670
|
+
// Only update if value actually changed
|
|
7671
|
+
if (prevValue === newValue) {
|
|
7672
|
+
return prevValue;
|
|
7673
|
+
}
|
|
7643
7674
|
// Otherwise set the new value
|
|
7644
7675
|
return newValue;
|
|
7645
7676
|
});
|
|
@@ -7853,9 +7884,12 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7853
7884
|
const walletsRef = useRef(null);
|
|
7854
7885
|
// Initialize and subscribe to events
|
|
7855
7886
|
useEffect(() => {
|
|
7887
|
+
let isMounted = true;
|
|
7856
7888
|
// Get initial state
|
|
7857
7889
|
const initialState = connector.getState();
|
|
7858
7890
|
setStatus(initialState.status);
|
|
7891
|
+
// Safety: Clear isConnecting on mount (in case it was stuck from previous session)
|
|
7892
|
+
setIsConnecting(false);
|
|
7859
7893
|
// Only set wallets once to prevent re-renders
|
|
7860
7894
|
if (!walletsRef.current) {
|
|
7861
7895
|
walletsRef.current = connector.getAllWallets();
|
|
@@ -7872,6 +7906,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7872
7906
|
setBalanceLoading(false);
|
|
7873
7907
|
}, 2000);
|
|
7874
7908
|
connector.getAccount().then(async (acc) => {
|
|
7909
|
+
if (!isMounted)
|
|
7910
|
+
return;
|
|
7875
7911
|
setAccount(acc);
|
|
7876
7912
|
// Load balance when account is available
|
|
7877
7913
|
if (acc && acc.chainType === 'ton') {
|
|
@@ -7882,10 +7918,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7882
7918
|
fetchTONBalance(acc),
|
|
7883
7919
|
fetchTONNFTs(acc)
|
|
7884
7920
|
]);
|
|
7921
|
+
if (!isMounted)
|
|
7922
|
+
return;
|
|
7885
7923
|
clearTimeout(safetyTimeout);
|
|
7886
7924
|
setIsInitializing(false);
|
|
7887
7925
|
}
|
|
7888
7926
|
catch (err) {
|
|
7927
|
+
if (!isMounted)
|
|
7928
|
+
return;
|
|
7889
7929
|
clearTimeout(safetyTimeout);
|
|
7890
7930
|
setIsInitializing(false);
|
|
7891
7931
|
}
|
|
@@ -7894,6 +7934,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7894
7934
|
try {
|
|
7895
7935
|
setBalanceLoading(true);
|
|
7896
7936
|
const hasRealBalance = await loadBalance();
|
|
7937
|
+
if (!isMounted)
|
|
7938
|
+
return;
|
|
7897
7939
|
// Always stop loading state after balance fetch
|
|
7898
7940
|
setBalanceLoading(false);
|
|
7899
7941
|
clearTimeout(safetyTimeout);
|
|
@@ -7901,6 +7943,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7901
7943
|
setIsInitializing(false);
|
|
7902
7944
|
}
|
|
7903
7945
|
catch (err) {
|
|
7946
|
+
if (!isMounted)
|
|
7947
|
+
return;
|
|
7904
7948
|
setBalanceLoading(false);
|
|
7905
7949
|
clearTimeout(safetyTimeout);
|
|
7906
7950
|
// Always stop initializing on error
|
|
@@ -7912,6 +7956,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7912
7956
|
const state = connector.getState();
|
|
7913
7957
|
const stateTwcBalance = state.twcBalance;
|
|
7914
7958
|
if (acc && stateTwcBalance && stateTwcBalance !== '0' && stateTwcBalance !== '0.00') {
|
|
7959
|
+
if (!isMounted)
|
|
7960
|
+
return;
|
|
7915
7961
|
setTwcBalance(stateTwcBalance);
|
|
7916
7962
|
setUsdValueStable(state.usdValue ?? null);
|
|
7917
7963
|
// Save to cache
|
|
@@ -7925,6 +7971,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7925
7971
|
// Try to load from cache as fallback
|
|
7926
7972
|
const cached = loadTWCBalanceFromCache(acc.address);
|
|
7927
7973
|
if (cached?.balance && cached.balance !== '0' && cached.balance !== '0.00') {
|
|
7974
|
+
if (!isMounted)
|
|
7975
|
+
return;
|
|
7928
7976
|
setTwcBalance(cached.balance);
|
|
7929
7977
|
setUsdValueStable(cached.usdValue);
|
|
7930
7978
|
clearTimeout(safetyTimeout);
|
|
@@ -7934,6 +7982,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7934
7982
|
// No real balance yet, but for EVM wallets, proactively fetch with retries
|
|
7935
7983
|
if (acc.chainType === 'evm') {
|
|
7936
7984
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
7985
|
+
if (!isMounted)
|
|
7986
|
+
return;
|
|
7937
7987
|
if (result) {
|
|
7938
7988
|
setTwcBalance(result.balance);
|
|
7939
7989
|
setUsdValueStable(result.usdValue);
|
|
@@ -7950,6 +8000,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7950
8000
|
setIsInitializing(false);
|
|
7951
8001
|
}
|
|
7952
8002
|
}).catch((error) => {
|
|
8003
|
+
if (!isMounted)
|
|
8004
|
+
return;
|
|
7953
8005
|
// On error - show connected button with 0 balance
|
|
7954
8006
|
setTwcBalance('0');
|
|
7955
8007
|
clearTimeout(safetyTimeout);
|
|
@@ -7965,9 +8017,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7965
8017
|
fetchTONBalance(acc),
|
|
7966
8018
|
fetchTONNFTs(acc)
|
|
7967
8019
|
]).then(() => {
|
|
8020
|
+
if (!isMounted)
|
|
8021
|
+
return;
|
|
7968
8022
|
clearTimeout(safetyTimeout);
|
|
7969
8023
|
setIsInitializing(false);
|
|
7970
8024
|
}).catch((err) => {
|
|
8025
|
+
if (!isMounted)
|
|
8026
|
+
return;
|
|
7971
8027
|
clearTimeout(safetyTimeout);
|
|
7972
8028
|
setIsInitializing(false);
|
|
7973
8029
|
});
|
|
@@ -7975,6 +8031,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7975
8031
|
else if (fetchBalance) {
|
|
7976
8032
|
// For other non-EVM chains: If fetchBalance is provided, load balance and then stop initializing
|
|
7977
8033
|
fetchTWCBalanceWithRetry(1, 100).then((result) => {
|
|
8034
|
+
if (!isMounted)
|
|
8035
|
+
return;
|
|
7978
8036
|
if (result) {
|
|
7979
8037
|
setTwcBalance(result.balance);
|
|
7980
8038
|
setUsdValueStable(result.usdValue);
|
|
@@ -7986,12 +8044,16 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7986
8044
|
clearTimeout(safetyTimeout);
|
|
7987
8045
|
setIsInitializing(false);
|
|
7988
8046
|
}).catch(() => {
|
|
8047
|
+
if (!isMounted)
|
|
8048
|
+
return;
|
|
7989
8049
|
// Stop initializing even on error
|
|
7990
8050
|
clearTimeout(safetyTimeout);
|
|
7991
8051
|
setIsInitializing(false);
|
|
7992
8052
|
});
|
|
7993
8053
|
}
|
|
7994
8054
|
else {
|
|
8055
|
+
if (!isMounted)
|
|
8056
|
+
return;
|
|
7995
8057
|
// No fetchBalance and no cached balance - stop initializing with 0 balance
|
|
7996
8058
|
setTwcBalance('0');
|
|
7997
8059
|
clearTimeout(safetyTimeout);
|
|
@@ -8002,6 +8064,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8002
8064
|
}
|
|
8003
8065
|
}
|
|
8004
8066
|
}).catch((err) => {
|
|
8067
|
+
if (!isMounted)
|
|
8068
|
+
return;
|
|
8005
8069
|
clearTimeout(safetyTimeout);
|
|
8006
8070
|
setIsInitializing(false);
|
|
8007
8071
|
// If we can't get account even though status is connected, disconnect
|
|
@@ -8014,9 +8078,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8014
8078
|
setIsInitializing(true);
|
|
8015
8079
|
// Set a shorter timeout to prevent stuck loading state
|
|
8016
8080
|
initTimeout = setTimeout(() => {
|
|
8081
|
+
if (!isMounted)
|
|
8082
|
+
return;
|
|
8017
8083
|
setIsInitializing(false);
|
|
8018
8084
|
// If still no account after timeout, ensure we show connect button
|
|
8019
8085
|
connector.getAccount().then((acc) => {
|
|
8086
|
+
if (!isMounted)
|
|
8087
|
+
return;
|
|
8020
8088
|
if (!acc) {
|
|
8021
8089
|
setAccount(null);
|
|
8022
8090
|
// If status is disconnected and no account, ensure we're fully disconnected
|
|
@@ -8028,11 +8096,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8028
8096
|
}
|
|
8029
8097
|
}
|
|
8030
8098
|
}).catch((err) => {
|
|
8099
|
+
if (!isMounted)
|
|
8100
|
+
return;
|
|
8031
8101
|
setAccount(null);
|
|
8032
8102
|
setStatus(ConnectionStatus.DISCONNECTED);
|
|
8033
8103
|
});
|
|
8034
8104
|
}, 1500); // Reduced to 1.5 second timeout to prevent stuck loading
|
|
8035
8105
|
connector.getAccount().then((acc) => {
|
|
8106
|
+
if (!isMounted)
|
|
8107
|
+
return;
|
|
8036
8108
|
if (initTimeout)
|
|
8037
8109
|
clearTimeout(initTimeout);
|
|
8038
8110
|
setAccount(acc);
|
|
@@ -8047,6 +8119,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8047
8119
|
}
|
|
8048
8120
|
}
|
|
8049
8121
|
}).catch((err) => {
|
|
8122
|
+
if (!isMounted)
|
|
8123
|
+
return;
|
|
8050
8124
|
if (initTimeout)
|
|
8051
8125
|
clearTimeout(initTimeout);
|
|
8052
8126
|
setIsInitializing(false);
|
|
@@ -8060,7 +8134,11 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8060
8134
|
}
|
|
8061
8135
|
// Subscribe to events
|
|
8062
8136
|
const unsubscribeAccount = connector.on(WalletEvent.ACCOUNT_CHANGED, async (acc) => {
|
|
8137
|
+
if (!isMounted)
|
|
8138
|
+
return;
|
|
8063
8139
|
setAccount(acc);
|
|
8140
|
+
// Clear isConnecting when account changes (connection succeeded)
|
|
8141
|
+
setIsConnecting(false);
|
|
8064
8142
|
// Don't set isInitializing to false yet - wait for balance to load
|
|
8065
8143
|
// Load cached balance for new account immediately
|
|
8066
8144
|
if (acc?.address) {
|
|
@@ -8078,9 +8156,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8078
8156
|
fetchTONBalance(acc),
|
|
8079
8157
|
fetchTONNFTs(acc)
|
|
8080
8158
|
]);
|
|
8159
|
+
if (!isMounted)
|
|
8160
|
+
return;
|
|
8081
8161
|
setIsInitializing(false);
|
|
8082
8162
|
}
|
|
8083
8163
|
catch (err) {
|
|
8164
|
+
if (!isMounted)
|
|
8165
|
+
return;
|
|
8084
8166
|
setIsInitializing(false);
|
|
8085
8167
|
}
|
|
8086
8168
|
}
|
|
@@ -8088,9 +8170,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8088
8170
|
setBalanceLoading(true);
|
|
8089
8171
|
try {
|
|
8090
8172
|
await loadBalance();
|
|
8173
|
+
if (!isMounted)
|
|
8174
|
+
return;
|
|
8091
8175
|
setIsInitializing(false);
|
|
8092
8176
|
}
|
|
8093
8177
|
catch (err) {
|
|
8178
|
+
if (!isMounted)
|
|
8179
|
+
return;
|
|
8094
8180
|
setIsInitializing(false);
|
|
8095
8181
|
setBalanceLoading(false);
|
|
8096
8182
|
}
|
|
@@ -8125,9 +8211,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8125
8211
|
});
|
|
8126
8212
|
const unsubscribeStatus = connector.on(WalletEvent.STATUS_CHANGED, (newStatus) => {
|
|
8127
8213
|
setStatus(newStatus);
|
|
8128
|
-
// If status changes to disconnected, stop initializing
|
|
8214
|
+
// If status changes to disconnected, stop initializing and connecting
|
|
8129
8215
|
if (newStatus === ConnectionStatus.DISCONNECTED) {
|
|
8130
8216
|
setIsInitializing(false);
|
|
8217
|
+
setIsConnecting(false);
|
|
8218
|
+
}
|
|
8219
|
+
// If status changes to connected, clear connecting state
|
|
8220
|
+
if (newStatus === ConnectionStatus.CONNECTED) {
|
|
8221
|
+
setIsConnecting(false);
|
|
8131
8222
|
}
|
|
8132
8223
|
});
|
|
8133
8224
|
const unsubscribeDisconnect = connector.on(WalletEvent.DISCONNECTED, () => {
|
|
@@ -8208,6 +8299,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8208
8299
|
}
|
|
8209
8300
|
});
|
|
8210
8301
|
return () => {
|
|
8302
|
+
isMounted = false;
|
|
8211
8303
|
clearTimeout(initTimeout);
|
|
8212
8304
|
unsubscribeAccount();
|
|
8213
8305
|
unsubscribeStatus();
|
|
@@ -8353,16 +8445,23 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8353
8445
|
}, [connector]);
|
|
8354
8446
|
// Load balance when account changes
|
|
8355
8447
|
useEffect(() => {
|
|
8448
|
+
let isActive = true;
|
|
8356
8449
|
if (account && fetchBalance) {
|
|
8357
8450
|
setBalanceLoading(true);
|
|
8358
8451
|
loadBalance()
|
|
8359
8452
|
.then(() => {
|
|
8453
|
+
if (!isActive)
|
|
8454
|
+
return;
|
|
8360
8455
|
// Always stop initializing once balance request completes
|
|
8361
8456
|
})
|
|
8362
8457
|
.catch(() => {
|
|
8458
|
+
if (!isActive)
|
|
8459
|
+
return;
|
|
8363
8460
|
// Ignore errors, we still clear loading states
|
|
8364
8461
|
})
|
|
8365
8462
|
.finally(() => {
|
|
8463
|
+
if (!isActive)
|
|
8464
|
+
return;
|
|
8366
8465
|
setBalanceLoading(false);
|
|
8367
8466
|
setIsInitializing(false);
|
|
8368
8467
|
});
|
|
@@ -8395,6 +8494,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8395
8494
|
// Only fetch if we don't have a balance yet
|
|
8396
8495
|
if (!hasBalance) {
|
|
8397
8496
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
8497
|
+
if (!isActive)
|
|
8498
|
+
return;
|
|
8398
8499
|
if (result) {
|
|
8399
8500
|
setTwcBalance(result.balance);
|
|
8400
8501
|
setUsdValueStable(result.usdValue);
|
|
@@ -8410,6 +8511,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8410
8511
|
setIsInitializing(false);
|
|
8411
8512
|
}
|
|
8412
8513
|
}).catch(() => {
|
|
8514
|
+
if (!isActive)
|
|
8515
|
+
return;
|
|
8413
8516
|
setIsInitializing(false);
|
|
8414
8517
|
});
|
|
8415
8518
|
}
|
|
@@ -8430,22 +8533,33 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8430
8533
|
}
|
|
8431
8534
|
}
|
|
8432
8535
|
}
|
|
8536
|
+
return () => {
|
|
8537
|
+
isActive = false;
|
|
8538
|
+
};
|
|
8433
8539
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8434
8540
|
}, [account?.address, fetchBalance]);
|
|
8435
8541
|
// Polling mechanism as fallback to ensure TWC balance is always fetched
|
|
8436
8542
|
useEffect(() => {
|
|
8437
|
-
if (!account || account.chainType !== 'evm'
|
|
8543
|
+
if (!account || account.chainType !== 'evm') {
|
|
8438
8544
|
return;
|
|
8439
8545
|
}
|
|
8440
|
-
//
|
|
8441
|
-
const
|
|
8442
|
-
|
|
8546
|
+
// Check if we already have a balance
|
|
8547
|
+
const currentBalance = twcBalance;
|
|
8548
|
+
const hasBalance = currentBalance && currentBalance !== '0' && currentBalance !== '0.00';
|
|
8549
|
+
if (!hasBalance && !isInitializing) {
|
|
8443
8550
|
// Poll every 2 seconds, up to 3 times (6 seconds total) - faster polling
|
|
8444
8551
|
let pollCount = 0;
|
|
8445
8552
|
const maxPolls = 3;
|
|
8553
|
+
let isActive = true;
|
|
8446
8554
|
const pollInterval = setInterval(() => {
|
|
8555
|
+
if (!isActive) {
|
|
8556
|
+
clearInterval(pollInterval);
|
|
8557
|
+
return;
|
|
8558
|
+
}
|
|
8447
8559
|
pollCount++;
|
|
8448
8560
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
8561
|
+
if (!isActive)
|
|
8562
|
+
return;
|
|
8449
8563
|
if (result) {
|
|
8450
8564
|
setTwcBalance(result.balance);
|
|
8451
8565
|
setUsdValueStable(result.usdValue);
|
|
@@ -8458,17 +8572,22 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8458
8572
|
clearInterval(pollInterval);
|
|
8459
8573
|
}
|
|
8460
8574
|
}).catch((error) => {
|
|
8575
|
+
if (!isActive)
|
|
8576
|
+
return;
|
|
8461
8577
|
if (pollCount >= maxPolls) {
|
|
8462
8578
|
clearInterval(pollInterval);
|
|
8463
8579
|
}
|
|
8464
8580
|
});
|
|
8465
8581
|
}, 2000); // Poll every 2 seconds (faster)
|
|
8466
8582
|
return () => {
|
|
8583
|
+
isActive = false;
|
|
8467
8584
|
clearInterval(pollInterval);
|
|
8468
8585
|
};
|
|
8469
8586
|
}
|
|
8587
|
+
return undefined;
|
|
8588
|
+
// Only depend on account address - check balance inside effect
|
|
8470
8589
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8471
|
-
}, [account?.address
|
|
8590
|
+
}, [account?.address]);
|
|
8472
8591
|
// Load transactions when details modal opens
|
|
8473
8592
|
useEffect(() => {
|
|
8474
8593
|
if (showDetailsModal && account) {
|
|
@@ -8478,6 +8597,11 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8478
8597
|
const handleConnect = useCallback(async (walletType) => {
|
|
8479
8598
|
setIsConnecting(true);
|
|
8480
8599
|
setError(null);
|
|
8600
|
+
// Safety timeout: ensure isConnecting is cleared after 75 seconds maximum
|
|
8601
|
+
const safetyTimeout = setTimeout(() => {
|
|
8602
|
+
setIsConnecting(false);
|
|
8603
|
+
setIsInitializing(false);
|
|
8604
|
+
}, 75000);
|
|
8481
8605
|
// Close modal BEFORE connecting for TON wallets and WalletConnect
|
|
8482
8606
|
// so external modals can show
|
|
8483
8607
|
const isTonWallet = ['tonkeeper', 'tonhub', 'mytonwallet'].includes(walletType);
|
|
@@ -8491,27 +8615,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8491
8615
|
setShowSendModal(false);
|
|
8492
8616
|
}
|
|
8493
8617
|
try {
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
setIsInitializing(false);
|
|
8499
|
-
}
|
|
8500
|
-
else {
|
|
8501
|
-
// Fallback: get account after connection
|
|
8502
|
-
const newAccount = await connector.getAccount();
|
|
8503
|
-
if (newAccount) {
|
|
8504
|
-
setAccount(newAccount);
|
|
8505
|
-
setIsInitializing(false);
|
|
8506
|
-
}
|
|
8507
|
-
}
|
|
8618
|
+
// connector.connect() returns void - state updates happen via events
|
|
8619
|
+
await connector.connect(walletType);
|
|
8620
|
+
// Connection succeeded - state is updated via ACCOUNT_CHANGED event
|
|
8621
|
+
// which also clears isConnecting
|
|
8508
8622
|
// Close modal after connection for non-TON/walletconnect wallets
|
|
8509
8623
|
if (!isTonWallet && !isWalletConnect) {
|
|
8510
8624
|
setShowModal(false);
|
|
8511
8625
|
}
|
|
8512
|
-
|
|
8626
|
+
// Clear safety timeout on success
|
|
8627
|
+
clearTimeout(safetyTimeout);
|
|
8513
8628
|
}
|
|
8514
8629
|
catch (err) {
|
|
8630
|
+
// Clear safety timeout on error
|
|
8631
|
+
clearTimeout(safetyTimeout);
|
|
8515
8632
|
// Always clear connection state on error
|
|
8516
8633
|
setAccount(null);
|
|
8517
8634
|
setStatus(ConnectionStatus.DISCONNECTED);
|
package/dist/index.js
CHANGED
|
@@ -2510,9 +2510,37 @@ class WalletConnector {
|
|
|
2510
2510
|
});
|
|
2511
2511
|
this.eventEmitter.emit(exports.WalletEvent.CONNECTED, account);
|
|
2512
2512
|
}
|
|
2513
|
+
else {
|
|
2514
|
+
// No account found - user likely cancelled or connection failed
|
|
2515
|
+
this.debugTools.info('WALLET_CONNECTOR', 'No account found after visibility change - resetting state');
|
|
2516
|
+
clearTimeout(connectionTimeout);
|
|
2517
|
+
clearTimeout(safetyTimeout);
|
|
2518
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
2519
|
+
this.updateState({
|
|
2520
|
+
status: exports.ConnectionStatus.DISCONNECTED,
|
|
2521
|
+
wallet: null,
|
|
2522
|
+
error: new Error('Connection cancelled or failed'),
|
|
2523
|
+
});
|
|
2524
|
+
this.eventEmitter.emit(exports.WalletEvent.ERROR, new Error('Connection cancelled or failed'));
|
|
2525
|
+
}
|
|
2513
2526
|
}
|
|
2514
2527
|
catch (err) {
|
|
2515
2528
|
this.debugTools.warn('WALLET_CONNECTOR', 'Failed to check account on visibility change', err);
|
|
2529
|
+
// On error checking account, reset state after a longer delay
|
|
2530
|
+
setTimeout(() => {
|
|
2531
|
+
if (this.state.status === exports.ConnectionStatus.CONNECTING) {
|
|
2532
|
+
this.debugTools.info('WALLET_CONNECTOR', 'Still connecting after visibility check error - resetting state');
|
|
2533
|
+
clearTimeout(connectionTimeout);
|
|
2534
|
+
clearTimeout(safetyTimeout);
|
|
2535
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
2536
|
+
this.updateState({
|
|
2537
|
+
status: exports.ConnectionStatus.DISCONNECTED,
|
|
2538
|
+
wallet: null,
|
|
2539
|
+
error: new Error('Connection timeout'),
|
|
2540
|
+
});
|
|
2541
|
+
this.eventEmitter.emit(exports.WalletEvent.ERROR, new Error('Connection timeout'));
|
|
2542
|
+
}
|
|
2543
|
+
}, 3000); // Give it 3 more seconds
|
|
2516
2544
|
}
|
|
2517
2545
|
}
|
|
2518
2546
|
}, 1000);
|
|
@@ -7504,7 +7532,7 @@ const defaultStyles = {
|
|
|
7504
7532
|
fontFamily: 'Lexend, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
7505
7533
|
boxShadow: '0 4px 14px 0 rgba(51, 150, 255, 0.39)',
|
|
7506
7534
|
}};
|
|
7507
|
-
const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
|
|
7535
|
+
const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className, style, showBalance = false, modalPosition = 'center', theme = 'auto', buttonText = 'Connect Wallet Now', fetchTransactions, getExplorerUrl, fetchBalance: fetchBalanceProp, }) => {
|
|
7508
7536
|
// Provide a default fetchBalance if not passed
|
|
7509
7537
|
const fetchBalance = fetchBalanceProp || (async (account) => {
|
|
7510
7538
|
// Default: return zero balance with symbol based on chain
|
|
@@ -7636,12 +7664,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7636
7664
|
});
|
|
7637
7665
|
// Stable USD value updater - only updates if value changes significantly
|
|
7638
7666
|
const setUsdValueStable = React.useCallback((newValue) => {
|
|
7639
|
-
// Set USD value immediately - only skip if value is the same
|
|
7640
7667
|
setUsdValue((prevValue) => {
|
|
7641
7668
|
// If new value is null/undefined and we have a previous value, keep it
|
|
7642
7669
|
if ((newValue === null || newValue === undefined) && prevValue !== null) {
|
|
7643
7670
|
return prevValue;
|
|
7644
7671
|
}
|
|
7672
|
+
// Only update if value actually changed
|
|
7673
|
+
if (prevValue === newValue) {
|
|
7674
|
+
return prevValue;
|
|
7675
|
+
}
|
|
7645
7676
|
// Otherwise set the new value
|
|
7646
7677
|
return newValue;
|
|
7647
7678
|
});
|
|
@@ -7855,9 +7886,12 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7855
7886
|
const walletsRef = React.useRef(null);
|
|
7856
7887
|
// Initialize and subscribe to events
|
|
7857
7888
|
React.useEffect(() => {
|
|
7889
|
+
let isMounted = true;
|
|
7858
7890
|
// Get initial state
|
|
7859
7891
|
const initialState = connector.getState();
|
|
7860
7892
|
setStatus(initialState.status);
|
|
7893
|
+
// Safety: Clear isConnecting on mount (in case it was stuck from previous session)
|
|
7894
|
+
setIsConnecting(false);
|
|
7861
7895
|
// Only set wallets once to prevent re-renders
|
|
7862
7896
|
if (!walletsRef.current) {
|
|
7863
7897
|
walletsRef.current = connector.getAllWallets();
|
|
@@ -7874,6 +7908,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7874
7908
|
setBalanceLoading(false);
|
|
7875
7909
|
}, 2000);
|
|
7876
7910
|
connector.getAccount().then(async (acc) => {
|
|
7911
|
+
if (!isMounted)
|
|
7912
|
+
return;
|
|
7877
7913
|
setAccount(acc);
|
|
7878
7914
|
// Load balance when account is available
|
|
7879
7915
|
if (acc && acc.chainType === 'ton') {
|
|
@@ -7884,10 +7920,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7884
7920
|
fetchTONBalance(acc),
|
|
7885
7921
|
fetchTONNFTs(acc)
|
|
7886
7922
|
]);
|
|
7923
|
+
if (!isMounted)
|
|
7924
|
+
return;
|
|
7887
7925
|
clearTimeout(safetyTimeout);
|
|
7888
7926
|
setIsInitializing(false);
|
|
7889
7927
|
}
|
|
7890
7928
|
catch (err) {
|
|
7929
|
+
if (!isMounted)
|
|
7930
|
+
return;
|
|
7891
7931
|
clearTimeout(safetyTimeout);
|
|
7892
7932
|
setIsInitializing(false);
|
|
7893
7933
|
}
|
|
@@ -7896,6 +7936,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7896
7936
|
try {
|
|
7897
7937
|
setBalanceLoading(true);
|
|
7898
7938
|
const hasRealBalance = await loadBalance();
|
|
7939
|
+
if (!isMounted)
|
|
7940
|
+
return;
|
|
7899
7941
|
// Always stop loading state after balance fetch
|
|
7900
7942
|
setBalanceLoading(false);
|
|
7901
7943
|
clearTimeout(safetyTimeout);
|
|
@@ -7903,6 +7945,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7903
7945
|
setIsInitializing(false);
|
|
7904
7946
|
}
|
|
7905
7947
|
catch (err) {
|
|
7948
|
+
if (!isMounted)
|
|
7949
|
+
return;
|
|
7906
7950
|
setBalanceLoading(false);
|
|
7907
7951
|
clearTimeout(safetyTimeout);
|
|
7908
7952
|
// Always stop initializing on error
|
|
@@ -7914,6 +7958,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7914
7958
|
const state = connector.getState();
|
|
7915
7959
|
const stateTwcBalance = state.twcBalance;
|
|
7916
7960
|
if (acc && stateTwcBalance && stateTwcBalance !== '0' && stateTwcBalance !== '0.00') {
|
|
7961
|
+
if (!isMounted)
|
|
7962
|
+
return;
|
|
7917
7963
|
setTwcBalance(stateTwcBalance);
|
|
7918
7964
|
setUsdValueStable(state.usdValue ?? null);
|
|
7919
7965
|
// Save to cache
|
|
@@ -7927,6 +7973,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7927
7973
|
// Try to load from cache as fallback
|
|
7928
7974
|
const cached = loadTWCBalanceFromCache(acc.address);
|
|
7929
7975
|
if (cached?.balance && cached.balance !== '0' && cached.balance !== '0.00') {
|
|
7976
|
+
if (!isMounted)
|
|
7977
|
+
return;
|
|
7930
7978
|
setTwcBalance(cached.balance);
|
|
7931
7979
|
setUsdValueStable(cached.usdValue);
|
|
7932
7980
|
clearTimeout(safetyTimeout);
|
|
@@ -7936,6 +7984,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7936
7984
|
// No real balance yet, but for EVM wallets, proactively fetch with retries
|
|
7937
7985
|
if (acc.chainType === 'evm') {
|
|
7938
7986
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
7987
|
+
if (!isMounted)
|
|
7988
|
+
return;
|
|
7939
7989
|
if (result) {
|
|
7940
7990
|
setTwcBalance(result.balance);
|
|
7941
7991
|
setUsdValueStable(result.usdValue);
|
|
@@ -7952,6 +8002,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7952
8002
|
setIsInitializing(false);
|
|
7953
8003
|
}
|
|
7954
8004
|
}).catch((error) => {
|
|
8005
|
+
if (!isMounted)
|
|
8006
|
+
return;
|
|
7955
8007
|
// On error - show connected button with 0 balance
|
|
7956
8008
|
setTwcBalance('0');
|
|
7957
8009
|
clearTimeout(safetyTimeout);
|
|
@@ -7967,9 +8019,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7967
8019
|
fetchTONBalance(acc),
|
|
7968
8020
|
fetchTONNFTs(acc)
|
|
7969
8021
|
]).then(() => {
|
|
8022
|
+
if (!isMounted)
|
|
8023
|
+
return;
|
|
7970
8024
|
clearTimeout(safetyTimeout);
|
|
7971
8025
|
setIsInitializing(false);
|
|
7972
8026
|
}).catch((err) => {
|
|
8027
|
+
if (!isMounted)
|
|
8028
|
+
return;
|
|
7973
8029
|
clearTimeout(safetyTimeout);
|
|
7974
8030
|
setIsInitializing(false);
|
|
7975
8031
|
});
|
|
@@ -7977,6 +8033,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7977
8033
|
else if (fetchBalance) {
|
|
7978
8034
|
// For other non-EVM chains: If fetchBalance is provided, load balance and then stop initializing
|
|
7979
8035
|
fetchTWCBalanceWithRetry(1, 100).then((result) => {
|
|
8036
|
+
if (!isMounted)
|
|
8037
|
+
return;
|
|
7980
8038
|
if (result) {
|
|
7981
8039
|
setTwcBalance(result.balance);
|
|
7982
8040
|
setUsdValueStable(result.usdValue);
|
|
@@ -7988,12 +8046,16 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
7988
8046
|
clearTimeout(safetyTimeout);
|
|
7989
8047
|
setIsInitializing(false);
|
|
7990
8048
|
}).catch(() => {
|
|
8049
|
+
if (!isMounted)
|
|
8050
|
+
return;
|
|
7991
8051
|
// Stop initializing even on error
|
|
7992
8052
|
clearTimeout(safetyTimeout);
|
|
7993
8053
|
setIsInitializing(false);
|
|
7994
8054
|
});
|
|
7995
8055
|
}
|
|
7996
8056
|
else {
|
|
8057
|
+
if (!isMounted)
|
|
8058
|
+
return;
|
|
7997
8059
|
// No fetchBalance and no cached balance - stop initializing with 0 balance
|
|
7998
8060
|
setTwcBalance('0');
|
|
7999
8061
|
clearTimeout(safetyTimeout);
|
|
@@ -8004,6 +8066,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8004
8066
|
}
|
|
8005
8067
|
}
|
|
8006
8068
|
}).catch((err) => {
|
|
8069
|
+
if (!isMounted)
|
|
8070
|
+
return;
|
|
8007
8071
|
clearTimeout(safetyTimeout);
|
|
8008
8072
|
setIsInitializing(false);
|
|
8009
8073
|
// If we can't get account even though status is connected, disconnect
|
|
@@ -8016,9 +8080,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8016
8080
|
setIsInitializing(true);
|
|
8017
8081
|
// Set a shorter timeout to prevent stuck loading state
|
|
8018
8082
|
initTimeout = setTimeout(() => {
|
|
8083
|
+
if (!isMounted)
|
|
8084
|
+
return;
|
|
8019
8085
|
setIsInitializing(false);
|
|
8020
8086
|
// If still no account after timeout, ensure we show connect button
|
|
8021
8087
|
connector.getAccount().then((acc) => {
|
|
8088
|
+
if (!isMounted)
|
|
8089
|
+
return;
|
|
8022
8090
|
if (!acc) {
|
|
8023
8091
|
setAccount(null);
|
|
8024
8092
|
// If status is disconnected and no account, ensure we're fully disconnected
|
|
@@ -8030,11 +8098,15 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8030
8098
|
}
|
|
8031
8099
|
}
|
|
8032
8100
|
}).catch((err) => {
|
|
8101
|
+
if (!isMounted)
|
|
8102
|
+
return;
|
|
8033
8103
|
setAccount(null);
|
|
8034
8104
|
setStatus(exports.ConnectionStatus.DISCONNECTED);
|
|
8035
8105
|
});
|
|
8036
8106
|
}, 1500); // Reduced to 1.5 second timeout to prevent stuck loading
|
|
8037
8107
|
connector.getAccount().then((acc) => {
|
|
8108
|
+
if (!isMounted)
|
|
8109
|
+
return;
|
|
8038
8110
|
if (initTimeout)
|
|
8039
8111
|
clearTimeout(initTimeout);
|
|
8040
8112
|
setAccount(acc);
|
|
@@ -8049,6 +8121,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8049
8121
|
}
|
|
8050
8122
|
}
|
|
8051
8123
|
}).catch((err) => {
|
|
8124
|
+
if (!isMounted)
|
|
8125
|
+
return;
|
|
8052
8126
|
if (initTimeout)
|
|
8053
8127
|
clearTimeout(initTimeout);
|
|
8054
8128
|
setIsInitializing(false);
|
|
@@ -8062,7 +8136,11 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8062
8136
|
}
|
|
8063
8137
|
// Subscribe to events
|
|
8064
8138
|
const unsubscribeAccount = connector.on(exports.WalletEvent.ACCOUNT_CHANGED, async (acc) => {
|
|
8139
|
+
if (!isMounted)
|
|
8140
|
+
return;
|
|
8065
8141
|
setAccount(acc);
|
|
8142
|
+
// Clear isConnecting when account changes (connection succeeded)
|
|
8143
|
+
setIsConnecting(false);
|
|
8066
8144
|
// Don't set isInitializing to false yet - wait for balance to load
|
|
8067
8145
|
// Load cached balance for new account immediately
|
|
8068
8146
|
if (acc?.address) {
|
|
@@ -8080,9 +8158,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8080
8158
|
fetchTONBalance(acc),
|
|
8081
8159
|
fetchTONNFTs(acc)
|
|
8082
8160
|
]);
|
|
8161
|
+
if (!isMounted)
|
|
8162
|
+
return;
|
|
8083
8163
|
setIsInitializing(false);
|
|
8084
8164
|
}
|
|
8085
8165
|
catch (err) {
|
|
8166
|
+
if (!isMounted)
|
|
8167
|
+
return;
|
|
8086
8168
|
setIsInitializing(false);
|
|
8087
8169
|
}
|
|
8088
8170
|
}
|
|
@@ -8090,9 +8172,13 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8090
8172
|
setBalanceLoading(true);
|
|
8091
8173
|
try {
|
|
8092
8174
|
await loadBalance();
|
|
8175
|
+
if (!isMounted)
|
|
8176
|
+
return;
|
|
8093
8177
|
setIsInitializing(false);
|
|
8094
8178
|
}
|
|
8095
8179
|
catch (err) {
|
|
8180
|
+
if (!isMounted)
|
|
8181
|
+
return;
|
|
8096
8182
|
setIsInitializing(false);
|
|
8097
8183
|
setBalanceLoading(false);
|
|
8098
8184
|
}
|
|
@@ -8127,9 +8213,14 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8127
8213
|
});
|
|
8128
8214
|
const unsubscribeStatus = connector.on(exports.WalletEvent.STATUS_CHANGED, (newStatus) => {
|
|
8129
8215
|
setStatus(newStatus);
|
|
8130
|
-
// If status changes to disconnected, stop initializing
|
|
8216
|
+
// If status changes to disconnected, stop initializing and connecting
|
|
8131
8217
|
if (newStatus === exports.ConnectionStatus.DISCONNECTED) {
|
|
8132
8218
|
setIsInitializing(false);
|
|
8219
|
+
setIsConnecting(false);
|
|
8220
|
+
}
|
|
8221
|
+
// If status changes to connected, clear connecting state
|
|
8222
|
+
if (newStatus === exports.ConnectionStatus.CONNECTED) {
|
|
8223
|
+
setIsConnecting(false);
|
|
8133
8224
|
}
|
|
8134
8225
|
});
|
|
8135
8226
|
const unsubscribeDisconnect = connector.on(exports.WalletEvent.DISCONNECTED, () => {
|
|
@@ -8210,6 +8301,7 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8210
8301
|
}
|
|
8211
8302
|
});
|
|
8212
8303
|
return () => {
|
|
8304
|
+
isMounted = false;
|
|
8213
8305
|
clearTimeout(initTimeout);
|
|
8214
8306
|
unsubscribeAccount();
|
|
8215
8307
|
unsubscribeStatus();
|
|
@@ -8355,16 +8447,23 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8355
8447
|
}, [connector]);
|
|
8356
8448
|
// Load balance when account changes
|
|
8357
8449
|
React.useEffect(() => {
|
|
8450
|
+
let isActive = true;
|
|
8358
8451
|
if (account && fetchBalance) {
|
|
8359
8452
|
setBalanceLoading(true);
|
|
8360
8453
|
loadBalance()
|
|
8361
8454
|
.then(() => {
|
|
8455
|
+
if (!isActive)
|
|
8456
|
+
return;
|
|
8362
8457
|
// Always stop initializing once balance request completes
|
|
8363
8458
|
})
|
|
8364
8459
|
.catch(() => {
|
|
8460
|
+
if (!isActive)
|
|
8461
|
+
return;
|
|
8365
8462
|
// Ignore errors, we still clear loading states
|
|
8366
8463
|
})
|
|
8367
8464
|
.finally(() => {
|
|
8465
|
+
if (!isActive)
|
|
8466
|
+
return;
|
|
8368
8467
|
setBalanceLoading(false);
|
|
8369
8468
|
setIsInitializing(false);
|
|
8370
8469
|
});
|
|
@@ -8397,6 +8496,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8397
8496
|
// Only fetch if we don't have a balance yet
|
|
8398
8497
|
if (!hasBalance) {
|
|
8399
8498
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
8499
|
+
if (!isActive)
|
|
8500
|
+
return;
|
|
8400
8501
|
if (result) {
|
|
8401
8502
|
setTwcBalance(result.balance);
|
|
8402
8503
|
setUsdValueStable(result.usdValue);
|
|
@@ -8412,6 +8513,8 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8412
8513
|
setIsInitializing(false);
|
|
8413
8514
|
}
|
|
8414
8515
|
}).catch(() => {
|
|
8516
|
+
if (!isActive)
|
|
8517
|
+
return;
|
|
8415
8518
|
setIsInitializing(false);
|
|
8416
8519
|
});
|
|
8417
8520
|
}
|
|
@@ -8432,22 +8535,33 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8432
8535
|
}
|
|
8433
8536
|
}
|
|
8434
8537
|
}
|
|
8538
|
+
return () => {
|
|
8539
|
+
isActive = false;
|
|
8540
|
+
};
|
|
8435
8541
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8436
8542
|
}, [account?.address, fetchBalance]);
|
|
8437
8543
|
// Polling mechanism as fallback to ensure TWC balance is always fetched
|
|
8438
8544
|
React.useEffect(() => {
|
|
8439
|
-
if (!account || account.chainType !== 'evm'
|
|
8545
|
+
if (!account || account.chainType !== 'evm') {
|
|
8440
8546
|
return;
|
|
8441
8547
|
}
|
|
8442
|
-
//
|
|
8443
|
-
const
|
|
8444
|
-
|
|
8548
|
+
// Check if we already have a balance
|
|
8549
|
+
const currentBalance = twcBalance;
|
|
8550
|
+
const hasBalance = currentBalance && currentBalance !== '0' && currentBalance !== '0.00';
|
|
8551
|
+
if (!hasBalance && !isInitializing) {
|
|
8445
8552
|
// Poll every 2 seconds, up to 3 times (6 seconds total) - faster polling
|
|
8446
8553
|
let pollCount = 0;
|
|
8447
8554
|
const maxPolls = 3;
|
|
8555
|
+
let isActive = true;
|
|
8448
8556
|
const pollInterval = setInterval(() => {
|
|
8557
|
+
if (!isActive) {
|
|
8558
|
+
clearInterval(pollInterval);
|
|
8559
|
+
return;
|
|
8560
|
+
}
|
|
8449
8561
|
pollCount++;
|
|
8450
8562
|
fetchTWCBalanceWithRetry(2, 200).then((result) => {
|
|
8563
|
+
if (!isActive)
|
|
8564
|
+
return;
|
|
8451
8565
|
if (result) {
|
|
8452
8566
|
setTwcBalance(result.balance);
|
|
8453
8567
|
setUsdValueStable(result.usdValue);
|
|
@@ -8460,17 +8574,22 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8460
8574
|
clearInterval(pollInterval);
|
|
8461
8575
|
}
|
|
8462
8576
|
}).catch((error) => {
|
|
8577
|
+
if (!isActive)
|
|
8578
|
+
return;
|
|
8463
8579
|
if (pollCount >= maxPolls) {
|
|
8464
8580
|
clearInterval(pollInterval);
|
|
8465
8581
|
}
|
|
8466
8582
|
});
|
|
8467
8583
|
}, 2000); // Poll every 2 seconds (faster)
|
|
8468
8584
|
return () => {
|
|
8585
|
+
isActive = false;
|
|
8469
8586
|
clearInterval(pollInterval);
|
|
8470
8587
|
};
|
|
8471
8588
|
}
|
|
8589
|
+
return undefined;
|
|
8590
|
+
// Only depend on account address - check balance inside effect
|
|
8472
8591
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8473
|
-
}, [account?.address
|
|
8592
|
+
}, [account?.address]);
|
|
8474
8593
|
// Load transactions when details modal opens
|
|
8475
8594
|
React.useEffect(() => {
|
|
8476
8595
|
if (showDetailsModal && account) {
|
|
@@ -8480,6 +8599,11 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8480
8599
|
const handleConnect = React.useCallback(async (walletType) => {
|
|
8481
8600
|
setIsConnecting(true);
|
|
8482
8601
|
setError(null);
|
|
8602
|
+
// Safety timeout: ensure isConnecting is cleared after 75 seconds maximum
|
|
8603
|
+
const safetyTimeout = setTimeout(() => {
|
|
8604
|
+
setIsConnecting(false);
|
|
8605
|
+
setIsInitializing(false);
|
|
8606
|
+
}, 75000);
|
|
8483
8607
|
// Close modal BEFORE connecting for TON wallets and WalletConnect
|
|
8484
8608
|
// so external modals can show
|
|
8485
8609
|
const isTonWallet = ['tonkeeper', 'tonhub', 'mytonwallet'].includes(walletType);
|
|
@@ -8493,27 +8617,20 @@ const ConnectButton = ({ connector, onConnect, onDisconnect, onError, className,
|
|
|
8493
8617
|
setShowSendModal(false);
|
|
8494
8618
|
}
|
|
8495
8619
|
try {
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
setIsInitializing(false);
|
|
8501
|
-
}
|
|
8502
|
-
else {
|
|
8503
|
-
// Fallback: get account after connection
|
|
8504
|
-
const newAccount = await connector.getAccount();
|
|
8505
|
-
if (newAccount) {
|
|
8506
|
-
setAccount(newAccount);
|
|
8507
|
-
setIsInitializing(false);
|
|
8508
|
-
}
|
|
8509
|
-
}
|
|
8620
|
+
// connector.connect() returns void - state updates happen via events
|
|
8621
|
+
await connector.connect(walletType);
|
|
8622
|
+
// Connection succeeded - state is updated via ACCOUNT_CHANGED event
|
|
8623
|
+
// which also clears isConnecting
|
|
8510
8624
|
// Close modal after connection for non-TON/walletconnect wallets
|
|
8511
8625
|
if (!isTonWallet && !isWalletConnect) {
|
|
8512
8626
|
setShowModal(false);
|
|
8513
8627
|
}
|
|
8514
|
-
|
|
8628
|
+
// Clear safety timeout on success
|
|
8629
|
+
clearTimeout(safetyTimeout);
|
|
8515
8630
|
}
|
|
8516
8631
|
catch (err) {
|
|
8632
|
+
// Clear safety timeout on error
|
|
8633
|
+
clearTimeout(safetyTimeout);
|
|
8517
8634
|
// Always clear connection state on error
|
|
8518
8635
|
setAccount(null);
|
|
8519
8636
|
setStatus(exports.ConnectionStatus.DISCONNECTED);
|
package/package.json
CHANGED