Create a Watcher with a Custom ABI

For contracts not covered by a CRE Connect extension, use watchers.Client.CreateWithABI. You provide the event ABI fragments yourself and CRE Connect provisions a generic listener for that contract.

When to use this

You should use CreateWithABI if...Otherwise use CreateWithService
The contract is custom or no published service covers it.A published extension covers your protocol (e.g. dta.v2).
You only need a subset of events from the ABI.You want service-managed defaults and typed decoders.

Procedure

The Platform UI exposes the same ABI-based creation flow:

  1. Open the Channels page and open your channel.
  2. Click Watchers → Add watcher.
  3. Enter the name, Network, Target contract address
  4. Click the Service dropdown, select Other.
  5. Upload the ABI file (JSON format).
  6. Select the Event types to subscribe to.
  7. Click Deploy watcher. The watcher will appear in pending status and transition to active once deployed.

Go SDK

import (
    "github.com/google/uuid"
    "github.com/smartcontractkit/crec-sdk/watchers"
)

abi := []watchers.EventABI{
    {
        Type: "event",
        Name: "Transfer",
        Inputs: []watchers.EventABIInput{
            {Indexed: true,  Name: "from",  Type: "address", InternalType: "address"},
            {Indexed: true,  Name: "to",    Type: "address", InternalType: "address"},
            {Indexed: false, Name: "value", Type: "uint256", InternalType: "uint256"},
        },
    },
    {
        Type: "event",
        Name: "Approval",
        Inputs: []watchers.EventABIInput{
            {Indexed: true,  Name: "owner",   Type: "address", InternalType: "address"},
            {Indexed: true,  Name: "spender", Type: "address", InternalType: "address"},
            {Indexed: false, Name: "value",   Type: "uint256", InternalType: "uint256"},
        },
    },
}

w, err := client.Watchers.CreateWithABI(ctx, channelID, watchers.CreateWithABIInput{
    Name:          "erc20-transfer-watcher",
    ChainSelector: chainSelector,
    Address:       "0xYourErc20",
    Events:        []string{"Transfer", "Approval"},
    ABI:           abi,
})

curl

curl -sS -X POST "$CREC_BASE_URL/channels/$CHANNEL_ID/watchers" \
  -H "Authorization: Apikey $CREC_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "name": "erc20-transfer-watcher",
  "chain_selector": "16015286601757825753",
  "address": "0xYourErc20",
  "events": ["Transfer","Approval"],
  "abi": [
    {
      "type": "event",
      "name": "Transfer",
      "inputs": [
        {"indexed":true,"name":"from","type":"address","internalType":"address"},
        {"indexed":true,"name":"to","type":"address","internalType":"address"},
        {"indexed":false,"name":"value","type":"uint256","internalType":"uint256"}
      ]
    },
    {
      "type": "event",
      "name": "Approval",
      "inputs": [
        {"indexed":true,"name":"owner","type":"address","internalType":"address"},
        {"indexed":true,"name":"spender","type":"address","internalType":"address"},
        {"indexed":false,"name":"value","type":"uint256","internalType":"uint256"}
      ]
    }
  ]
}
EOF

Validation rules

The SDK fails fast if the request is malformed:

Sentinel errorCause
watchers.ErrChannelIDRequiredThe channel UUID is uuid.Nil.
watchers.ErrChainSelectorRequiredChainSelector is empty or "0".
watchers.ErrAddressRequiredAddress is empty.
watchers.ErrEventsRequiredEvents is empty.
watchers.ErrABIRequiredABI is empty.
watchers.ErrInvalidABITypeAn entry has Type != "event". The CREC API only accepts event ABIs today.
watchers.ErrEventNotInABIOne of Events is not declared in ABI.
watchers.ErrWatcherNameTooShortName is shorter than 4 characters after trim.

These checks happen entirely client-side, so a failure does not consume API quota.

Wait for active

active, err := client.Watchers.WaitForActive(ctx, channelID, w.WatcherId, 2*time.Minute)
if err != nil {
    return err
}
fmt.Println(active.Status) // -> active

The SDK polls every Options.PollInterval (default 2 s) and tolerates 404 for Options.EventualConsistencyWindow (default 2 s) immediately after creation. See SDK Configuration to tune both.

Limitations

  • Only event ABIs are supported today. Function ABIs return watchers.ErrInvalidABIType.
  • Anonymous events are accepted (Anonymous: true field is preserved) but are uncommon and difficult to filter on later.
  • The Inputs you pass must match the on-chain event signature exactly, including parameter names, for the watcher to decode payloads correctly.

Next steps

Get the latest Chainlink content straight to your inbox.