diff --git a/package.json b/package.json index 1f280880..fc3b4fda 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dependencies": { "@ethereumjs/tx": "^4.2.0", "@metamask/eth-sig-util": "^7.0.1", - "@metamask/keyring-api": "^6.0.0", + "@metamask/keyring-api": "^6.1.0", "@metamask/snaps-controllers": "^8.0.0", "@metamask/snaps-sdk": "^4.0.1", "@metamask/snaps-utils": "^7.0.3", diff --git a/src/SnapKeyring.test.ts b/src/SnapKeyring.test.ts index 8f4c7c60..c756ce13 100644 --- a/src/SnapKeyring.test.ts +++ b/src/SnapKeyring.test.ts @@ -7,7 +7,13 @@ import type { KeyringAccount, KeyringExecutionContext, } from '@metamask/keyring-api'; -import { EthAccountType, EthMethod } from '@metamask/keyring-api'; +import { + BtcAccountType, + BtcMethod, + EthAccountType, + EthErc4337Method, + 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'; @@ -44,21 +50,41 @@ describe('SnapKeyring', () => { const snapId = 'local:snap.mock' as SnapId; + const ethEoaAccount1 = { + id: 'b05d918a-b37c-497a-bb28-3d15c0d56b7a', + address: '0xC728514Df8A7F9271f4B7a4dd2Aa6d2D723d3eE3'.toLowerCase(), + options: {}, + methods: [...Object.values(EthMethod)], + type: EthAccountType.Eoa, + }; + const ethEoaAccount2 = { + id: '33c96b60-2237-488e-a7bb-233576f3d22f', + address: '0x34b13912eAc00152bE0Cb409A301Ab8E55739e63'.toLowerCase(), + options: {}, + methods: [...Object.values(EthMethod)], + type: EthAccountType.Eoa, + }; + + const ethErc4337Account = { + id: 'fc926fff-f515-4eb5-9952-720bbd9b9849', + address: '0x2f15b30952aebe0ed5fdbfe5bf16fb9ecdb31d9a'.toLowerCase(), + options: {}, + methods: [...Object.values(EthErc4337Method)], + type: EthAccountType.Erc4337, + }; + const btcP2wpkhAccount = { + id: '11cffca0-12cc-4779-8f82-23273c062e29', + address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh'.toLowerCase(), + options: {}, + methods: [...Object.values(BtcMethod)], + type: BtcAccountType.P2wpkh, + }; + const accounts = [ - { - id: 'b05d918a-b37c-497a-bb28-3d15c0d56b7a', - address: '0xC728514Df8A7F9271f4B7a4dd2Aa6d2D723d3eE3'.toLowerCase(), - options: {}, - methods: [...Object.values(EthMethod)], - type: EthAccountType.Eoa, - }, - { - id: '33c96b60-2237-488e-a7bb-233576f3d22f', - address: '0x34b13912eAc00152bE0Cb409A301Ab8E55739e63'.toLowerCase(), - options: {}, - methods: [...Object.values(EthMethod)], - type: EthAccountType.Eoa, - }, + ethEoaAccount1, + ethEoaAccount2, + ethErc4337Account, + btcP2wpkhAccount, ] as const; const executionContext: KeyringExecutionContext = { @@ -92,13 +118,13 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountCreated, params: { account: { - ...(accounts[0] as unknown as KeyringAccount), + ...(ethEoaAccount1 as unknown as KeyringAccount), id: 'c6697bcf-5710-4751-a1cb-340e4b50617a', }, }, }), ).rejects.toThrow( - `Account address '${accounts[0].address}' already exists`, + `Account address '${ethEoaAccount1.address}' already exists`, ); }); @@ -109,25 +135,25 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountCreated, params: { account: { - ...(accounts[0] as unknown as KeyringAccount), + ...(ethEoaAccount1 as unknown as KeyringAccount), address: '0x0', }, }, }), - ).rejects.toThrow(`Account '${accounts[0].id}' already exists`); + ).rejects.toThrow(`Account '${ethEoaAccount1.id}' already exists`); }); it('updated the methods of an account', async () => { // Return the updated list of accounts when the keyring requests it. mockSnapController.handleRequest.mockResolvedValue([ - { ...accounts[0], methods: [] }, - { ...accounts[1] }, + { ...ethEoaAccount1, methods: [] }, + { ...ethEoaAccount2 }, ]); expect( await keyring.handleKeyringSnapMessage(snapId, { method: KeyringEvent.AccountUpdated, - params: { account: { ...accounts[0], methods: [] } }, + params: { account: { ...ethEoaAccount1, methods: [] } }, }), ).toBeNull(); @@ -142,7 +168,7 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountUpdated, params: { account: { - ...(accounts[0] as unknown as KeyringAccount), + ...(ethEoaAccount1 as unknown as KeyringAccount), id: '0b3551da-1685-4750-ad4c-01fc3a9e90b1', }, }, @@ -157,7 +183,7 @@ describe('SnapKeyring', () => { keyring.handleKeyringSnapMessage('a-different-snap-id' as SnapId, { method: KeyringEvent.AccountCreated, params: { - account: { ...(accounts[0] as unknown as KeyringAccount) }, + account: { ...(ethEoaAccount1 as unknown as KeyringAccount) }, }, }), ).rejects.toThrow( @@ -171,8 +197,8 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountUpdated, params: { account: { - ...(accounts[0] as unknown as KeyringAccount), - address: accounts[1].address, + ...(ethEoaAccount1 as unknown as KeyringAccount), + address: ethEoaAccount2.address, }, }, }), @@ -187,7 +213,7 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountUpdated, params: { account: { - ...(accounts[0] as unknown as KeyringAccount), + ...(ethEoaAccount1 as unknown as KeyringAccount), }, }, }), @@ -207,21 +233,25 @@ describe('SnapKeyring', () => { await keyring.handleKeyringSnapMessage(snapId, { method: KeyringEvent.AccountDeleted, - params: { id: accounts[0].id }, + params: { id: ethEoaAccount1.id }, }); expect(await keyring.getAccounts()).toStrictEqual([ - accounts[1].address.toLowerCase(), + ethEoaAccount2.address.toLowerCase(), + ethErc4337Account.address.toLowerCase(), + btcP2wpkhAccount.address.toLowerCase(), ]); }); it('cannot delete an account owned by another snap', async () => { await keyring.handleKeyringSnapMessage('invalid-snap-id' as SnapId, { method: KeyringEvent.AccountDeleted, - params: { id: accounts[0].id }, + params: { id: ethEoaAccount1.id }, }); expect(await keyring.getAccounts()).toStrictEqual([ - accounts[0].address.toLowerCase(), - accounts[1].address.toLowerCase(), + ethEoaAccount1.address.toLowerCase(), + ethEoaAccount2.address.toLowerCase(), + ethErc4337Account.address.toLowerCase(), + btcP2wpkhAccount.address.toLowerCase(), ]); }); @@ -256,7 +286,7 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountUpdated, params: { account: { - ...accounts[0], + ...ethEoaAccount1, methods: updatedMethods, }, }, @@ -264,9 +294,9 @@ describe('SnapKeyring', () => { ).toBeNull(); expect(keyring.listAccounts()[0]?.methods).toStrictEqual(updatedMethods); await expect( - keyring.signPersonalMessage(accounts[0].address, 'hello'), + keyring.signPersonalMessage(ethEoaAccount1.address, 'hello'), ).rejects.toThrow( - `Method '${EthMethod.PersonalSign}' not supported for account ${accounts[0].address}`, + `Method '${EthMethod.PersonalSign}' not supported for account ${ethEoaAccount1.address}`, ); // Restore `EthMethod.PersonalSign` and remove `EthMethod.SignTransaction` updatedMethods = Object.values(EthMethod).filter( @@ -277,7 +307,7 @@ describe('SnapKeyring', () => { method: KeyringEvent.AccountUpdated, params: { account: { - ...accounts[0], + ...ethEoaAccount1, methods: updatedMethods, }, }, @@ -296,9 +326,9 @@ describe('SnapKeyring', () => { }; const tx = TransactionFactory.fromTxData(mockTx); await expect( - keyring.signTransaction(accounts[0].address, tx), + keyring.signTransaction(ethEoaAccount1.address, tx), ).rejects.toThrow( - `Method '${EthMethod.SignTransaction}' not supported for account ${accounts[0].address}`, + `Method '${EthMethod.SignTransaction}' not supported for account ${ethEoaAccount1.address}`, ); }); @@ -307,7 +337,7 @@ describe('SnapKeyring', () => { pending: true, }); const requestPromise = keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, 'hello', ); @@ -348,7 +378,7 @@ describe('SnapKeyring', () => { redirect, }); const requestPromise = keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, 'hello', ); @@ -405,7 +435,7 @@ describe('SnapKeyring', () => { }, }); const requestPromise = keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, 'hello', ); @@ -440,7 +470,7 @@ describe('SnapKeyring', () => { redirect, }); const requestPromise = keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, 'hello', ); @@ -455,7 +485,7 @@ describe('SnapKeyring', () => { pending: true, }); const requestPromise = keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, 'hello', ); @@ -475,7 +505,7 @@ describe('SnapKeyring', () => { pending: true, }); // eslint-disable-next-line no-void - void keyring.signPersonalMessage(accounts[0].address, 'hello'); + void keyring.signPersonalMessage(ethEoaAccount1.address, 'hello'); const { calls } = mockSnapController.handleRequest.mock; const requestId: string = calls[calls.length - 1][0].request.params.id; @@ -492,7 +522,7 @@ describe('SnapKeyring', () => { pending: true, }); // eslint-disable-next-line no-void - void keyring.signPersonalMessage(accounts[0].address, 'hello'); + void keyring.signPersonalMessage(ethEoaAccount1.address, 'hello'); const { calls } = mockSnapController.handleRequest.mock; const requestId: string = calls[calls.length - 1][0].request.params.id; @@ -508,7 +538,7 @@ describe('SnapKeyring', () => { mockSnapController.handleRequest.mockRejectedValue(new Error('error')); const mockMessage = 'Hello World!'; await expect( - keyring.signPersonalMessage(accounts[0].address, mockMessage), + keyring.signPersonalMessage(ethEoaAccount1.address, mockMessage), ).rejects.toThrow('error'); const { calls } = mockSnapController.handleRequest.mock; @@ -560,7 +590,7 @@ describe('SnapKeyring', () => { await expect( keyring.handleKeyringSnapMessage(snapId, { method: KeyringEvent.AccountDeleted, - params: { id: accounts[0].id }, + params: { id: ethEoaAccount1.id }, }), ).rejects.toThrow('Some error occurred while removing account'); }); @@ -568,7 +598,7 @@ describe('SnapKeyring', () => { it('returns null after successfully updating an account', async () => { const result = await keyring.handleKeyringSnapMessage(snapId, { method: KeyringEvent.AccountUpdated, - params: { account: accounts[0] as unknown as KeyringAccount }, + params: { account: ethEoaAccount1 as unknown as KeyringAccount }, }); expect(mockCallbacks.saveState).toHaveBeenCalled(); expect(result).toBeNull(); @@ -588,8 +618,10 @@ describe('SnapKeyring', () => { it('returns the keyring state', async () => { const expectedState = { accounts: { - [accounts[0].id]: { account: accounts[0], snapId }, - [accounts[1].id]: { account: accounts[1], snapId }, + [ethEoaAccount1.id]: { account: ethEoaAccount1, snapId }, + [ethEoaAccount2.id]: { account: ethEoaAccount2, snapId }, + [ethErc4337Account.id]: { account: ethErc4337Account, snapId }, + [btcP2wpkhAccount.id]: { account: btcP2wpkhAccount, snapId }, }, }; const state = await keyring.serialize(); @@ -602,10 +634,10 @@ describe('SnapKeyring', () => { // State only contains the first account const state = { accounts: { - [accounts[0].id]: { account: accounts[0], snapId }, + [ethEoaAccount1.id]: { account: ethEoaAccount1, snapId }, }, }; - const expectedAddresses = [accounts[0].address]; + const expectedAddresses = [ethEoaAccount1.address]; await keyring.deserialize(state as unknown as KeyringState); const addresses = await keyring.getAccounts(); expect(addresses).toStrictEqual(expectedAddresses); @@ -661,7 +693,10 @@ describe('SnapKeyring', () => { result: mockSignedTx, }); - const signature = await keyring.signTransaction(accounts[0].address, tx); + const signature = await keyring.signTransaction( + ethEoaAccount1.address, + tx, + ); expect(mockSnapController.handleRequest).toHaveBeenCalledWith({ snapId, handler: 'onKeyringRequest', @@ -673,13 +708,13 @@ describe('SnapKeyring', () => { params: { id: expect.any(String), scope: expectedScope, - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_signTransaction', params: [ { ...mockTx, - from: accounts[0].address, + from: ethEoaAccount1.address, }, ], }, @@ -740,7 +775,7 @@ describe('SnapKeyring', () => { }); const signature = await keyring.signTypedData( - accounts[0].address, + ethEoaAccount1.address, dataToSign, ); expect(mockSnapController.handleRequest).toHaveBeenCalledWith({ @@ -754,10 +789,10 @@ describe('SnapKeyring', () => { params: { id: expect.any(String), scope: expectedScope, - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_signTypedData_v1', - params: [accounts[0].address, dataToSign], + params: [ethEoaAccount1.address, dataToSign], }, }, }, @@ -772,7 +807,7 @@ describe('SnapKeyring', () => { }); const signature = await keyring.signTypedData( - accounts[0].address, + ethEoaAccount1.address, dataToSign, { version: SignTypedDataVersion.V4 }, ); @@ -787,10 +822,10 @@ describe('SnapKeyring', () => { params: { id: expect.any(String), scope: expectedScope, - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_signTypedData_v4', - params: [accounts[0].address, dataToSign], + params: [ethEoaAccount1.address, dataToSign], }, }, }, @@ -805,7 +840,7 @@ describe('SnapKeyring', () => { }); const signature = await keyring.signTypedData( - accounts[0].address, + ethEoaAccount1.address, dataToSign, { version: 'V2' as any }, ); @@ -820,10 +855,10 @@ describe('SnapKeyring', () => { params: { id: expect.any(String), scope: expectedScope, - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_signTypedData_v1', - params: [accounts[0].address, dataToSign], + params: [ethEoaAccount1.address, dataToSign], }, }, }, @@ -850,7 +885,7 @@ describe('SnapKeyring', () => { }; const signature = await keyring.signTypedData( - accounts[0].address, + ethEoaAccount1.address, dataToSignWithoutDomainChainId, { version: SignTypedDataVersion.V4 }, ); @@ -867,10 +902,10 @@ describe('SnapKeyring', () => { // Without chainId alongside the typed message, we cannot // compute the scope for this request! scope: '', // Default value for `signTypedTransaction` - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_signTypedData_v4', - params: [accounts[0].address, dataToSignWithoutDomainChainId], + params: [ethEoaAccount1.address, dataToSignWithoutDomainChainId], }, }, }, @@ -912,7 +947,7 @@ describe('SnapKeyring', () => { }); const baseUserOp = await keyring.prepareUserOperation( - accounts[0].address, + ethErc4337Account.address, baseTxs, executionContext, ); @@ -931,7 +966,7 @@ describe('SnapKeyring', () => { KnownCaipNamespace.Eip155, executionContext.chainId, ), - account: accounts[0].id, + account: ethErc4337Account.id, request: { method: 'eth_prepareUserOperation', params: baseTxs, @@ -945,7 +980,7 @@ describe('SnapKeyring', () => { it('calls eth_patchUserOperation', async () => { const userOp = { - sender: accounts[0].address, + sender: ethErc4337Account.address, nonce: '0x1', initCode: '0x', callData: '0x1234', @@ -968,7 +1003,7 @@ describe('SnapKeyring', () => { }); const patch = await keyring.patchUserOperation( - accounts[0].address, + ethErc4337Account.address, userOp, executionContext, ); @@ -987,7 +1022,7 @@ describe('SnapKeyring', () => { KnownCaipNamespace.Eip155, executionContext.chainId, ), - account: accounts[0].id, + account: ethErc4337Account.id, request: { method: 'eth_patchUserOperation', params: [userOp], @@ -1001,7 +1036,7 @@ describe('SnapKeyring', () => { it('calls eth_signUserOperation', async () => { const userOp = { - sender: accounts[0].address, + sender: ethErc4337Account.address, nonce: '0x1', initCode: '0x', callData: '0x1234', @@ -1020,7 +1055,7 @@ describe('SnapKeyring', () => { }); const signature = await keyring.signUserOperation( - accounts[0].address, + ethErc4337Account.address, userOp, executionContext, ); @@ -1039,7 +1074,7 @@ describe('SnapKeyring', () => { KnownCaipNamespace.Eip155, executionContext.chainId, ), - account: accounts[0].id, + account: ethErc4337Account.id, request: { method: 'eth_signUserOperation', params: [userOp], @@ -1061,7 +1096,7 @@ describe('SnapKeyring', () => { result: expectedSignature, }); const signature = await keyring.signPersonalMessage( - accounts[0].address, + ethEoaAccount1.address, mockMessage, ); expect(signature).toStrictEqual(expectedSignature); @@ -1085,7 +1120,7 @@ describe('SnapKeyring', () => { result: expectedSignature, }); const signature = await keyring.signMessage( - accounts[0].address, + ethEoaAccount1.address, mockMessage, ); expect(signature).toStrictEqual(expectedSignature); @@ -1099,10 +1134,10 @@ describe('SnapKeyring', () => { params: { id: expect.any(String), scope: expect.any(String), - account: accounts[0].id, + account: ethEoaAccount1.id, request: { method: 'eth_sign', - params: [accounts[0].address, mockMessage], + params: [ethEoaAccount1.address, mockMessage], }, }, }, @@ -1113,7 +1148,7 @@ describe('SnapKeyring', () => { describe('exportAccount', () => { it('fails to export an account', async () => { - expect(() => keyring.exportAccount(accounts[0].address)).toThrow( + expect(() => keyring.exportAccount(ethEoaAccount1.address)).toThrow( 'Exporting accounts from snaps is not supported', ); }); @@ -1128,18 +1163,22 @@ describe('SnapKeyring', () => { it('removes an account', async () => { mockSnapController.handleRequest.mockResolvedValue(null); - await keyring.removeAccount(accounts[0].address); + await keyring.removeAccount(ethEoaAccount1.address); expect(await keyring.getAccounts()).toStrictEqual([ - accounts[1].address.toLowerCase(), + ethEoaAccount2.address, + accounts[2].address, + accounts[3].address, ]); }); it('removes the account and warn if snap fails', async () => { const spy = jest.spyOn(console, 'error').mockImplementation(); mockSnapController.handleRequest.mockRejectedValue('some error'); - await keyring.removeAccount(accounts[0].address); + await keyring.removeAccount(ethEoaAccount1.address); expect(await keyring.getAccounts()).toStrictEqual([ - accounts[1].address.toLowerCase(), + ethEoaAccount2.address, + accounts[2].address, + accounts[3].address, ]); expect(console.error).toHaveBeenCalledWith( "Account '0xc728514df8a7f9271f4b7a4dd2aa6d2d723d3ee3' may not have been removed from snap 'local:snap.mock':", @@ -1199,15 +1238,17 @@ describe('SnapKeyring', () => { enabled: true, }; mockSnapController.get.mockReturnValue(snapMetadata); - expect(keyring.getAccountByAddress(accounts[0].address)).toStrictEqual({ - ...accounts[0], - metadata: { - name: '', - importTime: 0, - snap: { id: snapId, name: 'snap-name', enabled: true }, - keyring: { type: 'Snap Keyring' }, + expect(keyring.getAccountByAddress(ethEoaAccount1.address)).toStrictEqual( + { + ...ethEoaAccount1, + metadata: { + name: '', + importTime: 0, + snap: { id: snapId, name: 'snap-name', enabled: true }, + keyring: { type: 'Snap Keyring' }, + }, }, - }); + ); }); }); @@ -1241,7 +1282,7 @@ describe('SnapKeyring', () => { }); await keyring.prepareUserOperation( - accounts[0].address, + ethErc4337Account.address, mockIntents, executionContext, ); @@ -1259,7 +1300,7 @@ describe('SnapKeyring', () => { KnownCaipNamespace.Eip155, executionContext.chainId, ), - account: accounts[0].id, + account: ethErc4337Account.id, request: { method: 'eth_prepareUserOperation', params: mockIntents, @@ -1277,7 +1318,7 @@ describe('SnapKeyring', () => { await expect( keyring.prepareUserOperation( - accounts[0].address, + ethErc4337Account.address, mockIntents, executionContext, ), @@ -1287,7 +1328,7 @@ describe('SnapKeyring', () => { describe('patchUserOperation', () => { const mockUserOp: EthUserOperation = { - sender: accounts[0].address, + sender: ethErc4337Account.address, callData: '0x70641a22000000000000000000000000f3de3c0d654fda23da', initCode: '0x', nonce: '0x1', @@ -1311,7 +1352,7 @@ describe('SnapKeyring', () => { }); await keyring.patchUserOperation( - accounts[0].address, + ethErc4337Account.address, mockUserOp, executionContext, ); @@ -1329,7 +1370,7 @@ describe('SnapKeyring', () => { KnownCaipNamespace.Eip155, executionContext.chainId, ), - account: accounts[0].id, + account: ethErc4337Account.id, request: { method: 'eth_patchUserOperation', params: [mockUserOp], @@ -1347,7 +1388,7 @@ describe('SnapKeyring', () => { await expect( keyring.patchUserOperation( - accounts[0].address, + ethErc4337Account.address, mockUserOp, executionContext, ), diff --git a/src/SnapKeyring.ts b/src/SnapKeyring.ts index 4be9551e..d7825681 100644 --- a/src/SnapKeyring.ts +++ b/src/SnapKeyring.ts @@ -2,17 +2,8 @@ import type { TypedTransaction } from '@ethereumjs/tx'; import { TransactionFactory } from '@ethereumjs/tx'; import type { TypedDataV1, TypedMessage } from '@metamask/eth-sig-util'; import { SignTypedDataVersion } from '@metamask/eth-sig-util'; -import type { - EthBaseTransaction, - EthBaseUserOperation, - EthUserOperation, - EthUserOperationPatch, - InternalAccount, - KeyringAccount, - KeyringResponse, - KeyringExecutionContext, -} from '@metamask/keyring-api'; import { + EthErc4337Method, AccountCreatedEventStruct, AccountDeletedEventStruct, AccountUpdatedEventStruct, @@ -24,6 +15,17 @@ import { RequestApprovedEventStruct, RequestRejectedEventStruct, } from '@metamask/keyring-api'; +import type { + EthBaseTransaction, + EthBaseUserOperation, + EthUserOperation, + EthUserOperationPatch, + InternalAccount, + KeyringAccount, + KeyringResponse, + KeyringExecutionContext, + BtcMethod, +} from '@metamask/keyring-api'; import type { SnapController } from '@metamask/snaps-controllers'; import type { SnapId } from '@metamask/snaps-sdk'; import type { Snap } from '@metamask/snaps-utils'; @@ -53,6 +55,10 @@ import { export const SNAP_KEYRING_TYPE = 'Snap Keyring'; +// TODO: to be removed when this is added to the keyring-api + +type AccountMethod = EthMethod | EthErc4337Method | BtcMethod; + /** * Snap keyring state. * @@ -407,7 +413,7 @@ export class SnapKeyring extends EventEmitter { expectSync?: boolean; }): Promise { const { account, snapId } = this.#resolveAddress(address); - if (!this.#hasMethod(account, method as EthMethod)) { + if (!this.#hasMethod(account, method as AccountMethod)) { throw new Error( `Method '${method}' not supported for account ${account.address}`, ); @@ -423,7 +429,7 @@ export class SnapKeyring extends EventEmitter { snapId, requestId, account, - method: method as EthMethod, + method: method as AccountMethod, params, chainId, }); @@ -458,8 +464,8 @@ export class SnapKeyring extends EventEmitter { * @param method - The Ethereum method to validate. * @returns `true` if the method is supported, `false` otherwise. */ - #hasMethod(account: KeyringAccount, method: EthMethod): boolean { - return account.methods.includes(method); + #hasMethod(account: KeyringAccount, method: AccountMethod): boolean { + return (account.methods as AccountMethod[]).includes(method); } /** @@ -502,7 +508,7 @@ export class SnapKeyring extends EventEmitter { snapId: SnapId; requestId: string; account: KeyringAccount; - method: EthMethod; + method: AccountMethod; params?: Json[] | Record | undefined; chainId: string; }): Promise { @@ -732,7 +738,7 @@ export class SnapKeyring extends EventEmitter { return strictMask( await this.#submitRequest({ address, - method: EthMethod.PrepareUserOperation, + method: EthErc4337Method.PrepareUserOperation, params: toJson(transactions), expectSync: true, // We assume the chain ID is already well formatted @@ -759,7 +765,7 @@ export class SnapKeyring extends EventEmitter { return strictMask( await this.#submitRequest({ address, - method: EthMethod.PatchUserOperation, + method: EthErc4337Method.PatchUserOperation, params: toJson([userOp]), expectSync: true, // We assume the chain ID is already well formatted @@ -785,7 +791,7 @@ export class SnapKeyring extends EventEmitter { return strictMask( await this.#submitRequest({ address, - method: EthMethod.SignUserOperation, + method: EthErc4337Method.SignUserOperation, params: toJson([userOp]), // We assume the chain ID is already well formatted chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId), diff --git a/yarn.lock b/yarn.lock index d012504a..8ab2e4a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1062,7 +1062,7 @@ __metadata: "@metamask/eslint-config-nodejs": ^12.1.0 "@metamask/eslint-config-typescript": ^12.1.0 "@metamask/eth-sig-util": ^7.0.1 - "@metamask/keyring-api": ^6.0.0 + "@metamask/keyring-api": ^6.1.0 "@metamask/snaps-controllers": ^8.0.0 "@metamask/snaps-sdk": ^4.0.1 "@metamask/snaps-utils": ^7.0.3 @@ -1144,18 +1144,19 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-api@npm:^6.0.0": - version: 6.0.0 - resolution: "@metamask/keyring-api@npm:6.0.0" +"@metamask/keyring-api@npm:^6.1.0": + version: 6.1.0 + resolution: "@metamask/keyring-api@npm:6.1.0" dependencies: "@metamask/snaps-sdk": ^4.0.0 "@metamask/utils": ^8.3.0 "@types/uuid": ^9.0.1 + bech32: ^2.0.0 superstruct: ^1.0.3 uuid: ^9.0.0 peerDependencies: "@metamask/providers": ">=15 <17" - checksum: d3d6d5d27945783ef74e8e1b9626d122a07df58a2a62e12c68ff0bda2894c6c0a16d6add40908159fb92dee0b98425c63fc494c9b86ae0d0a0be7dc74389997a + checksum: 493aff0569b2f62a9cbbda82e5b9df709562f5f11d32f5d97224a7d29be1bbd7139e23f1384d9d888e2e90d3858e64ff499c03780b3664d31724a054722b4e0a languageName: node linkType: hard @@ -2423,6 +2424,13 @@ __metadata: languageName: node linkType: hard +"bech32@npm:^2.0.0": + version: 2.0.0 + resolution: "bech32@npm:2.0.0" + checksum: fa15acb270b59aa496734a01f9155677b478987b773bf701f465858bf1606c6a970085babd43d71ce61895f1baa594cb41a2cd1394bd2c6698f03cc2d811300e + languageName: node + linkType: hard + "bin-links@npm:4.0.1": version: 4.0.1 resolution: "bin-links@npm:4.0.1"