Skip to content

Commit adb550b

Browse files
chore: switch over to @ethersproject packages at 5.7.0 for mobile compat (#5416)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> Mobile uses Ethers v5 libs so in order to align better with that we will be downgrading from v6 to v5 in the `BridgeController`. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> ## Changelog <!-- If you're making any consumer-facing changes, list those changes here as if you were updating a changelog, using the template below as a guide. (CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or FIXED. For security-related issues, follow the Security Advisory process.) Please take care to name the exact pieces of the API you've added or changed (e.g. types, interfaces, functions, or methods). If there are any breaking changes, make sure to offer a solution for consumers to follow once they upgrade to the changes. Finally, if you're only making changes to development scripts or tests, you may replace the template below with "None". --> ### `@metamask/bridge-controller` - **BREAKING**: Change `ethers` v6 dependency to `@ethersproject` subpackages at v5 for better Mobile compatibility. This changes the `ethers` v6 native JS `bigint` return values to `ethers` v5 `BigNumber` values. ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've highlighted breaking changes using the "BREAKING" category above as appropriate - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent e8d9fcf commit adb550b

File tree

10 files changed

+81
-55
lines changed

10 files changed

+81
-55
lines changed

packages/bridge-controller/package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,16 @@
4747
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
4848
},
4949
"dependencies": {
50+
"@ethersproject/address": "^5.7.0",
51+
"@ethersproject/bignumber": "^5.7.0",
52+
"@ethersproject/constants": "^5.7.0",
53+
"@ethersproject/contracts": "^5.7.0",
54+
"@ethersproject/providers": "^5.7.0",
5055
"@metamask/base-controller": "^8.0.0",
5156
"@metamask/controller-utils": "^11.5.0",
5257
"@metamask/metamask-eth-abis": "^3.1.1",
5358
"@metamask/polling-controller": "^12.0.3",
54-
"@metamask/utils": "^11.2.0",
55-
"ethers": "^6.12.0"
59+
"@metamask/utils": "^11.2.0"
5660
},
5761
"devDependencies": {
5862
"@metamask/accounts-controller": "^24.1.0",

packages/bridge-controller/src/bridge-controller.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { Contract } from '@ethersproject/contracts';
12
import type { Hex } from '@metamask/utils';
23
import { bigIntToHex } from '@metamask/utils';
3-
import { Contract } from 'ethers';
44
import nock from 'nock';
55

66
import { BridgeController } from './bridge-controller';
@@ -29,13 +29,13 @@ const messengerMock = {
2929
publish: jest.fn(),
3030
} as unknown as jest.Mocked<BridgeControllerMessenger>;
3131

32-
jest.mock('ethers', () => {
32+
jest.mock('@ethersproject/contracts', () => {
3333
return {
34-
...jest.requireActual('ethers'),
34+
...jest.requireActual('@ethersproject/contracts'),
3535
Contract: jest.fn(),
36-
BrowserProvider: jest.fn(),
3736
};
3837
});
38+
3939
const getLayer1GasFeeMock = jest.fn();
4040
const mockFetchFn = handleFetch;
4141

packages/bridge-controller/src/bridge-controller.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { BigNumber } from '@ethersproject/bignumber';
2+
import { Contract } from '@ethersproject/contracts';
3+
import { Web3Provider } from '@ethersproject/providers';
14
import type { StateMetadata } from '@metamask/base-controller';
25
import type { ChainId } from '@metamask/controller-utils';
36
import { abiERC20 } from '@metamask/metamask-eth-abis';
@@ -6,7 +9,6 @@ import { StaticIntervalPollingController } from '@metamask/polling-controller';
69
import type { TransactionParams } from '@metamask/transaction-controller';
710
import { numberToHex } from '@metamask/utils';
811
import type { Hex } from '@metamask/utils';
9-
import { BrowserProvider, Contract } from 'ethers';
1012

1113
import type { BridgeClientId } from './constants/bridge';
1214
import {
@@ -400,10 +402,10 @@ export class BridgeController extends StaticIntervalPollingController<BridgePoll
400402
throw new Error('No provider found');
401403
}
402404

403-
const ethersProvider = new BrowserProvider(provider);
405+
const ethersProvider = new Web3Provider(provider);
404406
const contract = new Contract(contractAddress, abiERC20, ethersProvider);
405407
const { address: walletAddress } = this.#getSelectedAccount();
406-
const allowance: bigint = await contract.allowance(
408+
const allowance: BigNumber = await contract.allowance(
407409
walletAddress,
408410
METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],
409411
);

packages/bridge-controller/src/constants/bridge.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { AddressZero } from '@ethersproject/constants';
12
import type { Hex } from '@metamask/utils';
2-
import { ZeroAddress } from 'ethers';
33

44
import { CHAIN_IDS } from './chains';
55
import type { BridgeControllerState } from '../types';
@@ -55,7 +55,7 @@ export const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState = {
5555
[BridgeFeatureFlagsKey.MOBILE_CONFIG]: DEFAULT_FEATURE_FLAG_CONFIG,
5656
},
5757
quoteRequest: {
58-
srcTokenAddress: ZeroAddress,
58+
srcTokenAddress: AddressZero,
5959
slippage: BRIDGE_DEFAULT_SLIPPAGE,
6060
},
6161
quotesInitialLoadTime: null,

packages/bridge-controller/src/utils/balance.test.ts

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { BigNumber } from '@ethersproject/bignumber';
2+
import { AddressZero } from '@ethersproject/constants';
3+
import { Contract } from '@ethersproject/contracts';
4+
import { Web3Provider } from '@ethersproject/providers';
15
import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
26
import { abiERC20 } from '@metamask/metamask-eth-abis';
3-
import { ZeroAddress } from 'ethers';
4-
import { BrowserProvider, Contract } from 'ethers';
57

68
import * as balanceUtils from './balance';
79
import { fetchTokenBalance } from './balance';
@@ -12,11 +14,17 @@ declare global {
1214
var ethereumProvider: SafeEventEmitterProvider;
1315
}
1416

15-
jest.mock('ethers', () => {
17+
jest.mock('@ethersproject/contracts', () => {
1618
return {
17-
...jest.requireActual('ethers'),
19+
...jest.requireActual('@ethersproject/contracts'),
1820
Contract: jest.fn(),
19-
BrowserProvider: jest.fn(),
21+
};
22+
});
23+
24+
jest.mock('@ethersproject/providers', () => {
25+
return {
26+
...jest.requireActual('@ethersproject/providers'),
27+
Web3Provider: jest.fn(),
2028
};
2129
});
2230

@@ -28,7 +36,9 @@ describe('balance', () => {
2836

2937
describe('calcLatestSrcBalance', () => {
3038
it('should return the ERC20 token balance', async () => {
31-
const mockBalanceOf = jest.fn().mockResolvedValueOnce(BigInt(100));
39+
const mockBalanceOf = jest
40+
.fn()
41+
.mockResolvedValueOnce(BigNumber.from(100));
3242
(Contract as unknown as jest.Mock).mockImplementation(() => ({
3343
balanceOf: mockBalanceOf,
3444
}));
@@ -40,16 +50,16 @@ describe('balance', () => {
4050
'0x456',
4151
'0x789',
4252
),
43-
).toStrictEqual(BigInt(100));
53+
).toStrictEqual(BigNumber.from(100));
4454
expect(mockBalanceOf).toHaveBeenCalledTimes(1);
4555
expect(mockBalanceOf).toHaveBeenCalledWith('0x123');
4656
});
4757

4858
it('should return the native asset balance', async () => {
4959
const mockGetBalance = jest.fn().mockImplementation(() => {
50-
return BigInt(100);
60+
return BigNumber.from(100);
5161
});
52-
(BrowserProvider as unknown as jest.Mock).mockImplementation(() => {
62+
(Web3Provider as unknown as jest.Mock).mockImplementation(() => {
5363
return {
5464
getBalance: mockGetBalance,
5565
};
@@ -59,10 +69,10 @@ describe('balance', () => {
5969
await balanceUtils.calcLatestSrcBalance(
6070
global.ethereumProvider,
6171
'0x141d32a89a1e0a5Ef360034a2f60a4B917c18838',
62-
ZeroAddress,
72+
AddressZero,
6373
'0x789',
6474
),
65-
).toStrictEqual(BigInt(100));
75+
).toStrictEqual(BigNumber.from(100));
6676
expect(mockGetBalance).toHaveBeenCalledTimes(1);
6777
expect(mockGetBalance).toHaveBeenCalledWith(
6878
'0x141d32a89a1e0a5Ef360034a2f60a4B917c18838',
@@ -71,7 +81,7 @@ describe('balance', () => {
7181

7282
it('should return undefined if token address and chainId are undefined', async () => {
7383
const mockGetBalance = jest.fn();
74-
(BrowserProvider as unknown as jest.Mock).mockImplementation(() => {
84+
(Web3Provider as unknown as jest.Mock).mockImplementation(() => {
7585
return {
7686
getBalance: mockGetBalance,
7787
};
@@ -97,19 +107,19 @@ describe('balance', () => {
97107
describe('hasSufficientBalance', () => {
98108
it('should return true if user has sufficient balance', async () => {
99109
const mockGetBalance = jest.fn();
100-
(BrowserProvider as unknown as jest.Mock).mockImplementation(() => {
110+
(Web3Provider as unknown as jest.Mock).mockImplementation(() => {
101111
return {
102112
getBalance: mockGetBalance,
103113
};
104114
});
105115

106116
mockGetBalance.mockImplementation(() => {
107-
return BigInt(10000000000000000000);
117+
return BigNumber.from('10000000000000000000');
108118
});
109119

110120
const mockBalanceOf = jest
111121
.fn()
112-
.mockResolvedValueOnce(BigInt('10000000000000000001'));
122+
.mockResolvedValueOnce(BigNumber.from('10000000000000000001'));
113123
(Contract as unknown as jest.Mock).mockImplementation(() => ({
114124
balanceOf: mockBalanceOf,
115125
}));
@@ -118,7 +128,7 @@ describe('balance', () => {
118128
await balanceUtils.hasSufficientBalance(
119129
global.ethereumProvider,
120130
'0x141d32a89a1e0a5ef360034a2f60a4b917c18838',
121-
ZeroAddress,
131+
AddressZero,
122132
'10000000000000000000',
123133
'0x1',
124134
),
@@ -137,20 +147,22 @@ describe('balance', () => {
137147

138148
it('should return false if user has native assets but insufficient ERC20 src tokens', async () => {
139149
const mockGetBalance = jest.fn();
140-
(BrowserProvider as unknown as jest.Mock).mockImplementation(() => {
150+
(Web3Provider as unknown as jest.Mock).mockImplementation(() => {
141151
return {
142152
getBalance: mockGetBalance,
143153
};
144154
});
145155

146156
mockGetBalance.mockImplementation(() => {
147-
return BigInt(10000000000000000000);
157+
return BigNumber.from('10000000000000000000');
148158
});
149159
const mockFetchTokenBalance = jest.spyOn(
150160
balanceUtils,
151161
'fetchTokenBalance',
152162
);
153-
mockFetchTokenBalance.mockResolvedValueOnce(BigInt(9000000000000000000));
163+
mockFetchTokenBalance.mockResolvedValueOnce(
164+
BigNumber.from('9000000000000000000'),
165+
);
154166

155167
expect(
156168
await balanceUtils.hasSufficientBalance(
@@ -188,25 +200,25 @@ describe('balance', () => {
188200
});
189201

190202
describe('fetchTokenBalance', () => {
191-
let mockProvider: SafeEventEmitterProvider;
203+
let mockProvider: FakeProvider;
192204
const mockAddress = '0x1234567890123456789012345678901234567890';
193205
const mockUserAddress = '0x9876543210987654321098765432109876543210';
194-
const mockBalance = BigInt(1000);
206+
const mockBalance = BigNumber.from(1000);
195207

196208
beforeEach(() => {
197209
jest.clearAllMocks();
198210
mockProvider = new FakeProvider();
199211

200-
// Mock BrowserProvider
201-
(BrowserProvider as jest.Mock).mockImplementation(() => ({
212+
// Mock Web3Provider
213+
(Web3Provider as unknown as jest.Mock).mockImplementation(() => ({
202214
// Add any provider methods needed
203215
}));
204216
});
205217

206218
it('should fetch token balance when contract is valid', async () => {
207219
// Mock Contract
208220
const mockBalanceOf = jest.fn().mockResolvedValue(mockBalance);
209-
(Contract as jest.Mock).mockImplementation(() => ({
221+
(Contract as unknown as jest.Mock).mockImplementation(() => ({
210222
balanceOf: mockBalanceOf,
211223
}));
212224

@@ -216,7 +228,7 @@ describe('fetchTokenBalance', () => {
216228
mockProvider,
217229
);
218230

219-
expect(BrowserProvider).toHaveBeenCalledWith(mockProvider);
231+
expect(Web3Provider).toHaveBeenCalledWith(mockProvider);
220232
expect(Contract).toHaveBeenCalledWith(
221233
mockAddress,
222234
abiERC20,
@@ -228,7 +240,7 @@ describe('fetchTokenBalance', () => {
228240

229241
it('should return undefined when contract is invalid', async () => {
230242
// Mock Contract to return an object without balanceOf method
231-
(Contract as jest.Mock).mockImplementation(() => ({
243+
(Contract as unknown as jest.Mock).mockImplementation(() => ({
232244
// Empty object without balanceOf method
233245
}));
234246

@@ -238,7 +250,7 @@ describe('fetchTokenBalance', () => {
238250
mockProvider,
239251
);
240252

241-
expect(BrowserProvider).toHaveBeenCalledWith(mockProvider);
253+
expect(Web3Provider).toHaveBeenCalledWith(mockProvider);
242254
expect(Contract).toHaveBeenCalledWith(
243255
mockAddress,
244256
abiERC20,

packages/bridge-controller/src/utils/balance.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
import { getAddress } from '@ethersproject/address';
2+
import type { BigNumber } from '@ethersproject/bignumber';
3+
import { AddressZero } from '@ethersproject/constants';
4+
import { Contract } from '@ethersproject/contracts';
5+
import { Web3Provider } from '@ethersproject/providers';
16
import { abiERC20 } from '@metamask/metamask-eth-abis';
27
import type { Provider } from '@metamask/network-controller';
38
import type { Hex } from '@metamask/utils';
4-
import { BrowserProvider, Contract, getAddress, ZeroAddress } from 'ethers';
59

610
export const fetchTokenBalance = async (
711
address: string,
812
userAddress: string,
913
provider: Provider,
10-
): Promise<bigint | undefined> => {
11-
const ethersProvider = new BrowserProvider(provider);
14+
): Promise<BigNumber | undefined> => {
15+
const ethersProvider = new Web3Provider(provider);
1216
const tokenContract = new Contract(address, abiERC20, ethersProvider);
1317
const tokenBalancePromise =
1418
typeof tokenContract?.balanceOf === 'function'
@@ -22,10 +26,10 @@ export const calcLatestSrcBalance = async (
2226
selectedAddress: string,
2327
tokenAddress: string,
2428
chainId: Hex,
25-
): Promise<bigint | undefined> => {
29+
): Promise<BigNumber | undefined> => {
2630
if (tokenAddress && chainId) {
27-
if (tokenAddress === ZeroAddress) {
28-
const ethersProvider = new BrowserProvider(provider);
31+
if (tokenAddress === AddressZero) {
32+
const ethersProvider = new Web3Provider(provider);
2933
return await ethersProvider.getBalance(getAddress(selectedAddress));
3034
}
3135
return await fetchTokenBalance(tokenAddress, selectedAddress, provider);
@@ -47,5 +51,5 @@ export const hasSufficientBalance = async (
4751
chainId,
4852
);
4953

50-
return srcTokenBalance ? srcTokenBalance >= BigInt(fromTokenAmount) : false;
54+
return srcTokenBalance ? srcTokenBalance.gte(fromTokenAmount) : false;
5155
};

packages/bridge-controller/src/utils/bridge.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable n/no-process-env */
2+
import { Contract } from '@ethersproject/contracts';
23
import { abiERC20 } from '@metamask/metamask-eth-abis';
34
import type { Hex } from '@metamask/utils';
4-
import { Contract } from 'ethers';
55

66
import {
77
getEthUsdtResetData,

packages/bridge-controller/src/utils/bridge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { Contract } from '@ethersproject/contracts';
12
import { abiERC20 } from '@metamask/metamask-eth-abis';
23
import type { Hex } from '@metamask/utils';
3-
import { Contract } from 'ethers';
44

55
import {
66
DEFAULT_BRIDGE_CONTROLLER_STATE,

packages/bridge-controller/src/utils/fetch.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ZeroAddress } from 'ethers';
1+
import { AddressZero } from '@ethersproject/constants';
22

33
import {
44
fetchBridgeFeatureFlags,
@@ -248,8 +248,8 @@ describe('fetch', () => {
248248
walletAddress: '0x123',
249249
srcChainId: 1,
250250
destChainId: 10,
251-
srcTokenAddress: ZeroAddress,
252-
destTokenAddress: ZeroAddress,
251+
srcTokenAddress: AddressZero,
252+
destTokenAddress: AddressZero,
253253
srcTokenAmount: '20000',
254254
slippage: 0.5,
255255
},
@@ -282,8 +282,8 @@ describe('fetch', () => {
282282
walletAddress: '0x123',
283283
srcChainId: 1,
284284
destChainId: 10,
285-
srcTokenAddress: ZeroAddress,
286-
destTokenAddress: ZeroAddress,
285+
srcTokenAddress: AddressZero,
286+
destTokenAddress: AddressZero,
287287
srcTokenAmount: '20000',
288288
slippage: 0.5,
289289
},
@@ -335,8 +335,8 @@ describe('fetch', () => {
335335
walletAddress: '0x123',
336336
srcChainId: 1,
337337
destChainId: 10,
338-
srcTokenAddress: ZeroAddress,
339-
destTokenAddress: ZeroAddress,
338+
srcTokenAddress: AddressZero,
339+
destTokenAddress: AddressZero,
340340
srcTokenAmount: '20000',
341341
slippage: 0.5,
342342
},

0 commit comments

Comments
 (0)