Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.
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
10 changes: 5 additions & 5 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ module.exports = {
coverageProvider: 'babel',

// A list of reporter names that Jest uses when writing coverage reports
coverageReporters: ['html', 'json-summary', 'text'],
coverageReporters: ['html', 'json-summary', 'text', 'lcov'],

// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 90.38,
functions: 96.61,
lines: 97.38,
statements: 97.44,
branches: 90.17,
functions: 96.82,
lines: 97.5,
statements: 97.56,
},
},
preset: 'ts-jest',
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@metamask/eth-hd-keyring": "^7.0.1",
"@metamask/eth-sig-util": "^7.0.0",
"@metamask/eth-simple-keyring": "^6.0.1",
"@metamask/keyring-api": "^2.0.0",
"@metamask/obs-store": "^9.0.0",
"@metamask/utils": "^8.2.0"
},
Expand All @@ -72,7 +73,7 @@
"depcheck": "^1.4.7",
"eslint": "^8.48.0",
"eslint-config-prettier": "^8.7.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-import": "~2.26.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-jsdoc": "^41",
"eslint-plugin-n": "^15.7.0",
Expand Down Expand Up @@ -100,8 +101,8 @@
"lavamoat": {
"allowScripts": {
"@lavamoat/preinstall-always-fail": false,
"@metamask/eth-hd-keyring>eth-simple-keyring>eth-sig-util>ethereumjs-util>keccak": false,
"@metamask/eth-hd-keyring>eth-simple-keyring>eth-sig-util>ethereumjs-util>secp256k1": false
"@metamask/keyring-api>@metamask/snaps-utils>@metamask/permission-controller>@metamask/controller-utils>ethereumjs-util>ethereum-cryptography>keccak": false,
"@metamask/keyring-api>@metamask/snaps-utils>@metamask/permission-controller>@metamask/controller-utils>ethereumjs-util>ethereum-cryptography>secp256k1": false
}
}
}
215 changes: 214 additions & 1 deletion src/KeyringController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
KeyringMockWithDestroy,
baseTransactionMockFactory,
KeyringMockWithSignTransaction,
KeyringMockWithUserOp,
} from './test';
import type { KeyringControllerArgs } from './types';

Expand Down Expand Up @@ -1476,8 +1477,220 @@ describe('KeyringController', () => {
});
});

describe('signUserOperation', () => {
it('prepares a base UserOperation', async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
constructorOptions: {
keyringBuilders: [keyringBuilderFactory(KeyringMockWithUserOp)],
},
});

await keyringController.addNewKeyring(KeyringMockWithUserOp.type);
const sender = '0x998B3FBB8159aF51a827DBf43A8054A5A3A28c95';
const baseTxs = [
{
to: '0x8cBC0EA145491fe83104abA9ef916f8632367227',
value: '0x0',
data: '0x',
},
];

const baseUserOp = {
callData: '0x7064',
initCode: '0x22ff',
nonce: '0x1',
gasLimits: {
callGasLimit: '0x58a83',
verificationGasLimit: '0xe8c4',
preVerificationGas: '0xc57c',
},
dummySignature: '0x0000',
dummyPaymasterAndData: '0x',
bundlerUrl: 'https://bundler.example.com/rpc',
};

jest
.spyOn(KeyringMockWithUserOp.prototype, 'getAccounts')
.mockResolvedValueOnce([sender]);

jest
.spyOn(KeyringMockWithUserOp.prototype, 'prepareUserOperation')
.mockResolvedValueOnce(baseUserOp);

const result = await keyringController.prepareUserOperation(
sender,
baseTxs,
);

expect(result).toStrictEqual(baseUserOp);
});

it('patches an UserOperation', async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
constructorOptions: {
keyringBuilders: [keyringBuilderFactory(KeyringMockWithUserOp)],
},
});

await keyringController.addNewKeyring(KeyringMockWithUserOp.type);
const sender = '0x998B3FBB8159aF51a827DBf43A8054A5A3A28c95';
const userOp = {
sender: '0x4584d2B4905087A100420AFfCe1b2d73fC69B8E4',
nonce: '0x1',
initCode: '0x',
callData: '0x7064',
callGasLimit: '0x58a83',
verificationGasLimit: '0xe8c4',
preVerificationGas: '0xc57c',
maxFeePerGas: '0x87f0878c0',
maxPriorityFeePerGas: '0x1dcd6500',
paymasterAndData: '0x',
signature: '0x',
};

const patch = {
paymasterAndData: '0x1234',
};

jest
.spyOn(KeyringMockWithUserOp.prototype, 'getAccounts')
.mockResolvedValueOnce([sender]);

jest
.spyOn(KeyringMockWithUserOp.prototype, 'patchUserOperation')
.mockResolvedValueOnce(patch);

const result = await keyringController.patchUserOperation(sender, userOp);
expect(result).toStrictEqual(patch);
});

it('signs an UserOperation', async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
constructorOptions: {
keyringBuilders: [keyringBuilderFactory(KeyringMockWithUserOp)],
},
});

await keyringController.addNewKeyring(KeyringMockWithUserOp.type);
const sender = '0x998B3FBB8159aF51a827DBf43A8054A5A3A28c95';
const userOp = {
sender: '0x4584d2B4905087A100420AFfCe1b2d73fC69B8E4',
nonce: '0x1',
initCode: '0x',
callData: '0x7064',
callGasLimit: '0x58a83',
verificationGasLimit: '0xe8c4',
preVerificationGas: '0xc57c',
maxFeePerGas: '0x87f0878c0',
maxPriorityFeePerGas: '0x1dcd6500',
paymasterAndData: '0x',
signature: '0x',
};

const signature = '0x1234';

jest
.spyOn(KeyringMockWithUserOp.prototype, 'getAccounts')
.mockResolvedValueOnce([sender]);

jest
.spyOn(KeyringMockWithUserOp.prototype, 'signUserOperation')
.mockResolvedValueOnce(signature);

const result = await keyringController.signUserOperation(sender, userOp);
expect(result).toStrictEqual(signature);
});

it("throws when the keyring doesn't implement prepareUserOperation", async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
seedPhrase: walletOneSeedWords,
});

const txs = [
{
to: '0x8cBC0EA145491fe83104abA9ef916f8632367227',
value: '0x0',
data: '0x',
},
];

const result = keyringController.prepareUserOperation(
walletOneAddresses[0] as string,
txs,
);

await expect(result).rejects.toThrow(
'KeyringController - The keyring for the current address does not support the method prepareUserOperation.',
);
});

it("throws when the keyring doesn't implement patchUserOperation", async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
seedPhrase: walletOneSeedWords,
});

const userOp = {
sender: '0x4584d2B4905087A100420AFfCe1b2d73fC69B8E4',
nonce: '0x1',
initCode: '0x',
callData: '0x7064',
callGasLimit: '0x58a83',
verificationGasLimit: '0xe8c4',
preVerificationGas: '0xc57c',
maxFeePerGas: '0x87f0878c0',
maxPriorityFeePerGas: '0x1dcd6500',
paymasterAndData: '0x',
signature: '0x',
};

const result = keyringController.patchUserOperation(
walletOneAddresses[0] as string,
userOp,
);

await expect(result).rejects.toThrow(
'KeyringController - The keyring for the current address does not support the method patchUserOperation.',
);
});

it("throws when the keyring doesn't implement signUserOperation", async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
seedPhrase: walletOneSeedWords,
});

const userOp = {
sender: '0x4584d2B4905087A100420AFfCe1b2d73fC69B8E4',
nonce: '0x1',
initCode: '0x',
callData: '0x7064',
callGasLimit: '0x58a83',
verificationGasLimit: '0xe8c4',
preVerificationGas: '0xc57c',
maxFeePerGas: '0x87f0878c0',
maxPriorityFeePerGas: '0x1dcd6500',
paymasterAndData: '0x',
signature: '0x',
};

const result = keyringController.signUserOperation(
walletOneAddresses[0] as string,
userOp,
);

await expect(result).rejects.toThrow(
'KeyringController - The keyring for the current address does not support the method signUserOperation.',
);
});
});

describe('signPersonalMessage', () => {
it('should sign personal message', async () => {
it('signPersonalMessage', async () => {
const keyringController = await initializeKeyringController({
password: PASSWORD,
seedPhrase: walletOneSeedWords,
Expand Down
Loading