Skip to content

Commit

Permalink
WIP: migrate from @ethereumjs/utils BN to native BigInt
Browse files Browse the repository at this point in the history
  • Loading branch information
legobeat committed Oct 13, 2023
1 parent 038068a commit 367b972
Show file tree
Hide file tree
Showing 26 changed files with 231 additions and 261 deletions.
8 changes: 2 additions & 6 deletions packages/assets-controllers/src/AccountTrackerController.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import type { BaseConfig, BaseState } from '@metamask/base-controller';
import { BaseController } from '@metamask/base-controller';
import {
BNToHex,
query,
safelyExecuteWithTimeout,
} from '@metamask/controller-utils';
import { query, safelyExecuteWithTimeout } from '@metamask/controller-utils';
import EthQuery from '@metamask/eth-query';
import type { Provider } from '@metamask/eth-query';
import type { PreferencesState } from '@metamask/preferences-controller';
Expand Down Expand Up @@ -176,7 +172,7 @@ export class AccountTrackerController extends BaseController<

for (const address of accountsToUpdate) {
accounts[address] = {
balance: BNToHex(await this.getBalanceFromChain(address)),
balance: (await this.getBalanceFromChain(address)) || '0x0',
};
}

Expand Down
13 changes: 6 additions & 7 deletions packages/assets-controllers/src/AssetsContractController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { BN } from '@ethereumjs/util';
import { Contract } from '@ethersproject/contracts';
import { Web3Provider } from '@ethersproject/providers';
import type { BaseConfig, BaseState } from '@metamask/base-controller';
Expand Down Expand Up @@ -63,7 +62,7 @@ export interface AssetsContractConfig extends BaseConfig {
* @property [tokenAddress] - Address of the token
*/
export interface BalanceMap {
[tokenAddress: string]: BN;
[tokenAddress: string]: bigint;
}

/**
Expand Down Expand Up @@ -218,13 +217,13 @@ export class AssetsContractController extends BaseController<
* @param address - Asset ERC20 contract address.
* @param selectedAddress - Current account public address.
* @param networkClientId - Network Client ID to fetch the provider with.
* @returns Promise resolving to BN object containing balance for current account on specific asset contract.
* @returns Promise resolving to BigInt value containing balance for current account on specific asset contract.
*/
async getERC20BalanceOf(
address: string,
selectedAddress: string,
networkClientId?: NetworkClientId,
): Promise<BN> {
): Promise<bigint> {
const erc20Standard = this.getERC20Standard(networkClientId);
return erc20Standard.getBalanceOf(address, selectedAddress);
}
Expand Down Expand Up @@ -298,7 +297,7 @@ export class AssetsContractController extends BaseController<
symbol?: string | undefined;
name?: string | undefined;
decimals?: string | undefined;
balance?: BN | undefined;
balance?: bigint | undefined;
}> {
// Asserts provider is available
this.getProvider(networkClientId);
Expand Down Expand Up @@ -441,7 +440,7 @@ export class AssetsContractController extends BaseController<
nftAddress: string,
nftId: string,
networkClientId?: NetworkClientId,
): Promise<BN> {
): Promise<bigint> {
const erc1155Standard = this.getERC1155Standard(networkClientId);
return erc1155Standard.getBalanceOf(nftAddress, userAddress, nftId);
}
Expand Down Expand Up @@ -507,7 +506,7 @@ export class AssetsContractController extends BaseController<
/* istanbul ignore else */
if (result.length > 0) {
tokensToDetect.forEach((tokenAddress, index) => {
const balance: BN = result[index];
const balance: bigint = result[index];
/* istanbul ignore else */
if (String(balance) !== '0') {
nonZeroBalances[tokenAddress] = balance;
Expand Down
9 changes: 4 additions & 5 deletions packages/assets-controllers/src/NftController.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { BN } from '@ethereumjs/util';
import type { Network } from '@ethersproject/providers';
import type {
AddApprovalRequest,
Expand Down Expand Up @@ -148,7 +147,7 @@ function setupController({
tokenAddress: string,
tokenId: string,
userAddress: string,
) => Promise<BN>;
) => Promise<bigint>;
} = {}) {
const preferences = new PreferencesController();
const onNetworkStateChangeListeners: ((state: NetworkState) => void)[] = [];
Expand Down Expand Up @@ -416,7 +415,7 @@ describe('NftController', () => {

it('should error if the user does not own the suggested ERC1155 NFT', async function () {
const { nftController, messenger } = setupController({
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => new BN(0)),
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => BigInt(0)),
});

const callActionSpy = jest.spyOn(messenger, 'call').mockResolvedValue({});
Expand Down Expand Up @@ -659,7 +658,7 @@ describe('NftController', () => {
getERC1155TokenURIStub: jest
.fn()
.mockImplementation(() => 'https://testtokenuri.com'),
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => new BN(1)),
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => BigInt(1)),
});
preferences.setOpenSeaEnabled(false);
preferences.setIsIpfsGatewayEnabled(true);
Expand Down Expand Up @@ -717,7 +716,7 @@ describe('NftController', () => {
getERC1155TokenURIStub: jest
.fn()
.mockImplementation(() => 'https://testtokenuri.com'),
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => new BN(1)),
getERC1155BalanceOfStub: jest.fn().mockImplementation(() => BigInt(1)),
});
preferences.setOpenSeaEnabled(true);
preferences.setIsIpfsGatewayEnabled(true);
Expand Down
8 changes: 4 additions & 4 deletions packages/assets-controllers/src/NftController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BN, stripHexPrefix } from '@ethereumjs/util';
import { stripHexPrefix } from '@ethereumjs/util';

Check failure on line 1 in packages/assets-controllers/src/NftController.ts

View workflow job for this annotation

GitHub Actions / Lint, build, and test / Lint (20.x)

'stripHexPrefix' is defined but never used
import { isAddress } from '@ethersproject/address';
import type { AddApprovalRequest } from '@metamask/approval-controller';
import type {
Expand All @@ -11,7 +11,6 @@ import {
safelyExecute,
handleFetch,
toChecksumHexAddress,
BNToHex,
fetchWithErrorHandling,
IPFS_DEFAULT_GATEWAY_URL,
ERC721,
Expand Down Expand Up @@ -460,7 +459,8 @@ export class NftController extends BaseController<NftConfig, NftState> {
return [tokenURI, ERC1155];
}

const hexTokenId = stripHexPrefix(BNToHex(new BN(tokenId)))
const hexTokenId = BigInt(tokenId)
.toString(16)
.padStart(64, '0')
.toLowerCase();
return [tokenURI.replace('{id}', hexTokenId), ERC1155];
Expand Down Expand Up @@ -1234,7 +1234,7 @@ export class NftController extends BaseController<NftConfig, NftState> {
tokenId,
networkClientId,
);
return !balance.isZero();
return balance !== BigInt(0);
// eslint-disable-next-line no-empty
} catch {
// Ignore ERC-1155 contract error
Expand Down
14 changes: 8 additions & 6 deletions packages/assets-controllers/src/Standards/ERC20Standard.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { toUtf8 } from '@ethereumjs/util';
import type { BN } from '@ethereumjs/util';
import { Contract } from '@ethersproject/contracts';
import type { Web3Provider } from '@ethersproject/providers';
import { decodeSingle } from '@metamask/abi-utils';
import { ERC20 } from '@metamask/controller-utils';
import { abiERC20 } from '@metamask/metamask-eth-abis';
import { assertIsStrictHexString } from '@metamask/utils';

import { ethersBigNumberToBN } from '../assetsUtil';
import { ethersBigNumberToBigInt } from '../assetsUtil';

export class ERC20Standard {
private readonly provider: Web3Provider;
Expand All @@ -21,12 +20,15 @@ export class ERC20Standard {
*
* @param address - Asset ERC20 contract address.
* @param selectedAddress - Current account public address.
* @returns Promise resolving to BN object containing balance for current account on specific asset contract.
* @returns Promise resolving to BigInt value containing balance for current account on specific asset contract.
*/
async getBalanceOf(address: string, selectedAddress: string): Promise<BN> {
async getBalanceOf(
address: string,
selectedAddress: string,
): Promise<bigint> {
const contract = new Contract(address, abiERC20, this.provider);
const balance = await contract.balanceOf(selectedAddress);
return ethersBigNumberToBN(balance);
return ethersBigNumberToBigInt(balance);
}

/**
Expand Down Expand Up @@ -117,7 +119,7 @@ export class ERC20Standard {
standard: string;
symbol: string | undefined;
decimals: string | undefined;
balance: BN | undefined;
balance: bigint | undefined;
}> {
const [decimals, symbol] = await Promise.all([
this.getTokenDecimals(address),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { BN } from '@ethereumjs/util';
import { Contract } from '@ethersproject/contracts';
import type { Web3Provider } from '@ethersproject/providers';
import {
Expand All @@ -10,7 +9,10 @@ import {
} from '@metamask/controller-utils';
import { abiERC1155 } from '@metamask/metamask-eth-abis';

import { getFormattedIpfsUrl, ethersBigNumberToBN } from '../../../assetsUtil';
import {
getFormattedIpfsUrl,
ethersBigNumberToBigInt,
} from '../../../assetsUtil';

export class ERC1155Standard {
private readonly provider: Web3Provider;
Expand Down Expand Up @@ -85,10 +87,10 @@ export class ERC1155Standard {
contractAddress: string,
address: string,
tokenId: string,
): Promise<BN> => {
): Promise<bigint> => {
const contract = new Contract(contractAddress, abiERC1155, this.provider);
const balance = await contract.balanceOf(address, tokenId);
return ethersBigNumberToBN(balance);
return ethersBigNumberToBigInt(balance);
};

/**
Expand Down
18 changes: 5 additions & 13 deletions packages/assets-controllers/src/TokenBalancesController.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { BN } from '@ethereumjs/util';
import { ControllerMessenger } from '@metamask/base-controller';
import { toHex } from '@metamask/controller-utils';
import type { NetworkControllerMessenger } from '@metamask/network-controller';
Expand All @@ -7,10 +6,7 @@ import { PreferencesController } from '@metamask/preferences-controller';
import * as sinon from 'sinon';

import { AssetsContractController } from './AssetsContractController';
import {
BN as exportedBn,
TokenBalancesController,
} from './TokenBalancesController';
import { TokenBalancesController } from './TokenBalancesController';
import type { Token } from './TokenRatesController';
import type { TokensControllerMessenger } from './TokensController';
import { TokensController } from './TokensController';
Expand All @@ -36,10 +32,6 @@ describe('TokenBalancesController', () => {
sinon.restore();
});

it('should re-export BN', () => {
expect(exportedBn).toStrictEqual(BN);
});

it('should set default state', () => {
const tokenBalances = new TokenBalancesController({
onTokensStateChange: sinon.stub(),
Expand Down Expand Up @@ -154,7 +146,7 @@ describe('TokenBalancesController', () => {
{
onTokensStateChange: (listener) => assets.subscribe(listener),
getSelectedAddress: () => preferences.state.selectedAddress,
getERC20BalanceOf: sinon.stub().returns(new BN(1)),
getERC20BalanceOf: sinon.stub().returns(BigInt(1)),
},
{
interval: 1337,
Expand Down Expand Up @@ -213,7 +205,7 @@ describe('TokenBalancesController', () => {
expect(mytoken?.balanceError).toHaveProperty('message', errorMsg);
expect(tokenBalances.state.contractBalances[address].toNumber()).toBe(0);

getERC20BalanceOfStub.returns(new BN(1));
getERC20BalanceOfStub.returns(BigInt(1));
await tokenBalances.updateBalances();
expect(mytoken?.balanceError).toBeNull();
expect(Object.keys(tokenBalances.state.contractBalances)).toContain(
Expand Down Expand Up @@ -282,7 +274,7 @@ describe('TokenBalancesController', () => {
{
onTokensStateChange,
getSelectedAddress: () => '0x1234',
getERC20BalanceOf: sinon.stub().returns(new BN(1)),
getERC20BalanceOf: sinon.stub().returns(BigInt(1)),
},
{
interval: 1337,
Expand All @@ -308,7 +300,7 @@ describe('TokenBalancesController', () => {
await tokenBalances.updateBalances();

expect(tokenBalances.state.contractBalances).toStrictEqual({
'0x02': new BN(1),
'0x02': BigInt(1),
});
});
});
10 changes: 3 additions & 7 deletions packages/assets-controllers/src/TokenBalancesController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { BN } from '@ethereumjs/util';
import type { BaseConfig, BaseState } from '@metamask/base-controller';
import { BaseController } from '@metamask/base-controller';
import { safelyExecute } from '@metamask/controller-utils';
Expand All @@ -8,9 +7,6 @@ import type { AssetsContractController } from './AssetsContractController';
import type { Token } from './TokenRatesController';
import type { TokensState } from './TokensController';

// TODO: Remove this export in the next major release
export { BN };

/**
* @type TokenBalancesConfig
*
Expand All @@ -30,7 +26,7 @@ export interface TokenBalancesConfig extends BaseConfig {
* @property contractBalances - Hash of token contract addresses to balances
*/
export interface TokenBalancesState extends BaseState {
contractBalances: { [address: string]: BN };
contractBalances: { [address: string]: bigint };
}

/**
Expand Down Expand Up @@ -115,7 +111,7 @@ export class TokenBalancesController extends BaseController<
return;
}
const { tokens } = this.config;
const newContractBalances: { [address: string]: BN } = {};
const newContractBalances: { [address: string]: bigint } = {};
for (const i in tokens) {
const { address } = tokens[i];
try {
Expand All @@ -125,7 +121,7 @@ export class TokenBalancesController extends BaseController<
);
tokens[i].balanceError = null;
} catch (error) {
newContractBalances[address] = new BN(0);
newContractBalances[address] = BigInt(0);
tokens[i].balanceError = error;
}
}
Expand Down
Loading

0 comments on commit 367b972

Please sign in to comment.