4

一.前言

前文提到目前有一些公司提供公共的以太坊对外服务,就是以你可以调用他的web3接口,之前一直被两个问题困扰,一个是觉得别人的节点不安全,还有初步尝试后发现Infura节点没有开放账户相关的方法。没法使用web3.eth.sendTransaction方法,以为只能进行一些查询服务,用处就较为鸡肋。最后毅然决然的选择自己同步节点的苦逼之路。看了大神文章,两个问题迎刃而解,并踩过大神文章重的一些坑,实际的写了一个群发币脚本。

二.申请Infura

目前较为主流的以太坊服务就是Infura,到Infura官网申请,只要输入一点基本资料和Email就可以得到API-key(输入自己常用邮箱,回复的邮件不要删除,因为Infura不存在登入系统,所以再次使用只能去邮箱找API-key,没保留只能再次申请了)。

三.用连接Infura发起智能合约交易

要发起交易首先要解决的就是问题一,web3.eth.sendTransaction不可以用。为什么不能用呢,其实web3.eth.sendTransaction的原理是创建一个交易然后发给你连接的以太坊节点,以太坊节点可以理解为有两个功能,一个是发出一笔签了名的正确交易,另一个是给本节点中处于解锁状态的账户中发来的交易签名。自己同步节点就可以先解锁在签名交易,然后发送交易给其他节点。但Infura提供给你的服务只有各种查询和转发交易,并没把钱包开放给你储存私钥(开放也不放心存过去)。是的但你可以把签名好的交易发给它他帮你转发掉。所以第二个安全问题也就解决了,因为你没有把私钥发给它,只是把你认可你自己签名的交易发给他了。

下面是实现web3中用智能合约私钥签名的细节:

1.创建一个交易对象
var _web3 = new Web3(yourInfuraAddress);
const txData = {
    nonce: _web3.utils.toHex(nonce),
    gasLimit: _web3.utils.toHex(99000),   //
    gasPrice: _web3.utils.toHex(10e9),    // 10 Gwei
    to: contract_address,
    from: address1,
    value: '0x00',         
    data: '0x'+'a9059cbb'+'000000000000000000000000'+address2+hexNum
}

参数解释:

  • nonce:整数类型,nonce从零开始计数每次加一,直接填写较大的会等待它前面的数的交易完成才能交易,较小会失败,使用与自己发送的处于pending状态的交易相同的nonce,则会取消掉前一笔交易,所以一般钱包发给同一个人的前一笔交易被拥堵可以发送一个0eth的交易取消前面交易。我们使用下面方法获取当前的nonce:
_web3.eth.getTransactionCount(sendAddress).then(function(res){
    nonce = res;
}
  • gasLimit和gasPrice: gasPrice一般可以设置1G位到10G位之间,gasLimit话费gas数量eth交易一般是固定21000个,智能合约会根据合约方法复杂程度自动变化,gaslimit可以设置消耗最大值,超过这个值将取消交易。(注意:需要转换成16进制,可以使用web3.utils.toHex方法。)
  • to:如果是智能合约交易则是智能合约地址
  • from:发起方的公钥
  • value:转账的eth数,智能合约交易请填0x00
  • data:这个有门道了,0x开头表示十六进制,前八位方法名一般基于erc20的tranlation方法为a9059cbb,其他的可以将合约粘贴到remix上面看,之后64位依次第一个参数接受token方第二个参数token数量(要16进制不够64位前面补0,补零方法在后边,更加牛逼的用法官网参数解释

补零方法:

function addPreZero(num){
  var t = (num+'').length,
  s = '';
  for(var i=0; i<64-t; i++){
    s += '0';
  }
  return s+num;
}
2.创建raw transaction

要引入另一個套件 ethereumjs-tx。記得先用 npm 安裝。建立raw transaction、

var Tx = require('ethereumjs-tx');
var tx = new Tx(rawTx);
3.使用私钥签名
const privateKey = new Buffer('<your-private-key>', 'hex'); tx.sign(privateKey);
4.交易序列化
const serializedTx = transaction.serialize().toString('hex')
5.发送交易及各种状态初六
var tran = _web3.eth.sendSignedTransaction('0x' + serializedTx);
    tran.on('confirmation', (confirmationNumber, receipt) => {
      //console.log('confirmation: ' + confirmationNumber);
    });
    tran.on('transactionHash', hash => {
        console.log('hash');
        console.log(hash);
    });
    tran.on('receipt', receipt => {
        console.log('receipt:');
        console.log(receipt);
    });
    tran.on('error', (err)=>{
        alert('出现错误请查看控制台');
        console.log(err);        
    });

sawyerLi
187 声望12 粉丝

前端工程师,会用点node,用vue,react写过点东西,最近看看区块链。