Skip to content
Open
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
2 changes: 2 additions & 0 deletions packages/wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add an optional `logger` option to `WalletOptions` for initialization diagnostics ([#9097](https://github.com/MetaMask/core/pull/9097))
- When provided (e.g. `{ logger: console }`), a `[wallet] ${name}: initialized` breadcrumb is emitted via `logger.info` immediately after each controller's `init()` completes, in initialization order. Defaults to no output.
- **BREAKING:** Add `AccountsController` and `ConnectivityController` as default initialized controllers ([#8924](https://github.com/MetaMask/core/pull/8924))
- Passing `instanceOptions.connectivityController.connectivityAdapter` is now required.
- Export `AlwaysOnlineAdapter` from the package root for environments without a platform-specific network API (e.g. Node/tests).
Expand Down
46 changes: 46 additions & 0 deletions packages/wallet/src/Wallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Json } from '@metamask/utils';
import { webcrypto } from 'crypto';

import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor';
import { defaultConfigurations } from './initialization/defaults';
import * as initializationModule from './initialization/initialization';
import { AlwaysOnlineAdapter } from './initialization/instances/connectivity-controller/always-online-adapter';
import { importSecretRecoveryPhrase } from './utilities';
Expand Down Expand Up @@ -149,6 +150,51 @@ describe('Wallet', () => {
expect((state as Record<string, Json>).TestService).toBeUndefined();
});

it('logs an initialization breadcrumb for each controller in order when a logger is provided', () => {
const info = jest.fn();

const wallet = new Wallet({
logger: { info },
instanceOptions: {
connectivityController: {
connectivityAdapter: new AlwaysOnlineAdapter(),
},
storageService: {
storage: new InMemoryStorageAdapter(),
},
remoteFeatureFlagController: REMOTE_FEATURE_FLAG_OPTIONS,
},
});

const loggedMessages = info.mock.calls.map(([message]) => message);
const expectedMessages = Object.values(defaultConfigurations).map(
(config) => `[wallet] ${config.name}: initialized`,
);

expect(loggedMessages).toStrictEqual(expectedMessages);
// The constructed wallet exposes the controllers it logged.
expect(
wallet.getInstance(defaultConfigurations.keyringController.name),
).toBeDefined();
});

it('does not throw when no logger is provided', () => {
expect(
() =>
new Wallet({
instanceOptions: {
connectivityController: {
connectivityAdapter: new AlwaysOnlineAdapter(),
},
storageService: {
storage: new InMemoryStorageAdapter(),
},
remoteFeatureFlagController: REMOTE_FEATURE_FLAG_OPTIONS,
},
}),
).not.toThrow();
});

it('exposes controllerMetadata for each initialized controller', async () => {
const wallet = await setupWallet();

Expand Down
2 changes: 2 additions & 0 deletions packages/wallet/src/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export class Wallet {
* required beyond the ones included by default.
* @param options.instanceOptions - An optional object containing options that should be passed
* to specific instances for additional customization.
* @param options.logger - An optional logger used to emit a breadcrumb after each controller's
* initialization completes. Defaults to no output.
*/
constructor(options: WalletOptions) {
this.#messenger =
Expand Down
3 changes: 3 additions & 0 deletions packages/wallet/src/initialization/initialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function initialize(options: InitializeOptions): DefaultInstances {
state = {},
initializationConfigurations = [],
instanceOptions,
logger,
} = options;

const overriddenConfiguration = initializationConfigurations.map(
Expand Down Expand Up @@ -55,6 +56,8 @@ export function initialize(options: InitializeOptions): DefaultInstances {
});

instances[name] = instance;

logger?.info(`[wallet] ${name}: initialized`);
}

return instances as DefaultInstances;
Expand Down
6 changes: 6 additions & 0 deletions packages/wallet/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export type WalletOptions = {
unknown
>[];
instanceOptions: InstanceSpecificOptions;
/**
* An optional logger used to emit initialization diagnostics. When provided,
* a breadcrumb is logged immediately after each controller's `init()`
* completes, in initialization order. Defaults to no output.
*/
logger?: Pick<Console, 'info'>;
};

export type InstanceSpecificOptions = {
Expand Down
Loading