MyCrypto/shared/enclave/server/wallets/ledger.ts

86 lines
2.2 KiB
TypeScript
Raw Normal View History

2018-05-04 04:00:34 +00:00
import EthTx from 'ethereumjs-tx';
import { addHexPrefix, toBuffer } from 'ethereumjs-util';
2018-05-04 04:26:25 +00:00
import { WalletLib } from 'shared/enclave/types';
2018-04-27 20:49:17 +00:00
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
import LedgerEth from '@ledgerhq/hw-app-eth';
2018-05-04 04:44:17 +00:00
let transport: any;
2018-04-27 20:49:17 +00:00
async function getEthApp() {
2018-05-04 04:00:34 +00:00
try {
2018-05-04 04:44:17 +00:00
if (!transport) {
transport = await TransportNodeHid.create();
transport.on('disconnect', () => (transport = null));
}
2018-05-04 04:00:34 +00:00
return new LedgerEth(transport);
} catch (err) {
if (err && err.message && err.message.includes('cannot open device with path')) {
throw new Error(
2018-05-04 04:44:17 +00:00
'Your Ledger is currently in use with another application. Please wait, or close other wallet applications before trying again.'
2018-05-04 04:00:34 +00:00
);
}
throw err;
}
2018-04-27 20:49:17 +00:00
}
const Ledger: WalletLib = {
2018-05-04 04:26:25 +00:00
async getChainCode(dpath) {
2018-04-27 20:49:17 +00:00
const app = await getEthApp();
try {
const res = await app.getAddress(dpath, false, true);
2018-04-27 20:49:17 +00:00
return {
publicKey: res.publicKey,
2018-05-04 20:59:04 +00:00
chainCode: res.chainCode as string
2018-04-27 20:49:17 +00:00
};
} catch (err) {
throw new Error('Failed to connect to Ledger');
2018-04-27 20:49:17 +00:00
}
2018-05-04 04:00:34 +00:00
},
2018-05-04 04:26:25 +00:00
async signTransaction(tx, path) {
2018-05-04 04:00:34 +00:00
const app = await getEthApp();
const ethTx = new EthTx({
...tx,
v: Buffer.from([tx.chainId]),
r: toBuffer(0),
s: toBuffer(0)
});
const rsv = await app.signTransaction(path, ethTx.serialize().toString('hex'));
const signedTx = new EthTx({
...tx,
r: addHexPrefix(rsv.r),
s: addHexPrefix(rsv.s),
v: addHexPrefix(rsv.v)
});
return {
signedTransaction: signedTx.serialize().toString('hex')
};
2018-05-04 04:26:25 +00:00
},
2018-05-04 04:40:32 +00:00
async signMessage(msg, path) {
2018-05-04 04:26:25 +00:00
const app = await getEthApp();
const msgHex = Buffer.from(msg).toString('hex');
const signed = await app.signPersonalMessage(path, msgHex);
const combined = addHexPrefix(signed.r + signed.s + signed.v.toString(16));
return {
signedMessage: combined
};
2018-05-04 04:40:32 +00:00
},
async displayAddress(path) {
try {
const app = await getEthApp();
await app.getAddress(path, true, false);
return {
success: true
};
} catch (err) {
return {
success: false
};
}
2018-04-27 20:49:17 +00:00
}
};
export default Ledger;