美文网首页
无需安装metamask钱包,如何使用私钥直接发送以太坊交易

无需安装metamask钱包,如何使用私钥直接发送以太坊交易

作者: JackyGu | 来源:发表于2018-09-08 14:04 被阅读489次

    By 古千峰

    很多DAPP应用,会要求在电脑浏览器中安装以太坊钱包metamask,当应用中需要发送ETH时,自动打开metamask,发送交易。

    但是在浏览器中如果没有metamask钱包(安装metamask的门槛并不低,需要学会科学上网),该怎么办呢?能不能像imtoken那样简单的操作呢?

    发送交易的本质是用发送方的私钥签名,所以除了metamask外,还可以使用另外两种方法签名:

    • 导入keystore文本,然后输入对应的密码。
      这也是imtoken使用的主要方式,用过keystore的都知道,每次发送交易,都需要输入一个密码。注意,这个密码并不是存放在钱包服务商服务器上的,而是加密后存放在keystore文本中。一旦遗失了这个keystore文件,就等于丢失了这个文件对应账户中资产的控制权。
    • 导入私钥
      这个方式比较简单,直接将私钥输入即可。但是风险比keystore方式高。因为几乎没人能够记住私钥,绝大多数人会把私钥保存在本地某个文件中,这样就使得私钥被盗的风险增加。而使用keystore方式时,只要解开keystore文件的密码没有被泄漏,账户还是安全的。

    本教程,就先来介绍使用私钥方式来签名并发送交易,而不需要安装metamask钱包,这类应用可广泛用于手机端Dapp。这类Dapp不需要与运营商的服务器进行交互,前端源码公开,对于运营商来说,比较容易自证清白。

    使用以太坊发送交易分为两步:

    • 把交易内容json进行签名
    • 发送签名后的数据

    一、准备工作

    1- 在编程之前,需要导入两个库:

    • web3.js,推荐使用0.20.x版本
    • ethereumjs-tx.js,用于发送交易,即Tx

    1.1 如果你喜欢使用nodejs,用以下命令安装:

    npm install web3@0.20.3 --save
    npm install ethereumjs-tx --save
    

    在程序中,使用以下命令导入库:

    var Web3 = require("web3");
    var Tx = require("ethereumjs-tx");
    

    1.2 如果你喜欢使用原生javascript,则需要在html中使用如下方式导入以上两个库:

    <script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
    <script src="https://cdn.rawgit.com/ethereumjs/browser-builds/2fb69a714afe092b06645286f14b94f41e5c062c/dist/ethereumjs-tx.js"></script>
    

    2- 注册infura,并获取API KEY

    开发以太坊Dapp,一般需要在本地安装geth,但这种方法需要花比较多的时间和空间来同步区块,利用infura可以简单很多,infura提供公开以太坊和测试节点,可以利用infura提供的api访问以太坊以及IPFS

    官网网址:infura.io。只需要提供email注册得到链接即可,进到infuradashboard中,新建一个DAPP,即可获得API KEY,如下图。

    API KEY

    二、连接以太坊网络

    一般使用以下统一代码:

    function init() {
        var network = "mainnet";//或者ropsten等测试网络名称
        var infura_apikey = "infura的API_KEY";
        if (typeof web3 !== 'undefined') {
            //如果浏览器中安装有metamask,则执行这里
            web3 = new Web3(web3.currentProvider);
        } else {
            /*
            //开发环境,如果在本地有以太坊的testrpc或者Ganache测试环境,则使用以下方式链接
            web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
            */
            //通过infura连接以太坊网络
            web3 = new Web3(new Web3.providers.HttpProvider('https://' + network + '.infura.io/v3/' + infura_apikey));
        }
    }
    

    三、配置发送交易的数据

    function getTx() {
        //发送1个eth
        var wei = web3.toWei("1", "ether");
        //获取当前Gas价格,Gas价格一直变动,发送交易前建议动态获取
        var gasPrice = web3.eth.gasPrice.toNumber();
        //获取当前发送账号的所有交易,包括pending的交易,用来确定nonce值
        //web3.eth.getTransactionCount 有bug,有时候无法正确获取,最好在客户端设置nonce值
        var nonce = web3.eth.getTransactionCount('发送者地址', 'pending');
        //获取估计的Gas值
        var estimategas = web3.eth.estimateGas({
            to: '收款方地址,或者合约地址',
            data: '发送数据'
        });
        //获取gas限额
        var gasLimit = web3.eth.getBlock("latest").gasLimit;
    
        //配置交易参数
        var rawTransaction = {
            nonce:     web3.toHex(nonce),
            gasPrice:  web3.toHex(gasPrice * 2),
            gasLimit:  web3.toHex(gasLimit),
            gas:       web3.toHex(estimategas),
            value:     web3.toHex(wei),
            chainId:   3, //ropsten测试网络用3,主网用1
            to:        '收款方地址',
            data:      '发送数据'
        }
        return rawTransaction;
    

    四、签名

    如果是用nodejs,使用如下代码:

    var privateKey = new Buffer('发送账户的私钥', 'hex')
    var tx = new Tx(rawTransaction);
    tx.sign(privateKey);
    var serializedTx = tx.serialize().toString('hex');//签名结果
    

    如果用原生javascript,使用如下代码:

    var privateKey = new EthJS.Buffer.Buffer('发送账户的私钥', 'hex');
    var tx = new EthJS.Tx(rawTransaction);
    tx.sign(privateKey);
    var serializedTx = tx.serialize().toString('hex');
    

    五、发送交易

    使用如下代码:

    web3.eth.sendRawTransaction("0x" + serializedTx, function (err, hash) {
        if (!err) console.log("Tx: " + hash); //交易发送成功后的TX值
        else console.log(err.toString());
    });
    

    nodejs版全部代码如下:

    var Web3 = require('web3');
    var Tx = require('ethereumjs-tx');
    
    const network = "ropsten";//mainnet, ropsten
    const chainId = 3;//1- mainnet, 3-ropsten
    const sender = "0x615b80388e3d3cac6aa3a904803acfe7939"; //发送者公钥
    const privateKey = new Buffer('19608a60b54943cd840c84b8e833ef84732a18eb562cdee09f8dba532ea', 'hex')
    const toAddress = "0x3fe7995bf0a505a51196aa11218b181c849"; //接受者公钥
    const ethAmount = "0";//发送的ETH
    const hexData = "Hello World!";
    
    const infura_apikey = "3446259cb0e74d68b614f9a103";
    
    init();
    sendTx();
    
    function sendTx() {
        var wei = web3.toWei(ethAmount, "ether");
        var nonce = web3.eth.getTransactionCount(sender, 'pending');
        var estimategas = web3.eth.estimateGas({
            to: toAddress,
            data: hexData
        });
        var gasPrice = web3.eth.gasPrice.toNumber();
        var gasLimit = web3.eth.getBlock("latest").gasLimit;
    
        var rawTransaction = {
            nonce: web3.toHex(nonce),
            gasPrice: web3.toHex(gasPrice * 2), //2倍Gas价格
            gasLimit: web3.toHex(gasLimit),
            gas: web3.toHex(estimategas),
            value: web3.toHex(wei),
            chainId: chainId,
            to: toAddress,
            data: hexData
        }
    
        var tx = new Tx(rawTransaction);
        tx.sign(privateKey);
    
        var serializedTx = tx.serialize().toString('hex');
        console.log(serializedTx);
        
        web3.eth.sendRawTransaction("0x" + serializedTx, function (err, hash) {
            if (!err) console.log("Tx: " + hash);
            else console.log(err.toString());
        });
        
    }
    
    function init() {
        if (typeof web3 !== 'undefined') {
            web3 = new Web3(web3.currentProvider);
        } else {
            //web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
            web3 = new Web3(new Web3.providers.HttpProvider('https://' + network + '.infura.io/v3/' + infura_apikey));
        }
    }
    

    如果使用原生javascript,可以参考以下链接:
    https://codepen.io/jackygu/pen/zJdVyj

    相关文章

      网友评论

          本文标题:无需安装metamask钱包,如何使用私钥直接发送以太坊交易

          本文链接:https://www.haomeiwen.com/subject/ojbkgftx.html