Skip to content

Commit

Permalink
Resolve: [Ledger] Fix/extend HD pathes for ETH (#2374)
Browse files Browse the repository at this point in the history
- [x] Fix/extend HD pathes for ETH
- [x] Test `getDerivationPath`
- [x] Update `i18n`
- [x] Fix styles
  • Loading branch information
luxuereal authored Aug 23, 2022
1 parent 00c5bc8 commit ca67ee1
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Quick fix: Disable manage button in PoolsDetails [#2353](https://github.com/thorchain/asgardex-electron/pull/2353)
- Use 9R Midgard by default [#2363](https://github.com/thorchain/asgardex-electron/pull/2363)
- Fix deprecated usage of Antd.Menu children [#2372](https://github.com/thorchain/asgardex-electron/pull/2372)
- [Ledger] Fix/extend HD pathes for ETH [#2344](https://github.com/thorchain/asgardex-electron/issues/2344)

## Remove

Expand Down
9 changes: 4 additions & 5 deletions src/renderer/components/settings/WalletSettings.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,13 @@ export const RemoveLedgerIcon = styled(RemoveIcon)`
height: ${ICON_SIZE}px;
`

export const EthDerivationModeRadioGroup = styled(StyledR.Radio.Group)`
display: flex;
align-items: center;
`

export const EthDerivationModeRadioLabel = styled(StyledR.RadioLabel)`
display: flex;
align-items: center;
margin-top: 10px;
${media.lg`
margin-top: 0;
`}
`

export const WalletIndexInput = styled(A.InputNumber)`
Expand Down
66 changes: 39 additions & 27 deletions src/renderer/components/settings/WalletSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export const WalletSettings: React.FC<Props> = (props): JSX.Element => {
}

const renderAddLedger = (chain: Chain, loading: boolean) => (
<div className="flex w-full flex-col md:w-auto md:flex-row">
<div className="flex w-full flex-col md:w-auto lg:flex-row">
<div className="mr-30px flex items-center md:mr-0">
<Styled.AddLedgerButton loading={loading} onClick={() => addLedgerAddress(chain, walletIndexMap[chain])}>
<Styled.AddLedgerIcon /> {intl.formatMessage({ id: 'ledger.add.device' })}
Expand Down Expand Up @@ -238,32 +238,44 @@ export const WalletSettings: React.FC<Props> = (props): JSX.Element => {
)}
</div>
{isEthChain(chain) && (
<div className="flex items-center pl-0 pt-10px md:pt-0 md:pl-30px">
<Styled.EthDerivationModeRadioGroup onChange={onChangeEthDerivationMode} value={ethDerivationMode}>
<StyledR.Radio value="ledgerlive" key="ledgerlive">
<Styled.EthDerivationModeRadioLabel>
{intl.formatMessage({ id: 'common.ledgerlive' })}
<InfoIcon
tooltip={intl.formatMessage(
{ id: 'setting.wallet.hdpath.ledgerlive.info' },
{ path: getEthDerivationPath(walletIndexMap[ETHChain], 'ledgerlive') }
)}
/>
</Styled.EthDerivationModeRadioLabel>
</StyledR.Radio>
<StyledR.Radio value="legacy" key="legacy">
<Styled.EthDerivationModeRadioLabel>
{intl.formatMessage({ id: 'common.legacy' })}
<InfoIcon
tooltip={intl.formatMessage(
{ id: 'setting.wallet.hdpath.legacy.info' },
{ path: getEthDerivationPath(walletIndexMap[ETHChain], 'legacy') }
)}
/>
</Styled.EthDerivationModeRadioLabel>
</StyledR.Radio>
</Styled.EthDerivationModeRadioGroup>
</div>
<StyledR.Radio.Group
className="!flex flex-col items-start lg:flex-row lg:items-center lg:!pl-30px"
onChange={onChangeEthDerivationMode}
value={ethDerivationMode}>
<StyledR.Radio value="ledgerlive" key="ledgerlive" className="">
<Styled.EthDerivationModeRadioLabel>
{intl.formatMessage({ id: 'common.ledgerlive' })}
<InfoIcon
tooltip={intl.formatMessage(
{ id: 'setting.wallet.hdpath.ledgerlive.info' },
{ path: getEthDerivationPath(walletIndexMap[ETHChain], 'ledgerlive') }
)}
/>
</Styled.EthDerivationModeRadioLabel>
</StyledR.Radio>
<StyledR.Radio value="legacy" key="legacy">
<Styled.EthDerivationModeRadioLabel>
{intl.formatMessage({ id: 'common.legacy' })}
<InfoIcon
tooltip={intl.formatMessage(
{ id: 'setting.wallet.hdpath.legacy.info' },
{ path: getEthDerivationPath(walletIndexMap[ETHChain], 'legacy') }
)}
/>
</Styled.EthDerivationModeRadioLabel>
</StyledR.Radio>
<StyledR.Radio value="metamask" key="metamask">
<Styled.EthDerivationModeRadioLabel>
{intl.formatMessage({ id: 'common.metamask' })}
<InfoIcon
tooltip={intl.formatMessage(
{ id: 'setting.wallet.hdpath.metamask.info' },
{ path: getEthDerivationPath(walletIndexMap[ETHChain], 'metamask') }
)}
/>
</Styled.EthDerivationModeRadioLabel>
</StyledR.Radio>
</StyledR.Radio.Group>
)}
</div>
)
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/i18n/de/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const common: CommonMessages = {
'common.next': 'Weiter',
'common.finish': 'Beenden',
'common.copy': 'Kopieren',
'common.loading': 'Lade...',
'common.loading': 'Lade',
'common.error': 'Fehler',
'common.test': 'Test',
'common.change': 'Ändern',
Expand Down Expand Up @@ -114,7 +114,8 @@ const common: CommonMessages = {
'common.recipient': 'Empfänger',
'common.sender': 'Absender',
'common.legacy': 'Veraltet',
'common.ledgerlive': 'Ledger Live'
'common.ledgerlive': 'Ledger Live',
'common.metamask': 'MetaMask'
}

export default common
1 change: 1 addition & 0 deletions src/renderer/i18n/de/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const settings: SettingMessages = {
'setting.wallet.index.info': 'Trage die Index Nummer der Ledger Addresse ein, die Du verwenden möchtest',
'setting.wallet.hdpath.legacy.info': 'Veralteter Derivation Pfad {path}',
'setting.wallet.hdpath.ledgerlive.info': 'Ledger Live Derivation Pfad {path}',
'setting.wallet.hdpath.metamask.info': 'Metamask Derivation Pfad {path}',
'setting.thornode.node.error.unhealthy':
'THORNode API URL scheint "unhealthy" zu sein beim Überprüfen von "{endpoint}"',
'setting.thornode.node.error.url': 'Ungültige THORNode API URL. Bitte überprüfe diese und versuche es erneut.',
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/i18n/de/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const wallet: WalletMessages = {
'wallet.create.title': 'Erstelle eine Wallet',
'wallet.create.enter.phrase': 'Gebe Deine Phrase in richtiger Reihenfolge ein',
'wallet.create.words.click': 'Klicke die Wörter in der richtigen Reihenfolge',
'wallet.create.creating': 'Erstelle eine Wallet ...',
'wallet.create.creating': 'Erstelle eine Wallet',
'wallet.create.error': 'Fehler beim Erstellen der Wallet',
'wallet.create.error.phrase': 'Falsche Phrase. Bitte überprüfe Deine Phrase und gebe diese erneut ein.',
'wallet.receive.address.error': 'Keine Addresse für den Empfang vorhanden',
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/i18n/en/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const common: CommonMessages = {
'common.next': 'Next',
'common.finish': 'Finish',
'common.copy': 'Copy',
'common.loading': 'Loading...',
'common.loading': 'Loading',
'common.error': 'Error',
'common.test': 'Test',
'common.change': 'Change',
Expand Down Expand Up @@ -114,7 +114,8 @@ const common: CommonMessages = {
'common.recipient': 'Recipient',
'common.sender': 'Sender',
'common.legacy': 'Legacy',
'common.ledgerlive': 'Ledger Live'
'common.ledgerlive': 'Ledger Live',
'common.metamask': 'MetaMask'
}

export default common
1 change: 1 addition & 0 deletions src/renderer/i18n/en/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const settings: SettingMessages = {
'setting.wallet.index.info': 'Enter the index number of the Ledger address you want to use',
'setting.wallet.hdpath.legacy.info': 'Legacy derivation path {path}',
'setting.wallet.hdpath.ledgerlive.info': 'Ledger Live derivation path {path}',
'setting.wallet.hdpath.metamask.info': 'Metamask derivation path {path}',
'setting.thornode.node.error.unhealthy': 'THORNode API seems to be unhealthy by checking "{endpoint}"',
'setting.thornode.node.error.url': 'Invalid THORNode API URL. Please double check and try again',
'setting.thornode.rpc.error.url': 'Invalid THORNode RPC URL. Please double check and try again',
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/i18n/en/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const wallet: WalletMessages = {
'wallet.create.enter.phrase': 'Enter your phrase in a right order',
'wallet.create.error.phrase': 'Wrong phrase. Please double check your phrase and re-enter it again.',
'wallet.create.words.click': 'Click the word in correct order',
'wallet.create.creating': 'Creating wallet',
'wallet.create.creating': 'Creating wallet',
'wallet.create.error': 'Error while creating a wallet',
'wallet.receive.address.error': 'No address available to receive funds',
'wallet.receive.address.errorQR': 'Error while rendering QR code: {error}',
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/i18n/fr/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const common: CommonMessages = {
'common.next': 'Suivant',
'common.finish': 'Finir',
'common.copy': 'Copier',
'common.loading': 'Chargement...',
'common.loading': 'Chargement',
'common.error': 'Erreur',
'common.test': 'Test - FR',
'common.change': 'Modifier',
Expand Down Expand Up @@ -114,7 +114,8 @@ const common: CommonMessages = {
'common.recipient': 'Destinataire',
'common.sender': 'Sender - FR',
'common.legacy': 'Legacy - FR',
'common.ledgerlive': 'Ledger Live'
'common.ledgerlive': 'Ledger Live',
'common.metamask': 'MetaMask'
}

export default common
1 change: 1 addition & 0 deletions src/renderer/i18n/fr/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const settings: SettingMessages = {
'setting.wallet.index.info': "Entrez le numéro d'index de l'adresse Ledger que vous souhaitez utiliser",
'setting.wallet.hdpath.legacy.info': 'Legacy derivation path {path} - FR',
'setting.wallet.hdpath.ledgerlive.info': 'Ledger Live derivation path {path} - FR',
'setting.wallet.hdpath.metamask.info': 'Metamask derivation path {path} - FR',
'setting.thornode.node.error.unhealthy': 'THORNode API seems to be unhealthy by checking "{endpoint} - FR"',
'setting.thornode.node.error.url': 'Invalid THORNode API URL. Please double check and try again - FR',
'setting.thornode.rpc.error.url': 'Invalid THORNode RPC URL. Please double check and try again - FR',
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/i18n/ru/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ const common: CommonMessages = {
'common.recipient': 'Получатель',
'common.sender': 'Отправитель',
'common.legacy': 'Устаревший',
'common.ledgerlive': 'Ledger Live'
'common.ledgerlive': 'Ledger Live',
'common.metamask': 'MetaMask'
}

export default common
1 change: 1 addition & 0 deletions src/renderer/i18n/ru/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const settings: SettingMessages = {
'setting.wallet.index.info': 'Введите индекс Ledger адреса, который вы хотите использовать',
'setting.wallet.hdpath.legacy.info': 'Устаревший путь деривации {path}',
'setting.wallet.hdpath.ledgerlive.info': 'Путь деривации Ledger Live {path}',
'setting.wallet.hdpath.metamask.info': 'Metamask derivation path {path} - RU',
'setting.thornode.node.error.unhealthy': 'THORNode API seems to be unhealthy by checking "{endpoint} - RU"',
'setting.thornode.node.error.url': 'Invalid THORNode API URL. Please double check and try again - RU',
'setting.thornode.rpc.error.url': 'Invalid THORNode RPC URL. Please double check and try again - RU',
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/i18n/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export type CommonMessageKey =
| 'common.sender'
| 'common.legacy'
| 'common.ledgerlive'
| 'common.metamask'

export type CommonMessages = {
[key in CommonMessageKey]: string
Expand Down Expand Up @@ -329,6 +330,7 @@ type SettingMessageKey =
| 'setting.wallet.index.info'
| 'setting.wallet.hdpath.legacy.info'
| 'setting.wallet.hdpath.ledgerlive.info'
| 'setting.wallet.hdpath.metamask.info'
| 'setting.thornode.node.error.url'
| 'setting.thornode.node.error.unhealthy'
| 'setting.thornode.rpc.error.url'
Expand Down
18 changes: 18 additions & 0 deletions src/shared/ethereum/ledger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getDerivationPath } from './ledger'

describe('shared/eth/ledger', () => {
describe('getDerivationPath', () => {
it('metamask', () => {
expect(getDerivationPath(0, 'metamask')).toEqual(`m/44'/60'/0'/0/0`)
expect(getDerivationPath(1, 'metamask')).toEqual(`m/44'/60'/0'/0/1`)
})
it('ledger live', () => {
expect(getDerivationPath(0, 'ledgerlive')).toEqual(`m/44'/60'/0'/0/0`)
expect(getDerivationPath(1, 'ledgerlive')).toEqual(`m/44'/60'/1'/0/0`)
})
it('legacy', () => {
expect(getDerivationPath(0, 'legacy')).toEqual(`m/44'/60'/0'/0`)
expect(getDerivationPath(1, 'legacy')).toEqual(`m/44'/60'/0'/1`)
})
})
})
14 changes: 10 additions & 4 deletions src/shared/ethereum/ledger.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { EthDerivationMode } from './types'

// ETH derivation pathes `Legacy` + `Ledger Live`
// Based on https://github.com/LedgerHQ/ledger-live/blob/0059ab0aa6bbc2d952476e65ef9db0f557321cba/libs/ledger-live-common/src/derivation.ts#L42-L53
const DERIVATION_MAP: Record<EthDerivationMode, string> = { legacy: `m/44'/60'/0'/`, ledgerlive: `m/44'/60'/0'/0/` }
// ETH derivation pathes `Legacy`, `Ledger Live`, `MetaMask`
// Based on
// - Definitions in LedgerLive https://github.com/LedgerHQ/ledger-live/blob/develop/libs/ledger-live-common/src/derivation.ts#L43-L55
// - Definitions in MetaMask https://github.com/MetaMask/metamask-extension/blob/develop/ui/pages/create-account/connect-hardware/index.js#L24-L31
const DERIVATION_MAP: Record<EthDerivationMode, string> = {
legacy: `m/44'/60'/0'/{account}`,
ledgerlive: `m/44'/60'/{account}'/0/0`,
metamask: `m/44'/60'/0'/0/{account}`
}

export const getDerivationPath = (walletIndex: number, mode: EthDerivationMode): string =>
`${DERIVATION_MAP[mode]}${walletIndex}`
`${DERIVATION_MAP[mode]}`.replace(/{account}/, `${walletIndex}`)
2 changes: 1 addition & 1 deletion src/shared/ethereum/types.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type EthDerivationMode = 'legacy' | 'ledgerlive'
export type EthDerivationMode = 'legacy' | 'ledgerlive' | 'metamask'

0 comments on commit ca67ee1

Please sign in to comment.