Leyendo los eventos de un contrato con GO

Para poder interactuar con contratos en la blockchain de Meter, el lenguaje de programación con GO, primero necesitaremos instalar el compilador de Solidity.

Nosotros usamos, macOS, por lo que seguiremos estos pasos para instalar el compilador de Solidity. Para otros sistemas operativos:

https://docs.soliditylang.org/en/latest/installing-solidity.html#static-binaries

brew update
brew upgrade
brew tap ethereum/ethereum
brew install solidity

Comprobamos que se ha instalado correctamente ejecutando el siguiente commando en una terminal y revisando que devuelve el listado de opciones:

solc

Necesitaremos instalar una utilidad llamada abigen, para generar el código ABI en GO.

go get -u github.com/ethereum/go-ethereum
cd $GOPATH/pkg/mod/github.com/ethereum/go-ethereum@v1.10.26
sudo make
make devtools

Si devuelve el error “Please install protoc” tendremos que instalar protobuf.

brew install protobuf

Una vez instalado todo, el binario abigen estará en la ruta $GOPATH/bin/abigen

Creamos el contrato GoMeter.sol que usaremos para leer los eventos en GO.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

contract GoMeter {
    string text;
    event SetText(string _text);

    function setText(string memory _text) public {
        emit SetText(_text);
        text = _text;
    }

    function getText() public view returns(string memory) {
        return text;
    }
}

Se trata de un contrato muy simple con dos funciones y un evento. Una de las funciones, setText es la encargada de modificar la variable text y emitir un evento. La otra función, getText, devuelve el valor actual de la variable text. Este contrato ya ha sido desplegado en la red Testnet de Meter en la siguiente dirección: 0xBdf284F41BC52eFDAF474B6f8d9454545440a06D. Podemos ver todas las transacciones que se han realizado en esta URL: https://scan-warringstakes.meter.io/address/0xbdf284f41bc52efdaf474b6f8d9454545440a06d

Para poder interactuar con el contrato en GO, necesitaremos generar el código ABI. Para ello ejecutaremos las siguientes funciones. Si todo ha ido correctamente se crearán los archivos GoMeter.abi y GoMeter.bin en la carpeta build.

solc --abi --bin ./contracts/GoMeter.sol -o build
$GOPATH/bin/abigen --bin=./build/GoMeter.bin --abi=./build/GoMeter.abi --pkg=goMeter --out=goMeter/goMeter.go

Para interactuar con este contrato crearemos un fichero llamada main.go e introduciremos el siguiente código.

package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"math/big"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"

	"log"

	"github.com/antonimassomola/go-meter.io/goMeter"

	"github.com/ethereum/go-ethereum/ethclient"
)

func main() {
	/**
	 * Conexión con el proveedor
	 */
	client, err := ethclient.Dial("wss://wstest.meter.io")

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

	// Sin el 0x
	goMeterAddress := "Bdf284F41BC52eFDAF474B6f8d9454545440a06D"

	// conectando con el contrato
	contractAddress := common.HexToAddress(goMeterAddress)
	goMeterClient, err := goMeter.NewGoMeter(contractAddress, client)

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

	// Llamando al método del contrato
	tx, err := goMeterClient.GetText(nil)

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

	// Imprimos el resultado de la llamada al método
	fmt.Printf("Resultado: %s\n", tx)

	/**
	 * Eventos
	 */

	header, err := client.HeaderByNumber(context.Background(), nil)
	if err != nil {
		log.Fatal(err)
	}

	// Extraemos el último bloque
	lastBlock, err := strconv.ParseInt(header.Number.String(), 10, 64)

	query := ethereum.FilterQuery{
		FromBlock: big.NewInt(0),
		ToBlock:   big.NewInt(lastBlock),
		Addresses: []common.Address{
			contractAddress,
		},
	}

	logs, err := client.FilterLogs(context.Background(), query)
	if err != nil {
		log.Fatal(err)
	}

	abiPath, _ := filepath.Abs("./build/GoMeter.abi")
	file, err := ioutil.ReadFile(abiPath)

	if err != nil {
		fmt.Println("No se ha podido leer el archivo:", err)
	}

	contractAbi, err := abi.JSON(strings.NewReader(string(file)))
	if err != nil {
		fmt.Println("ABI inválido:", err)
	}

	for i, vLog := range logs {

		if i > 0 {
			event := struct {
				Text string
			}{}
			err := contractAbi.UnpackIntoInterface(&event, "SetText", vLog.Data)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Println(event.Text)
		}
	}
}

Instalamos todas las dependencias para que nuestra aplicación se compile correctamente.

go get -d ./...

Finalmente podemos probar que nuestra aplicación se conecta a la red Testnet de Meter y lee los eventos del contrato.

go run main.go

Veremos un resultado similar este.

captura1 1

Puedes descargarte el proyecto completo aquí:

Si necesitas cualquier tipo de ayuda relacionada con este tutorial puedes unirte al canal: https://t.me/codigoweb3

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *