From 0f8c00927ba35c2e667d7f8b358acc474bb9809e Mon Sep 17 00:00:00 2001 From: ahsan-javaiid Date: Thu, 24 Nov 2022 20:55:34 +0500 Subject: [PATCH] fix: use network as derivation path --- background/constants/networks.ts | 1 + background/main.ts | 5 +++-- background/networks.ts | 1 + background/redux-slices/keyrings.ts | 6 +++--- .../redux-slices/selectors/accountsSelectors.ts | 4 ++++ background/services/keyring/index.ts | 13 +++++++++++-- .../AccountsNotificationPanelAccounts.tsx | 13 ++++++++++--- ui/pages/Onboarding/OnboardingImportMetamask.tsx | 6 +++++- .../OnboardingInterstitialCreatePhrase.tsx | 12 +++++++++--- ui/pages/Onboarding/Tabbed/ImportSeed.tsx | 7 +++++-- ui/pages/Onboarding/Tabbed/NewSeed.tsx | 8 +++++--- .../Onboarding/VerifySeed/VerifySeedSuccess.tsx | 6 +++++- 12 files changed, 62 insertions(+), 20 deletions(-) diff --git a/background/constants/networks.ts b/background/constants/networks.ts index 6e3c090c2d..8c165a41b0 100644 --- a/background/constants/networks.ts +++ b/background/constants/networks.ts @@ -24,6 +24,7 @@ export const ROOTSTOCK: EVMNetwork = { name: "Rootstock", baseAsset: RBTC, chainID: "30", + derivationPath: "m/44'/137'/0'/0", family: "EVM", coingeckoPlatformID: "rootstock", } diff --git a/background/main.ts b/background/main.ts index 243b18df90..e0f8cda537 100644 --- a/background/main.ts +++ b/background/main.ts @@ -1083,13 +1083,14 @@ export default class Main extends BaseService { }) }) - keyringSliceEmitter.on("generateNewKeyring", async () => { + keyringSliceEmitter.on("generateNewKeyring", async (path) => { // TODO move unlocking to a reasonable place in the initialization flow const generated: { id: string mnemonic: string[] } = await this.keyringService.generateNewKeyring( - KeyringTypes.mnemonicBIP39S256 + KeyringTypes.mnemonicBIP39S256, + path ) this.store.dispatch(setKeyringToVerify(generated)) diff --git a/background/networks.ts b/background/networks.ts index 1f800abe40..41adfbd24a 100644 --- a/background/networks.ts +++ b/background/networks.ts @@ -35,6 +35,7 @@ export type Network = { family: NetworkFamily chainID?: string coingeckoPlatformID?: string + derivationPath?: string } /** diff --git a/background/redux-slices/keyrings.ts b/background/redux-slices/keyrings.ts index 61e8ca8108..35e677fdd0 100644 --- a/background/redux-slices/keyrings.ts +++ b/background/redux-slices/keyrings.ts @@ -32,7 +32,7 @@ export type Events = { createPassword: string unlockKeyrings: string lockKeyrings: never - generateNewKeyring: never + generateNewKeyring: string | undefined deriveAddress: string importKeyring: ImportKeyring } @@ -134,8 +134,8 @@ export default keyringsSlice.reducer // Async thunk to bubble the generateNewKeyring action from store to emitter. export const generateNewKeyring = createBackgroundAsyncThunk( "keyrings/generateNewKeyring", - async () => { - await emitter.emit("generateNewKeyring") + async (path?: string) => { + await emitter.emit("generateNewKeyring", path) } ) diff --git a/background/redux-slices/selectors/accountsSelectors.ts b/background/redux-slices/selectors/accountsSelectors.ts index beb246f04a..d65b97420e 100644 --- a/background/redux-slices/selectors/accountsSelectors.ts +++ b/background/redux-slices/selectors/accountsSelectors.ts @@ -288,6 +288,7 @@ export type AccountTotal = AddressOnNetwork & { // FIXME Add `categoryFor(accountSigner): string` utility function to // FIXME generalize beyond keyrings. keyringId: string | null + path: string | null accountSigner: AccountSigner name?: string avatarURL?: string @@ -373,6 +374,7 @@ function getNetworkAccountTotalsByCategory( const accountSigner = accountSignersByAddress[address] const keyringId = keyringsByAddresses[address]?.id + const path = keyringsByAddresses[address]?.path const accountType = getAccountType( address, @@ -387,6 +389,7 @@ function getNetworkAccountTotalsByCategory( shortenedAddress, accountType, keyringId, + path, accountSigner, } } @@ -397,6 +400,7 @@ function getNetworkAccountTotalsByCategory( shortenedAddress, accountType, keyringId, + path, accountSigner, name: accountData.ens.name ?? accountData.defaultName, avatarURL: accountData.ens.avatarURL ?? accountData.defaultAvatar, diff --git a/background/services/keyring/index.ts b/background/services/keyring/index.ts index 9287d50134..793d6292e2 100644 --- a/background/services/keyring/index.ts +++ b/background/services/keyring/index.ts @@ -28,6 +28,7 @@ export const MAX_OUTSIDE_IDLE_TIME = 60 * MINUTE export type Keyring = { type: KeyringTypes id: string | null + path: string | null addresses: string[] } @@ -301,7 +302,8 @@ export default class KeyringService extends BaseService { * accessed at generation time through this return value. */ async generateNewKeyring( - type: KeyringTypes + type: KeyringTypes, + path?: string ): Promise<{ id: string; mnemonic: string[] }> { this.requireUnlocked() @@ -311,7 +313,13 @@ export default class KeyringService extends BaseService { ) } - const newKeyring = new HDKeyring({ strength: 256 }) + const options: { strength: number; path?: string } = { strength: 256 } + + if (path) { + options.path = path + } + + const newKeyring = new HDKeyring(options) const { mnemonic } = newKeyring.serializeSync() @@ -382,6 +390,7 @@ export default class KeyringService extends BaseService { .filter((address) => this.#hiddenAccounts[address] !== true), ], id: kr.id, + path: kr.path, })) } diff --git a/ui/components/AccountsNotificationPanel/AccountsNotificationPanelAccounts.tsx b/ui/components/AccountsNotificationPanel/AccountsNotificationPanelAccounts.tsx index a2d9486e1b..29cd1ecad6 100644 --- a/ui/components/AccountsNotificationPanel/AccountsNotificationPanelAccounts.tsx +++ b/ui/components/AccountsNotificationPanel/AccountsNotificationPanelAccounts.tsx @@ -11,6 +11,7 @@ import { updateSignerTitle, } from "@tallyho/tally-background/redux-slices/ui" import { deriveAddress } from "@tallyho/tally-background/redux-slices/keyrings" +import { ROOTSTOCK } from "@tallyho/tally-background/constants" import { AccountTotal, selectCurrentNetworkAccountTotalsByCategory, @@ -77,12 +78,14 @@ function WalletTypeHeader({ accountType, onClickAddAddress, walletNumber, + path, accountSigner, }: { accountType: AccountType onClickAddAddress?: () => void accountSigner: AccountSigner walletNumber?: number + path?: string | null }) { const { t } = useTranslation() const { title, icon } = walletTypeDetails[accountType] @@ -103,10 +106,13 @@ function WalletTypeHeader({ const sectionTitle = useMemo(() => { if (accountType === AccountType.ReadOnly) return title - if (sectionCustomName) return sectionCustomName + let networkName = "" // Only for Rootstock + if (path === ROOTSTOCK.derivationPath) networkName = `(${ROOTSTOCK.name})` - return `${title} ${walletNumber}` - }, [accountType, title, sectionCustomName, walletNumber]) + if (sectionCustomName) return `${sectionCustomName} ${networkName}` + + return `${title} ${walletNumber} ${networkName}` + }, [accountType, title, sectionCustomName, walletNumber, path]) const history = useHistory() const areKeyringsUnlocked = useAreKeyringsUnlocked(false) @@ -339,6 +345,7 @@ export default function AccountsNotificationPanelAccounts({ ("m/44'/60'/0'/0") + const [path, setPath] = useState( + selectedNetwork.derivationPath ?? "m/44'/60'/0'/0" + ) const [isImporting, setIsImporting] = useState(false) const dispatch = useBackgroundDispatch() diff --git a/ui/pages/Onboarding/OnboardingInterstitialCreatePhrase.tsx b/ui/pages/Onboarding/OnboardingInterstitialCreatePhrase.tsx index 5f9ad2be58..9b1d947ba3 100644 --- a/ui/pages/Onboarding/OnboardingInterstitialCreatePhrase.tsx +++ b/ui/pages/Onboarding/OnboardingInterstitialCreatePhrase.tsx @@ -1,10 +1,16 @@ import React, { ReactElement, useCallback, useEffect } from "react" import { generateNewKeyring } from "@tallyho/tally-background/redux-slices/keyrings" +import { selectCurrentNetwork } from "@tallyho/tally-background/redux-slices/selectors" import { useHistory } from "react-router-dom" -import { useBackgroundDispatch, useAreKeyringsUnlocked } from "../../hooks" +import { + useBackgroundDispatch, + useAreKeyringsUnlocked, + useBackgroundSelector, +} from "../../hooks" export default function OnboardingInterstitialCreatePhrase(): ReactElement { const dispatch = useBackgroundDispatch() + const selectedNetwork = useBackgroundSelector(selectCurrentNetwork) const history = useHistory() const areKeyringsUnlocked = useAreKeyringsUnlocked(true) @@ -12,11 +18,11 @@ export default function OnboardingInterstitialCreatePhrase(): ReactElement { const generateThenContinue = useCallback( async function generateThenContinue() { if (areKeyringsUnlocked) { - await dispatch(generateNewKeyring()) + await dispatch(generateNewKeyring(selectedNetwork.derivationPath)) history.push("/onboarding/save-seed") } }, - [areKeyringsUnlocked, dispatch, history] + [areKeyringsUnlocked, dispatch, history, selectedNetwork] ) useEffect(() => { diff --git a/ui/pages/Onboarding/Tabbed/ImportSeed.tsx b/ui/pages/Onboarding/Tabbed/ImportSeed.tsx index d370b9ff3f..b4fb5429d7 100644 --- a/ui/pages/Onboarding/Tabbed/ImportSeed.tsx +++ b/ui/pages/Onboarding/Tabbed/ImportSeed.tsx @@ -4,6 +4,7 @@ import { Redirect, useHistory } from "react-router-dom" import { isValidMnemonic } from "@ethersproject/hdnode" import { FeatureFlags, isEnabled } from "@tallyho/tally-background/features" import { useTranslation } from "react-i18next" +import { selectCurrentNetwork } from "@tallyho/tally-background/redux-slices/selectors" import SharedButton from "../../../components/Shared/SharedButton" import OnboardingDerivationPathSelect from "../../../components/Onboarding/OnboardingDerivationPathSelect" import { @@ -19,12 +20,14 @@ type Props = { export default function ImportSeed(props: Props): ReactElement { const { nextPage } = props - + const selectedNetwork = useBackgroundSelector(selectCurrentNetwork) const areKeyringsUnlocked = useAreKeyringsUnlocked(false) const [recoveryPhrase, setRecoveryPhrase] = useState("") const [errorMessage, setErrorMessage] = useState("") - const [path, setPath] = useState("m/44'/60'/0'/0") + const [path, setPath] = useState( + selectedNetwork.derivationPath ?? "m/44'/60'/0'/0" + ) const [isImporting, setIsImporting] = useState(false) const { t } = useTranslation("translation", { diff --git a/ui/pages/Onboarding/Tabbed/NewSeed.tsx b/ui/pages/Onboarding/Tabbed/NewSeed.tsx index 045108c6e7..f5d21d2ce7 100644 --- a/ui/pages/Onboarding/Tabbed/NewSeed.tsx +++ b/ui/pages/Onboarding/Tabbed/NewSeed.tsx @@ -10,6 +10,7 @@ import { useHistory, useRouteMatch, } from "react-router-dom" +import { selectCurrentNetwork } from "@tallyho/tally-background/redux-slices/selectors" import OnboardingStepsIndicator from "../../../components/Onboarding/OnboardingStepsIndicator" import { useAreKeyringsUnlocked, @@ -60,6 +61,7 @@ export default function NewSeed(): ReactElement { const mnemonic = useBackgroundSelector( (state) => state.keyrings.keyringToVerify?.mnemonic ) + const selectedNetwork = useBackgroundSelector(selectCurrentNetwork) const areKeyringsUnlocked = useAreKeyringsUnlocked(false) @@ -67,9 +69,9 @@ export default function NewSeed(): ReactElement { const { path } = useRouteMatch() const showNewSeedPhrase = () => { - dispatch(generateNewKeyring()).then(() => - history.push(NewSeedRoutes.REVIEW_SEED) - ) + dispatch( + generateNewKeyring(selectedNetwork.derivationPath ?? "m/44'/60'/0'/0") + ).then(() => history.push(NewSeedRoutes.REVIEW_SEED)) } const showSeedVerification = () => { diff --git a/ui/pages/Onboarding/VerifySeed/VerifySeedSuccess.tsx b/ui/pages/Onboarding/VerifySeed/VerifySeedSuccess.tsx index 7af972ea5f..ba1786ce14 100644 --- a/ui/pages/Onboarding/VerifySeed/VerifySeedSuccess.tsx +++ b/ui/pages/Onboarding/VerifySeed/VerifySeedSuccess.tsx @@ -2,8 +2,9 @@ import React, { ReactElement } from "react" import { useHistory } from "react-router-dom" import { importKeyring } from "@tallyho/tally-background/redux-slices/keyrings" import { useTranslation } from "react-i18next" +import { selectCurrentNetwork } from "@tallyho/tally-background/redux-slices/selectors" import SharedButton from "../../../components/Shared/SharedButton" -import { useBackgroundDispatch } from "../../../hooks" +import { useBackgroundDispatch, useBackgroundSelector } from "../../../hooks" import { OnboardingBox, OnboardingMessageHeader } from "../styles" function VerifySeedSuccess({ @@ -17,6 +18,8 @@ function VerifySeedSuccess({ keyPrefix: "onboarding.seedVerification", }) const dispatch = useBackgroundDispatch() + const selectedNetwork = useBackgroundSelector(selectCurrentNetwork) + const history = useHistory() return ( @@ -40,6 +43,7 @@ function VerifySeedSuccess({ importKeyring({ mnemonic: mnemonic.join(" "), source: "internal", + path: selectedNetwork.derivationPath ?? "m/44'/60'/0'/0", }) ) history.push(nextPage)