96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package contract
|
|
|
|
import (
|
|
"amb-monitor/entity"
|
|
"amb-monitor/ethclient"
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
)
|
|
|
|
type Contract struct {
|
|
Address common.Address
|
|
client *ethclient.Client
|
|
abi abi.ABI
|
|
}
|
|
|
|
func NewContract(client *ethclient.Client, addr common.Address, abi abi.ABI) *Contract {
|
|
return &Contract{addr, client, abi}
|
|
}
|
|
|
|
func (c *Contract) AllEvents() map[string]bool {
|
|
events := make(map[string]bool, len(c.abi.Events))
|
|
for _, event := range c.abi.Events {
|
|
events[event.String()] = true
|
|
}
|
|
return events
|
|
}
|
|
|
|
func (c *Contract) ValidatorContractAddress(ctx context.Context) (common.Address, error) {
|
|
data, err := c.abi.Pack("validatorContract")
|
|
if err != nil {
|
|
return common.Address{}, fmt.Errorf("cannot encode abi calldata: %w", err)
|
|
}
|
|
res, err := c.client.CallContract(ctx, ethereum.CallMsg{
|
|
To: &c.Address,
|
|
Data: data,
|
|
})
|
|
if err != nil {
|
|
return common.Address{}, fmt.Errorf("cannot call validatorContract(): %w", err)
|
|
}
|
|
return common.BytesToAddress(res), nil
|
|
}
|
|
|
|
func (c *Contract) ParseLog(log *entity.Log) (string, map[string]interface{}, error) {
|
|
if log.Topic0 == nil {
|
|
return "", nil, fmt.Errorf("cannot process event without topics")
|
|
}
|
|
topics := make([]common.Hash, 0, 3)
|
|
if log.Topic1 != nil {
|
|
topics = append(topics, *log.Topic1)
|
|
if log.Topic2 != nil {
|
|
topics = append(topics, *log.Topic2)
|
|
if log.Topic3 != nil {
|
|
topics = append(topics, *log.Topic3)
|
|
}
|
|
}
|
|
}
|
|
var event *abi.Event
|
|
var indexed abi.Arguments
|
|
for _, e := range c.abi.Events {
|
|
if e.ID == *log.Topic0 {
|
|
indexed = Indexed(e.Inputs)
|
|
if len(indexed) == len(topics) {
|
|
event = &e
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if event == nil {
|
|
return "", nil, nil
|
|
}
|
|
m := make(map[string]interface{})
|
|
if len(indexed) < len(event.Inputs) {
|
|
if err := event.Inputs.UnpackIntoMap(m, log.Data); err != nil {
|
|
return "", nil, fmt.Errorf("can't unpack data: %w", err)
|
|
}
|
|
}
|
|
if err := abi.ParseTopicsIntoMap(m, indexed, topics); err != nil {
|
|
return "", nil, fmt.Errorf("can't unpack topics: %w", err)
|
|
}
|
|
return event.String(), m, nil
|
|
}
|
|
|
|
func Indexed(args abi.Arguments) abi.Arguments {
|
|
var indexed abi.Arguments
|
|
for _, arg := range args {
|
|
if arg.Indexed {
|
|
indexed = append(indexed, arg)
|
|
}
|
|
}
|
|
return indexed
|
|
}
|