当前位置: 首页 > 后端技术 > Node.js

Web3公测版教程(三)-不同步以太坊节点直接发起签名交易

时间:2023-04-03 16:59:44 Node.js

1.前言上面说了,目前有一些公司对外提供公有的以太坊对外服务,所以可以调用他的web3接口,我一直困扰两个之前的问题,一是别人的节点不安全,经过初步尝试发现Infura节点没有开户相关的方法。无法使用web3.eth.sendTransaction方法,以为它只能进行一些查询服务,没用。最终,我毅然选择了硬同步节点的方式。看了大神的文章,这两个问题就迎刃而解了,踩了大神文章的一些坑,居然写了一个群发的脚本。2.申请Infura目前主流的以太坊服务是Infura。在Infura官网申请,只需要输入一些基本信息和邮箱就可以获取API-key(输入你常用的邮箱,不要删除回复邮件,因为Infura没有登录系统,所以要再次使用只能去邮箱找API-key,如果没有保留只能重新申请)。3.使用Infura发起智能合约交易。发起交易,首先要解决的问题是不能使用web3.eth.sendTransaction。为什么不能用?其实web3.eth.sendTransaction的原理就是创建一个交易,然后发送给你连接的以太坊节点。以太坊节点可以理解为有两个功能,一个是发送经过签名的正确交易,另一个是对本节点中处于解锁状态的账户发送的交易进行签名。通过自己同步节点,可以先解锁已签名的交易,再将交易发送给其他节点。但Infura为您提供的服务只是各种查询和转发交易,并没有为您开启钱包存放私钥(开启则无需保存)。可以,但是你可以把签名的交易发给它,他会帮你转发。这样第二个安全问题就解决了,因为你没有把私钥发给他,只是把你认可的自己签名的交易发给他。下面是在web3中使用智能合约私钥进行签名的具体步骤:1.创建交易对象var_web3=newWeb3(yourInfuraAddress);consttxData={nonce:_web3.utils.toHex(nonce),gasLimit:_web3.utils.toHex(99000),//gasPrice:_web3.utils.toHex(10e9),//10Gweito:contract_address,from:address1,value:'0x00',data:'0x'+'a9059cbb'+'00000000000000000000000000'+address2+hexNum}参数说明:nonce:整数类型,nonce从零开始计数,每次加一,直接填大的等待前面的数交易完成后再交易,小的填会失败,使用自己发送的pending状态的交易有相同的nonce,之前的交易会被取消。因此,如果钱包发送给同一个人的前一笔交易拥塞,可以发送一笔0eth的交易来取消前一笔交易。我们使用下面的方法获取当前的nonce:_web3.eth.getTransactionCount(sendAddress).then(function(res){nonce=res;}gasLimit和gasPrice:gasPrice一般可以设置在1G到10G之间,gasLimit是gaschargedamountofgaschargedeth交易笔数一般固定为21000笔,智能合约会根据合约方式的复杂程度自动变化,gaslimit可以设置最大消耗值,超过这个值交易将被取消.(注意:需要转成十六进制,可以使用web3.utils.toHex方法。)to:如果是智能合约交易,则为智能合约地址from:发起方的公钥value:转账的eth数量,智能合约交易请填写0x00data:这个有自己的办法,0x开头表示十六进制,前八位方法名一般是a9059cbb,基于erc20的翻译方法。对于其他人,您可以将合同粘贴到remix上以供查看。之后,第一个参数接受令牌,第二个参数是令牌的数量,补零的方法在后面,用判断网络参数来说明更牛逼)补零的方法:functionaddPreZero(num){vart=(num+'').length,s='';for(vari=0;i<64-t;i++){s+='0';}returns+num;}2.创建原始交易以引入另一个套件ethereumjs-tx。记得先用npm安装。创建原始交易,varTx=require('ethereumjs-tx');vartx=newTx(rawTx);3.使用私钥签名constprivateKey=newBuffer('','hex');tx.sign(私钥);4.交易序列化constserializedTx=transaction.serialize().toString('hex')5.发送交易及各种状态vartran=_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);});