Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add MultichainNetworkController to handle both EVM and non-EVM network and account switching #5215

Open
wants to merge 69 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
47c7310
feat add multichain-network-controller package
gantunesr Jan 24, 2025
7b64a8c
chore: update exports
gantunesr Jan 24, 2025
37dc7c5
fix: build
gantunesr Jan 24, 2025
454c3db
chore: update initial state
gantunesr Jan 27, 2025
2f4d06c
add setter for update nonEvmNetwork state variable to true and setter…
tommasini Jan 29, 2025
4ee7b32
merge main and solve yarn lock file conflicts
tommasini Jan 29, 2025
2f8058a
added blank line between functions
tommasini Jan 29, 2025
6b7b3b6
removed unused import and re order imports, to fix lint warnings
tommasini Jan 29, 2025
8a5c9d0
Handle network and account updates when switching networks
Cal-L Jan 29, 2025
f898056
Register message handlers
Cal-L Jan 29, 2025
edb6868
Separate concerns when updating network on multichain network controller
Cal-L Jan 30, 2025
1c3dc66
Handle switching network when account changes
Cal-L Jan 30, 2025
c1050f7
Remove unused actions and events
Cal-L Jan 30, 2025
a89bff4
btc and solana chain id from keyring api, update types and added java…
tommasini Jan 30, 2025
f159822
Merge branch 'feat/multichain-networks-controller' of github.com:Meta…
Cal-L Jan 30, 2025
dab430b
Remove draft type
Cal-L Jan 30, 2025
6994dbe
Fix account change subscription in multichain network controller
Cal-L Jan 30, 2025
ebe7e29
Add comment
Cal-L Jan 30, 2025
20a1dbc
replace nativeAsset name varialbe for nativeCurrency name variable
tommasini Jan 31, 2025
063e25a
Merge branch 'feat/multichain-networks-controller' of github.com:Meta…
Cal-L Jan 31, 2025
cf31cc3
git commit -m "Duplicate internal accounts mock"
Cal-L Feb 4, 2025
429f6ad
Update package deps
Cal-L Feb 4, 2025
a1618ab
Clean up MultichainNetworkController
Cal-L Feb 4, 2025
7f1ecd9
Update constants
Cal-L Feb 4, 2025
ba0d1ea
Update branch coverage threshold
Cal-L Feb 4, 2025
f0d9e53
Update yarn lock
Cal-L Feb 4, 2025
81b318e
Handle multichain network change on accounts controller
Cal-L Feb 4, 2025
85fcbb5
Increase unit test coverage on util
Cal-L Feb 4, 2025
a3b670b
Increase test coverage for MultichainNetworkController
Cal-L Feb 4, 2025
22f0511
Increase test coverage for accounts controller
Cal-L Feb 4, 2025
51ed3fa
Simplify tests
Cal-L Feb 4, 2025
1fef6c2
Remove unused import
Cal-L Feb 4, 2025
b5dc0eb
Fix all lint issues
Cal-L Feb 4, 2025
2a51326
Fix unit tests
Cal-L Feb 4, 2025
b0d8baf
Remove empty object
Cal-L Feb 4, 2025
a2dbe43
Remove ts expect for build to pass
Cal-L Feb 4, 2025
0f6d846
Merge branch 'main' of github.com:MetaMask/core into feat/handle-mult…
Cal-L Feb 4, 2025
107d1d5
Add missing condition when switching accounts
Cal-L Feb 4, 2025
2c65ccd
Update package versions
Cal-L Feb 4, 2025
a4fbabc
Keep consistent accounts controller version
Cal-L Feb 4, 2025
3c653e6
Make utils package consistent
Cal-L Feb 4, 2025
a9f942f
Update imports from keyring-api
Cal-L Feb 4, 2025
1a1abeb
Fix import
Cal-L Feb 4, 2025
dcca502
Remove lint warnings for utils
Cal-L Feb 4, 2025
f86d786
chore: update network types (#5277)
gantunesr Feb 5, 2025
c58256d
chore: add block explorer URLs (#5288)
gantunesr Feb 5, 2025
38ec763
Run update-readme-content script to update README graph
Cal-L Feb 7, 2025
123f2de
Merge branch 'feat/handle-multichain-network-and-account-switching' o…
Cal-L Feb 7, 2025
f733a45
Update packages/multichain-network-controller/tsconfig.json
Cal-L Feb 7, 2025
8017a64
Update event to onNetworkChange
Cal-L Feb 7, 2025
4745dac
Update packages/multichain-network-controller/src/MultichainNetworkCo…
Cal-L Feb 7, 2025
8328825
Change nonEvmSelected to isEvmSelected
Cal-L Feb 8, 2025
ff3296f
Update packages/multichain-network-controller/src/constants.ts
Cal-L Feb 8, 2025
51b4348
Update event name for MultichainNetworkController
Cal-L Feb 8, 2025
6902a4f
Update function name
Cal-L Feb 8, 2025
bbb7ab1
Begin addressing comments in PR
Cal-L Feb 11, 2025
bae44cc
Merge branch 'feat/handle-multichain-network-and-account-switching' o…
Cal-L Feb 11, 2025
d2185e9
Change evmClientId to evmNetworkClientId
Cal-L Feb 11, 2025
c683df3
use overload for setActiveNetwork
Cal-L Feb 11, 2025
dc8b579
Update root package json and README
Cal-L Feb 12, 2025
60c52ee
Clean up multichain network controller
Cal-L Feb 12, 2025
5256788
Remove unused imports
Cal-L Feb 12, 2025
2596c18
Fix lint errors on MultichainNetworkController
Cal-L Feb 12, 2025
2e5eed3
Fix lint errors on accounts controller files
Cal-L Feb 12, 2025
2892d25
Update codeowners
Cal-L Feb 12, 2025
1f61229
Merge branch 'main' of github.com:MetaMask/core into feat/handle-mult…
Cal-L Feb 12, 2025
a0bcef5
Merge with main
Cal-L Feb 12, 2025
fdfe886
Update based off latest main
Cal-L Feb 12, 2025
f36c02e
Run yarn update-readme-content
Cal-L Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions eslint-warning-thresholds.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
"packages/accounts-controller/src/AccountsController.test.ts": {
"import-x/namespace": 1
},
"packages/accounts-controller/src/utils.ts": {
"jsdoc/tag-lines": 3
},
"packages/address-book-controller/src/AddressBookController.ts": {
"jsdoc/check-tag-names": 13
},
Expand Down
173 changes: 113 additions & 60 deletions packages/accounts-controller/src/AccountsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
} from '@metamask/keyring-internal-api';
import type { SnapControllerState } from '@metamask/snaps-controllers';
import { SnapStatus } from '@metamask/snaps-utils';
import type { CaipChainId } from '@metamask/utils';
import { type CaipChainId } from '@metamask/utils';
import * as uuid from 'uuid';

Check warning on line 23 in packages/accounts-controller/src/AccountsController.test.ts

View workflow job for this annotation

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

No exported names found in module 'uuid'
import type { V4Options } from 'uuid';

import type {
Expand Down Expand Up @@ -307,6 +307,7 @@
'SnapKeyring:accountAssetListUpdated',
'SnapKeyring:accountBalancesUpdated',
'SnapKeyring:accountTransactionsUpdated',
'MultichainNetworkController:setActiveNetwork',
],
allowedActions: [
'KeyringController:getAccounts',
Expand Down Expand Up @@ -339,6 +340,10 @@
AccountsControllerActions | AllowedActions,
AccountsControllerEvents | AllowedEvents
>;
triggerMultichainNetworkChange: (args: {
evmClientId?: string;
nonEvmChainId?: CaipChainId;
}) => void;
} {
const accountsControllerMessenger =
buildAccountsControllerMessenger(messenger);
Expand All @@ -347,10 +352,47 @@
messenger: accountsControllerMessenger,
state: { ...defaultState, ...initialState },
});
return { accountsController, messenger };

const triggerMultichainNetworkChange = ({
evmClientId,
nonEvmChainId,
}: {
evmClientId?: string;
nonEvmChainId?: CaipChainId;
}) => {
messenger.publish('MultichainNetworkController:setActiveNetwork', {
evmClientId,
nonEvmChainId,
});
};

return { accountsController, messenger, triggerMultichainNetworkChange };
}

describe('AccountsController', () => {
const mockBtcAccount = createExpectedInternalAccount({
id: 'mock-non-evm',
name: 'non-evm',
address: 'bc1qzqc2aqlw8nwa0a05ehjkk7dgt8308ac7kzw9a6',
keyringType: KeyringTypes.snap,
type: BtcAccountType.P2wpkh,
});

const mockOlderEvmAccount = createExpectedInternalAccount({
id: 'mock-id-1',
name: 'mock account 1',
address: 'mock-address-1',
keyringType: KeyringTypes.hd,
lastSelected: 11111,
});
const mockNewerEvmAccount = createExpectedInternalAccount({
id: 'mock-id-2',
name: 'mock account 2',
address: 'mock-address-2',
keyringType: KeyringTypes.hd,
lastSelected: 22222,
});

describe('onSnapStateChange', () => {
it('be used enable an account if the Snap is enabled and not blocked', async () => {
const messenger = buildMessenger();
Expand Down Expand Up @@ -1514,6 +1556,63 @@
});
});

describe('handle MultichainNetworkController:setActiveNetwork event', () => {
it('should update selected account to non-EVM account when switching to non-EVM network', () => {
const messenger = buildMessenger();
const { accountsController, triggerMultichainNetworkChange } =
setupAccountsController({
initialState: {
internalAccounts: {
accounts: {
[mockOlderEvmAccount.id]: mockOlderEvmAccount,
[mockNewerEvmAccount.id]: mockNewerEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: mockNewerEvmAccount.id,
},
},
messenger,
});

// Triggered from network switch to Bitcoin mainnet
triggerMultichainNetworkChange({
nonEvmChainId: BtcScope.Mainnet,
});

// BTC account is now selected
expect(accountsController.state.internalAccounts.selectedAccount).toBe(
mockBtcAccount.id,
);
});

it('should update selected account to EVM account when switching to EVM network', () => {
const messenger = buildMessenger();
const { accountsController, triggerMultichainNetworkChange } =
setupAccountsController({
initialState: {
internalAccounts: {
accounts: {
[mockNewerEvmAccount.id]: mockNewerEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: mockBtcAccount.id,
},
},
messenger,
});

// Triggered from network switch to Bitcoin mainnet
triggerMultichainNetworkChange({
evmClientId: EthScope.Mainnet,
});

// ETH mainnet account is now selected
expect(accountsController.state.internalAccounts.selectedAccount).toBe(
mockNewerEvmAccount.id,
);
});
});

describe('updateAccounts', () => {
const mockAddress1 = '0x123';
const mockAddress2 = '0x456';
Expand Down Expand Up @@ -2144,29 +2243,6 @@
});

describe('getSelectedAccount', () => {
const mockNonEvmAccount = createExpectedInternalAccount({
id: 'mock-non-evm',
name: 'non-evm',
address: 'bc1qzqc2aqlw8nwa0a05ehjkk7dgt8308ac7kzw9a6',
keyringType: KeyringTypes.snap,
type: BtcAccountType.P2wpkh,
});

const mockOlderEvmAccount = createExpectedInternalAccount({
id: 'mock-id-1',
name: 'mock account 1',
address: 'mock-address-1',
keyringType: KeyringTypes.hd,
lastSelected: 11111,
});
const mockNewerEvmAccount = createExpectedInternalAccount({
id: 'mock-id-2',
name: 'mock account 2',
address: 'mock-address-2',
keyringType: KeyringTypes.hd,
lastSelected: 22222,
});

it.each([
{
lastSelectedAccount: mockNewerEvmAccount,
Expand All @@ -2177,7 +2253,7 @@
expected: mockOlderEvmAccount,
},
{
lastSelectedAccount: mockNonEvmAccount,
lastSelectedAccount: mockBtcAccount,
expected: mockNewerEvmAccount,
},
])(
Expand All @@ -2189,7 +2265,7 @@
accounts: {
[mockOlderEvmAccount.id]: mockOlderEvmAccount,
[mockNewerEvmAccount.id]: mockNewerEvmAccount,
[mockNonEvmAccount.id]: mockNonEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: lastSelectedAccount.id,
},
Expand All @@ -2205,9 +2281,9 @@
initialState: {
internalAccounts: {
accounts: {
[mockNonEvmAccount.id]: mockNonEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: mockNonEvmAccount.id,
selectedAccount: mockBtcAccount.id,
},
},
});
Expand All @@ -2234,29 +2310,6 @@
});

describe('getSelectedMultichainAccount', () => {
const mockNonEvmAccount = createExpectedInternalAccount({
id: 'mock-non-evm',
name: 'non-evm',
address: 'bc1qzqc2aqlw8nwa0a05ehjkk7dgt8308ac7kzw9a6',
keyringType: KeyringTypes.snap,
type: BtcAccountType.P2wpkh,
});

const mockOlderEvmAccount = createExpectedInternalAccount({
id: 'mock-id-1',
name: 'mock account 1',
address: 'mock-address-1',
keyringType: KeyringTypes.hd,
lastSelected: 11111,
});
const mockNewerEvmAccount = createExpectedInternalAccount({
id: 'mock-id-2',
name: 'mock account 2',
address: 'mock-address-2',
keyringType: KeyringTypes.hd,
lastSelected: 22222,
});

it.each([
{
chainId: undefined,
Expand All @@ -2265,18 +2318,18 @@
},
{
chainId: undefined,
selectedAccount: mockNonEvmAccount,
expected: mockNonEvmAccount,
selectedAccount: mockBtcAccount,
expected: mockBtcAccount,
},
{
chainId: 'eip155:1',
selectedAccount: mockNonEvmAccount,
selectedAccount: mockBtcAccount,
expected: mockNewerEvmAccount,
},
{
chainId: 'bip122:000000000019d6689c085ae165831e93',
selectedAccount: mockNonEvmAccount,
expected: mockNonEvmAccount,
selectedAccount: mockBtcAccount,
expected: mockBtcAccount,
},
])(
"chainId $chainId with selectedAccount '$selectedAccount.id' should return $expected.id",
Expand All @@ -2287,7 +2340,7 @@
accounts: {
[mockOlderEvmAccount.id]: mockOlderEvmAccount,
[mockNewerEvmAccount.id]: mockNewerEvmAccount,
[mockNonEvmAccount.id]: mockNonEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: selectedAccount.id,
},
Expand All @@ -2312,9 +2365,9 @@
accounts: {
[mockOlderEvmAccount.id]: mockOlderEvmAccount,
[mockNewerEvmAccount.id]: mockNewerEvmAccount,
[mockNonEvmAccount.id]: mockNonEvmAccount,
[mockBtcAccount.id]: mockBtcAccount,
},
selectedAccount: mockNonEvmAccount.id,
selectedAccount: mockBtcAccount.id,
},
},
});
Expand Down
Loading
Loading