¿Cuál es la mejor manera actualmente de enviar eventos a una aplicación Go que usa go-ethereum?

Generé y usé enlaces Go para implementar algunos contratos y funcionó muy bien, pero veo que los eventos aún no están implementados. ¿Se discute este trabajo en alguna parte?

Me gustaría entender qué opciones hay para una aplicación del lado del servidor en Ir para ver eventos en contratos inteligentes implementados.

Sé que los eventos envuelven las operaciones de registro de EVM y residen como entradas dentro de los recibos de transacciones. Además, la visualización de eventos se realiza por instancia de contrato (no por clase).

Me gustaría evitar el análisis manual de eventos que podría hacer mediante el sondeo de cambios de registro JSON RPC o RPC pub/sub para registros .

¿Cuál es la forma sugerida actualmente en Go? Muestre con un ejemplo en código. ¡Gracias!

ACTUALIZAR

Abrió un problema para go-ethereum para agregar eventos para enlaces Go , así que haga +1. :)

¿Encontraste una manera de cómo hacerlo? Yo tambien tengo la misma necesidad.

Respuestas (2)

Hasta abigenque genere código para acceder a eventos a través de la interfaz del contrato, debe usar el método Client.SubscribeFilterLogs . Es bastante autoexplicativo. Debe proporcionar un canal que será alimentado por registros. Además, no te olvides de escuchar en Subscription.Err().

Consulte el artículo de consenso: Introducción técnica a eventos y registros en Ethereum para obtener información sobre el manejo de registros en Ethereum.

Ejemplo:

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))
    }
}

aquí hay un ejemplo

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)
        }
    }

}

Ejemplo de contrato utilizado

pragma solidity ^0.4.9;

contract Greeter {
  event _Greet(string name);

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