Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions packages/accounts-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
"dependencies": {
"@ethereumjs/util": "^8.1.0",
"@metamask/base-controller": "^7.1.1",
"@metamask/eth-snap-keyring": "^8.1.1",
"@metamask/keyring-api": "^14.0.0",
"@metamask/keyring-internal-api": "^2.0.1",
"@metamask/eth-snap-keyring": "^9.0.0",
"@metamask/keyring-api": "^15.0.0",
"@metamask/keyring-internal-api": "^3.0.0",
"@metamask/snaps-sdk": "^6.7.0",
"@metamask/snaps-utils": "^8.3.0",
"@metamask/utils": "^11.0.1",
Expand Down
123 changes: 122 additions & 1 deletion packages/accounts-controller/src/AccountsController.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { ControllerMessenger } from '@metamask/base-controller';
import type {
AccountAssetListUpdatedEventPayload,
AccountBalancesUpdatedEventPayload,
AccountTransactionsUpdatedEventPayload,
} from '@metamask/keyring-api';
import {
BtcAccountType,
EthAccountType,
Expand Down Expand Up @@ -134,7 +139,7 @@ const mockAccount4: InternalAccount = {
};

class MockNormalAccountUUID {
#accountIds: Record<string, string> = {};
readonly #accountIds: Record<string, string> = {};

constructor(accounts: InternalAccount[]) {
for (const account of accounts) {
Expand Down Expand Up @@ -299,6 +304,9 @@ function buildAccountsControllerMessenger(messenger = buildMessenger()) {
allowedEvents: [
'SnapController:stateChange',
'KeyringController:stateChange',
'SnapKeyring:accountAssetListUpdated',
'SnapKeyring:accountBalancesUpdated',
'SnapKeyring:accountTransactionsUpdated',
],
allowedActions: [
'KeyringController:getAccounts',
Expand Down Expand Up @@ -1393,6 +1401,119 @@ describe('AccountsController', () => {
);
});

describe('onSnapKeyringEvents', () => {
const setupTest = () => {
const account = createExpectedInternalAccount({
id: 'mock-id',
name: 'Bitcoin Account',
address: 'tb1q4q7h8wuplrpmkxqvv6rrrq7qyhhjsj5uqcsxqu',
keyringType: KeyringTypes.snap,
snapId: 'mock-snap',
type: BtcAccountType.P2wpkh,
});

const messenger = buildMessenger();
const { accountsController } = setupAccountsController({
initialState: {
internalAccounts: {
accounts: {
[account.id]: account,
},
selectedAccount: account.id,
},
},
messenger,
});

return { messenger, account, accountsController };
};

it('re-publishes keyring events: SnapKeyring:accountBalancesUpdated', () => {
const { account, messenger } = setupTest();

const payload: AccountBalancesUpdatedEventPayload = {
balances: {
[account.id]: {
'bip122:000000000019d6689c085ae165831e93/slip44:0': {
amount: '0.1',
unit: 'BTC',
},
},
},
};

const mockRePublishedCallback = jest.fn();
messenger.subscribe(
'AccountsController:accountBalancesUpdated',
mockRePublishedCallback,
);
messenger.publish('SnapKeyring:accountBalancesUpdated', payload);
expect(mockRePublishedCallback).toHaveBeenCalledWith(payload);
});

it('re-publishes keyring events: SnapKeyring:accountAssetListUpdated', () => {
const { account, messenger } = setupTest();

const payload: AccountAssetListUpdatedEventPayload = {
assets: {
[account.id]: {
added: ['bip122:000000000019d6689c085ae165831e93/slip44:0'],
removed: ['bip122:000000000933ea01ad0ee984209779ba/slip44:0'],
},
},
};

const mockRePublishedCallback = jest.fn();
messenger.subscribe(
'AccountsController:accountAssetListUpdated',
mockRePublishedCallback,
);
messenger.publish('SnapKeyring:accountAssetListUpdated', payload);
expect(mockRePublishedCallback).toHaveBeenCalledWith(payload);
});

it('re-publishes keyring events: SnapKeyring:accountTransactionsUpdated', () => {
const { account, messenger } = setupTest();

const payload: AccountTransactionsUpdatedEventPayload = {
transactions: {
[account.id]: [
{
id: 'f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6',
timestamp: null,
chain: 'bip122:000000000019d6689c085ae165831e93',
status: 'submitted',
type: 'receive',
account: account.id,
from: [],
to: [],
fees: [
{
type: 'base',
asset: {
fungible: true,
type: 'bip122:000000000019d6689c085ae165831e93/slip44:0',
unit: 'BTC',
amount: '0.0001',
},
},
],
events: [],
},
],
},
};

const mockRePublishedCallback = jest.fn();
messenger.subscribe(
'AccountsController:accountTransactionsUpdated',
mockRePublishedCallback,
);
messenger.publish('SnapKeyring:accountTransactionsUpdated', payload);
expect(mockRePublishedCallback).toHaveBeenCalledWith(payload);
});
});

describe('updateAccounts', () => {
const mockAddress1 = '0x123';
const mockAddress2 = '0x456';
Expand Down
77 changes: 75 additions & 2 deletions packages/accounts-controller/src/AccountsController.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import type {
ControllerGetStateAction,
ControllerStateChangeEvent,
ExtractEventPayload,
RestrictedControllerMessenger,
} from '@metamask/base-controller';
import { BaseController } from '@metamask/base-controller';
import type {
SnapKeyringAccountAssetListUpdatedEvent,
SnapKeyringAccountBalancesUpdatedEvent,
SnapKeyringAccountTransactionsUpdatedEvent,
} from '@metamask/eth-snap-keyring';
import { SnapKeyring } from '@metamask/eth-snap-keyring';
import {
EthAccountType,
Expand Down Expand Up @@ -161,15 +167,38 @@ export type AccountsControllerAccountRenamedEvent = {
payload: [InternalAccount];
};

export type AllowedEvents = SnapStateChange | KeyringControllerStateChangeEvent;
export type AccountsControllerAccountBalancesUpdatesEvent = {
type: `${typeof controllerName}:accountBalancesUpdated`;
payload: SnapKeyringAccountBalancesUpdatedEvent['payload'];
};

export type AccountsControllerAccountTransactionsUpdatedEvent = {
type: `${typeof controllerName}:accountTransactionsUpdated`;
payload: SnapKeyringAccountTransactionsUpdatedEvent['payload'];
};

export type AccountsControllerAccountAssetListUpdatedEvent = {
type: `${typeof controllerName}:accountAssetListUpdated`;
payload: SnapKeyringAccountAssetListUpdatedEvent['payload'];
};

export type AllowedEvents =
| SnapStateChange
| KeyringControllerStateChangeEvent
| SnapKeyringAccountAssetListUpdatedEvent
| SnapKeyringAccountBalancesUpdatedEvent
| SnapKeyringAccountTransactionsUpdatedEvent;

export type AccountsControllerEvents =
| AccountsControllerChangeEvent
| AccountsControllerSelectedAccountChangeEvent
| AccountsControllerSelectedEvmAccountChangeEvent
| AccountsControllerAccountAddedEvent
| AccountsControllerAccountRemovedEvent
| AccountsControllerAccountRenamedEvent;
| AccountsControllerAccountRenamedEvent
| AccountsControllerAccountBalancesUpdatesEvent
| AccountsControllerAccountTransactionsUpdatedEvent
| AccountsControllerAccountAssetListUpdatedEvent;

export type AccountsControllerMessenger = RestrictedControllerMessenger<
typeof controllerName,
Expand Down Expand Up @@ -261,6 +290,33 @@ export class AccountsController extends BaseController<
(keyringState) => this.#handleOnKeyringStateChange(keyringState),
);

this.messagingSystem.subscribe(
'SnapKeyring:accountAssetListUpdated',
(snapAccountEvent) =>
this.#handleOnSnapKeyringAccountEvent(
'AccountsController:accountAssetListUpdated',
snapAccountEvent,
),
);

this.messagingSystem.subscribe(
'SnapKeyring:accountBalancesUpdated',
(snapAccountEvent) =>
this.#handleOnSnapKeyringAccountEvent(
'AccountsController:accountBalancesUpdated',
snapAccountEvent,
),
);

this.messagingSystem.subscribe(
'SnapKeyring:accountTransactionsUpdated',
(snapAccountEvent) =>
this.#handleOnSnapKeyringAccountEvent(
'AccountsController:accountTransactionsUpdated',
snapAccountEvent,
),
);

this.#registerMessageHandlers();
}

Expand Down Expand Up @@ -677,6 +733,23 @@ export class AccountsController extends BaseController<
return internalAccounts;
}

/**
* Re-publish an account event.
*
* @param event - The event type. This is a unique identifier for this event.
* @param payload - The event payload. The type of the parameters for each event handler must
* match the type of this payload.
* @template EventType - A Snap keyring event type.
*/
#handleOnSnapKeyringAccountEvent<
EventType extends AccountsControllerEvents['type'],
>(
event: EventType,
...payload: ExtractEventPayload<AccountsControllerEvents, EventType>
): void {
this.messagingSystem.publish(event, ...payload);
}

/**
* Handles changes in the keyring state, specifically when new accounts are added or removed.
*
Expand Down
6 changes: 3 additions & 3 deletions packages/assets-controllers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@
"@metamask/approval-controller": "^7.1.2",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/ethjs-provider-http": "^0.3.0",
"@metamask/keyring-api": "^14.0.0",
"@metamask/keyring-api": "^15.0.0",
"@metamask/keyring-controller": "^19.0.4",
"@metamask/keyring-internal-api": "^2.0.1",
"@metamask/keyring-snap-client": "^3.0.0",
"@metamask/keyring-internal-api": "^3.0.0",
"@metamask/keyring-snap-client": "^3.0.1",
"@metamask/network-controller": "^22.1.1",
"@metamask/preferences-controller": "^15.0.1",
"@metamask/providers": "^18.1.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/keyring-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
"@metamask/eth-hd-keyring": "^7.0.4",
"@metamask/eth-sig-util": "^8.0.0",
"@metamask/eth-simple-keyring": "^6.0.5",
"@metamask/keyring-api": "^14.0.0",
"@metamask/keyring-internal-api": "^2.0.1",
"@metamask/keyring-api": "^15.0.0",
"@metamask/keyring-internal-api": "^3.0.0",
"@metamask/message-manager": "^12.0.0",
"@metamask/utils": "^11.0.1",
"async-mutex": "^0.5.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/multichain-transactions-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
},
"dependencies": {
"@metamask/base-controller": "^7.1.1",
"@metamask/keyring-api": "^14.0.0",
"@metamask/keyring-internal-api": "^2.0.1",
"@metamask/keyring-snap-client": "^3.0.0",
"@metamask/keyring-api": "^15.0.0",
"@metamask/keyring-internal-api": "^3.0.0",
"@metamask/keyring-snap-client": "^3.0.1",
"@metamask/polling-controller": "^12.0.2",
"@metamask/snaps-controllers": "^9.10.0",
"@metamask/snaps-sdk": "^6.7.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/profile-sync-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
},
"dependencies": {
"@metamask/base-controller": "^7.1.1",
"@metamask/keyring-api": "^14.0.0",
"@metamask/keyring-api": "^15.0.0",
"@metamask/keyring-controller": "^19.0.4",
"@metamask/network-controller": "^22.1.1",
"@metamask/snaps-sdk": "^6.7.0",
Expand All @@ -117,7 +117,7 @@
"@lavamoat/preinstall-always-fail": "^2.1.0",
"@metamask/accounts-controller": "^21.0.2",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/keyring-internal-api": "^2.0.1",
"@metamask/keyring-internal-api": "^3.0.0",
"@metamask/providers": "^18.1.1",
"@metamask/snaps-controllers": "^9.10.0",
"@types/jest": "^27.4.1",
Expand Down
Loading