Skip to content

Commit 2bcdda0

Browse files
authored
Log and restore if possible while showing secret (#949)
* log and restore keychain if needed * add more logging for wallets
1 parent b114499 commit 2bcdda0

File tree

3 files changed

+116
-8
lines changed

3 files changed

+116
-8
lines changed

src/components/settings-menu/BackupSection.js

+100-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import analytics from '@segment/analytics-react-native';
2+
import { captureMessage } from '@sentry/react-native';
23
import PropTypes from 'prop-types';
34
import React, { useCallback, useState } from 'react';
45
import FastImage from 'react-native-fast-image';
56
import styled from 'styled-components';
67
import SeedPhraseImageSource from '../../assets/seed-phrase-icon.png';
78
import { useWallets } from '../../hooks';
8-
import { loadSeedPhraseAndMigrateIfNeeded } from '../../model/wallet';
9+
import {
10+
getAllWallets,
11+
getSelectedWallet,
12+
loadAddress,
13+
loadSeedPhraseAndMigrateIfNeeded,
14+
} from '../../model/wallet';
15+
import store from '../../redux/store';
16+
import { walletsLoadState, walletsUpdate } from '../../redux/wallets';
17+
import { logger } from '../../utils';
918
import { Button } from '../buttons';
1019
import CopyTooltip from '../copy-tooltip';
1120
import { Centered, Column } from '../layout';
@@ -28,21 +37,107 @@ const ToggleSeedPhraseButton = styled(Button)`
2837
const BackupSection = ({ navigation }) => {
2938
const [seedPhrase, setSeedPhrase] = useState(null);
3039
const { selectedWallet } = useWallets();
40+
const [shouldRetry, setShouldRetry] = useState(true);
3141

3242
const hideSeedPhrase = () => setSeedPhrase(null);
3343

44+
const logAndAttemptRestore = useCallback(
45+
async error => {
46+
if (!shouldRetry) {
47+
hideSeedPhrase();
48+
return;
49+
}
50+
51+
setShouldRetry(false);
52+
53+
// 1 - Log the error if exists
54+
if (error) {
55+
logger.sentry(
56+
'[logAndAttemptRestore]: Error while revealing seed',
57+
error
58+
);
59+
}
60+
61+
// 2 - Log redux and public keychain entries
62+
logger.sentry('[logAndAttemptRestore]: REDUX DATA:', store.getState());
63+
try {
64+
logger.sentry(
65+
'[logAndAttemptRestore]: Keychain allWallets:',
66+
await getAllWallets()
67+
);
68+
// eslint-disable-next-line no-empty
69+
} catch (e) {}
70+
71+
try {
72+
logger.sentry(
73+
'[logAndAttemptRestore]: Keychain selectedWallet:',
74+
await getSelectedWallet()
75+
);
76+
// eslint-disable-next-line no-empty
77+
} catch (e) {}
78+
79+
try {
80+
logger.sentry(
81+
'[logAndAttemptRestore]: Keychain address:',
82+
await loadAddress()
83+
);
84+
// eslint-disable-next-line no-empty
85+
} catch (e) {}
86+
87+
// 3 - Send message to sentry
88+
captureMessage(`Error while revealing seed`);
89+
logger.sentry('[logAndAttemptRestore] message sent to sentry');
90+
91+
// 4 - Attempt to restore
92+
try {
93+
// eslint-disable-next-line no-unused-vars
94+
const { wallets } = await getAllWallets();
95+
logger.sentry('[logAndAttemptRestore] Got all wallets');
96+
} catch (e) {
97+
logger.sentry(
98+
'[logAndAttemptRestore] Got error getting all wallets',
99+
e
100+
);
101+
// if we don't have all wallets, let's see if we have a selected wallet
102+
const selected = await getSelectedWallet();
103+
logger.sentry('[logAndAttemptRestore] Got selected wallet');
104+
if (selected?.wallet?.id) {
105+
const { wallet } = selected;
106+
// We can recover it based in the selected wallet
107+
await store.dispatch(walletsUpdate({ [wallet.id]: wallet }));
108+
logger.sentry('[logAndAttemptRestore] Updated wallets');
109+
await store.dispatch(walletsLoadState());
110+
logger.sentry('[logAndAttemptRestore] Reloaded wallets state');
111+
// Retrying one more time
112+
const keychainValue = await loadSeedPhraseAndMigrateIfNeeded(
113+
wallet.id
114+
);
115+
if (keychainValue) {
116+
setSeedPhrase(keychainValue);
117+
captureMessage(`Restore from selected wallet successful`);
118+
}
119+
}
120+
}
121+
},
122+
[shouldRetry]
123+
);
124+
34125
const handlePressToggleSeedPhrase = useCallback(() => {
35126
if (!seedPhrase) {
36127
loadSeedPhraseAndMigrateIfNeeded(selectedWallet.id)
37128
.then(keychainValue => {
38-
setSeedPhrase(keychainValue);
39-
analytics.track('Viewed backup seed phrase text');
129+
if (!keychainValue) {
130+
logAndAttemptRestore();
131+
} else {
132+
setSeedPhrase(keychainValue);
133+
analytics.track('Viewed backup seed phrase text');
134+
}
40135
})
41-
.catch(hideSeedPhrase);
136+
.catch(e => logAndAttemptRestore(e));
42137
} else {
43138
hideSeedPhrase();
44139
}
45-
}, [seedPhrase, selectedWallet.id]);
140+
}, [logAndAttemptRestore, seedPhrase, selectedWallet.id]);
46141

47142
return (
48143
<Column align="center" css={padding(80, 40, 0)} flex={1}>

src/redux/wallets.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { captureException } from '@sentry/react-native';
12
import { toChecksumAddress } from 'ethereumjs-util';
23
import { filter, flatMap, get, map, values } from 'lodash';
34
import {
@@ -15,6 +16,7 @@ import {
1516
setSelectedWallet,
1617
} from '../model/wallet';
1718
import { settingsUpdateAccountAddress } from '../redux/settings';
19+
import { logger } from '../utils';
1820

1921
// -- Constants --------------------------------------- //
2022
const WALLETS_ADDED_ACCOUNT = 'wallets/WALLETS_ADDED_ACCOUNT';
@@ -44,6 +46,7 @@ export const walletsLoadState = () => async (dispatch, getState) => {
4446
});
4547
if (found) {
4648
selectedWallet = someWallet;
49+
logger.sentry('Found selected wallet based on loadAddress result');
4750
}
4851
return found;
4952
});
@@ -52,6 +55,9 @@ export const walletsLoadState = () => async (dispatch, getState) => {
5255
// Recover from broken state (account address not in selected wallet)
5356
if (!addressFromKeychain) {
5457
addressFromKeychain = await loadAddress();
58+
logger.sentry(
59+
'addressFromKeychain wasnt set on settings so it is being loaded from loadAddress'
60+
);
5561
}
5662

5763
const selectedAddress = selectedWallet.addresses.find(a => {
@@ -62,6 +68,9 @@ export const walletsLoadState = () => async (dispatch, getState) => {
6268
const account = selectedWallet.addresses.find(a => a.visible);
6369
await dispatch(settingsUpdateAccountAddress(account.address));
6470
await saveAddress(account.address);
71+
logger.sentry(
72+
'Selected the first visible address because there was not selected one'
73+
);
6574
}
6675

6776
const walletNames = await getWalletNames();
@@ -76,9 +85,10 @@ export const walletsLoadState = () => async (dispatch, getState) => {
7685
});
7786

7887
dispatch(fetchWalletNames());
79-
80-
// eslint-disable-next-line no-empty
81-
} catch (error) {}
88+
} catch (error) {
89+
logger.sentry('Exception during walletsLoadState');
90+
captureException(error);
91+
}
8292
};
8393

8494
export const walletsUpdate = wallets => dispatch => {

src/utils/logger.js

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ const Logger = {
4141
} else {
4242
sentryUtils.addDataBreadcrumb.apply(null, args);
4343
}
44+
if (__DEV__) {
45+
console.log(...args);
46+
}
4447
},
4548
warn(...args) {
4649
if (__DEV__) {

0 commit comments

Comments
 (0)