Annotation of the Monitor
This section provides a very well-annotated version of the monitor program of the Hello World BVS. It aims to help developers get familiar with the programming environment. The monitor program simply listens to events on a BVS and prints it to the console.
In pseudo (and Python-like) code, the monitor program acts as the following:
chainio = init_chainio()
indexer = init_indexer(
starting_block=chainio.latest_block,
event_filter=["wasm-NewTaskCreated", "wasm-TaskResponded"])
while True:
event = await indexer.wait_for_new_event()
print(event)
Here's the annotated version taken from commit c5764b62732516f634c08251258474cb8f4a97db
// The Monitor structure
type Monitor struct {
bvsContract string // The address of the BVS contract
chainIO io.ChainIO // ChainIO to enable communication with the BVS
}
// RunMonitor runs the monitor. This is the entery point of the monitor
func RunMonitor() {
m := NewMonitor()
m.Run()
}
// NewMonitor creates a new instance of the Monitor struct.
func NewMonitor() *Monitor {
// Create a new ChainIO instance
// ChainIO is our main interfaace from a off-chain program to any on-chain contract
chainIO, err := io.NewChainIO(core.C.Chain.Id, core.C.Chain.Rpc, core.C.Owner.KeyDir, core.C.Owner.Bech32Prefix, elkLogger, metricsIndicators, types.TxManagerParams{
MaxRetries: 3,
RetryInterval: 1 * time.Second,
ConfirmationTimeout: 60 * time.Second,
GasPriceAdjustmentRate: "1.1",
})
if err != nil {
panic(err)
}
// Setup the keyring so we have access to private keys
client, err := chainIO.SetupKeyring(core.C.Owner.KeyName, core.C.Owner.KeyringBackend)
if err != nil {
panic(err)
}
// Query the BVS directory and find the BVS we are monitoring
txResp, err := api.NewBVSDirectoryImpl(client, core.C.Chain.BvsDirectory).GetBVSInfo(core.C.Chain.BvsHash)
if err != nil {
panic(err)
}
// Construct and returnthe Monitor structure
return &Monitor{
bvsContract: txResp.BVSContract,
chainIO: client,
}
}
// Run runs the event indexer and monitors for new task created and task responded events.
func (m *Monitor) Run() {
// Create a context (see https://pkg.go.dev/context for detail) that ChainIO and
// other components will run in.
ctx := context.Background()
// Queries the RPC node to reterve the current latest block. The information
// is later on passed to the EvenIndexer to listen to newly created event
res, err := m.chainIO.QueryNodeStatus(ctx)
if err != nil {
panic(err)
}
latestBlock := res.SyncInfo.LatestBlockHeight
fmt.Println("latestBlock: ", latestBlock)
// Create the EventIndexer with listening to the BVS for new events
// of type "wasm-NewTaskCreated" and "wasm-TaskResponded". And with a very
// small rate limiter. The last 2 parameters 1, 5 denotes 1 event (in a bucket
// rate limiter) and 5 events per second.
evtIndexer := indexer.NewEventIndexer(
m.chainIO.GetClientCtx(),
m.bvsContract,
latestBlock,
[]string{"wasm-NewTaskCreated", "wasm-TaskResponded"},
1,
5)
// start the event indexer
evtChain, err := evtIndexer.Run(ctx)
if err != nil {
panic(err)
}
fmt.Println("chain: ", evtChain)
// Now wait for events and print their respective information. Event data
// is stored in evt.AttrMap while the type can be determined by checking
// evt.EventType
for evt := range evtChain {
switch evt.EventType {
// For a NewTaskCreated event, we print the block height, transaction hash
// the TaskId and it's input value
case "wasm-NewTaskCreated":
blockHeight := evt.BlockHeight
txnHash := evt.TxHash
taskId := evt.AttrMap["taskId"]
taskInput := evt.AttrMap["input"]
fmt.Printf("[NewTaskCreated] blockHeight: %d, txnHash: %s, taskId: %s, taskInput: %s\n", blockHeight, txnHash, taskId, taskInput)
// For a TaskResponded event, print block height, transaction hash taskId, result
// and the operators whom performed the calculations.
case "wasm-TaskResponded":
blockHeight := evt.BlockHeight
txnHash := evt.TxHash
taskId := evt.AttrMap["taskId"]
taskResult := evt.AttrMap["result"]
taskOperators := evt.AttrMap["operators"]
fmt.Printf("[TaskResponded] blockHeight: %d, txnHash: %s, taskId: %s, taskResult: %s, taskOperators: %s\n", blockHeight, txnHash, taskId, taskResult, taskOperators)
default:
// Should not reach here as we covered all event types specsifed to the EventIndexer
fmt.Printf("Unknown event type. evt: %+v\n", evt)
}
}
}
Last updated