Skip to content

Commit

Permalink
fix: do not preload & poll for NFT balances by default (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
meeh0w authored Oct 16, 2024
1 parent c41a9ee commit eddb1e1
Show file tree
Hide file tree
Showing 22 changed files with 231 additions and 89 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"sentry": "node sentryscript.js"
},
"dependencies": {
"@avalabs/avalanche-module": "0.8.0",
"@avalabs/avalanche-module": "0.10.0",
"@avalabs/avalanchejs": "4.0.5",
"@avalabs/bitcoin-module": "0.8.0",
"@avalabs/bitcoin-module": "0.10.0",
"@avalabs/bridge-unified": "2.1.0",
"@avalabs/core-bridge-sdk": "3.1.0-alpha.7",
"@avalabs/core-chains-sdk": "3.1.0-alpha.7",
Expand All @@ -37,11 +37,11 @@
"@avalabs/core-token-prices-sdk": "3.1.0-alpha.7",
"@avalabs/core-utils-sdk": "3.1.0-alpha.7",
"@avalabs/core-wallets-sdk": "3.1.0-alpha.7",
"@avalabs/evm-module": "0.8.0",
"@avalabs/evm-module": "0.10.0",
"@avalabs/glacier-sdk": "3.1.0-alpha.7",
"@avalabs/hw-app-avalanche": "0.14.1",
"@avalabs/types": "3.1.0-alpha.3",
"@avalabs/vm-module-types": "0.8.0",
"@avalabs/vm-module-types": "0.10.0",
"@blockaid/client": "0.10.0",
"@coinbase/cbpay-js": "1.6.0",
"@cubist-labs/cubesigner-sdk": "0.3.28",
Expand Down
21 changes: 15 additions & 6 deletions src/background/services/balances/BalanceAggregatorService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,25 @@ describe('src/background/services/balances/BalanceAggregatorService.ts', () => {
});

it('calls BalancesService.getBalancesForNetwork() with proper params', async () => {
await service.getBalancesForNetworks([network1.chainId], [account1]);
await service.getBalancesForNetworks(
[network1.chainId],
[account1],
[TokenType.NATIVE]
);
expect(balancesServiceMock.getBalancesForNetwork).toBeCalledTimes(1);
expect(balancesServiceMock.getBalancesForNetwork).toBeCalledWith(
network1,
[account1],
[TokenType.NATIVE],
undefined
);
});

it('can fetch the balance for multiple networks and one account', async () => {
const balances = await service.getBalancesForNetworks(
[network1.chainId, network2.chainId],
[account1]
[account1],
[TokenType.NATIVE, TokenType.ERC20, TokenType.ERC721]
);
expect(balancesServiceMock.getBalancesForNetwork).toBeCalledTimes(2);
const expected = {
Expand Down Expand Up @@ -245,7 +251,8 @@ describe('src/background/services/balances/BalanceAggregatorService.ts', () => {
it('fetches the balances for multiple networks and accounts', async () => {
const result = await service.getBalancesForNetworks(
[network1.chainId, network2.chainId],
[account1, account2]
[account1, account2],
[TokenType.NATIVE, TokenType.ERC20, TokenType.ERC721]
);

const expected = {
Expand Down Expand Up @@ -286,7 +293,8 @@ describe('src/background/services/balances/BalanceAggregatorService.ts', () => {

const updatePromise = service.getBalancesForNetworks(
[network1.chainId],
[account1]
[account1],
[TokenType.NATIVE, TokenType.ERC20, TokenType.ERC721]
);

// eslint-disable-next-line
Expand All @@ -307,7 +315,8 @@ describe('src/background/services/balances/BalanceAggregatorService.ts', () => {

await service.getBalancesForNetworks(
[network1.chainId, network2.chainId],
[account1]
[account1],
[TokenType.NATIVE, TokenType.ERC20, TokenType.ERC721]
);

expect(balancesServiceMock.getBalancesForNetwork).toBeCalledTimes(2);
Expand Down Expand Up @@ -395,7 +404,7 @@ describe('src/background/services/balances/BalanceAggregatorService.ts', () => {
balances: cachedBalances,
});

await service.getBalancesForNetworks([network2.chainId], [account1]);
await service.getBalancesForNetworks([network2.chainId], [account1], []);

await service.onUnlock();

Expand Down
19 changes: 13 additions & 6 deletions src/background/services/balances/BalanceAggregatorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { resolve } from '@avalabs/core-utils-sdk';
import { SettingsService } from '../settings/SettingsService';
import { isFulfilled } from '@src/utils/typeUtils';
import { NftTokenWithBalance } from '@avalabs/vm-module-types';
import { NftTokenWithBalance, TokenType } from '@avalabs/vm-module-types';
import { groupTokensByType } from './utils/groupTokensByType';
import { BalancesInfo } from './events/balancesUpdatedEvent';

Expand Down Expand Up @@ -54,7 +54,8 @@ export class BalanceAggregatorService implements OnLock, OnUnlock {

async getBalancesForNetworks(
chainIds: number[],
accounts: Account[]
accounts: Account[],
tokenTypes: TokenType[]
): Promise<{ tokens: Balances; nfts: Balances<NftTokenWithBalance> }> {
const sentryTracker = Sentry.startTransaction({
name: 'BalanceAggregatorService: getBatchedUpdatedBalancesForNetworks',
Expand All @@ -72,6 +73,7 @@ export class BalanceAggregatorService implements OnLock, OnUnlock {
await this.balancesService.getBalancesForNetwork(
network,
accounts,
tokenTypes,
priceChangesData
);

Expand Down Expand Up @@ -112,10 +114,15 @@ export class BalanceAggregatorService implements OnLock, OnUnlock {
const aggregatedBalances = merge({}, this.balances, freshBalances.tokens);
// NFTs don't have balance = 0, if they are sent they should be removed
// from the list, hence deep merge doesn't work
const aggregatedNfts = {
...this.nfts,
...freshBalances.nfts,
};
const hasFetchedNfts =
tokenTypes.includes(TokenType.ERC721) ||
tokenTypes.includes(TokenType.ERC1155);
const aggregatedNfts = hasFetchedNfts
? {
...this.nfts,
...freshBalances.nfts,
}
: this.nfts;
const hasChanges = networksWithChanges.length > 0;

if (hasChanges && !this.lockService.locked) {
Expand Down
11 changes: 9 additions & 2 deletions src/background/services/balances/BalancePollingService.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TokenType } from '@avalabs/vm-module-types';
import { BalanceAggregatorService } from './BalanceAggregatorService';
import { BalancePollingService } from './BalancePollingService';

Expand All @@ -18,6 +19,7 @@ describe('src/background/services/balances/BalancePollingService.ts', () => {
const account = {} as any;
const activeNetworkId = 1;
const roundRobinChainIds = [2, 3, 4];
const tokenTypes = [TokenType.NATIVE, TokenType.ERC20];

const getFetchedNetworksForCall = (mock, callIndex) => {
return mock.calls[callIndex][0];
Expand All @@ -37,13 +39,18 @@ describe('src/background/services/balances/BalancePollingService.ts', () => {
describe('when polling is active', () => {
beforeEach(async () => {
const service = new BalancePollingService(aggregatorServiceMock);
await service.startPolling(account, activeNetworkId, roundRobinChainIds);
await service.startPolling(
account,
activeNetworkId,
roundRobinChainIds,
tokenTypes
);
});

it('polls for active and favorite networks on the first run', () => {
expect(
aggregatorServiceMock.getBalancesForNetworks
).toHaveBeenLastCalledWith([1, 2, 3, 4], expect.anything());
).toHaveBeenLastCalledWith([1, 2, 3, 4], expect.anything(), tokenTypes);
});

it('polls for active network on every run', () => {
Expand Down
38 changes: 31 additions & 7 deletions src/background/services/balances/BalancePollingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import { singleton } from 'tsyringe';
import { Account } from '../accounts/models';
import { BalanceAggregatorService } from './BalanceAggregatorService';
import { TokenType } from '@avalabs/vm-module-types';

@singleton()
export class BalancePollingService implements OnLock, OnAllExtensionClosed {
Expand All @@ -28,13 +29,19 @@ export class BalancePollingService implements OnLock, OnAllExtensionClosed {
async startPolling(
account: Account,
activeChainId: number,
roundRobinChainIds: number[]
roundRobinChainIds: number[],
tokenTypes: TokenType[]
) {
// Stop any polling that may be occurring already
this.stopPolling();
// Start a new interval
// this._preventSchedulingNextUpdate = false;
return this.pollBalances(account, activeChainId, roundRobinChainIds);
return this.pollBalances(
account,
activeChainId,
roundRobinChainIds,
tokenTypes
);
}

onAllExtensionsClosed() {
Expand All @@ -52,7 +59,8 @@ export class BalancePollingService implements OnLock, OnAllExtensionClosed {
private async pollBalances(
account: Account,
activeChainId: number,
roundRobinChainIds: number[]
roundRobinChainIds: number[],
tokenTypes: TokenType[]
) {
const thisPollingStartedAt = performance.now();
this.#lastPollingStartedAt = thisPollingStartedAt;
Expand All @@ -67,26 +75,42 @@ export class BalancePollingService implements OnLock, OnAllExtensionClosed {
]);

try {
await this.balanceAggregator.getBalancesForNetworks(chainIds, [account]);
await this.balanceAggregator.getBalancesForNetworks(
chainIds,
[account],
tokenTypes
);
} catch {
// Do nothing, just schedule another attempt
}

// Only schedule the next update if another polling was not started
// while we were waiting for balance results.
if (thisPollingStartedAt === this.#lastPollingStartedAt) {
this.scheduleNextUpdate(account, activeChainId, roundRobinChainIds);
this.scheduleNextUpdate(
account,
activeChainId,
roundRobinChainIds,
tokenTypes
);
}
}

private scheduleNextUpdate(
account: Account,
activeChainId: number,
roundRobinChainIds: number[]
roundRobinChainIds: number[],
tokenTypes: TokenType[]
) {
this.#pollingIteration += 1;
this.#timer = setTimeout(
() => this.pollBalances(account, activeChainId, roundRobinChainIds),
() =>
this.pollBalances(
account,
activeChainId,
roundRobinChainIds,
tokenTypes
),
BalancePollingService.INTERVAL
);
}
Expand Down
48 changes: 39 additions & 9 deletions src/background/services/balances/BalancesService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ModuleManager } from '@src/background/vmModules/ModuleManager';
import { NetworkVMType } from '@avalabs/core-chains-sdk';
import * as Sentry from '@sentry/browser';
import { SettingsService } from '../settings/SettingsService';
import LRUCache from 'lru-cache';

jest.mock('@src/background/vmModules/ModuleManager');
jest.mock('@sentry/browser', () => {
Expand Down Expand Up @@ -205,9 +206,11 @@ describe('src/background/services/balances/BalancesService.ts', () => {
it('should get balances for P-Chain', async () => {
moduleMock.getBalances.mockResolvedValue(pvmResult);
const network = { vmName: NetworkVMType.PVM, caipId: 'pvm' };
const result = await service.getBalancesForNetwork(network as any, [
account,
]);
const result = await service.getBalancesForNetwork(
network as any,
[account],
[]
);

expect(result).toEqual({
['networkId2']: {
Expand All @@ -226,13 +229,19 @@ describe('src/background/services/balances/BalancesService.ts', () => {
currency: 'eur',
network,
customTokens: [],
tokenTypes: [],
storage: expect.any(LRUCache),
});
});

it('should get balances for X-Chain', async () => {
moduleMock.getBalances.mockResolvedValue(avmResult);
const network = { vmName: NetworkVMType.AVM, caipId: 'avm' } as any;
const result = await service.getBalancesForNetwork(network, [account]);
const result = await service.getBalancesForNetwork(
network,
[account],
[]
);

expect(result).toEqual({
['networkId2']: {
Expand All @@ -251,6 +260,8 @@ describe('src/background/services/balances/BalancesService.ts', () => {
currency: 'eur',
network,
customTokens: [],
tokenTypes: [],
storage: expect.any(LRUCache),
});
});

Expand Down Expand Up @@ -279,7 +290,11 @@ describe('src/background/services/balances/BalancesService.ts', () => {
caipId: 'eip155:1337',
chainId: 1337,
} as any;
const result = await service.getBalancesForNetwork(network, [account]);
const result = await service.getBalancesForNetwork(
network,
[account],
[TokenType.NATIVE, TokenType.ERC20]
);

expect(result).toEqual({
['networkId2']: {
Expand All @@ -299,13 +314,19 @@ describe('src/background/services/balances/BalancesService.ts', () => {
currency: 'usd',
network,
customTokens: [{ ...customToken, type: TokenType.ERC20 }],
tokenTypes: [TokenType.NATIVE, TokenType.ERC20],
storage: expect.any(LRUCache),
});
});

it('should get balances for Bitcoin', async () => {
moduleMock.getBalances.mockResolvedValue(btcResult);
const network = { vmName: NetworkVMType.BITCOIN, caipId: 'btc' } as any;
const result = await service.getBalancesForNetwork(network, [account]);
const result = await service.getBalancesForNetwork(
network,
[account],
[]
);

expect(result).toEqual({
['networkId3']: {
Expand All @@ -325,15 +346,22 @@ describe('src/background/services/balances/BalancesService.ts', () => {
currency: 'eur',
network,
customTokens: [],
tokenTypes: [],
storage: expect.any(LRUCache),
});
});

it('should calculate price changes if provided', async () => {
moduleMock.getBalances.mockResolvedValue(evmResult);
const network = { vmName: NetworkVMType.EVM, caipId: 'evm' } as any;
const result = await service.getBalancesForNetwork(network, [account], {
test2: { priceChangePercentage: 25 },
});
const result = await service.getBalancesForNetwork(
network,
[account],
[],
{
test2: { priceChangePercentage: 25 },
}
);

expect(result).toEqual({
['networkId2']: {
Expand All @@ -353,6 +381,8 @@ describe('src/background/services/balances/BalancesService.ts', () => {
currency: 'eur',
network,
customTokens: [],
tokenTypes: [],
storage: expect.any(LRUCache),
});
});
});
Expand Down
Loading

0 comments on commit eddb1e1

Please sign in to comment.