Skip to content

feat: import srp #30598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Mar 5, 2025
Merged

feat: import srp #30598

merged 29 commits into from
Mar 5, 2025

Conversation

montelaidev
Copy link
Contributor

@montelaidev montelaidev commented Feb 27, 2025

Description

This PR introduces importing srps as a new feature. It is split from a previous pr

Open in GitHub Codespaces

Related issues

Fixes:

Manual testing steps

Importing a new SRP

  1. Click on the account selector
  2. Click on connect more
  3. Click on Import secret recovery phrase
  4. Paste in a SRP
  5. Continue
  6. See a new account is created
  7. Click on the account selector and see new pills indicating the SRP numbers

Screenshots/Recordings

Before

After

Importing a new SRP

Screen.Recording.2025-02-14.at.17.26.32.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot
Copy link
Collaborator

Builds ready [3ccc9f1]
Page Load Metrics (2013 ± 132 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint36424821829516248
domContentLoaded163527051975261125
load164927162013275132
domInteractive26172513215
backgroundConnect12169474120
firstReactRender1989452412
getState673272110
initialActions01000
loadScripts121621771493215103
setupStore892292512
uiStartup193832672356377181
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 627 Bytes (0.01%)
  • common: 1.46 KiB (0.01%)

@metamaskbot
Copy link
Collaborator

Builds ready [ea82ea4]
Page Load Metrics (1862 ± 103 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint43324911789377181
domContentLoaded15772413183020699
load162324981862215103
domInteractive28141492814
backgroundConnect989362713
firstReactRender1673382211
getState65716157
initialActions01000
loadScripts11821872137817785
setupStore865252110
uiStartup187226892122219105
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 627 Bytes (0.01%)
  • common: 1.34 KiB (0.01%)

@montelaidev montelaidev marked this pull request as ready for review February 27, 2025 06:46
@montelaidev montelaidev requested a review from a team as a code owner February 27, 2025 06:46
@metamaskbot
Copy link
Collaborator

Builds ready [c3ea3b0]
Page Load Metrics (2020 ± 103 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint175126952017207100
domContentLoaded17432645199119996
load174927472020214103
domInteractive30223534220
backgroundConnect10101322412
firstReactRender177129189
getState674282311
initialActions01000
loadScripts12712055148017182
setupStore862272210
uiStartup201732192306258124
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 627 Bytes (0.01%)
  • common: 1.34 KiB (0.01%)

@@ -46,7 +46,7 @@ class AccountListPage {
'[data-testid="multichain-account-menu-popover-add-watch-only-account"]';

private readonly addHardwareWalletButton = {
text: 'Add hardware wallet',
text: 'Hardware wallet',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reviewers: Those changes are expected, and match the new designs (the "Add " prefix has now been dropped for most "add*Account" labels)

@@ -197,7 +197,7 @@
"message": "Add friends and addresses you trust"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment for the entire file:

Since this PR also uses the new "account list" design, I've spotted some differences for some kind of accounts:

  • addHardwareWallet, addNewBitcoinAccount and addNewBitcoinTestnetAccount could be renamed to add*Label (to match the new naming convention)
  • addNewBitcoinAccount and addNewBitcoinTestnetAccount still uses the old description "Add a new ...", we could remove those (we can double-check with the designs for this)
  • addNewAccount is no longer used, so we can remove it IMO

Comment on lines 4308 to 4316
const alreadyImportedSRP = await this.keyringController
.getKeyringsByType(KeyringTypes.hd)
.some((keyring) => {
return (
keyring.accounts.includes(address) &&
keyring.type === KeyringTypes.hd
Buffer.from(
this._convertEnglishWordlistIndicesToCodepoints(keyring.mnemonic),
).toString('utf8') === mnemonic
);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this logic relies on a @deprecated method, we could move it to the KeyringController? That would also hide the "detailed implementation" about how mnemonics are being encoded for HD keyrings.

Or should we have a withKeyrings(keyringType) (note the s) that we would use similarly to withKeyring? Just random thoughts on this.

I'd like to get your opinion (if possible) on this @mikesposito 😄 thanks!

(For now, adding a TODO seems like a good option)

// TODO: `getKeyringsByType` is deprecated, this logic should probably be moved to the `KeyringController`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think withKeyrings(keyringType) would be pretty helpful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides withKeyrings we could also simply iterate through the keyrings list on KeyringController.state and get the mnemonic with primitives we already have, like withKeyring

Though, I'm wondering if this is really needed here, since it's the controller to check for duplicates: https://github.com/MetaMask/core/blob/5b74b24875491b480a01dd5d950e04020fba7e26/packages/keyring-controller/src/KeyringController.ts#L2483
The HD keyring will always include at least one address, and if the same SRP is imported twice, the second one will throw an error on KeyrignController

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, IMO, we should have this kind of guarantee at the controller level.

Though, currently the #checkForDuplicate do not check anything for HD keyrings (if I read that correctly)? But I do agree that having that we should have a check there (and checking the mnemonic together would allow to have a "specific error" like KeyringControllerError.DuplicatedMnemonic rather than KeyringControllerError.DuplicatedAccount).

That will be also useful for mobile integration IMO.

WDYT @montelaidev?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't check the specific mnemonic that is being imported, but it throws error if there are two keyrings with the same address. I'm assuming that the same SRP will always create the same first account, and since we automatically add one when importing the SRP, that means we'll have at least one duplicated account when calling #checkForDuplicate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed together internally, the current logic of #checkForDuplicates is not covering every cases (and not this one 🙈), here's the ticket to track this:

@metamaskbot
Copy link
Collaborator

Builds ready [51550c4]
Page Load Metrics (1752 ± 66 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint15001978175213967
domContentLoaded14901940172013766
load15041967175213766
domInteractive25133422412
backgroundConnect10103412613
firstReactRender1569372110
getState57018199
initialActions01000
loadScripts10851478128911053
setupStore76220199
uiStartup17562285201514972
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 627 Bytes (0.01%)
  • common: 1.31 KiB (0.01%)

Comment on lines 4308 to 4316
const alreadyImportedSRP = await this.keyringController
.getKeyringsByType(KeyringTypes.hd)
.some((keyring) => {
return (
keyring.accounts.includes(address) &&
keyring.type === KeyringTypes.hd
Buffer.from(
this._convertEnglishWordlistIndicesToCodepoints(keyring.mnemonic),
).toString('utf8') === mnemonic
);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, IMO, we should have this kind of guarantee at the controller level.

Though, currently the #checkForDuplicate do not check anything for HD keyrings (if I read that correctly)? But I do agree that having that we should have a check there (and checking the mnemonic together would allow to have a "specific error" like KeyringControllerError.DuplicatedMnemonic rather than KeyringControllerError.DuplicatedAccount).

That will be also useful for mobile integration IMO.

WDYT @montelaidev?

@montelaidev
Copy link
Contributor Author

Yup, IMO, we should have this kind of guarantee at the controller level.

Though, currently the #checkForDuplicate do not check anything for HD keyrings (if I read that correctly)? But I do agree that having that we should have a check there (and checking the mnemonic together would allow to have a "specific error" like KeyringControllerError.DuplicatedMnemonic rather than KeyringControllerError.DuplicatedAccount).

That will be also useful for mobile integration IMO.

Yea it would be much better to do it in the controller

@@ -0,0 +1,309 @@
import React, { useCallback, useMemo, useState } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for the entire file: As discussed internally with @montelaidev, this file will be refactored in a follow-up PR to avoid duplicating the logic with input-srp.

So I will adds more comments on this new PR once this one will be merged.

See: https://github.com/MetaMask/metamask-extension/pull/30598/files#r1977094784

@metamaskbot
Copy link
Collaborator

Builds ready [e9e193e]
Page Load Metrics (1825 ± 61 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint16042070182312962
domContentLoaded15922021180412560
load16042066182512761
domInteractive27129422311
backgroundConnect116324168
firstReactRender1679422613
getState46015188
initialActions01000
loadScripts11811585134311455
setupStore861222010
uiStartup18342326208314268
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 632 Bytes (0.01%)
  • common: 1.31 KiB (0.01%)

Comment on lines 159 to 164
"addBitcoinAccountLabel": {
"message": "Add a new Bitcoin account (Beta)"
},
"addBitcoinTestnetAccountLabel": {
"message": "Add a new Bitcoin account (Testnet)"
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to: https://github.com/MetaMask/metamask-extension/pull/30598/files#r1973162748

Are we also renaming those to Bitcoin account?

@ccharly
Copy link
Contributor

ccharly commented Mar 4, 2025

Tested ✅

$ jq '.metamask.internalAccounts.accounts | to_entries[] | .value.address' state.json
"0x33f5be2b61b33b4423e4f15fdd9a344c0b2e3a0d"
"0x8e29b63f510f6f3714fa23c7cc0614e3a928fb16"
$ jq '.metamask | {keyrings, keyringsMetadata}' state.json
{
  "keyrings": [
    {
      "type": "HD Key Tree",
      "accounts": [
        "0x33f5be2b61b33b4423e4f15fdd9a344c0b2e3a0d"
      ]
    },
    {
      "type": "HD Key Tree",
      "accounts": [
        "0x8e29b63f510f6f3714fa23c7cc0614e3a928fb16"
      ]
    }
  ],
  "keyringsMetadata": [
    {
      "id": "01JNH032HRW8A1CYC9W90WDAFP",
      "name": ""
    },
    {
      "id": "01JNH053FZDK57D3SR1DMMK4R3",
      "name": ""
    }
  ]
}

Found one small UI issue, the "plus" sign is bigger for Ethereum than for Solana:

Screenshot 2025-03-04 at 17 43 30

@metamaskbot
Copy link
Collaborator

Builds ready [2d0ecd9]
Page Load Metrics (2022 ± 79 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint25322421838546262
domContentLoaded16902210198315675
load17022247202216479
domInteractive30124522311
backgroundConnect12118422914
firstReactRender177730199
getState76319157
initialActions01000
loadScripts12431643148412460
setupStore971282311
uiStartup20252615230217383
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 632 Bytes (0.01%)
  • common: 1.31 KiB (0.01%)

Copy link
Contributor

@ccharly ccharly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for all those changes, LGTM now 😄 (and already tested, see my previous comment)

@metamaskbot
Copy link
Collaborator

Builds ready [487db25]
Page Load Metrics (1546 ± 46 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint1377182515479847
domContentLoaded1365180615249847
load1375182515469646
domInteractive147637189
backgroundConnect97727199
firstReactRender146618115
getState45216178
initialActions00000
loadScripts987138811288440
setupStore76216178
uiStartup15102137175412660
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 632 Bytes (0.01%)
  • common: 1.29 KiB (0.01%)

@github-project-automation github-project-automation bot moved this from Review in progress to Review finalised - Ready to be merged in PR review queue Mar 5, 2025
@montelaidev montelaidev added this pull request to the merge queue Mar 5, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 5, 2025
@montelaidev montelaidev added this pull request to the merge queue Mar 5, 2025
@montelaidev montelaidev mentioned this pull request Mar 5, 2025
7 tasks
Merged via the queue into main with commit 6210f00 Mar 5, 2025
74 checks passed
@montelaidev montelaidev deleted the feat/multi-srp-import-srp branch March 5, 2025 14:15
@github-actions github-actions bot locked and limited conversation to collaborators Mar 5, 2025
@metamaskbot metamaskbot added the release-12.15.0 Issue or pull request that will be included in release 12.15.0 label Mar 5, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
release-12.15.0 Issue or pull request that will be included in release 12.15.0 team-accounts
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants