Skip to content

Commit

Permalink
Revert "Revert "Custom HD Path for account recovery""
Browse files Browse the repository at this point in the history
  • Loading branch information
gutsyphilip authored May 11, 2022
1 parent 01eb104 commit d16414c
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 19 deletions.
29 changes: 21 additions & 8 deletions packages/frontend/src/components/accounts/ledger/SetupLedger.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import {
import { showCustomAlert } from '../../../redux/actions/status';
import { selectAccountSlice } from '../../../redux/slices/account';
import { createNewAccount } from '../../../redux/slices/account/createAccountThunks';
import { actions as ledgerActions } from '../../../redux/slices/ledger';
import { actions as ledgerActions, LEDGER_HD_PATH_PREFIX } from '../../../redux/slices/ledger';
import { actions as linkdropActions } from '../../../redux/slices/linkdrop';
import { selectStatusMainLoader } from '../../../redux/slices/status';
import { setLedgerHdPath } from '../../../utils/localStorage';
import parseFundingOptions from '../../../utils/parseFundingOptions';
import { setKeyMeta, ENABLE_IDENTITY_VERIFIED_ACCOUNT } from '../../../utils/wallet';
import FormButton from '../../common/FormButton';
Expand All @@ -27,11 +28,9 @@ import Container from '../../common/styled/Container.css';
import { isRetryableRecaptchaError, Recaptcha } from '../../Recaptcha';
import LedgerIcon from '../../svg/LedgerIcon';
import InstructionsModal from './InstructionsModal';
import LedgerHdPaths from './LedgerHdPaths';

const {
checkAndHideLedgerModal
} = ledgerActions;

const { checkAndHideLedgerModal } = ledgerActions;
const { setLinkdropAmount } = linkdropActions;

// FIXME: Use `debug` npm package so we can keep some debug logging around but not spam the console everywhere
Expand All @@ -45,6 +44,9 @@ const SetupLedger = (props) => {
const [isNewAccount, setIsNewAccount] = useState(null);
// TODO: Custom recaptcha hook
const [recaptchaToken, setRecaptchaToken] = useState(null);
const [confirmedPath, setConfirmedPath] = useState(1);
const ledgerHdPath = `${LEDGER_HD_PATH_PREFIX}${confirmedPath}'`;

const recaptchaRef = useRef(null);
const fundingOptions = parseFundingOptions(props.location.search);
const shouldRenderRecaptcha = !fundingOptions && RECAPTCHA_CHALLENGE_API_KEY && isNewAccount && !ENABLE_IDENTITY_VERIFIED_ACCOUNT;
Expand Down Expand Up @@ -78,12 +80,16 @@ const SetupLedger = (props) => {
let publicKey;

try {

debugLog(DISABLE_CREATE_ACCOUNT, fundingOptions);
publicKey = await dispatch(getLedgerPublicKey());
publicKey = await dispatch(getLedgerPublicKey(ledgerHdPath));
await setKeyMeta(publicKey, { type: 'ledger' });
Mixpanel.track('SR-Ledger Set key meta');

// Set custom path to localstorage
if (ledgerHdPath) {
setLedgerHdPath({ accountId, path: ledgerHdPath });
}

// COIN-OP VERIFY ACCOUNT
if (DISABLE_CREATE_ACCOUNT && ENABLE_IDENTITY_VERIFIED_ACCOUNT && !fundingOptions) {
await dispatch(fundCreateAccountLedger(accountId, publicKey));
Expand Down Expand Up @@ -126,7 +132,7 @@ const SetupLedger = (props) => {
errorMessage: err.message
}));
} else {
recaptchaRef.current.reset();
recaptchaRef?.current?.reset();

dispatch(showCustomAlert({
errorMessage: err.message,
Expand Down Expand Up @@ -179,6 +185,13 @@ const SetupLedger = (props) => {
<Translate id='setupLedger.one' />
&nbsp;<Translate id='setupLedger.two' /> <span className='link underline' onClick={openShowInstructions}><Translate id='setupLedger.twoLink' /></span>.
</h2>
<LedgerHdPaths
confirmedPath={confirmedPath}
setConfirmedPath={(path) => {
setConfirmedPath(path);
Mixpanel.track('SR-Ledger Setup set custom HD path');
}}
/>
{
shouldRenderRecaptcha && <Recaptcha
ref={recaptchaRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ import React, { useState } from 'react';
import { Translate } from 'react-localize-redux';

import { Mixpanel } from '../../../mixpanel/index';
import { LEDGER_HD_PATH_PREFIX } from '../../../redux/slices/ledger';
import FormButton from '../../common/FormButton';
import Container from '../../common/styled/Container.css';
import LedgerIcon from '../../svg/LedgerIcon';
import InstructionsModal from './InstructionsModal';
import LedgerHdPaths from './LedgerHdPaths';

export default ({
onClickConnectLedger
}) => {
const [showInstructions, setShowInstructions] = useState(false);
const [confirmedPath, setConfirmedPath] = useState(1);
const ledgerHdPath = `${LEDGER_HD_PATH_PREFIX}${confirmedPath}'`;
return (
<Container className='small-centered border ledger-theme'>
<h1><Translate id='setupLedger.header' /></h1>
Expand All @@ -28,7 +32,16 @@ export default ({
<Translate id='setupLedger.twoLink' />
</span>.
</h2>
<FormButton onClick={onClickConnectLedger}>
<LedgerHdPaths
confirmedPath={confirmedPath}
setConfirmedPath={(path) => {
setConfirmedPath(path);
Mixpanel.track('SR-Ledger Setup set custom HD path');
}}
/>
<FormButton onClick={()=>{
onClickConnectLedger(ledgerHdPath);
}}>
<Translate id='button.continue' />
</FormButton>
<FormButton
Expand Down
5 changes: 4 additions & 1 deletion packages/frontend/src/components/common/FormButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ const CustomButton = styled.button`
&.link {
width: auto !important;
height: auto;
min-height: 50px;
padding: 0;
margin: 0;
border-radius: 0px;
Expand Down Expand Up @@ -505,7 +506,8 @@ const FormButton = ({
id,
trackingId,
swapButton,
'data-test-id': testId
'data-test-id': testId,
style
}) => (
<CustomButton
swapButton={swapButton}
Expand All @@ -520,6 +522,7 @@ const FormButton = ({
}}
tabIndex='3'
data-test-id={testId}
style={style}
>
{sending
? <Translate id={sendingString ? sendingString : 'sending'} />
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/src/components/navigation/ConnectLedger.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const ConnectLedgerButton = styled.div`
align-items: center;
padding: 12px 16px;
cursor: pointer;
white-space: nowrap;
svg {
width: 16px;
height: 16px;
Expand Down
7 changes: 5 additions & 2 deletions packages/frontend/src/components/navigation/NavLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const Container = styled.div`
transition: 100ms;
color: #72727A;
font-size: 15px;
white-space: nowrap;
:hover, &.selected {
text-decoration: none;
Expand Down Expand Up @@ -71,6 +72,7 @@ const Container = styled.div`
background: #D6EDFF;
font-weight: 600;
color: black;
white-space: nowrap;
:hover {
background: #0072CE;
Expand Down Expand Up @@ -163,8 +165,9 @@ const NavLinks = () => (
<img src={USN_LOGO} alt='open-link'></img>
</div>

<>Buy $USN</>
</a>}
<>Buy $USN</>
</a>
}
</Container>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { WalletError } from '../../../utils/walletError';
import { finishAccountSetup } from '../../actions/account';
import { SLICE_NAME } from './';


const {
RECAPTCHA_ENTERPRISE_SITE_KEY,
NETWORK_ID,
Expand Down
8 changes: 6 additions & 2 deletions packages/frontend/src/routes/SetupLedgerNewAccountWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { useDispatch } from 'react-redux';
import SetupLedgerNewAccount from '../components/accounts/ledger/SetupLedgerNewAccount';
import { getLedgerPublicKey, redirectTo } from '../redux/actions/account';
import { showCustomAlert } from '../redux/actions/status';
import { setLedgerHdPath } from '../utils/localStorage';
import { setKeyMeta, wallet } from '../utils/wallet';

export function SetupLedgerNewAccountWrapper() {
const dispatch = useDispatch();
return (
<SetupLedgerNewAccount
onClickConnectLedger={async () => {
onClickConnectLedger={async (path) => {
try {
const ledgerPublicKey = await dispatch(getLedgerPublicKey());
const ledgerPublicKey = await dispatch(getLedgerPublicKey(path));
const implicitAccountId = Buffer.from(ledgerPublicKey.data).toString('hex');
const account = wallet.getAccountBasic(implicitAccountId);
try {
Expand All @@ -29,6 +30,9 @@ export function SetupLedgerNewAccountWrapper() {
throw e;
}
}
if (path) {
setLedgerHdPath({ accountId: implicitAccountId, path });
}
await setKeyMeta(ledgerPublicKey, { type: 'ledger' });
dispatch(redirectTo(`/create-implicit-account?implicitAccountId=${implicitAccountId}&recoveryMethod=ledger`));
} catch (e) {
Expand Down
30 changes: 30 additions & 0 deletions packages/frontend/src/utils/ledger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import TransportU2F from '@ledgerhq/hw-transport-u2f';
import { createClient } from 'near-ledger-js';

import { WalletError } from './walletError';

async function createLedgerU2FTransport() {
let transport;
try {
transport = await TransportU2F.create();
} catch (error) {
if (error.id === 'U2FNotSupported') {
throw new WalletError(error.message, 'getLedgerAccountIds.U2FNotSupported');
}
throw error;
}
transport.setScrambleKey('NEAR');
return transport;
}

async function createLedgerU2FClient() {
const transport = await createLedgerU2FTransport();
const client = await createClient(transport);
return client;
}

function getLedgerHDPath(confirmedPath){
return confirmedPath ? `44'/397'/0'/0'/${confirmedPath}'` : null;
}

export { createLedgerU2FClient, getLedgerHDPath };
6 changes: 2 additions & 4 deletions packages/frontend/src/utils/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,9 @@ class Wallet {
}
}

async addLedgerAccessKey() {
async addLedgerAccessKey(path) {
const accountId = this.accountId;
const ledgerPublicKey = await this.getLedgerPublicKey();
const ledgerPublicKey = await this.getLedgerPublicKey(path);
const accessKeys = await this.getAccessKeys();
const accountHasLedgerKey = accessKeys.map((key) => key.public_key).includes(ledgerPublicKey.toString());
await setKeyMeta(ledgerPublicKey, { type: 'ledger' });
Expand Down Expand Up @@ -570,8 +570,6 @@ class Wallet {

async getLedgerAccountIds({ path }) {
const publicKey = await this.getLedgerPublicKey(path);

// TODO: getXXX methods shouldn't be modifying the state
await setKeyMeta(publicKey, { type: 'ledger' });

let accountIds;
Expand Down

0 comments on commit d16414c

Please sign in to comment.