Skip to content

Commit

Permalink
Merge branch 'main' into 3922-re-simulate-transactions-for-every-new-…
Browse files Browse the repository at this point in the history
…block
  • Loading branch information
OGPoyraz authored Jan 28, 2025
2 parents f3d5e31 + bd681cf commit f159aea
Show file tree
Hide file tree
Showing 24 changed files with 1,146 additions and 1,578 deletions.
2 changes: 1 addition & 1 deletion eslint-warning-thresholds.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"@typescript-eslint/no-unsafe-enum-comparison": 34,
"@typescript-eslint/no-unused-vars": 41,
"@typescript-eslint/prefer-promise-reject-errors": 33,
"@typescript-eslint/prefer-readonly": 147,
"@typescript-eslint/prefer-readonly": 143,
"import-x/namespace": 189,
"import-x/no-named-as-default": 1,
"import-x/no-named-as-default-member": 8,
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": "288.0.0",
"version": "289.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 @@ -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
11 changes: 11 additions & 0 deletions packages/assets-controllers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add `onBreak` and `onDegraded` methods to `CodefiTokenPricesServiceV2` ([#5109](https://github.com/MetaMask/core/pull/5109))
- These serve the same purpose as the `onBreak` and `onDegraded` constructor options, but align more closely with the Cockatiel policy API.

### Changed

- Deprecate `ClientConfigApiService` constructor options `onBreak` and `onDegraded` in favor of methods ([#5109](https://github.com/MetaMask/core/pull/5109))
- Add `@metamask/controller-utils@^11.4.5` as a dependency ([#5109](https://github.com/MetaMask/core/pull/5109))
- `cockatiel` should still be in the dependency tree because it's now a dependency of `@metamask/controller-utils`

## [46.0.1]

### Changed
Expand Down
7 changes: 3 additions & 4 deletions packages/assets-controllers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@metamask/contract-metadata": "^2.4.0",
"@metamask/controller-utils": "^11.4.5",
"@metamask/eth-query": "^4.0.0",
"@metamask/keyring-api": "^15.0.0",
"@metamask/metamask-eth-abis": "^3.1.1",
"@metamask/polling-controller": "^12.0.2",
"@metamask/rpc-errors": "^7.0.2",
Expand All @@ -68,7 +69,6 @@
"async-mutex": "^0.5.0",
"bitcoin-address-validation": "^2.2.3",
"bn.js": "^5.2.1",
"cockatiel": "^3.1.2",
"immer": "^9.0.6",
"lodash": "^4.17.21",
"multiformats": "^13.1.0",
Expand All @@ -81,10 +81,9 @@
"@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-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
16 changes: 6 additions & 10 deletions packages/assets-controllers/src/TokenRatesController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2093,11 +2093,9 @@ describe('TokenRatesController', () => {
price: 0.002,
},
}),
validateCurrencySupported: jest.fn().mockReturnValue(
false,
// Cast used because this method has an assertion in the return
// value that I don't know how to type properly with Jest's mock.
) as unknown as AbstractTokenPricesService['validateCurrencySupported'],
validateCurrencySupported(_currency: unknown): _currency is string {
return false;
},
});
nock('https://min-api.cryptocompare.com')
.get('/data/price')
Expand Down Expand Up @@ -2288,11 +2286,9 @@ describe('TokenRatesController', () => {
value: 0.002,
},
}),
validateChainIdSupported: jest.fn().mockReturnValue(
false,
// Cast used because this method has an assertion in the return
// value that I don't know how to type properly with Jest's mock.
) as unknown as AbstractTokenPricesService['validateChainIdSupported'],
validateChainIdSupported(_chainId: unknown): _chainId is Hex {
return false;
},
});
await withController(
{
Expand Down
2 changes: 1 addition & 1 deletion packages/assets-controllers/src/TokenRatesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export class TokenRatesController extends StaticIntervalPollingController<TokenR

#pollState = PollState.Inactive;

#tokenPricesService: AbstractTokenPricesService;
readonly #tokenPricesService: AbstractTokenPricesService;

#inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ServicePolicy } from '@metamask/controller-utils';
import type { Hex } from '@metamask/utils';

/**
Expand Down Expand Up @@ -53,7 +54,7 @@ export type AbstractTokenPricesService<
ChainId extends Hex = Hex,
TokenAddress extends Hex = Hex,
Currency extends string = string,
> = {
> = Partial<Pick<ServicePolicy, 'onBreak' | 'onDegraded'>> & {
/**
* Retrieves prices in the given currency for the tokens identified by the
* given addresses which are expected to live on the given chain.
Expand Down
Loading

0 comments on commit f159aea

Please sign in to comment.