合約的呼叫

weixin_34050427發表於2018-04-17

獲取合約例項的方法:

1.使用truffle-contract

//App.js
import React, { Component } from 'react'
import Voting from '../build/contracts/Voting.json'
import getWeb3 from './utils/getWeb3'
...
componentWillMount() {
    //連線到一個節點的Web3例項
     getWeb3
    .then(results => {
      this.setState({
        web3: results.web3
      })

      // Instantiate contract once web3 provided.
      this.instantiateContract()
    })
    .catch(() => {
      console.log('Error finding web3.')
    })
  }
...
instantiateContract() {
    
    const contract = require('truffle-contract')
    const voting = contract(Voting)
    voting.setProvider(this.state.web3.currentProvider)

    // Declaring this for later so we can chain functions on SimpleStorage.
    

    // Get accounts.
    this.state.web3.eth.getAccounts((error, accounts) => {
      ...
      voting.deployed().then((instance) => {
        ...
        console.log(instance.address);
        
//getWeb3.js
import Web3 from 'web3'

let getWeb3 = new Promise(function(resolve, reject) {
  // Wait for loading completion to avoid race conditions with web3 injection timing.
  window.addEventListener('load', function() {
    var results
    var web3 = window.web3

    // Checking if Web3 has been injected by the browser (Mist/MetaMask)
    if (typeof web3 !== 'undefined') {
      // Use Mist/MetaMask's provider.
      web3 = new Web3(web3.currentProvider)

      results = {
        web3: web3
      }

      console.log('Injected web3 detected.');

      resolve(results)
    } else {
      // Fallback to localhost if no web3 injection.
      var provider = new Web3.providers.HttpProvider('http://localhost:8545')

      web3 = new Web3(provider)

      results = {
        web3: web3
      }

      console.log('No web3 instance injected, using Local web3.');

      resolve(results)
    }
  })
})

export default getWeb3

2.使用web3.eth.contract

var Web3 = require("web3");
var ABI = require("./abi.js");
...
//連線到一個節點的Web3例項
web3 = new Web3(new Web3.providers.HttpProvider("http://47.93.40.96:8888"));    
//建立合約物件
var proofContract = web3.eth.contract(ABI);
//使用at方法獲取與ABI匹配的、一個已部署合約的引用
var proof = proofContract.at("0xb8928051ed59a97cdc34c9bfe9f9498ef419b564");

建立合約例項的三種方法

  1. contractName.new([arg1,arg2,...],[tx params]);
    
  2. contractName.at(address)
    
  3. contractName.deployed()
    
  • contractName.new([arg1,arg2,...],[tx params])函式使用合約要求的任何constructor引數,最後一個引數是可選的,可以用它來傳送包括來自地址的交易、gasLimit和gasPrice在內的交易引數。該方法不會對合約的artifacts物件進行任何修改,將在合約抽象用到的網路部署新的合約,並且獲取新部署的合約例項
  • contractName.at(address)函式需要知道合約地址,將解析一個合約抽象例項
  • contractName.deployed()函式的地址是從artifacts物件中檢索的,將解析一個已部署的合約的合約例項
    合約抽象例項:多個網路中的已部署的此合約
    合約例項:一個特定網路中的已部署合約

呼叫合約方法的三種方式

  1. testInstance.testFunc.sendTransaction();
    
  2. testInstance.testFunc();
    
  3. testInstance.testFunc.call();
    

如果你只對返回值感興趣,那麼你應該用call 。如果你的功能呼叫通過傳送交易來執行,就應該用sendTransaction。

  • testInstance.testFunc.sendTransaction(); 會建立一個交易,呼叫之後會返回一個交易hash值,它會廣播到網路,等待礦工打包, 它會消耗gas。
  • testInstance.testFunc.call(); 它完全是一個本地呼叫,不會向區塊鏈網路廣播任何東西,它的返回值完全取決於 testFunc 方法的程式碼,不會消耗gas
  • testInstance.testFunc(); 它會比較特殊,由於有constant標識的方法不會修改狀態變數,所以它不會被編譯器執行,web3.js會執行call()的本地操作。如果沒有constant標識,會執行sendTransaction()操作。

捕獲事件

可以通過result.logs獲取交易觸發的事件:


MetaCoin.at(contract_address).then(function(instance){
    // 呼叫sendCoin會向區塊鏈傳送一筆交易
    return instance.sendCoin(account_two, 100, {from:account_one});
}).then(function(result){
    // 這個回撥函式在交易生效之後才會被執行
    // result.logs是一個陣列,陣列的每個元素是一個事件物件
    // 通過查詢result.logs可以獲得感興趣的事件
    for (var i = 0; i < result.logs.length; i++) {
        var log = result.logs[i];
        if (log.event == "Transfer") {
            console.log("from:", log.args._from);
            console.log("to:", log.args._to);
            console.log("amount:", log.args._value.toNumber());
            break;
        }
    }
}).catch(function(err){
    console.log(err);
});

// 輸出:
from: 0x68b73956d704007514e9257813bdc58cdf3c969a
to: 0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e
amount: 100

sendCoin執行完後會觸發一個Transfer事件,在回撥函式中,通過查詢result.logs可以獲取到這個事件,進而可以得到事件的引數值。
參考文章

相關文章