108 lines
2.3 KiB
Go
108 lines
2.3 KiB
Go
package watchers
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/common/dbutil"
|
|
"github.com/wormhole-foundation/wormhole-explorer/event-watcher/clients"
|
|
"go.uber.org/zap"
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
const bulkSize = 100
|
|
|
|
func min[T constraints.Ordered](a, b T) T {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
type EvmWatcher struct {
|
|
logger *zap.Logger
|
|
db *dbutil.Session
|
|
client *clients.EthRpcClient
|
|
coreContractAddress string
|
|
logTopic string
|
|
}
|
|
|
|
func NewEvmWatcher(
|
|
logger *zap.Logger,
|
|
db *dbutil.Session,
|
|
coreContractAddress string,
|
|
logTopic string,
|
|
url string,
|
|
auth string,
|
|
) *EvmWatcher {
|
|
|
|
w := EvmWatcher{
|
|
logger: logger,
|
|
db: db,
|
|
client: clients.NewEthRpcClient(url, auth),
|
|
coreContractAddress: coreContractAddress,
|
|
logTopic: logTopic,
|
|
}
|
|
|
|
return &w
|
|
}
|
|
|
|
func (w *EvmWatcher) Watch(ctx context.Context) {
|
|
|
|
//TODO:
|
|
// - initialize current block in the database, if not already initialized.
|
|
// - get current block from database
|
|
var currentBlock uint64 = 0
|
|
|
|
for {
|
|
// Get the current blockchain head
|
|
latestBlock, err := w.client.GetBlockNumber(ctx)
|
|
if err != nil {
|
|
w.logger.Error("failed to get latest block number",
|
|
zap.String("url", w.client.Url),
|
|
zap.Error(err),
|
|
)
|
|
continue
|
|
}
|
|
|
|
// Process blocks in bulk
|
|
for currentBlock < latestBlock {
|
|
from := currentBlock
|
|
to := min(currentBlock+bulkSize, latestBlock)
|
|
w.processBlockRange(ctx, from, to)
|
|
|
|
currentBlock = latestBlock
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *EvmWatcher) processBlockRange(ctx context.Context, fromBlock uint64, toBlock uint64) {
|
|
|
|
var logs []clients.Log
|
|
var err error
|
|
|
|
// Retry until success
|
|
for {
|
|
logs, err = w.client.GetLogs(ctx, fromBlock, toBlock, w.coreContractAddress, w.logTopic)
|
|
if err != nil {
|
|
w.logger.Error("failed to get logs",
|
|
zap.String("url", w.client.Url),
|
|
zap.String("coreContractAddress", w.coreContractAddress),
|
|
zap.String("topic", w.logTopic),
|
|
zap.Uint64("fromBlock", fromBlock),
|
|
zap.Uint64("toBlock", toBlock),
|
|
zap.Error(err),
|
|
)
|
|
}
|
|
break
|
|
}
|
|
|
|
// Process logs
|
|
// TODO:
|
|
// - update current block in database
|
|
// - fire events for other services
|
|
for i := range logs {
|
|
log := logs[i]
|
|
w.logger.Info("found log", zap.String("transactionHash", log.TransactionHash))
|
|
}
|
|
}
|