以太坊开发:如何使用web3js通过私钥签名发起一笔交易

在使用web3开发时,如果需要通过js发送一笔交易或者调用合约中的某个方法时,都会提示:Error: authentication needed: password or unlock,这时我们一般会在geth解锁该账户再重新发起。

但是如果需要在前端js实现通过某个事件发送一笔交易或者调用合约某个方法,这样便无法实现。本文将介绍通过用私钥对交易进行签名从而发起交易。

1.发送一笔交易

我们将使用web3提供的函数sendRawTransaction:

//signedTransactionData为已经签名的16进制交易数据
web3.eth.sendRawTransaction(signedTransactionData [, callback])

实例代码

       //导入ethereumjs-tx库,通过npm install安装
        var Tx = require('ethereumjs-tx');
        //_from为发起交易的地址
        var _from = "0xc73dfe8e6ba891ea1ea70cd23f3af0eac85fd6e7";
       //nonce随机数,这里取该账号的交易数量
        var number = web3.eth.getTransactionCount(_from).toString(16);
        var privateKey = new Buffer('地址对应的私钥', 'hex');

        var rawTx = {
            nonce: '0x'+number,//随机数
           //gasPrice和gasLimit如果不知道怎么填,可以参考etherscan上的任意一笔交易的值
            gasPrice: '0x77359400',
            gasLimit: '0x295f05',
            to: '0xc886c791708402c26fbf7c156845e0732cd243de',//接受方地址或者合约地址
            value: '0x100',//发送的金额,这里是16进制,实际表示发送256个wei
            data: ''
        }

        //使用私钥对原始的交易信息进行签名,得到签名后的交易数据
        var tx = new Tx(rawTx);
        tx.sign(privateKey);

        var serializedTx = tx.serialize();

        web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
            if (!err){
                console.log(hash);
            }else{
                console.log(err);
            }
        });

这个方法逻辑很简单,是将0xc73dfe8e6ba891ea1ea70cd23f3af0eac85fd6e7账户的256个wei发送到0xc886c791708402c26fbf7c156845e0732cd243de账户中。

  • 发送前先查询0xc886c791708402c26fbf7c156845e0732cd243de的余额:


  • 执行实例代码发送交易,返回这笔交易的hash

  • 待这笔交易完成后,在查看账户余额,多了256个wei

2.如何调用合约方法

调用合约方法其实也是往以太网络发送一笔交易的过程,那如何通过代码调用合约方法呢?

大致逻辑基本相同,只需要修改rawTx中的to和data即可:

var rawTx = {
            nonce: '0x'+number,//随机数
           //gasPrice和gasLimit如果不知道怎么填,可以参考etherscan上的任意一笔交易的值
            gasPrice: '0x77359400',
            gasLimit: '0x295f05',
            to: '合约地址',
            value: '0x0',//如果你的合约方法是payable,可以接受eth的话可以给value赋值
            data: '合约方法的16进制数据'
        }

  • 这里需要说明的是data,当调用合约方法时,data需要填写合约方法的16进制数据,那这个数据怎么获得呢?

通过remix IDE调用你的合约方法,然后在控制台中点击detail,
如下图,我通过IDE调用了合约的drawing方法,可以看到detail中的input就是我后续要的data,将“0xb77200b1”填写到rawText中的data即可通过js调用合约的drawing方法了。

以太坊开发:如何使用web3js通过私钥签名发起一笔交易_第1张图片

3.如何调用带参数的合约方法

根据上个例子已经了解如何通过代码调用合约方法,但是如果合约方法需要传递参数应该如何操作呢?

首先我们先在remix中调用一个需要参数的合约方法:

以太坊开发:如何使用web3js通过私钥签名发起一笔交易_第2张图片

可以看到,我调用了createGame方法,在input中0x41cb3b7b为方法名,其他为参数。我们只需要生成同样的input放入到rawTx的data即可。

那如何生成这个input的16进制数据呢?

3.1 在线生成16进制数据

使用:https://abi.hashex.org/

这个网站是专门用于生成abi的16进制数据。

以太坊开发:如何使用web3js通过私钥签名发起一笔交易_第3张图片

按照上面步骤填入信息后,会自动生成16进制数据,非常方便。

以太坊开发:如何使用web3js通过私钥签名发起一笔交易_第4张图片

3.2通过代码生成16进制数据

这种方法较为灵活,可以直接在js代码中生成。你需要引入ethereumjs-abi库,官方地址:https://github.com/ethereumjs/ethereumjs-abi

var abi = require('ethereumjs-abi')
var paramsData = abi.rawEncode(["uint", "uint", "uint", "uint", "string", "string"], [1,2,3,4,"a","b").toString('hex');

rawEncode第一个入参为类型数组,即合约方法的入参类型。
第二个参数为数据数据,和类型对应的,每个类型的值为多少。

最后paramsData为参数的16进制数据,拼接上合约方法名的16进制即可,如:

var data = "0x41cb3b7b"+paramsData;
//将data传入到rawTx发起交易
...

你可能感兴趣的:(以太坊开发:如何使用web3js通过私钥签名发起一笔交易)