github.com/diadata-org/diadata@v1.4.593/pkg/dia/helpers/substrate-helper/event.go (about)

     1  package substratehelper
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	gsrpc "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc"
     8  	"github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/parser"
     9  	"github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/retriever"
    10  	"github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/state"
    11  
    12  	"github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/types"
    13  
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  type SubstrateEventHelper struct {
    18  	logger *logrus.Entry
    19  	API    *gsrpc.SubstrateAPI
    20  }
    21  
    22  func NewSubstrateEventHelper(nodeURL string, logger *logrus.Entry) (*SubstrateEventHelper, error) {
    23  	api, err := gsrpc.NewSubstrateAPI(nodeURL)
    24  	if err != nil {
    25  		return nil, fmt.Errorf("failed to connect to Substrate node: %v", err)
    26  	}
    27  	return &SubstrateEventHelper{API: api, logger: logger}, nil
    28  }
    29  
    30  func (s *SubstrateEventHelper) ListenForSpecificBlock(blockNumber uint64, callback func([]*parser.Event, uint64)) error {
    31  	blockHash, err := s.API.RPC.Chain.GetBlockHash(blockNumber)
    32  	if err != nil {
    33  		message := fmt.Sprintf("Failed to fetch block hash: %v", err)
    34  		s.logger.Errorf(message, err)
    35  		return errors.New(message)
    36  	}
    37  
    38  	events, err := s.DecodeEvents(blockHash)
    39  	if err != nil {
    40  		message := fmt.Sprintf("Failed to decode events: %v", err)
    41  		s.logger.Errorf(message, err)
    42  		return err
    43  	}
    44  
    45  	callback(events, blockNumber)
    46  
    47  	return nil
    48  }
    49  
    50  func (s *SubstrateEventHelper) DecodeEvents(blockHash types.Hash) ([]*parser.Event, error) {
    51  	r, err := retriever.NewDefaultEventRetriever(state.NewEventProvider(s.API.RPC.State), s.API.RPC.State)
    52  
    53  	if err != nil {
    54  		return nil, fmt.Errorf("couldn't create event retriever: %s", err)
    55  	}
    56  
    57  	events, err := r.GetEvents(blockHash)
    58  
    59  	if err != nil {
    60  		return nil, fmt.Errorf("couldn't retrieve events for block hash %d: %s", blockHash, err)
    61  	}
    62  
    63  	s.logger.Infof("Found %d events\n", len(events))
    64  
    65  	return events, nil
    66  }
    67  
    68  // ListenForNewBlocks listens for new blocks and continuously decodes events.
    69  func (s *SubstrateEventHelper) ListenForNewBlocks(callback func([]*parser.Event, uint64)) error {
    70  	sub, err := s.API.RPC.Chain.SubscribeNewHeads()
    71  	if err != nil {
    72  		return fmt.Errorf("failed to subscribe to new heads: %v", err)
    73  	}
    74  	s.logger.Info("Listening for new blocks...")
    75  
    76  	for {
    77  		head := <-sub.Chan()
    78  		blockNumber := uint64(head.Number)
    79  		blockHash, err := s.API.RPC.Chain.GetBlockHash(blockNumber)
    80  		if err != nil {
    81  			s.logger.Errorf("Failed to fetch block hash: %v\n", err)
    82  			continue
    83  		}
    84  		s.logger.Infof("\nNew block detected! Block number: %v, Block hash: %v\n", head.Number, blockHash.Hex())
    85  
    86  		events, err := s.DecodeEvents(blockHash)
    87  		if err != nil {
    88  			s.logger.Errorf("Failed to decode events: %v\n", err)
    89  			continue
    90  		}
    91  
    92  		callback(events, blockNumber)
    93  	}
    94  }