Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
18 changes: 16 additions & 2 deletions app/scripts/metamask-controller.actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,27 @@ describe('MetaMaskController', function () {
await metamaskController.createNewVaultAndRestore('test@123', TEST_SEED);
const result2 = metamaskController.keyringController.state;

expect(result1.keyrings).toHaveLength(2);
expect(result1.keyrings[0].metadata.id).toBe(mockULIDs[0]); // 0: Primary HD keyring
expect(result1.keyrings[1].metadata.id).toBe(mockULIDs[1]); // 1: Snap keyring

// On restore, a new keyring metadata is generated.
expect(result1.keyrings[0].metadata.id).toBe(mockULIDs[0]);
const ulidNewIndex = 2;
expect(result2).toStrictEqual({
...result1,
keyrings: [
{
...result1.keyrings[0],
metadata: {
...result1.keyrings[0].metadata,
id: mockULIDs[1],
id: mockULIDs[ulidNewIndex + 0], // 0: New primary HD keyring
},
},
{
...result1.keyrings[1],
metadata: {
...result1.keyrings[1].metadata,
id: mockULIDs[ulidNewIndex + 1], // 1: New Snap keyring
},
},
],
Expand Down Expand Up @@ -817,6 +828,9 @@ describe('MetaMaskController', function () {
)
.mockResolvedValue();

// We now need the Snap keyring after unlocking the wallet.
jest.spyOn(metamaskController, 'getSnapKeyring').mockReturnValue({});

const syncAndUnlockResult =
await metamaskController.syncPasswordAndUnlockWallet(password);

Expand Down
83 changes: 82 additions & 1 deletion app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,44 @@ export default class MetamaskController extends EventEmitter {
}
return snapKeyring;
}

/**
* Get the snap keyring instance if available.
*
* @returns {SnapKeyring}
*/
getSnapKeyringIfAvailable() {
// Check if the controller has been unlocked, otherwise this will throw.
if (this.keyringController.isUnlocked()) {
// TODO: Use `withKeyring` instead
const [snapKeyring] = this.keyringController.getKeyringsByType(
KeyringType.snap,
);

return snapKeyring;
}
return undefined;
}

/**
* Forward currently selected account group to the Snap keyring.
*
* @param snapKeyring - Snap keyring instance or undefined if not available.
* @param groupId - Currently selected account group.
*/
async forwardSelectedAccountGroupToSnapKeyring(snapKeyring, groupId) {
if (!snapKeyring) {
// Nothing to forward if the Snap keyring is not available.
return;
}

if (groupId) {
const group = this.accountTreeController.getAccountGroupObject(groupId);
if (group) {
await snapKeyring.setSelectedAccounts(group.accounts);
}
}
}
///: END:ONLY_INCLUDE_IF

trackInsightSnapView(snapId) {
Expand Down Expand Up @@ -1611,7 +1649,15 @@ export default class MetamaskController extends EventEmitter {
// wallet_notify for solana accountChanged when selected account group changes
this.controllerMessenger.subscribe(
`${this.accountTreeController.name}:selectedAccountGroupChange`,
() => {
(groupId) => {
// TODO: Move this logic to the SnapKeyring directly.
// Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts.
// eslint-disable-next-line no-void
void this.forwardSelectedAccountGroupToSnapKeyring(
this.getSnapKeyringIfAvailable(),
groupId,
);

const [account] =
this.accountTreeController.getAccountsFromSelectedAccountGroup({
scopes: [SolScope.Mainnet],
Expand Down Expand Up @@ -1658,6 +1704,23 @@ export default class MetamaskController extends EventEmitter {
},
);

// TODO: Move this logic to the SnapKeyring directly.
// Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts.
this.controllerMessenger.subscribe(
`${this.multichainAccountService.name}:multichainAccountGroupUpdated`,
(group) => {
// If the current group gets updated, then maybe there are more accounts being "selected"
// now, so we have to forward them to the Snap keyring too!
if (this.accountTreeController.getSelectedAccountGroup() === group.id) {
// eslint-disable-next-line no-void
void this.forwardSelectedAccountGroupToSnapKeyring(
this.getSnapKeyringIfAvailable(),
group.id,
);
}
},
);

this.controllerMessenger.subscribe(
`${this.permissionController.name}:stateChange`,
async (currentValue, previousValue) => {
Expand Down Expand Up @@ -4028,6 +4091,12 @@ export default class MetamaskController extends EventEmitter {
await this.accountsController.updateAccounts();
// Then we can build the initial tree.
this.accountTreeController.init();
// TODO: Move this logic to the SnapKeyring directly.
// Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts.
await this.forwardSelectedAccountGroupToSnapKeyring(
await this.getSnapKeyring(),
this.accountTreeController.getSelectedAccountGroup(),
);

return primaryKeyring;
} finally {
Expand Down Expand Up @@ -4411,6 +4480,12 @@ export default class MetamaskController extends EventEmitter {
// TODO: Remove this once the `accounts-controller` once only
// depends only on keyrings `:stateChange`.
this.accountTreeController.reinit();
// TODO: Move this logic to the SnapKeyring directly.
// Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts.
await this.forwardSelectedAccountGroupToSnapKeyring(
await this.getSnapKeyring(),
this.accountTreeController.getSelectedAccountGroup(),
);

if (completedOnboarding) {
if (this.isMultichainAccountsFeatureState2Enabled()) {
Expand Down Expand Up @@ -4765,6 +4840,12 @@ export default class MetamaskController extends EventEmitter {
///: END:ONLY_INCLUDE_IF
// Force account-tree refresh after all accounts have been updated.
this.accountTreeController.init();
// TODO: Move this logic to the SnapKeyring directly.
// Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts.
await this.forwardSelectedAccountGroupToSnapKeyring(
await this.getSnapKeyring(),
this.accountTreeController.getSelectedAccountGroup(),
);
}

async _loginUser(password) {
Expand Down
Loading
Loading