@@ -254,7 +254,9 @@ export class TokenBalancesController extends StaticIntervalPollingController<Tok
254
254
255
255
this . #allTokens = allTokens ;
256
256
this . #allDetectedTokens = allDetectedTokens ;
257
- this . updateBalances ( { chainIds : chainIdsToUpdate } ) . catch ( console . error ) ;
257
+ this . #handleTokensControllerStateChange( {
258
+ chainIds : chainIdsToUpdate ,
259
+ } ) . catch ( console . error ) ;
258
260
} ;
259
261
260
262
/**
@@ -331,37 +333,71 @@ export class TokenBalancesController extends StaticIntervalPollingController<Tok
331
333
) ;
332
334
}
333
335
334
- #cleanupCurrentTokenBalances(
335
- accountTokenPairs : { accountAddress : Hex ; tokenAddress : Hex } [ ] ,
336
- chainId : Hex ,
337
- ) {
338
- // TODO move this to a private fct
339
- const currentTokenBalances = this . messagingSystem . call (
336
+ async #handleTokensControllerStateChange( {
337
+ chainIds,
338
+ } : { chainIds ?: Hex [ ] } = { } ) {
339
+ const currentTokenBalancesState = this . messagingSystem . call (
340
340
'TokenBalancesController:getState' ,
341
341
) ;
342
+ const currentTokenBalances = currentTokenBalancesState . tokenBalances ;
343
+ const currentAllTokens = this . #allTokens;
344
+
345
+ // first we check if the state change was due to a token being removed
346
+ const accKeys = Object . keys ( currentTokenBalances ) ;
347
+ for ( const currentAccount of accKeys ) {
348
+ const allChains = currentTokenBalances [ currentAccount as `0x${string } `] ;
349
+ const chainsArray = Object . keys ( allChains ) ;
350
+
351
+ for ( const currentChain of chainsArray ) {
352
+ const tokensObject = allChains [ currentChain as Hex ] ;
353
+ const allCurrentTokens = Object . keys ( tokensObject ) ;
354
+ const existingTokensInState =
355
+ currentAllTokens [ currentChain as Hex ] ?. [
356
+ currentAccount as `0x${string } `
357
+ ] || [ ] ;
358
+ const existingSet = new Set (
359
+ existingTokensInState . map ( ( elm ) => elm . address ) ,
360
+ ) ;
361
+
362
+ for ( const singleToken of allCurrentTokens ) {
363
+ if ( ! existingSet . has ( singleToken ) ) {
364
+ console . log (
365
+ `Missing token has been removed: ${ singleToken } under account: ${ currentAccount } , chain: ${ currentChain } ` ,
366
+ ) ;
367
+ this . update ( ( state ) => {
368
+ delete state . tokenBalances [ currentAccount as Hex ] [
369
+ currentChain as Hex
370
+ ] [ singleToken as `0x${string } `] ;
371
+ } ) ;
372
+ }
373
+ }
374
+ }
375
+ }
342
376
343
- // in case currentTokenBalances has a token that is not in accountTokenPairs, we will remove it from currentTokenBalances
344
- // loop through currentTokenBalances.tokenBalances, for each account loop though the account[chainId] array of tokens and check if the token is in accountTokenPairs
345
- // if not, remove it from currentTokenBalances
346
- for ( const accountAddress of Object . keys (
347
- currentTokenBalances . tokenBalances ,
348
- ) ) {
349
- for ( const tokenAddress of Object . keys (
350
- currentTokenBalances . tokenBalances [ accountAddress as `0x${string } `] [
351
- chainId
352
- ] ,
353
- ) ) {
354
- if (
355
- ! accountTokenPairs . some ( ( pair ) => pair . tokenAddress === tokenAddress )
356
- ) {
357
- this . update ( ( state ) => {
358
- delete state . tokenBalances [ accountAddress as Hex ] [ chainId as Hex ] [
359
- tokenAddress as `0x${string } `
360
- ] ;
361
- } ) ;
377
+ // then we check if the state change was due to a token being added
378
+ let shouldUpdate = false ;
379
+ const allTokensStateChains = Object . keys ( currentAllTokens ) ;
380
+ for ( const currentChain of allTokensStateChains ) {
381
+ const accountsPerChain = currentAllTokens [ currentChain as Hex ] ;
382
+ const allAccounts = Object . keys ( accountsPerChain ) ;
383
+
384
+ for ( const currentAccount of allAccounts ) {
385
+ const tokensList = accountsPerChain [ currentAccount as `0x${string } `] ;
386
+ const tokenBalancesObject =
387
+ currentTokenBalances [ currentAccount as `0x${string } `] ?. [
388
+ currentChain as Hex
389
+ ] || { } ;
390
+ for ( const singleToken of tokensList ) {
391
+ if ( ! tokenBalancesObject ?. [ singleToken . address as `0x${string } `] ) {
392
+ shouldUpdate = true ;
393
+ break ;
394
+ }
362
395
}
363
396
}
364
397
}
398
+ if ( shouldUpdate ) {
399
+ await this . updateBalances ( { chainIds } ) . catch ( console . error ) ;
400
+ }
365
401
}
366
402
367
403
/**
@@ -396,8 +432,6 @@ export class TokenBalancesController extends StaticIntervalPollingController<Tok
396
432
397
433
let results : MulticallResult [ ] = [ ] ;
398
434
399
- // in case currentTokenBalances has a token that is not in accountTokenPairs, we will remove it from currentTokenBalances
400
- this . #cleanupCurrentTokenBalances( accountTokenPairs , chainId ) ;
401
435
const currentTokenBalances = this . messagingSystem . call (
402
436
'TokenBalancesController:getState' ,
403
437
) ;
0 commit comments