I'm trying to sign ethereum transaction with Ledger Nano S from NodeJS. It generates hexed transaction, but when I try to send it to the testnet Rinkeby, it returns error 'invalid sender'. I'm building an app with elecrtonJS.
I tried to send this way MEW-generated and the same Ledger-sined hex and it worked. So, I think that signature is incorrect. But why?
When I execute this code, Ledger receives request, shows details of a transaction (amount in eth and address to send) after pressing Ledger's confirm button in a js-console appears an error: 'Error: Returned error: invalid sender' without any details.
Here's code which I use. (full code)
ledger.comm_node.create_async().then(function(comm) {
let eth1 = new ledger.eth(comm);
let hdk;
let pathBase;
let offset = 0;
eth1.getAddress_async('m/44\'/1\'/0\'/0', false, true)
.then(res => {
if (res.publicKey && res.chainCode) {
hdk = new HDKey();
hdk.publicKey = new Buffer(res.publicKey, 'hex');
hdk.chainCode = new Buffer(res.chainCode, 'hex');
pathBase = 'm';
} else {
return;
}
let wallets = [];
for (let i = 0; i < 20; i++) {
const index = i + offset;
const dkey = hdk.derive(`${pathBase}/${index}`);
const address = publicToAddress(dkey.publicKey, true).toString('hex');
wallets.push({
index,
address: toChecksumAddress(address),
tokenValues: {}
});
}
web3.eth.getTransactionCount(wallets[0]['address']).then(nonce => {
let rawTx = {
nonce: web3.utils.numberToHex(nonce),
gasPrice: web3.utils.numberToHex(web3.utils.toWei('20', 'gwei')),
gasLimit: web3.utils.numberToHex(config.gasLimitFor['eth']),
to: '0x973F795C5aaaf07f8c8d92d57e945f0239DEDF67',
value: web3.utils.numberToHex(web3.utils.toWei('0.001', 'ether'))
};
let t = new EthTx(rawTx);
t.v = Buffer.from([t._chainId]);
t.r = toBuffer(0);
t.s = toBuffer(0);
eth1.signTransaction_async('m/44\'/1\'/0\'/0/0', t.serialize().toString('hex')).then(result => {
const strTx = getTransactionFields(t);
const txToSerialize = Object.assign(strTx, {
v: addHexPrefix(result.v),
r: addHexPrefix(result.r),
s: addHexPrefix(result.s)
});
console.log(txToSerialize);
const serializedTx = new EthTx(txToSerialize).serialize();
console.log(serializedTx.toString('hex'));
web3.eth.sendSignedTransaction(addHexPrefix(serializedTx.toString('hex')))
.then(res => {
console.log(res);
}).catch(err => {
console.log('sendSignedTransaction');
console.log(err);
});
}).catch(err => {
console.log('signTransaction_async');
console.log(err);
});
}).catch(err => {
console.log('getTransactionCount');
console.log(err);
reject(err);
});
})
.catch(err => {
console.log(err);
if (err && err.metaData && err.metaData.code === 5) {
}
});
console.log(comm);
});