7

I have generated and used Go bindings to deploy a few contracts and that worked very well, but I see events are not implemented yet. Is this work discussed somewhere?

I'd like to understand what options there are for a server-side app in Go to watch events on deployed smart contracts?

I know events are wrappers around EVM log ops and reside as entries inside transaction receipts. Also, watching events are done per contract instance (not by class).

I would like to avoid manually parsing out events which I could do using either polling JSON RPC log changes or RPC pub/sub for logs.

What is the currently suggested way in Go? Please show with an example in code. Thanks!

UPDATE

Opened an issue for go-ethereum to add events for Go bindings so please +1. :)

  • did you found a way how to do it? I also have the same need. – Robert Zaremba Sep 4 '17 at 9:50
1

Until the abigen will generate code to access events through the contract interface you should use Client.SubscribeFilterLogs method. It's pretty self-explained. You have to provide a channel which will be fed by logs. Also, don't forget to listen on Subscription.Err().

Check consensys article: Technical Introduction to Events and Logs in Ethereum for information about handling Logs in Ethereum.

Example:

query := ethereum.FilterQuery{
    FromBlock: nil,
    ToBlock:   nil,
    // Topics [][]common.Hash
    Addresses: []common.Address{myContractAddress}}
var logs = make(chan types.Log, 2)
s, err := client.SubscribeFilterLogs(context.TODO(), query, logs)
// check err
errChan := s.Err()
for {
    select {
    case err := <-errChan:
        logger.Error("Logs subscription error", err)
        break
    case l := <-logs:
        logger.Info("new log", log15.Spew(l))
    }
}
1

Here's an example

package main

import (
    "context"
    "fmt"
    "github.com/ethereum/go-ethereum"
    "github.com/ethereum/go-ethereum/accounts/abi/bind"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/miguelmota/go-web3-example/greeter"
    "log"
)

func main() {
    client, err := ethclient.Dial("wss://rinkeby.infura.io/ws")

    if err != nil {
        log.Fatal(err)
    }

    greeterAddress := "a7b2eb1b9fff7c9625373a6a6d180e36b552fc4c"
    priv := "abcdbcf6bdc3a8e57f311a2b4f513c25b20e3ad4606486d7a927d8074872cefg"

    key, err := crypto.HexToECDSA(priv)

    contractAddress := common.HexToAddress(greeterAddress)
    greeterClient, err := greeter.NewGreeter(contractAddress, client)

    if err != nil {
        log.Fatal(err)
    }

    auth := bind.NewKeyedTransactor(key)

    // not sure why I have to set this when using testrpc
    // var nonce int64 = 0
    // auth.Nonce = big.NewInt(nonce)

    tx, err := greeterClient.Greet(auth, "hello")

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Pending TX: 0x%x\n", tx.Hash())

    query := ethereum.FilterQuery{
        Addresses: []common.Address{contractAddress},
    }

    var ch = make(chan types.Log)
    ctx := context.Background()

    sub, err := client.SubscribeFilterLogs(ctx, query, ch)

    if err != nil {
        log.Println("Subscribe:", err)
        return
    }

    for {
        select {
        case err := <-sub.Err():
            log.Fatal(err)
        case log := <-ch:
            fmt.Println("Log:", log)
        }
    }

}

Example contract used

pragma solidity ^0.4.9;

contract Greeter {
  event _Greet(string name);

  function greet(string name) public {
    _Greet(name);
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.