Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
5b1e954
feat: add Ethereum MPC keyring package
matthiasgeihs Sep 2, 2026
1027e20
feat: add EIP-7702 authorization signing to MPC keyring
matthiasgeihs Sep 2, 2026
86dfe55
fix: satisfy constraints and changelog checks for MPC keyring
matthiasgeihs Sep 2, 2026
952442e
fix: apply oxfmt to MPC keyring package files
matthiasgeihs Sep 2, 2026
ae37af3
fix: convert transaction signature v for ethereumjs typed txs
matthiasgeihs Sep 2, 2026
faca5e6
fix: sort root package.json resolutions for oxfmt
matthiasgeihs Sep 2, 2026
68ca3ba
fix: add static type on MPCKeyring for controller registration
matthiasgeihs Sep 2, 2026
870ccb5
fix: dedupe yarn.lock after MPC MFA dependencies
matthiasgeihs Sep 2, 2026
cb37f58
feat: use share epochs for MPC create, rotate, and sync
matthiasgeihs Sep 3, 2026
e5a53ee
fix: serialize MPC sign, rotate, and sync on one op queue
matthiasgeihs Sep 3, 2026
f56ee36
fix: bind MPC key-share backups to the DKG attempt nonce
matthiasgeihs Sep 3, 2026
16e4e99
feat: use bearer token in requests (#630)
ieow Sep 4, 2026
ab3f2a0
feat: loadKeyShare use getJson (#631)
ieow Sep 4, 2026
236bce3
feat: implement MPC addAccounts for the single initialized account
matthiasgeihs Sep 18, 2026
4463a0e
feat: wait for backend status completion in MPC create and rotate (#635)
ieow Sep 25, 2026
6a89027
fix: time out hung MPC cloud HTTP requests
matthiasgeihs Sep 28, 2026
2761e18
docs: note that any sign error drops the MPC TSS setup
matthiasgeihs Sep 28, 2026
6e65c53
refactor: name the MPC signing threshold constant
matthiasgeihs Sep 28, 2026
24590c8
refactor: rename MPC keyring types to Mpc
matthiasgeihs Sep 28, 2026
2845913
docs: document the MpcKeyring class and constructor
matthiasgeihs Sep 28, 2026
2182cf2
docs: keep the MPC keyring changelog to the initial release
matthiasgeihs Sep 28, 2026
4d574d3
feat: validate MPC responses and persisted state with superstruct
matthiasgeihs Sep 28, 2026
67e4125
fix: serialize MPC keyring init with the other state-writing operations
matthiasgeihs Sep 28, 2026
043a708
lint
matthiasgeihs Sep 28, 2026
4b24aef
refactor: adopt the renamed MFA wallet SDK packages
matthiasgeihs Sep 28, 2026
6512fdf
Merge branch 'main' into mg/mpc-keyring
matthiasgeihs Oct 6, 2026
47cafb0
fix(keyring-eth-mpc): re-align with MFA SDK (#666)
ccharly Oct 12, 2026
ddf7c58
Merge branch 'main' into mg/mpc-keyring
ccharly Oct 12, 2026
fc6b24f
esm only import
matthiasgeihs Oct 12, 2026
0a1cc6d
fix(keyring-eth-mpc): resolve Node16 .js imports in Jest
matthiasgeihs Oct 12, 2026
b848adc
fix(keyring-eth-mpc): reject corrupt key state that also includes a s…
matthiasgeihs Oct 12, 2026
8d36768
refactor(keyring-eth-mpc): use one public-key-to-address helper
matthiasgeihs Oct 12, 2026
a820df8
refactor(keyring-eth-mpc): encrypt backups with @metamask/cryptography
matthiasgeihs Oct 12, 2026
61a5e57
cleanup CHANGELOG
matthiasgeihs Oct 12, 2026
abe312d
refactor(keyring-eth-money-mpc): rename the MPC keyring for money acc…
matthiasgeihs Oct 13, 2026
dfc96da
cleanup CHANGELOG
matthiasgeihs Oct 13, 2026
6638007
refactor(keyring-eth-money-mpc): remove unsupported transaction signing
matthiasgeihs Oct 13, 2026
be2f86f
fix imports
matthiasgeihs Oct 13, 2026
f2e2e31
feat(keyring-eth-money-mpc): skip MFA for whitelisted signatures
matthiasgeihs Oct 13, 2026
58d90f9
chore(keyring-eth-money-mpc): use the MFA whitelist preview build
matthiasgeihs Oct 13, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/validate-pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ jobs:
keyring-api
keyring-eth-hd
keyring-eth-money
keyring-eth-money-mpc
keyring-eth-ledger-bridge
keyring-eth-simple
keyring-eth-trezor
keyring-eth-mpc
keyring-internal-api
keyring-internal-snap-client
keyring-sdk
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This repository contains the following packages [^fn1]:
- [`@metamask/eth-hd-keyring`](packages/keyring-eth-hd)
- [`@metamask/eth-ledger-bridge-keyring`](packages/keyring-eth-ledger-bridge)
- [`@metamask/eth-money-keyring`](packages/keyring-eth-money)
- [`@metamask/eth-mpc-keyring`](packages/keyring-eth-mpc)
- [`@metamask/eth-money-mpc-keyring`](packages/keyring-eth-money-mpc)
- [`@metamask/eth-qr-keyring`](packages/keyring-eth-qr)
- [`@metamask/eth-simple-keyring`](packages/keyring-eth-simple)
- [`@metamask/eth-snap-keyring`](packages/keyring-snap-bridge)
Expand Down Expand Up @@ -53,7 +53,7 @@ linkStyle default opacity:0.5
eth_hd_keyring(["@metamask/eth-hd-keyring"]);
eth_ledger_bridge_keyring(["@metamask/eth-ledger-bridge-keyring"]);
eth_money_keyring(["@metamask/eth-money-keyring"]);
eth_mpc_keyring(["@metamask/eth-mpc-keyring"]);
eth_money_mpc_keyring(["@metamask/eth-money-mpc-keyring"]);
eth_qr_keyring(["@metamask/eth-qr-keyring"]);
eth_simple_keyring(["@metamask/eth-simple-keyring"]);
eth_trezor_keyring(["@metamask/eth-trezor-keyring"]);
Expand Down Expand Up @@ -81,9 +81,9 @@ linkStyle default opacity:0.5
eth_money_keyring --> keyring_api;
eth_money_keyring --> keyring_sdk;
eth_money_keyring --> keyring_utils;
eth_mpc_keyring --> keyring_api;
eth_mpc_keyring --> keyring_sdk;
eth_mpc_keyring --> keyring_utils;
eth_money_mpc_keyring --> keyring_api;
eth_money_mpc_keyring --> keyring_sdk;
eth_money_mpc_keyring --> keyring_utils;
eth_qr_keyring --> keyring_api;
eth_qr_keyring --> keyring_sdk;
eth_qr_keyring --> keyring_utils;
Expand Down
10 changes: 10 additions & 0 deletions jest.config.packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ module.exports = {
// Here we ensure that Jest resolves `@metamask/*` imports to the uncompiled source code for packages that live in this repo.
// NOTE: This must be synchronized with the `paths` option in `tsconfig.packages.json`.
moduleNameMapper: {
// Listed before the `@metamask/*` wildcard so the AES-GCM subpath is not
// rewritten to a workspace source directory.
'^@metamask/cryptography/aes-gcm$':
'<rootDir>/../../node_modules/@metamask/cryptography/dist/aes-gcm.js',
'^@metamask/(.+)/v2$': [
'<rootDir>/../$1/src/v2',
// Some @metamask/* packages we are referencing aren't in this monorepo,
Expand All @@ -97,6 +101,12 @@ module.exports = {
// Some @metamask/* packages we are referencing aren't in this monorepo,
// so in that case use their published versions
'<rootDir>/../../node_modules/@metamask/$1',
// Some published @metamask/* packages are ESM-only and have no `main`
// field, so resolving their package directory fails. In that case, use
// their ESM entrypoint directly. This is only safe for modules that are
// mocked with `jest.mock`, since Jest's CommonJS runtime cannot execute
// native ESM.
'<rootDir>/../../node_modules/@metamask/$1/dist/index.js',
],
},

Expand Down
15 changes: 15 additions & 0 deletions packages/keyring-eth-money-mpc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Initial release of `@metamask/eth-money-mpc-keyring` ([#627](https://github.com/MetaMask/accounts/pull/627))
- Skip MFA for whitelisted signature requests, and retry with a 2FA token when the backend returns `mfa_required` ([#TODO](https://github.com/MetaMask/accounts/pull/TODO))

[Unreleased]: https://github.com/MetaMask/accounts/
23 changes: 23 additions & 0 deletions packages/keyring-eth-money-mpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# MPC Money Keyring

A Keyring for Ethereum money accounts that uses Multi-Party Computation (MPC) for key management and signing, built on top of the [MFA Wallet SDK](https://github.com/MetaMask/mfa-wallet-sdk).

The default export is the V1 `MpcMoneyKeyring` implementation. A V2 adapter that wraps it is available from `@metamask/eth-money-mpc-keyring/v2`.

## MFA

Pass `getMfaWhitelistConfig` to let signature requests skip MFA when they match [`@metamask/money-account-mfa-whitelist`](https://github.com/MetaMask/core/tree/main/packages/money-account-mfa-whitelist). The keyring sends the original request with the hash. The backend repeats the check with its own account, hash, and pinned configuration. When that still requires MFA, `/sign` responds with `{ "code": "mfa_required" }`. The keyring then requests a 2FA profile token and calls `/sign` once more.

Key generation, import, share rotation, share sync, and transaction signing always use a 2FA token. Omitting `getMfaWhitelistConfig` does too.

## Installation

`yarn add @metamask/eth-money-mpc-keyring`

or

`npm install @metamask/eth-money-mpc-keyring`

## Contributing

This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/accounts#readme).
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ module.exports = merge(baseConfig, {
// The display name when running multiple projects
displayName,

// Source files use Node16-style `.js` specifiers. Map them back to the
// TypeScript sources so Jest can load the modules under test.
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},

// `@metamask/cryptography` is ESM-only. Transform it so Jest's CommonJS
// runtime can load the AES-GCM helpers.
transformIgnorePatterns: ['/node_modules/(?!@metamask/cryptography/)'],
transform: {
'/@metamask/cryptography/.+\\.js$': path.join(
__dirname,
'jest.cryptography-transform.cjs',
),
},

// An array of regexp pattern strings used to skip coverage collection
coveragePathIgnorePatterns: ['./src/tests'],

Expand Down
33 changes: 33 additions & 0 deletions packages/keyring-eth-money-mpc/jest.cryptography-transform.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Jest runs this package as CommonJS, and `@metamask/cryptography` ships
* ESM only. Transpile those files when the test runtime loads them.
*
* This file is CommonJS because Jest loads transformers without the
* package's TypeScript build.
*/
const ts = require('typescript');

/**
* @type {import('@jest/transform').Transformer}
*/
module.exports = {
/**
* Transpile an ESM file to CommonJS.
*
* @param {string} sourceText - ESM source from `@metamask/cryptography`.
* @param {string} sourcePath - Absolute path of the source file.
* @returns {{ code: string }} CommonJS source Jest can execute.
*/
process(sourceText, sourcePath) {
const result = ts.transpileModule(sourceText, {
compilerOptions: {
esModuleInterop: true,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2020,
},
fileName: sourcePath,
});

return { code: result.outputText };
},
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@metamask/eth-mpc-keyring",
"name": "@metamask/eth-money-mpc-keyring",
"version": "0.0.0",
"description": "A Keyring for Ethereum accounts that uses Multi-Party Computation (MPC) for key management and signing",
"description": "A Keyring for Ethereum money accounts that uses Multi-Party Computation (MPC) for key management and signing",
"keywords": [
"ethereum",
"keyring"
],
"homepage": "https://github.com/MetaMask/accounts/tree/main/packages/keyring-eth-mpc#readme",
"homepage": "https://github.com/MetaMask/accounts/tree/main/packages/keyring-eth-money-mpc#readme",
"bugs": {
"url": "https://github.com/MetaMask/accounts/issues"
},
Expand All @@ -16,32 +16,18 @@
"url": "https://github.com/MetaMask/accounts.git"
},
"files": [
"dist/",
"v2.js"
"dist/"
],
"type": "module",
"sideEffects": false,
"main": "./dist/index.cjs",
"types": "./dist/index.d.cts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"./v2": {
"import": {
"types": "./dist/v2/index.d.mts",
"default": "./dist/v2/index.mjs"
},
"require": {
"types": "./dist/v2/index.d.cts",
"default": "./dist/v2/index.cjs"
}
"types": "./dist/v2/index.d.mts",
"default": "./dist/v2/index.mjs"
},
"./package.json": "./package.json"
},
Expand All @@ -50,33 +36,40 @@
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references --format module",
"build:clean": "yarn build --clean",
"build:docs": "typedoc",
"changelog:update": "../../scripts/update-changelog.sh @metamask/eth-mpc-keyring",
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/eth-mpc-keyring",
"changelog:update": "../../scripts/update-changelog.sh @metamask/eth-money-mpc-keyring",
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/eth-money-mpc-keyring",
"publish:preview": "yarn npm publish --tag preview",
"test": "yarn test:source && yarn test:types",
"test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
"test:clean": "jest --clearCache",
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean --format module",
"since-latest-release": "../../scripts/since-latest-release.sh",
"test:source": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
"test:source": "jest --reporters=jest-silent-reporter",
"test:types": "../../scripts/tsd-test.sh ./src",
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
"test:verbose": "jest --verbose",
"test:watch": "jest --watch"
},
"dependencies": {
"@ethereumjs/util": "^9.1.0",
"@metamask/cryptography": "^1.1.2",
"@metamask/eth-sig-util": "^9.0.0",
"@metamask/keyring-api": "^24.2.0",
"@metamask/keyring-sdk": "^4.0.0",
"@metamask/keyring-utils": "^5.0.0",
"@metamask/mfa-wallet-cl24": "^0.1.0",
"@metamask/mfa-wallet-dkls23": "^0.1.0",
"@metamask/mfa-wallet-network": "^0.1.0",
"@metamask/money-account-mfa-whitelist": "npm:@metamask-previews/money-account-mfa-whitelist@0.0.0-preview-6ccf7a055",
"@metamask/superstruct": "^3.4.1",
"@metamask/utils": "^11.11.0"
},
"devDependencies": {
"@ethereumjs/tx": "^5.4.0",
"@lavamoat/allow-scripts": "^3.2.1",
"@lavamoat/preinstall-always-fail": "^2.1.0",
"@metamask/auto-changelog": "^6.1.0",
"@metamask/eth-sig-util": "^9.0.0",
"@metamask/mfa-wallet-interface": "^0.1.0",
"@ts-bridge/cli": "^0.6.3",
"@types/jest": "^29.5.12",
"deepmerge": "^4.2.2",
Expand All @@ -88,7 +81,8 @@
},
"lavamoat": {
"allowScripts": {
"@lavamoat/preinstall-always-fail": false
"@lavamoat/preinstall-always-fail": false,
"@metamask/mfa-wallet-network>centrifuge>protobufjs": false
}
}
}
Loading
Loading