Send signed transactions to Ropsten or Truffle develop network with Trezor (Hardware Wallet)

白昼怎懂夜的黑 提交于 2019-12-03 10:19:13

Well, after a lot of trying we have managed to send a raw transaction signed with Trezor to Ropsten, Truffle (see the edit on the bottom of the answer) and also to a local private Geth network, so, the code is ok and there is no problem with Trezor integration on those environments

https://ropsten.etherscan.io/address/0x89e2c46b22881f747797cf67310aad1a831d50b7

This are the things that i had changed in order to make it possible to send signed transactions to the Ropsten testnet.

This assumes that you have your contract deployed into Ropsten and you have the contract address.

1) Get the address of your Trezor account

  getTrezorAddress = async() => {
        let trezor=  await this.getTrezor();
        // spend one change output
        let address_n = "m/44'/1'/0'/0/0";
        trezor.ethereumGetAddress(address_n, function (result) {
            if (result.success) { // success
                console.log('Address: ', result.address);
            } else {
                console.error('Error:', result.error); // error message
            }
        });
    }

2) Put the trezor address into the from field of your raw transaction, get the nonce of the transaction by getting the transaction count for that address. Important: use the "pending" optional parameter on getTransactionCount to get all the transactions of the account, otherwise you will be overriting pending transactions.

getNonce = async(address) => {

        let web3 = await this.getWeb3();
        return new Promise (function (resolve,reject) {
            web3.eth.getTransactionCount(address, "pending", function (error,result){
                console.log("Nonce "+result);
                resolve(result);


            });
        });

    }

let count = null;
        await this.getNonce("0xedff546ac229317df81ef9e6cb3b67c0e6425fa7").then(result => {
            if(result.length % 2 !==0){
                result = "0"+result;
            }
            count = "0x"+result;

       });

let tx = {
            nonce: count ,
            gasPrice: web3.toHex(gasPriceGwei*1e9),
            gasLimit: web3.toHex(gasLimit),
            to: CONTRACT_ADDRESS,
            value: '0x00',
            data: getData,
            chainId:chainId,
            from:"yourTrezzorAddress"
        };

3) The r, s, v parameters were incorrect, the right way to handle them is take that values for the trezor response and just convert it to hexa:

// response is the Trezor sign response
tx.v= response.v;
tx.r="0x"+response.r;
tx.s="0x"+response.s;
let ethtx = new ethereumjs(tx);.
const serializedTx = ethtx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
 //finally pass this data parameter to send Transaction
web3.eth.sendRawTransaction(rawTx, someCallbackFunction);

Important: the mining time in ropsten will be between 15 and 30 secs so if in your someCallbackFunction you check for the transaction receipt, using the hash, you will get null as result, because the transaction is in a pending state.

4) To test it at ropsten we use Infura, so we change the web3 provider:

import Web3 from 'web3'
import HDWalletProvider from "truffle-hdwallet-provider";

let getWeb3 = new Promise(function(resolve, reject) {
    // Wait for loading completion to avoid race conditions with web3 injection timing.
    window.addEventListener('load', function() {
        let results
        let web3 = window.web3

        // Checking if Web3 has been injected by the browser (Mist/MetaMask)
        if (typeof web3 !== 'undefined') {
            // Use Mist/MetaMask's provider.
            web3 = new Web3(web3.currentProvider)

            results = {
                web3: web3
            }

            console.log('Injected web3 detected.');

            return resolve(results)
        } else {
            // Fallback to localhost if no web3 injection. We've configured this to
            // use the development console's port by default.
            // let provider = new Web3.providers.HttpProvider("https://ropsten.infura.io/your_infura_api_key")

            let mnemonic = "infura mnemonic"
            let provider = new HDWalletProvider(mnemonic, "https://ropsten.infura.io/your_infura_api_key")
            web3 = new Web3(provider)

            results = {
                web3: web3
            }

            console.log('No web3 instance injected, using Local web3.');

            return resolve(results)
        }
    })
})

export default getWeb3

EDIT:

This also works on Truffle! check the last comments of this issue https://github.com/trufflesuite/truffle/issues/973

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!