Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Commit

Permalink
feat!: add KeyringExecutionContext to user ops methods (#253)
Browse files Browse the repository at this point in the history
* feat!: add chainId to user ops

* refactor: remove caip helpers + use caip from @metamask/utils
  • Loading branch information
ccharly authored Mar 18, 2024
1 parent c22f7be commit 5433d91
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 110 deletions.
58 changes: 49 additions & 9 deletions src/SnapKeyring.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import type {
EthUserOperation,
EthUserOperationPatch,
KeyringAccount,
KeyringExecutionContext,
} from '@metamask/keyring-api';
import { EthAccountType, EthMethod } from '@metamask/keyring-api';
import { KeyringEvent } from '@metamask/keyring-api/dist/events';
import type { SnapController } from '@metamask/snaps-controllers';
import type { SnapId } from '@metamask/snaps-sdk';
import { KnownCaipNamespace, toCaipChainId } from '@metamask/utils';

import type { KeyringState } from '.';
import { SnapKeyring } from '.';
Expand Down Expand Up @@ -59,6 +61,10 @@ describe('SnapKeyring', () => {
},
] as const;

const executionContext: KeyringExecutionContext = {
chainId: '1',
};

beforeEach(async () => {
keyring = new SnapKeyring(
mockSnapController as unknown as SnapController,
Expand Down Expand Up @@ -908,6 +914,7 @@ describe('SnapKeyring', () => {
const baseUserOp = await keyring.prepareUserOperation(
accounts[0].address,
baseTxs,
executionContext,
);

expect(mockSnapController.handleRequest).toHaveBeenCalledWith({
Expand All @@ -920,7 +927,10 @@ describe('SnapKeyring', () => {
method: 'keyring_submitRequest',
params: {
id: expect.any(String),
scope: expect.any(String),
scope: toCaipChainId(
KnownCaipNamespace.Eip155,
executionContext.chainId,
),
account: accounts[0].id,
request: {
method: 'eth_prepareUserOperation',
Expand Down Expand Up @@ -960,6 +970,7 @@ describe('SnapKeyring', () => {
const patch = await keyring.patchUserOperation(
accounts[0].address,
userOp,
executionContext,
);

expect(mockSnapController.handleRequest).toHaveBeenCalledWith({
Expand All @@ -972,7 +983,10 @@ describe('SnapKeyring', () => {
method: 'keyring_submitRequest',
params: {
id: expect.any(String),
scope: expect.any(String),
scope: toCaipChainId(
KnownCaipNamespace.Eip155,
executionContext.chainId,
),
account: accounts[0].id,
request: {
method: 'eth_patchUserOperation',
Expand Down Expand Up @@ -1008,6 +1022,7 @@ describe('SnapKeyring', () => {
const signature = await keyring.signUserOperation(
accounts[0].address,
userOp,
executionContext,
);

expect(mockSnapController.handleRequest).toHaveBeenCalledWith({
Expand All @@ -1020,7 +1035,10 @@ describe('SnapKeyring', () => {
method: 'keyring_submitRequest',
params: {
id: expect.any(String),
scope: expect.any(String),
scope: toCaipChainId(
KnownCaipNamespace.Eip155,
executionContext.chainId,
),
account: accounts[0].id,
request: {
method: 'eth_signUserOperation',
Expand Down Expand Up @@ -1220,7 +1238,11 @@ describe('SnapKeyring', () => {
result: mockExpectedUserOp,
});

await keyring.prepareUserOperation(accounts[0].address, mockIntents);
await keyring.prepareUserOperation(
accounts[0].address,
mockIntents,
executionContext,
);

expect(mockSnapController.handleRequest).toHaveBeenCalledWith({
handler: 'onKeyringRequest',
Expand All @@ -1231,7 +1253,10 @@ describe('SnapKeyring', () => {
method: 'keyring_submitRequest',
params: {
id: expect.any(String),
scope: expect.any(String),
scope: toCaipChainId(
KnownCaipNamespace.Eip155,
executionContext.chainId,
),
account: accounts[0].id,
request: {
method: 'eth_prepareUserOperation',
Expand All @@ -1249,7 +1274,11 @@ describe('SnapKeyring', () => {
});

await expect(
keyring.prepareUserOperation(accounts[0].address, mockIntents),
keyring.prepareUserOperation(
accounts[0].address,
mockIntents,
executionContext,
),
).rejects.toThrow(regexForUUIDInRequiredSyncErrorMessage);
});
});
Expand Down Expand Up @@ -1279,7 +1308,11 @@ describe('SnapKeyring', () => {
result: mockExpectedPatch,
});

await keyring.patchUserOperation(accounts[0].address, mockUserOp);
await keyring.patchUserOperation(
accounts[0].address,
mockUserOp,
executionContext,
);

expect(mockSnapController.handleRequest).toHaveBeenCalledWith({
handler: 'onKeyringRequest',
Expand All @@ -1290,7 +1323,10 @@ describe('SnapKeyring', () => {
method: 'keyring_submitRequest',
params: {
id: expect.any(String),
scope: expect.any(String),
scope: toCaipChainId(
KnownCaipNamespace.Eip155,
executionContext.chainId,
),
account: accounts[0].id,
request: {
method: 'eth_patchUserOperation',
Expand All @@ -1308,7 +1344,11 @@ describe('SnapKeyring', () => {
});

await expect(
keyring.patchUserOperation(accounts[0].address, mockUserOp),
keyring.patchUserOperation(
accounts[0].address,
mockUserOp,
executionContext,
),
).rejects.toThrow(regexForUUIDInRequiredSyncErrorMessage);
});
});
Expand Down
26 changes: 22 additions & 4 deletions src/SnapKeyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
InternalAccount,
KeyringAccount,
KeyringResponse,
KeyringExecutionContext,
} from '@metamask/keyring-api';
import {
AccountCreatedEventStruct,
Expand All @@ -27,12 +28,15 @@ import type { SnapController } from '@metamask/snaps-controllers';
import type { SnapId } from '@metamask/snaps-sdk';
import type { Snap } from '@metamask/snaps-utils';
import type { Json } from '@metamask/utils';
import { bigIntToHex } from '@metamask/utils';
import {
bigIntToHex,
toCaipChainId,
KnownCaipNamespace,
} from '@metamask/utils';
import { EventEmitter } from 'events';
import { assert, mask, object, string } from 'superstruct';
import { v4 as uuid } from 'uuid';

import { toCaipChainId, CaipNamespaces } from './caip';
import { DeferredPromise } from './DeferredPromise';
import { KeyringSnapControllerClient } from './KeyringSnapControllerClient';
import { projectLogger as log } from './logger';
Expand Down Expand Up @@ -609,7 +613,7 @@ export class SnapKeyring extends EventEmitter {
address,
method: EthMethod.SignTransaction,
params: [tx],
chainId: toCaipChainId(CaipNamespaces.Eip155, `${chainId}`),
chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),
});

// ! It's *** CRITICAL *** that we mask the signature here, otherwise the
Expand Down Expand Up @@ -665,7 +669,9 @@ export class SnapKeyring extends EventEmitter {
params: toJson<Json[]>([address, data]),
...(chainId === undefined
? {}
: { chainId: toCaipChainId(CaipNamespaces.Eip155, `${chainId}`) }),
: {
chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),
}),
}),
EthBytesStruct,
);
Expand Down Expand Up @@ -715,18 +721,22 @@ export class SnapKeyring extends EventEmitter {
*
* @param address - Address of the sender.
* @param transactions - Base transactions to include in the UserOperation.
* @param context - Keyring execution context.
* @returns A pseudo-UserOperation that can be used to construct a real.
*/
async prepareUserOperation(
address: string,
transactions: EthBaseTransaction[],
context: KeyringExecutionContext,
): Promise<EthBaseUserOperation> {
return strictMask(
await this.#submitRequest({
address,
method: EthMethod.PrepareUserOperation,
params: toJson<Json[]>(transactions),
expectSync: true,
// We assume the chain ID is already well formatted
chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),
}),
EthBaseUserOperationStruct,
);
Expand All @@ -738,18 +748,22 @@ export class SnapKeyring extends EventEmitter {
*
* @param address - Address of the sender.
* @param userOp - UserOperation to patch.
* @param context - Keyring execution context.
* @returns A patch to apply to the UserOperation.
*/
async patchUserOperation(
address: string,
userOp: EthUserOperation,
context: KeyringExecutionContext,
): Promise<EthUserOperationPatch> {
return strictMask(
await this.#submitRequest({
address,
method: EthMethod.PatchUserOperation,
params: toJson<Json[]>([userOp]),
expectSync: true,
// We assume the chain ID is already well formatted
chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),
}),
EthUserOperationPatchStruct,
);
Expand All @@ -760,17 +774,21 @@ export class SnapKeyring extends EventEmitter {
*
* @param address - Address of the sender.
* @param userOp - UserOperation to sign.
* @param context - Leyring execution context.
* @returns The signature of the UserOperation.
*/
async signUserOperation(
address: string,
userOp: EthUserOperation,
context: KeyringExecutionContext,
): Promise<string> {
return strictMask(
await this.#submitRequest({
address,
method: EthMethod.SignUserOperation,
params: toJson<Json[]>([userOp]),
// We assume the chain ID is already well formatted
chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),
}),
EthBytesStruct,
);
Expand Down
46 changes: 0 additions & 46 deletions src/caip.test.ts

This file was deleted.

51 changes: 0 additions & 51 deletions src/caip.ts

This file was deleted.

0 comments on commit 5433d91

Please sign in to comment.