viem-goviem-go

watchContractEvent

Watches and returns emitted contract event logs with ABI decoding

Unlike watchEvent, watchContractEvent:

  • Requires an ABI for event decoding
  • Automatically encodes event topics from ABI
  • Decodes event logs using the ABI
  • Filters by EventName

Watch actions return a channel of events. Cancel the context to stop watching.

Import

Import the public actions package so you can call this action.

import "github.com/ChefBingbong/viem-go/actions/public"

Usage

An example showing how to watch for a specific contract event and decode logs using an ABI.

import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/actions/public"
"github.com/ChefBingbong/viem-go/abi"
"github.com/ChefBingbong/viem-go/client"
"github.com/ChefBingbong/viem-go/client/transport"
"github.com/ChefBingbong/viem-go/chain/definitions"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{
Chain: definitions.Mainnet,
Transport: transport.HTTP("https://eth.llamarpc.com"),
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = publicClient.Close() }()
contractAddr := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
erc20ABI, _ := abi.ParseABI(`[{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]`)
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
Batch: true,
})
for event := range events {
if event.Error != nil {
log.Printf("error: %v", event.Error)
continue
}
fmt.Printf("Received %d Transfer logs
", len(event.Logs))
}

Returns

<-chan WatchContractEventEvent

A channel that emits WatchContractEventEvent structs containing:

  • Logs []formatters.Log - The decoded event logs (may contain multiple when Batch is true)
  • Error error - Any error that occurred

Parameters

Configuration options accepted by this action.

Address

  • Type: any (accepts common.Address, *common.Address, []common.Address, string, or []string)
  • Required

The contract address(es) to filter logs from.

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/actions/public"
)
contractAddr := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
})

ABI

  • Type: *abi.ABI
  • Required

The contract ABI for decoding event logs.

import "github.com/ChefBingbong/viem-go/abi"
erc20ABI, _ := abi.ParseABI(`[{"anonymous":false,"inputs":[...],"name":"Transfer",...}]`)
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
})

EventName

  • Type: string
  • Required

The name of the event to filter for. Must match an event in the ABI.

events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
})

Args

  • Type: map[string]any
  • Optional

Indexed event arguments to filter by. Keys are parameter names, values are the expected values.

senderAddr := common.HexToAddress("0xd8da6bf26964af9d7eed9e03e53415d37aa96045")
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
Args: map[string]any{"from": senderAddr},
})

Batch

  • Type: bool
  • Default: true
  • Optional

Whether to batch logs together. When true, multiple logs are collected and emitted together. When false, each log is emitted as a separate event.

events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
Batch: false,
})

FromBlock

  • Type: *uint64
  • Optional

The block number to start watching from. If set, forces polling mode.

fromBlock := uint64(16330000)
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
FromBlock: &fromBlock,
})

Poll

  • Type: *bool
  • Default: false for WebSocket Transports, true for non-WebSocket Transports
  • Optional

Whether or not to use a polling mechanism instead of a WebSocket subscription.

poll := true
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
Poll: &poll,
})

PollingInterval

  • Type: time.Duration
  • Default: Client's PollingInterval
  • Optional

The interval between polls when using polling mode.

import "time"
events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
PollingInterval: 5 * time.Second,
})

Strict

  • Type: bool
  • Default: false
  • Optional

Determines whether logs must match the event definition exactly. When true, logs with mismatched indexed/non-indexed arguments are skipped.

events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
Strict: true,
})

WorkerPoolSize

  • Type: int
  • Default: 4
  • Optional

The number of workers for parallel log decoding.

events := public.WatchContractEvent(ctx, publicClient, public.WatchContractEventParameters{
Address: contractAddr,
ABI: erc20ABI,
EventName: "Transfer",
WorkerPoolSize: 8,
})

JSON-RPC Method

Underlying JSON-RPC methods used by this action.