web3公測版本教程(三)-不用自己同步以太坊節點,直接發起簽名交易

sawyerLi發表於2019-02-16

一.前言

前文提到目前有一些公司提供公共的以太坊對外服務,就是以你可以呼叫他的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);        
    });

相關文章