diff --git a/packages/snap/CHANGELOG.md b/packages/snap/CHANGELOG.md index 59fb422..1f65df2 100644 --- a/packages/snap/CHANGELOG.md +++ b/packages/snap/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Implement `keyring_setSelectedAccounts` and `keyring_resolveAccountAddress` ([#163](https://github.com/MetaMask/snap-simple-keyring/pull/163)) + - Required for compatibility with `@metamask/eth-snap-keyring@^22`, which invokes these methods when MetaMask switches the active account or needs to resolve the signer for a request. +- Allow the `metamask` origin to call `keyring_createAccount`, `keyring_resolveAccountAddress`, and `keyring_setSelectedAccounts` ([#163](https://github.com/MetaMask/snap-simple-keyring/pull/163)) + ## [2.0.1] ### Changed diff --git a/packages/snap/snap.manifest.json b/packages/snap/snap.manifest.json index c0e7b70..5935e63 100644 --- a/packages/snap/snap.manifest.json +++ b/packages/snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "git+https://github.com/MetaMask/snap-simple-keyring.git" }, "source": { - "shasum": "TfeKGNKMSPQqAKQ/IrnOaziMcLqC6tWSjKRWo5YHMLs=", + "shasum": "GOVQr60E+i51GtXbwdaFzHmBrDKxwBVoDKUICf6V8HI=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/snap/src/keyring.ts b/packages/snap/src/keyring.ts index 033c3d1..a70cd1d 100644 --- a/packages/snap/src/keyring.ts +++ b/packages/snap/src/keyring.ts @@ -22,6 +22,7 @@ import type { KeyringAccount, KeyringEventPayload, KeyringRequest, + ResolvedAccountAddress, SubmitRequestResponse, } from '@metamask/keyring-api'; import { @@ -31,7 +32,11 @@ import { KeyringEvent, } from '@metamask/keyring-api'; import { emitSnapKeyringEvent } from '@metamask/keyring-snap-sdk'; -import { type Json, type JsonRpcRequest } from '@metamask/utils'; +import { + type CaipChainId, + type Json, + type JsonRpcRequest, +} from '@metamask/utils'; import { Buffer } from 'buffer'; import { v4 as uuid } from 'uuid'; @@ -49,6 +54,7 @@ export type KeyringState = { wallets: Record; pendingRequests: Record; useSyncApprovals: boolean; + selectedAccounts: string[]; }; export type Wallet = { @@ -158,6 +164,53 @@ export class SimpleKeyring implements Keyring { } } + async setSelectedAccounts(accounts: string[]): Promise { + this.#state.selectedAccounts = accounts; + await this.#saveState(); + } + + async resolveAccountAddress( + scope: CaipChainId, + request: JsonRpcRequest, + ): Promise { + const from = this.#extractFromAddress(request); + if (from === undefined) { + return null; + } + + const wallet = Object.values(this.#state.wallets).find( + (entry) => entry.account.address.toLowerCase() === from.toLowerCase(), + ); + if (!wallet) { + return null; + } + + return { address: `${scope}:${wallet.account.address}` }; + } + + #extractFromAddress(request: JsonRpcRequest): string | undefined { + const params = (request.params ?? []) as Json[]; + switch (request.method) { + case EthMethod.PersonalSign: { + const [, from] = params as [string, string]; + return from; + } + case EthMethod.SignTransaction: { + const [tx] = params as [{ from?: string }]; + return tx?.from; + } + case EthMethod.SignTypedDataV1: + case EthMethod.SignTypedDataV3: + case EthMethod.SignTypedDataV4: + case EthMethod.Sign: { + const [from] = params as [string]; + return from; + } + default: + return undefined; + } + } + async listRequests(): Promise { return Object.values(this.#state.pendingRequests); } diff --git a/packages/snap/src/permissions.ts b/packages/snap/src/permissions.ts index 7c12439..b68ddd2 100644 --- a/packages/snap/src/permissions.ts +++ b/packages/snap/src/permissions.ts @@ -12,12 +12,15 @@ export const originPermissions = new Map([ // Keyring methods KeyringRpcMethod.ListAccounts, KeyringRpcMethod.GetAccount, + KeyringRpcMethod.CreateAccount, KeyringRpcMethod.FilterAccountChains, KeyringRpcMethod.DeleteAccount, KeyringRpcMethod.ListRequests, KeyringRpcMethod.GetRequest, KeyringRpcMethod.SubmitRequest, KeyringRpcMethod.RejectRequest, + KeyringRpcMethod.ResolveAccountAddress, + KeyringRpcMethod.SetSelectedAccounts, ], ], [ diff --git a/packages/snap/src/stateManagement.ts b/packages/snap/src/stateManagement.ts index 1e2eb89..f0062e4 100644 --- a/packages/snap/src/stateManagement.ts +++ b/packages/snap/src/stateManagement.ts @@ -8,6 +8,7 @@ const defaultState: KeyringState = { wallets: {}, pendingRequests: {}, useSyncApprovals: true, + selectedAccounts: [], }; /**