Skip to content

Commit

Permalink
Merge branch 'main' into brian/network-controller-race-condition
Browse files Browse the repository at this point in the history
  • Loading branch information
bergeron authored Jan 13, 2025
2 parents 4b650b8 + a7ed53d commit 8a52867
Show file tree
Hide file tree
Showing 62 changed files with 2,041 additions and 238 deletions.
4 changes: 2 additions & 2 deletions examples/example-controllers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^7.1.0",
"@metamask/base-controller": "^7.1.1",
"@metamask/utils": "^11.0.1"
},
"devDependencies": {
"@metamask/auto-changelog": "^3.4.4",
"@metamask/controller-utils": "^11.4.4",
"@metamask/controller-utils": "^11.4.5",
"@types/jest": "^27.4.1",
"deepmerge": "^4.2.2",
"jest": "^27.5.1",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@metamask/core-monorepo",
"version": "277.0.0",
"version": "280.0.0",
"private": true,
"description": "Monorepo for packages shared between MetaMask clients",
"repository": {
Expand Down
6 changes: 3 additions & 3 deletions packages/accounts-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
},
"dependencies": {
"@ethereumjs/util": "^8.1.0",
"@metamask/base-controller": "^7.1.0",
"@metamask/eth-snap-keyring": "^7.0.0",
"@metamask/base-controller": "^7.1.1",
"@metamask/eth-snap-keyring": "^8.0.0",
"@metamask/keyring-api": "^13.0.0",
"@metamask/keyring-internal-api": "^1.1.0",
"@metamask/keyring-internal-api": "^2.0.0",
"@metamask/snaps-sdk": "^6.7.0",
"@metamask/snaps-utils": "^8.3.0",
"@metamask/utils": "^11.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/address-book-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^7.1.0",
"@metamask/controller-utils": "^11.4.4",
"@metamask/base-controller": "^7.1.1",
"@metamask/controller-utils": "^11.4.5",
"@metamask/utils": "^11.0.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/announcement-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^7.1.0"
"@metamask/base-controller": "^7.1.1"
},
"devDependencies": {
"@metamask/auto-changelog": "^3.4.4",
Expand Down
8 changes: 7 additions & 1 deletion packages/approval-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [7.1.2]

### Changed

- Bump `nanoid` from `^3.1.31` to `^3.3.8` ([#5073](https://github.com/MetaMask/core/pull/5073))
- Bump `@metamask/utils` from `^10.0.0` to `^11.0.1` ([#5080](https://github.com/MetaMask/core/pull/5080))
- Bump `@metamask/rpc-errors` from `^7.0.0` to `^7.0.2` ([#5080](https://github.com/MetaMask/core/pull/5080))
- Bump `@metamask/base-controller` from `^7.0.0` to `^7.1.0` ([#5079](https://github.com/MetaMask/core/pull/5079))

## [7.1.1]
Expand Down Expand Up @@ -257,7 +262,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

All changes listed after this point were applied to this package following the monorepo conversion.

[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/[email protected]
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/[email protected]
[7.1.2]: https://github.com/MetaMask/core/compare/@metamask/[email protected]...@metamask/[email protected]
[7.1.1]: https://github.com/MetaMask/core/compare/@metamask/[email protected]...@metamask/[email protected]
[7.1.0]: https://github.com/MetaMask/core/compare/@metamask/[email protected]...@metamask/[email protected]
[7.0.4]: https://github.com/MetaMask/core/compare/@metamask/[email protected]...@metamask/[email protected]
Expand Down
4 changes: 2 additions & 2 deletions packages/approval-controller/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@metamask/approval-controller",
"version": "7.1.1",
"version": "7.1.2",
"description": "Manages requests that require user approval",
"keywords": [
"MetaMask",
Expand Down Expand Up @@ -47,7 +47,7 @@
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^7.1.0",
"@metamask/base-controller": "^7.1.1",
"@metamask/rpc-errors": "^7.0.2",
"@metamask/utils": "^11.0.1",
"nanoid": "^3.3.8"
Expand Down
14 changes: 10 additions & 4 deletions packages/assets-controllers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,19 @@
"@ethersproject/contracts": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@metamask/abi-utils": "^2.0.3",
"@metamask/base-controller": "^7.1.0",
"@metamask/base-controller": "^7.1.1",
"@metamask/contract-metadata": "^2.4.0",
"@metamask/controller-utils": "^11.4.4",
"@metamask/controller-utils": "^11.4.5",
"@metamask/eth-query": "^4.0.0",
"@metamask/metamask-eth-abis": "^3.1.1",
"@metamask/polling-controller": "^12.0.2",
"@metamask/rpc-errors": "^7.0.2",
"@metamask/snaps-utils": "^8.3.0",
"@metamask/utils": "^11.0.1",
"@types/bn.js": "^5.1.5",
"@types/uuid": "^8.3.0",
"async-mutex": "^0.5.0",
"bitcoin-address-validation": "^2.2.3",
"bn.js": "^5.2.1",
"cockatiel": "^3.1.2",
"immer": "^9.0.6",
Expand All @@ -76,14 +78,18 @@
"devDependencies": {
"@babel/runtime": "^7.23.9",
"@metamask/accounts-controller": "^20.0.2",
"@metamask/approval-controller": "^7.1.1",
"@metamask/approval-controller": "^7.1.2",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/ethjs-provider-http": "^0.3.0",
"@metamask/keyring-api": "^13.0.0",
"@metamask/keyring-controller": "^19.0.2",
"@metamask/keyring-internal-api": "^1.1.0",
"@metamask/keyring-internal-api": "^2.0.0",
"@metamask/keyring-snap-client": "^2.0.0",
"@metamask/network-controller": "^22.1.1",
"@metamask/preferences-controller": "^15.0.1",
"@metamask/providers": "^18.1.1",
"@metamask/snaps-controllers": "^9.10.0",
"@metamask/snaps-sdk": "^6.7.0",
"@types/jest": "^27.4.1",
"@types/lodash": "^4.14.191",
"@types/node": "^16.18.54",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { BtcAccountType, BtcMethod } from '@metamask/keyring-api';
import { KeyringTypes } from '@metamask/keyring-controller';
import { v4 as uuidv4 } from 'uuid';

import { BalancesTracker } from './BalancesTracker';
import { Poller } from './Poller';

const MOCK_TIMESTAMP = 1709983353;

const mockBtcAccount = {
address: '',
id: uuidv4(),
metadata: {
name: 'Bitcoin Account 1',
importTime: Date.now(),
keyring: {
type: KeyringTypes.snap,
},
snap: {
id: 'mock-btc-snap',
name: 'mock-btc-snap',
enabled: true,
},
lastSelected: 0,
},
options: {},
methods: [BtcMethod.SendBitcoin],
type: BtcAccountType.P2wpkh,
};

/**
* Sets up a BalancesTracker instance for testing.
* @returns The BalancesTracker instance and a mock update balance function.
*/
function setupTracker() {
const mockUpdateBalance = jest.fn();
const tracker = new BalancesTracker(mockUpdateBalance);

return {
tracker,
mockUpdateBalance,
};
}

describe('BalancesTracker', () => {
it('starts polling when calling start', async () => {
const { tracker } = setupTracker();
const spyPoller = jest.spyOn(Poller.prototype, 'start');

tracker.start();
expect(spyPoller).toHaveBeenCalledTimes(1);
});

it('stops polling when calling stop', async () => {
const { tracker } = setupTracker();
const spyPoller = jest.spyOn(Poller.prototype, 'stop');

tracker.start();
tracker.stop();
expect(spyPoller).toHaveBeenCalledTimes(1);
});

it('is not tracking if none accounts have been registered', async () => {
const { tracker, mockUpdateBalance } = setupTracker();

tracker.start();
await tracker.updateBalances();

expect(mockUpdateBalance).not.toHaveBeenCalled();
});

it('tracks account balances', async () => {
const { tracker, mockUpdateBalance } = setupTracker();

tracker.start();
// We must track account IDs explicitly
tracker.track(mockBtcAccount.id, 0);
// Trigger balances refresh (not waiting for the Poller here)
await tracker.updateBalances();

expect(mockUpdateBalance).toHaveBeenCalledWith(mockBtcAccount.id);
});

it('untracks account balances', async () => {
const { tracker, mockUpdateBalance } = setupTracker();

tracker.start();
tracker.track(mockBtcAccount.id, 0);
await tracker.updateBalances();
expect(mockUpdateBalance).toHaveBeenCalledWith(mockBtcAccount.id);

tracker.untrack(mockBtcAccount.id);
await tracker.updateBalances();
expect(mockUpdateBalance).toHaveBeenCalledTimes(1); // No second call after untracking
});

it('tracks account after being registered', async () => {
const { tracker } = setupTracker();

tracker.start();
tracker.track(mockBtcAccount.id, 0);
expect(tracker.isTracked(mockBtcAccount.id)).toBe(true);
});

it('does not track account if not registered', async () => {
const { tracker } = setupTracker();

tracker.start();
expect(tracker.isTracked(mockBtcAccount.id)).toBe(false);
});

it('does not refresh balance if they are considered up-to-date', async () => {
const { tracker, mockUpdateBalance } = setupTracker();

const blockTime = 10 * 60 * 1000; // 10 minutes in milliseconds.
jest
.spyOn(global.Date, 'now')
.mockImplementation(() => new Date(MOCK_TIMESTAMP).getTime());

tracker.start();
tracker.track(mockBtcAccount.id, blockTime);
await tracker.updateBalances();
expect(mockUpdateBalance).toHaveBeenCalledTimes(1);

await tracker.updateBalances();
expect(mockUpdateBalance).toHaveBeenCalledTimes(1); // No second call since the balances is already still up-to-date

jest
.spyOn(global.Date, 'now')
.mockImplementation(() => new Date(MOCK_TIMESTAMP + blockTime).getTime());

await tracker.updateBalances();
expect(mockUpdateBalance).toHaveBeenCalledTimes(2); // Now the balance will update
});

it('throws an error if trying to update balance of an untracked account', async () => {
const { tracker } = setupTracker();

await expect(tracker.updateBalance(mockBtcAccount.id)).rejects.toThrow(
`Account is not being tracked: ${mockBtcAccount.id}`,
);
});
});
Loading

0 comments on commit 8a52867

Please sign in to comment.