Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8422734
create package
matthiasgeihs Jan 13, 2026
12523b3
init mpc keyring
matthiasgeihs Jan 13, 2026
7af2dc3
init role
matthiasgeihs Jan 13, 2026
0765414
create key
matthiasgeihs Jan 13, 2026
00a41d9
signTransaction
matthiasgeihs Jan 14, 2026
5100527
wip
matthiasgeihs Jan 15, 2026
9a87a43
signPersonalMessage
matthiasgeihs Jan 15, 2026
52caa1a
signTypedData
matthiasgeihs Jan 15, 2026
29426ee
implement backend requests
matthiasgeihs Jan 19, 2026
623b0a5
serialization
matthiasgeihs Jan 19, 2026
0a7cce4
generate session id
matthiasgeihs Jan 19, 2026
ffd5ecc
recover parity bit
matthiasgeihs Jan 19, 2026
72fc13b
ensure low s
matthiasgeihs Jan 19, 2026
c315fd8
add comments
matthiasgeihs Jan 19, 2026
d378b73
cleanup
matthiasgeihs Jan 19, 2026
d8337a9
f
matthiasgeihs Jan 19, 2026
577bbaa
wip build
matthiasgeihs Jan 20, 2026
b63be6a
wip
matthiasgeihs Jan 20, 2026
f707b24
wip
matthiasgeihs Jan 20, 2026
6e37655
wip
matthiasgeihs Jan 20, 2026
7a028a7
export types
matthiasgeihs Jan 20, 2026
84c4c4b
integrate network
matthiasgeihs Jan 23, 2026
33a9d55
use createScopedSessionId
matthiasgeihs Jan 26, 2026
6c34914
cleanup session
matthiasgeihs Jan 26, 2026
aa82621
revise cloud api
matthiasgeihs Jan 26, 2026
dfa4ad3
compatibility
matthiasgeihs Jan 27, 2026
cad523f
use publicKeyToAddressHex in toEthSig
matthiasgeihs Feb 2, 2026
d69bd18
update API
matthiasgeihs Feb 2, 2026
0ee93a1
add support for verifiers
matthiasgeihs Feb 5, 2026
26b0599
fixup
matthiasgeihs Feb 13, 2026
0e650db
update network
matthiasgeihs Feb 13, 2026
541d9a1
add getCustodianId
matthiasgeihs Feb 13, 2026
d7a261d
add getCustodians
matthiasgeihs Feb 13, 2026
87405ca
addCustodian
matthiasgeihs Feb 13, 2026
2f320a4
update update API
matthiasgeihs Feb 13, 2026
c80d20f
setup join mode
matthiasgeihs Feb 13, 2026
c99a07d
fixup
matthiasgeihs Feb 14, 2026
4a966ba
join with joinData
matthiasgeihs Feb 16, 2026
f81de13
bug fix
matthiasgeihs Feb 16, 2026
62a97bc
update cl24 and mpc interface
matthiasgeihs Feb 16, 2026
f429527
fix selection of signers
matthiasgeihs Feb 16, 2026
5cc9e9a
update wallet network
matthiasgeihs Feb 17, 2026
0b5969a
add local packages
matthiasgeihs Feb 17, 2026
72ed805
measure time and log to console
matthiasgeihs Feb 24, 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
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@
"@types/web": "^0.0.69",
"@typescript/lib-dom": "npm:@types/web@^0.0.69",
"axios@1.7.3": "^1.7.7",
"ws@7.4.6": "^7.5.10"
"ws@7.4.6": "^7.5.10",
"@metamask/mfa-wallet-cl24-lib": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-cl24-lib-0.0.0.tgz",
"@metamask/mfa-wallet-dkls19-lib": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-dkls19-lib-0.0.0.tgz",
"@metamask/mfa-wallet-e2ee": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-e2ee-0.0.0.tgz",
"@metamask/mfa-wallet-interface": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-interface-0.0.0.tgz",
"@metamask/mfa-wallet-network": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-network-0.0.0.tgz",
"@metamask/mfa-wallet-util": "file:./packages/keyring-eth-mpc/metamask-mfa-wallet-util-0.0.0.tgz",
"@metamask/mpc-libs-interface": "file:./packages/keyring-eth-mpc/metamask-mpc-libs-interface-0.0.0.tgz"
},
"devDependencies": {
"@lavamoat/allow-scripts": "^3.2.1",
Expand Down
10 changes: 10 additions & 0 deletions packages/keyring-eth-mpc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 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]

[Unreleased]: https://github.com/MetaMask/accounts
15 changes: 15 additions & 0 deletions packages/keyring-eth-mpc/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ISC License

Copyright (c) 2020 MetaMask

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
128 changes: 128 additions & 0 deletions packages/keyring-eth-mpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# MPC Keyring

A Keyring for Ethereum 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).

## Installation

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

or

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

## The Keyring Class Protocol

One of the goals of this class is to allow developers to easily add new signing strategies to MetaMask. We call these signing strategies Keyrings, because they can manage multiple keys.

### Keyring.type

A class property that returns a unique string describing the Keyring.
This is the only class property or method, the remaining methods are instance methods.

### constructor( options )

As a Javascript class, your Keyring object will be used to instantiate new Keyring instances using the new keyword. For example:

```
const keyring = new YourKeyringClass(options);
```

The constructor currently receives an options object that will be defined by your keyring-building UI, once the user has gone through the steps required for you to fully instantiate a new keyring. For example, choosing a pattern for a vanity account, or entering a seed phrase.

We haven't defined the protocol for this account-generating UI yet, so for now please ensure your Keyring behaves nicely when not passed any options object.

## Keyring Instance Methods

All below instance methods must return Promises to allow asynchronous resolution.

### serialize()

In this method, you must return any JSON-serializable JavaScript object that you like. It will be encoded to a string, encrypted with the user's password, and stored to disk. This is the same object you will receive in the deserialize() method, so it should capture all the information you need to restore the Keyring's state.

### deserialize( object )

As discussed above, the deserialize() method will be passed the JavaScript object that you returned when the serialize() method was called.

### addAccounts( n = 1 )

The addAccounts(n) method is used to inform your keyring that the user wishes to create a new account. You should perform whatever internal steps are needed so that a call to serialize() will persist the new account, and then return an array of the new account addresses.

The method may be called with or without an argument, specifying the number of accounts to create. You should generally default to 1 per call.

### getAccounts()

When this method is called, you must return an array of hex-string addresses for the accounts that your Keyring is able to sign for.

### signTransaction(address, transaction)

This method will receive a hex-prefixed, all-lowercase address string for the account you should sign the incoming transaction with.

For your convenience, the transaction is an instance of ethereumjs-tx, (https://github.com/ethereumjs/ethereumjs-tx) so signing can be as simple as:

```
transaction.sign(privateKey)
```

You must return a valid signed ethereumjs-tx (https://github.com/ethereumjs/ethereumjs-tx) object when complete, it can be the same transaction you received.

### signMessage(address, data)

The `eth_sign` method will receive the incoming data, alread hashed, and must sign that hash, and then return the raw signed hash.

### exportAccount(address)

Exports the specified account as a private key hex string.

## Contributing

### Setup

- Install [Node.js](https://nodejs.org) version 18
- If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you.
- Install [Yarn v3](https://yarnpkg.com/getting-started/install)
- Run `yarn install` to install dependencies and run any required post-install scripts

### Testing and Linting

Run `yarn test` to run the tests once. To run tests on file changes, run `yarn test:watch`.

Run `yarn lint` to run the linter, or run `yarn lint:fix` to run the linter and fix any automatically fixable issues.

### Release & Publishing

The project follows the same release process as the other libraries in the MetaMask organization. The GitHub Actions [`action-create-release-pr`](https://github.com/MetaMask/action-create-release-pr) and [`action-publish-release`](https://github.com/MetaMask/action-publish-release) are used to automate the release process; see those repositories for more information about how they work.

1. Choose a release version.

- The release version should be chosen according to SemVer. Analyze the changes to see whether they include any breaking changes, new features, or deprecations, then choose the appropriate SemVer version. See [the SemVer specification](https://semver.org/) for more information.

2. If this release is backporting changes onto a previous release, then ensure there is a major version branch for that version (e.g. `1.x` for a `v1` backport release).

- The major version branch should be set to the most recent release with that major version. For example, when backporting a `v1.0.2` release, you'd want to ensure there was a `1.x` branch that was set to the `v1.0.1` tag.

3. Trigger the [`workflow_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch) event [manually](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) for the `Create Release Pull Request` action to create the release PR.

- For a backport release, the base branch should be the major version branch that you ensured existed in step 2. For a normal release, the base branch should be the main branch for that repository (which should be the default value).
- This should trigger the [`action-create-release-pr`](https://github.com/MetaMask/action-create-release-pr) workflow to create the release PR.

4. Update the changelog to move each change entry into the appropriate change category ([See here](https://keepachangelog.com/en/1.0.0/#types) for the full list of change categories, and the correct ordering), and edit them to be more easily understood by users of the package.

- Generally any changes that don't affect consumers of the package (e.g. lockfile changes or development environment changes) are omitted. Exceptions may be made for changes that might be of interest despite not having an effect upon the published package (e.g. major test improvements, security improvements, improved documentation, etc.).
- Try to explain each change in terms that users of the package would understand (e.g. avoid referencing internal variables/concepts).
- Consolidate related changes into one change entry if it makes it easier to explain.
- Run `yarn auto-changelog validate --rc` to check that the changelog is correctly formatted.

5. Review and QA the release.

- If changes are made to the base branch, the release branch will need to be updated with these changes and review/QA will need to restart again. As such, it's probably best to avoid merging other PRs into the base branch while review is underway.

6. Squash & Merge the release.

- This should trigger the [`action-publish-release`](https://github.com/MetaMask/action-publish-release) workflow to tag the final release commit and publish the release on GitHub.

7. Publish the release on npm.

- Be very careful to use a clean local environment to publish the release, and follow exactly the same steps used during CI.
- Use `npm publish --dry-run` to examine the release contents to ensure the correct files are included. Compare to previous releases if necessary (e.g. using `https://unpkg.com/browse/[package name]@[package version]/`).
- Once you are confident the release contents are correct, publish the release using `npm publish`.
4 changes: 4 additions & 0 deletions packages/keyring-eth-mpc/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# TODO

- Check for "not implemented" and "TODO" in code
- Add support for managing verifiers: add/remove
32 changes: 32 additions & 0 deletions packages/keyring-eth-mpc/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/

const merge = require('deepmerge');
const path = require('path');

const baseConfig = require('../../jest.config.packages');

const displayName = path.basename(__dirname);

module.exports = merge(baseConfig, {
// The display name when running multiple projects
displayName,

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

// The glob patterns Jest uses to detect test files
testMatch: ['**/*.test.[jt]s?(x)'],

// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 100,
functions: 100,
lines: 100,
statements: 100,
},
},
});
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
81 changes: 81 additions & 0 deletions packages/keyring-eth-mpc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"name": "@metamask/eth-mpc-keyring",
"version": "0.0.0",
"description": "A Keyring for Ethereum accounts that uses Multi-Party Computation (MPC) for key management and signing.",
"keywords": [
"ethereum",
"keyring"
],
"homepage": "https://github.com/MetaMask/eth-mpc-keyring#readme",
"bugs": {
"url": "https://github.com/MetaMask/eth-mpc-keyring/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/MetaMask/eth-mpc-keyring.git"
},
"license": "ISC",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"main": "./dist/index.cjs",
"types": "./dist/index.d.cts",
"files": [
"dist/"
],
"scripts": {
"build": "ts-bridge --project tsconfig.build.json --no-references",
"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",
"publish:preview": "yarn npm publish --tag preview",
"test": "jest",
"test:clean": "jest --clearCache"
},
"dependencies": {
"@ethereumjs/util": "^9.1.0",
"@metamask/eth-sig-util": "^8.2.0",
"@metamask/mfa-wallet-cl24-lib": "^0.0.0",
"@metamask/mfa-wallet-dkls19-lib": "^0.0.0",
"@metamask/mfa-wallet-e2ee": "^0.0.0",
"@metamask/mfa-wallet-network": "^0.0.0",
"@metamask/mfa-wallet-util": "^0.0.0"
},
"devDependencies": {
"@ethereumjs/tx": "^5.4.0",
"@lavamoat/allow-scripts": "^3.2.1",
"@lavamoat/preinstall-always-fail": "^2.1.0",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/keyring-utils": "workspace:^",
"@metamask/mfa-wallet-interface": "^0.0.0",
"@metamask/mpc-libs-interface": "^0.0.0",
"@metamask/utils": "^11.1.0",
"@ts-bridge/cli": "^0.6.3",
"@types/jest": "^29.5.12",
"deepmerge": "^4.2.2",
"jest": "^29.5.0"
},
"engines": {
"node": "^18.18 || >=20"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"lavamoat": {
"allowScripts": {
"@lavamoat/preinstall-always-fail": false,
"@metamask/mfa-wallet-network>centrifuge>protobufjs": false
}
}
}
Loading