Last active
December 5, 2018 17:12
-
-
Save amdev9/3e1314f8cc62cd675fa5c8f7bbe97923 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Web3 = require('web3'); | |
const EthereumTx = require('ethereumjs-tx'); | |
const ethUtil = require('ethereumjs-util'); | |
const rlp = require('rlp'); | |
var txDecoder = require('ethereum-tx-decoder'); | |
let flag = false; | |
let buffer; | |
const API_KEY = 'https://ropsten.infura.io/v3/YOUR_INFURA_KEY'; | |
let web3 = new Web3(new Web3.providers.HttpProvider(API_KEY)); | |
const WebSocket = require('ws'); | |
const ws = new WebSocket('ws://localhost:16384/'); | |
const keyname = 'YOUR_KEYCHAIN_KEY_NAME'; | |
const toAdd = '0xE8899BA12578d60e4D0683a596EDaCbC85eC18CC'; | |
const publicKey = 'YOUR_PUBLIC_KEY_FROM_KEYCHAIN'; | |
const fromAdd = ethUtil.publicToAddress(publicKey).toString('hex'); | |
const valueTx = 100; | |
console.log('fromAddress ', fromAdd); | |
const rsv = (signature, chainIdHere) => { | |
const ret = {}; | |
ret.r = `0x${signature.slice(0, 64)}`; | |
ret.s = `0x${signature.slice(64, 128)}`; | |
const recovery = parseInt(signature.slice(128, 130), 16); | |
let tmpV = recovery + 27; | |
if (chainIdHere > 0) { | |
tmpV += chainIdHere * 2 + 8; | |
} | |
ret.v = tmpV; | |
return ret; | |
} | |
const publishTx = async (rawhex) => { | |
var decodedTx = txDecoder.decodeTx(rawhex); | |
console.log('decodedTx: ', decodedTx); | |
return web3.eth.sendSignedTransaction(rawhex) | |
} | |
const signHexCommand = (hexraw) => { | |
return { | |
"command": "sign_hex", | |
"params": { | |
"transaction": hexraw, | |
"blockchain_type": "ethereum", | |
"keyname": keyname | |
} | |
} | |
} | |
ws.onopen = async () => { | |
console.log('ws open'); | |
const rawHex = await buildTxSinature( | |
null, // signature | |
fromAdd, | |
toAdd, | |
valueTx | |
) | |
console.log('sign tx:', rawHex); | |
sendCommand(signHexCommand(rawHex)); | |
} | |
function sendCommand(command) { | |
ws.send(JSON.stringify(command)); | |
console.log('command:', command); | |
} | |
ws.on('message', async (response) => { | |
const data = JSON.parse(response); | |
console.log(data.result); // signature | |
flag = true; | |
const rawHex = await buildTxSinature( | |
data.result, // signature | |
fromAdd, | |
toAdd, | |
valueTx | |
) | |
console.log('keychain tx:', rawHex); | |
try { | |
await publishTx(`0x${rawHex}`); | |
} catch (e) { | |
console.log(e); | |
} | |
ws.close(); | |
}); | |
const buildTxSinature = async (signature, fromAddress, to, value, data = '') => { | |
console.log('buildTxSinature') | |
const nonce = await web3.eth.getTransactionCount(fromAddress); | |
const gasPrice = await web3.eth.getGasPrice().then(wei => Number(wei)) | |
const chainIdHere = 3; | |
const draftTxParams = { | |
nonce, | |
gasPrice, | |
to, | |
value, | |
data, | |
// EIP 155 chainId - mainnet: 1, ropsten: 3, rinkeby: 4 | |
chainId: chainIdHere | |
} | |
const gasLimit = 21000; // await web3.eth.estimateGas(draftTxParams) || | |
let txParams = { | |
...draftTxParams, | |
gasLimit | |
} | |
if (signature) { | |
const ret = rsv(signature, chainIdHere); | |
txParams = { ...txParams, | |
...ret | |
}; | |
} | |
console.log('tx keychain params', txParams) | |
class EthereumTxKeychain extends EthereumTx { | |
hashEncode(includeSignature) { | |
if (includeSignature === undefined) includeSignature = true | |
// EIP155 spec: | |
// when computing the hash of a transaction for purposes of signing or recovering, | |
// instead of hashing only the first six elements (ie. nonce, gasprice, startgas, to, value, data), | |
// hash nine elements, with v replaced by CHAIN_ID, r = 0 and s = 0 | |
let items | |
if (includeSignature) { | |
items = this.raw | |
} else { | |
if (this._chainId > 0) { | |
const raw = this.raw.slice() | |
this.v = this._chainId | |
this.r = 0 | |
this.s = 0 | |
items = this.raw | |
this.raw = raw | |
} else { | |
items = this.raw.slice(0, 6) | |
} | |
} | |
// create hash | |
return rlp.encode(items) | |
} | |
} | |
const tx = new EthereumTxKeychain(txParams); | |
if (flag) { | |
console.log("validate sign transaction status: ", tx.validate() ? "SUCCESS" : "FAILURE"); | |
buffer = tx.serialize() | |
} else { | |
buffer = tx.hashEncode(false); | |
} | |
const hex = buffer.toString('hex') | |
console.log('final hex: ', hex); | |
return hex; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment