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
10 changes: 10 additions & 0 deletions packages/keyring-internal-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add `KeyringInternalFeature` and `KeyringInternalFeatures` support ([#423](https://github.com/MetaMask/accounts/pull/423))
- They can be used to describe the internal feature supported by a keyring (for internal use).

### Removed

- **BREAKING:** Remove `KeyringVersion` support ([#423](https://github.com/MetaMask/accounts/pull/423))
- Use `KeyringInternalFeature` and `KeyringInternalFeatures` instead.

## [9.1.1]

### Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/keyring-internal-api/src/compatibility/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './v1';
export * from './legacy';
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { EthMethod, EthScope } from '@metamask/keyring-api';

import { toKeyringRequestV1 } from './v1';
import { toLegacyKeyringRequest } from './legacy';

describe('v1', () => {
describe('toKeyringRequestV1', () => {
describe('toLegacyKeyringRequest', () => {
const request = {
id: 'mock-request-id',
scope: EthScope.Mainnet,
Expand All @@ -17,7 +17,7 @@ describe('v1', () => {
const { origin, ...requestV1 } = request;

it('converts a keyring request to a keyring request v1', () => {
expect(toKeyringRequestV1(request)).toStrictEqual(requestV1);
expect(toLegacyKeyringRequest(request)).toStrictEqual(requestV1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,30 @@ import { omit, type Infer } from '@metamask/superstruct';
/**
* Keyring request (v1).
*/
export const KeyringRequestV1Struct = omit(KeyringRequestStruct, ['origin']);
export const LegacyKeyringRequestStruct = omit(KeyringRequestStruct, [
'origin',
]);

export type KeyringRequestV1 = Infer<typeof KeyringRequestV1Struct>;
export type LegacyKeyringRequest = Infer<typeof LegacyKeyringRequestStruct>;

/**
* Response to a call to `submitRequest` (v1).
*/
export const KeyringResponseV1Struct = KeyringResponseStruct;
export const LegacyKeyringResponseStruct = KeyringResponseStruct;

export type KeyringResponseV1 = Infer<typeof KeyringResponseV1Struct>;
export type LegacyKeyringResponse = Infer<typeof LegacyKeyringResponseStruct>;

export const SubmitRequestResponseV1Struct = KeyringResponseV1Struct;
export const SubmitRequestResponseV1Struct = LegacyKeyringResponseStruct;

/**
* Converts a keyring request to a keyring request v1.
*
* @param request - A keyring request.
* @returns A keyring request v1.
*/
export function toKeyringRequestV1(request: KeyringRequest): KeyringRequestV1 {
export function toLegacyKeyringRequest(
request: KeyringRequest,
): LegacyKeyringRequest {
const { origin, ...requestV1 } = request;

return requestV1;
Expand Down
12 changes: 7 additions & 5 deletions packages/keyring-internal-api/src/versions.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export enum KeyringVersion {
/** Default. */
V1 = 'v1',

export enum KeyringInternalFeature {
/**
* Introduction of `KeyringRequest.origin`.
*
* Snap will now receive the `origin` as part of a `KeyringRequest` when `submitRequest` is invoked.
* We also expect Snaps to display this `origin` in their confirmation screens (if any).
*/
V2 = 'v2',
UseOrigin = 'use-origin',
}

/**
* Type representing a set of keyring internal features.
*/
export type KeyringInternalFeatures = Set<KeyringInternalFeature>;
4 changes: 4 additions & 0 deletions packages/keyring-internal-snap-client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump `@metamask/snaps-sdk` from `^9.0.0` to `^10.3.0` ([#422](https://github.com/MetaMask/accounts/pull/422))
- Bump `@metamask/snaps-utils` from `^11.0.0` to `^11.7.0` ([#422](https://github.com/MetaMask/accounts/pull/422))

### Removed

- **BREAKING:** Rename `submitRequestV1` method to `submitLegacyRequest` ([#423](https://github.com/MetaMask/accounts/pull/423))

## [8.0.1]

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
EthScope,
type KeyringAccount,
} from '@metamask/keyring-api';
import type { KeyringRequestV1 } from '@metamask/keyring-internal-api';
import type { LegacyKeyringRequest } from '@metamask/keyring-internal-api';
import type { SnapId } from '@metamask/snaps-sdk';

import {
Expand Down Expand Up @@ -87,8 +87,8 @@ describe('KeyringInternalSnapClient', () => {
});
});

describe('submitRequestV1', () => {
const keyringRequest: KeyringRequestV1 = {
describe('submitLegacyRequest', () => {
const keyringRequest: LegacyKeyringRequest = {
id: 'mock-request-id',
scope: EthScope.Mainnet,
account: MOCK_ACCOUNT.id,
Expand All @@ -109,7 +109,7 @@ describe('KeyringInternalSnapClient', () => {
},
};

it('calls the submitRequestV1 method', async () => {
it('calls the submitLegacyRequest method', async () => {
const client = new KeyringInternalSnapClient({
messenger: messenger as unknown as KeyringInternalSnapClientMessenger,
snapId,
Expand All @@ -119,7 +119,7 @@ describe('KeyringInternalSnapClient', () => {
pending: false,
result: null,
});
await client.submitRequestV1(keyringRequest);
await client.submitLegacyRequest(keyringRequest);
expect(messenger.call).toHaveBeenCalledWith(
'SnapController:handleRequest',
request,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { KeyringRpcMethod } from '@metamask/keyring-api';
import type {
KeyringRequestV1,
KeyringResponseV1,
LegacyKeyringRequest,
LegacyKeyringResponse,
} from '@metamask/keyring-internal-api';
import { SubmitRequestResponseV1Struct } from '@metamask/keyring-internal-api';
import { KeyringClient, type Sender } from '@metamask/keyring-snap-client';
Expand Down Expand Up @@ -131,7 +131,9 @@ export class KeyringInternalSnapClient extends KeyringClient {
* @param request - Keyring request.
* @returns Keyring request's response.
*/
async submitRequestV1(request: KeyringRequestV1): Promise<KeyringResponseV1> {
async submitLegacyRequest(
request: LegacyKeyringRequest,
): Promise<LegacyKeyringResponse> {
return strictMask(
await this.send({
method: KeyringRpcMethod.SubmitRequest,
Expand Down
7 changes: 7 additions & 0 deletions packages/keyring-snap-bridge/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump `@metamask/snaps-sdk` from `^9.0.0` to `^10.3.0` ([#422](https://github.com/MetaMask/accounts/pull/422))
- Bump `@metamask/snaps-utils` from `^11.0.0` to `^11.7.0` ([#422](https://github.com/MetaMask/accounts/pull/422))

### Removed

- **BREAKING:** Remove `KeyringVersion` support ([#423](https://github.com/MetaMask/accounts/pull/423))
- Both `getKeyringVersionFromPlatform`, `PLATFORM_VERSION_TO_KEYRING_VERSION` got removed too.
- Use `KeyringInternalFeature` instead.
- **BREAKING:** Rename `submitRequestV1` method to `submitLegacyRequest` ([#423](https://github.com/MetaMask/accounts/pull/423))

## [18.0.2]

### Fixed
Expand Down
67 changes: 24 additions & 43 deletions packages/keyring-snap-bridge/src/SnapKeyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type {
ResolvedAccountAddress,
CaipChainId,
MetaMaskOptions,
KeyringRequest,
KeyringResponse,
} from '@metamask/keyring-api';
import {
Expand All @@ -28,10 +27,13 @@ import {
AccountTransactionsUpdatedEventStruct,
AnyAccountType,
} from '@metamask/keyring-api';
import type {
KeyringInternalFeatures,
InternalAccount,
} from '@metamask/keyring-internal-api';
import {
KeyringVersion,
toKeyringRequestV1,
type InternalAccount,
KeyringInternalFeature,
toLegacyKeyringRequest,
} from '@metamask/keyring-internal-api';
import { KeyringInternalSnapClient } from '@metamask/keyring-internal-snap-client';
import {
Expand Down Expand Up @@ -84,7 +86,7 @@ import {
toJson,
unique,
} from './util';
import { getKeyringVersionFromPlatform } from './versions';
import { getKeyringFeaturesFromPlatform } from './versions';

export const SNAP_KEYRING_TYPE = 'Snap Keyring';

Expand Down Expand Up @@ -248,13 +250,13 @@ export class SnapKeyring {
}

/**
* Gets keyring's version for a given Snap.
* Gets keyring's features for a given Snap.
*
* @param snapId - The Snap ID.
* @returns The Snap's keyring version.
* @returns The Snap's keyring features.
*/
#getKeyringVersion(snapId: SnapId): KeyringVersion {
return getKeyringVersionFromPlatform((version: SemVerVersion) => {
#getKeyringFeatures(snapId: SnapId): KeyringInternalFeatures {
return getKeyringFeaturesFromPlatform((version: SemVerVersion) => {
return this.#messenger.call(
'SnapController:isMinimumPlatformVersion',
snapId,
Expand Down Expand Up @@ -1012,34 +1014,6 @@ export class SnapKeyring {
});
}

/**
* Submits a request to a Snap and fix-up the payload depending on the version currently supported.
*
* @param options - The options for the Snap request.
* @param options.version - The supported keyring version for the Snap.
* @param options.snapId - The Snap ID to submit the request to.
* @param options.request - The Snap request.
* @returns A promise that resolves to the keyring response from the Snap.
*/
async #submitSnapRequestForVersion({
snapId,
version,
request,
}: {
snapId: SnapId;
version: KeyringVersion;
request: KeyringRequest;
}): Promise<KeyringResponse> {
// Get specific client for that Snap.
const client = this.#snapClient.withSnapId(snapId);

if (version === KeyringVersion.V1) {
return await client.submitRequestV1(toKeyringRequestV1(request));
}

return await client.submitRequest(request);
}

/**
* Submits a request to a Snap.
*
Expand Down Expand Up @@ -1093,7 +1067,7 @@ export class SnapKeyring {
);

try {
const version = this.#getKeyringVersion(snapId);
const features = this.#getKeyringFeatures(snapId);

const request = {
id: requestId,
Expand All @@ -1108,11 +1082,18 @@ export class SnapKeyring {

log('Submit Snap request: ', request);

const response = await this.#submitSnapRequestForVersion({
version,
snapId,
request,
});
// Get specific client for that Snap.
const client = this.#snapClient.withSnapId(snapId);

let response: KeyringResponse;
if (features.has(KeyringInternalFeature.UseOrigin)) {
response = await client.submitRequest(request);
} else {
// LegacyV1 keyring request did not support the `origin` field.
response = await client.submitLegacyRequest(
toLegacyKeyringRequest(request),
);
}

// Some methods, like the ones used to prepare and patch user operations,
// require the Snap to answer synchronously in order to work with the
Expand Down
26 changes: 13 additions & 13 deletions packages/keyring-snap-bridge/src/versions.test.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import { KeyringVersion } from '@metamask/keyring-internal-api';
import { KeyringInternalFeature } from '@metamask/keyring-internal-api';
import { isValidSemVerVersion, type SemVerVersion } from '@metamask/utils';

import {
getKeyringVersionFromPlatform,
PLATFORM_VERSION_TO_KEYRING_VERSION,
getKeyringFeaturesFromPlatform,
PLATFORM_VERSION_TO_KEYRING_FEATURES,
} from './versions';

describe('getKeyringVersionFromPlatform', () => {
it('gets the keyring version v1 as default', () => {
describe('getKeyringFeaturesFromPlatform', () => {
it('gets an empty feature set as default', () => {
const isSupportedVersion = (): boolean => false;

expect(getKeyringVersionFromPlatform(isSupportedVersion)).toBe(
KeyringVersion.V1,
expect(getKeyringFeaturesFromPlatform(isSupportedVersion)).toStrictEqual(
new Set(),
);
});

it('gets the keyring version v2 if the platform version is 7.0.0', () => {
it('gets the UseOrigin feature if the platform version is 7.0.0', () => {
const isSupportedVersion = (version: SemVerVersion): boolean => {
return version === '7.0.0';
};

expect(getKeyringVersionFromPlatform(isSupportedVersion)).toBe(
KeyringVersion.V2,
expect(getKeyringFeaturesFromPlatform(isSupportedVersion)).toStrictEqual(
new Set([KeyringInternalFeature.UseOrigin]),
);
});
});

describe('PLATFORM_VERSION_TO_KEYRING_VERSION', () => {
it.each(PLATFORM_VERSION_TO_KEYRING_VERSION)(
describe('PLATFORM_VERSION_TO_KEYRING_FEATURES', () => {
it.each(PLATFORM_VERSION_TO_KEYRING_FEATURES)(
'is a valid semver version: %s',
// `PLATFORM_VERSION_TO_KEYRING_VERSION` items are flattened by `it.each`, no need
// `PLATFORM_VERSION_TO_KEYRING_FEATURES` items are flattened by `it.each`, no need
// to destructure the tuple here.
(version) => {
expect(isValidSemVerVersion(version)).toBe(true);
Expand Down
Loading
Loading