Skip to content

Commit

Permalink
fix: unresponsive ledger device
Browse files Browse the repository at this point in the history
  • Loading branch information
r4mmer committed Jan 8, 2024
1 parent cbecaf1 commit 416a4db
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 128 deletions.
231 changes: 123 additions & 108 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"version": "0.27.1-rc2",
"private": true,
"dependencies": {
"@hathor/wallet-lib": "1.0.2",
"@ledgerhq/hw-transport-node-hid": "6.27.1",
"@hathor/wallet-lib": "1.0.4",
"@ledgerhq/hw-transport-node-hid": "6.28.1",
"@sentry/electron": "3.0.7",
"babel-polyfill": "6.26.0",
"bootstrap": "4.6.1",
Expand Down Expand Up @@ -108,7 +108,9 @@
},
"mac": {
"provisioningProfile": "keys/mac_production.provisionprofile",
"notarize": { "teamId": "TEAM-ID-HERE" },
"notarize": {
"teamId": "TEAM-ID-HERE"
},
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "build/entitlements.mac.plist",
Expand Down
31 changes: 24 additions & 7 deletions public/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,12 @@ class Ledger {
this.subscriptor = Transport.listen({
next: e => {
if (e.type === 'add') {
console.log(`Device detected: ${e.deviceModel?.id}`);
// We get this event when any app is opened on Ledger (Bitcoin, Ethereum, Hathor, etc). We have
// the getVersion call next to make sure we're on the Hathor app.
this.getVersion();
} else if (e.type === 'remove') {
console.log(`Device removed: ${e.deviceModel?.id}`);
// This is called in some situations
// - Usb disconnected
// - When user quits an app
Expand All @@ -134,7 +136,10 @@ class Ledger {
}
}
},
error: error => {},
error: error => {
console.log('Error communicating with device');
console.log(error);
},
complete: () => {}
})

Expand Down Expand Up @@ -175,11 +180,21 @@ class Ledger {

const { command, p1, p2, data, resolve, reject } = this.sendQueue.shift();
this.getTransport()
.then(transport => transport.send(ledgerCLA, command, p1, p2, data))
.then((response) => { resolve(response) }, (error) => { reject(error) })
.then(transport => {
console.log(`Sending to ledger ${command} ${p1} ${p2}`);
return transport.send(ledgerCLA, command, p1, p2, data);
})
.then((response) => {
console.log(`Got response ${response.toString('hex')}`);
resolve(response);
}, (error) => {
console.log(error);
reject(error);
})
.finally(() => {
// When done, check the queue again
this.checkSendQueue();
console.log('Finished sending command, will retry queue');
// When done, check the queue again
this.checkSendQueue();
});
}

Expand All @@ -190,7 +205,7 @@ class Ledger {
* @return {Promise} Promise resolved when there's a response from Ledger
*/
sendToQueue = (command, p1, p2, data) => {
console.log('sending to Ledger:', command, p1, p2);
console.log('sending to queue:', command, p1, p2);
const promise = new Promise((resolve, reject) => {
const element = {
command,
Expand Down Expand Up @@ -240,7 +255,9 @@ class Ledger {
this.transport.decorateAppAPIMethods(this, this.methods, "HTR");
resolve(transport);
}, (e) => {
reject(Ledger.parseLedgerError(e));
console.log('Error creating transport');
console.log(e);
reject(Ledger.parseLedgerError(e));
});
});
return promiseMethod;
Expand Down
11 changes: 11 additions & 0 deletions public/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ process.once('loaded', () => {
// Set closed in localStorage, so user does not open in the wallet page
localStorage.setItem('localstorage:closed', 'true');

const accessDataRaw = localStorage.getItem('localstorage:accessdata');
if (accessDataRaw) {
// check if the access data is from a hardware wallet, if so we need to remove it
// This ensures that a previously closed hardware wallet will not be loaded again
// unless the device is connected
const accessData = JSON.parse(accessDataRaw);
if ((accessData?.walletFlags & 0x02) > 0) {
localStorage.removeItem('localstorage:accessdata');
}
}

// Sending to main process the information about systray message
const systrayMessageChecked = JSON.parse(localStorage.getItem('wallet:systray_message_checked')) === true;
ipcRenderer.send('systray_message:check', systrayMessageChecked);
Expand Down
4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ const returnLoadedWalletComponent = (Component, props) => {
const isServerScreen = props.match.path === '/server';

// If was closed and is loaded we need to redirect to locked screen
if ((!isServerScreen) && (LOCAL_STORE.wasClosed() || LOCAL_STORE.isLocked())) {
if ((!isServerScreen) && (LOCAL_STORE.wasClosed() || LOCAL_STORE.isLocked()) && (!LOCAL_STORE.isHardwareWallet())) {
return <Redirect to={{ pathname: '/locked/' }} />;
}

Expand Down Expand Up @@ -250,7 +250,7 @@ const returnStartedRoute = (Component, props, rest) => {
// the locked screen since the wallet would not be able to be started otherwise
const isServerScreen = props.match.path === '/server';
// Wallet is locked, go to locked screen
if (LOCAL_STORE.isLocked() && !isServerScreen) {
if (LOCAL_STORE.isLocked() && !isServerScreen && !LOCAL_STORE.isHardwareWallet()) {
return <Redirect to={{pathname: '/locked/'}}/>;
}

Expand Down
4 changes: 1 addition & 3 deletions src/screens/StartHardwareWallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class StartHardwareWallet extends React.Component {
const xpub = hathorLib.walletUtils.xpubFromData(compressedPubkey, chainCode, fingerprint);

LOCAL_STORE.setHardwareWallet(true);
LOCAL_STORE.markBackupDone();
this.props.startWallet({
words: null,
passphrase: '',
Expand All @@ -128,9 +129,6 @@ class StartHardwareWallet extends React.Component {
xpub,
hardware: true,
});
LOCAL_STORE.markBackupDone();

this.props.history.push('/wallet/');
} else {
// Error
this.setState({ errorMessage: arg.error.message });
Expand Down
24 changes: 19 additions & 5 deletions src/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,26 @@ export class LocalStorageStore {
}
}

cleanWallet() {
this.removeItem(IS_HARDWARE_KEY);
this.removeItem(CLOSED_KEY);
/**
* Clean access data from persistent storage, making the wallet 'not loaded'
*/
cleanAccessData() {
this.removeItem(ACCESS_DATA_KEY);
delete this._storage;
this._storage = null;
}

/**
* Clean wallet metadata
*/
cleanWallet() {
this.removeItem(IS_HARDWARE_KEY);
this.removeItem(CLOSED_KEY);
}

/**
* Reset the storage, removing all managed keys from localStorage
*/
resetStorage() {
for (const key of storageKeys) {
this.removeItem(key);
Expand All @@ -224,7 +236,7 @@ export class LocalStorageStore {
networkName: config.getNetwork().name,
}
);
STORE.setItem(ACCESS_DATA_KEY, accessData);
this.setItem(ACCESS_DATA_KEY, accessData);
const storage = this.getStorage();
await storage.saveAccessData(accessData);
this._storage = storage;
Expand All @@ -239,7 +251,7 @@ export class LocalStorageStore {
xpub,
{ hardware: true }
);
STORE.setItem(ACCESS_DATA_KEY, accessData);
this.setItem(ACCESS_DATA_KEY, accessData);
const storage = this.getStorage();
await storage.saveAccessData(accessData);
this._storage = storage;
Expand Down Expand Up @@ -373,6 +385,7 @@ export class LocalStorageStore {
// We are migrating from an version of wallet-lib prior to 1.0.0
// This will generate the encrypted keys and other metadata
const accessData = this.migrateAccessData(pin);
this.setItem(ACCESS_DATA_KEY, accessData);
// Prepare the storage with the migrated access data
this._storage = null;
this.setHardwareWallet(false);
Expand All @@ -381,6 +394,7 @@ export class LocalStorageStore {
this._storage = storage;

await this.handleMigrationOldRegisteredTokens(storage);
// Migrate old backup flag
const isBackupDone = this.getItem('wallet:backup');
if (isBackupDone) {
this.markBackupDone();
Expand Down
1 change: 1 addition & 0 deletions src/utils/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ const wallet = {
async cleanWallet(wallet) {
await wallet.storage.cleanStorage(true, true);
LOCAL_STORE.cleanWallet();
LOCAL_STORE.cleanAccessData();
this.cleanWalletRedux(wallet);
},

Expand Down

0 comments on commit 416a4db

Please sign in to comment.