add error unpacking. simplify WatchLogs api.
This commit is contained in:
parent
4fc62e94b3
commit
1f25c68ec4
|
@ -148,4 +148,24 @@ var (
|
|||
return out, nil
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Errors}}
|
||||
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Normalized.Name}} error raised by the {{$contract.Type}} contract.
|
||||
type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}}
|
||||
{{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{end}}; {{end}}
|
||||
}
|
||||
|
||||
func {{$contract.Type}}{{.Normalized.Name}}ErrorID() common.Hash {
|
||||
return common.HexToHash("{{.Original.ID}}")
|
||||
}
|
||||
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Error(raw []byte) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||
errName := "{{.Normalized.Name}}"
|
||||
out := new({{$contract.Type}}{{.Normalized.Name}})
|
||||
if err := _{{$contract.Type}}.abi.UnpackIntoInterface(out, errName, raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
|
@ -237,7 +237,7 @@ func FilterLogs[T any](instance *ContractInstance, opts *bind.FilterOpts, eventI
|
|||
// contract to be intercepted, unpacked, and forwarded to sink. If
|
||||
// unpack returns an error, the returned subscription is closed with the
|
||||
// error.
|
||||
func WatchLogs[T any](instance *ContractInstance, abi abi.ABI, opts *bind.WatchOpts, eventID common.Hash, unpack func(*types.Log) (*T, error), sink chan<- *T, topics ...[]any) (event.Subscription, error) {
|
||||
func WatchLogs(instance *ContractInstance, abi abi.ABI, opts *bind.WatchOpts, eventID common.Hash, onLog func(*types.Log) error, topics ...[]any) (event.Subscription, error) {
|
||||
backend := instance.Backend
|
||||
c := bind.NewBoundContract(instance.Address, abi, backend, backend, backend)
|
||||
logs, sub, err := c.WatchLogsForId(opts, eventID, topics...)
|
||||
|
@ -249,19 +249,10 @@ func WatchLogs[T any](instance *ContractInstance, abi abi.ABI, opts *bind.WatchO
|
|||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
ev, err := unpack(&log)
|
||||
err := onLog(&log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
select {
|
||||
case sink <- ev:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
|
|
|
@ -381,26 +381,28 @@ func TestEvents(t *testing.T) {
|
|||
backend,
|
||||
}
|
||||
|
||||
unpackBasic := func(raw *types.Log) (*events.CBasic1, error) {
|
||||
return &events.CBasic1{
|
||||
Id: (new(big.Int)).SetBytes(raw.Topics[0].Bytes()),
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}, nil
|
||||
}
|
||||
unpackBasic2 := func(raw *types.Log) (*events.CBasic2, error) {
|
||||
return &events.CBasic2{
|
||||
Flag: false, // TODO: how to unpack different types to go types? this should be exposed via abi package.
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}, nil
|
||||
}
|
||||
newCBasic1Ch := make(chan *events.CBasic1)
|
||||
newCBasic2Ch := make(chan *events.CBasic2)
|
||||
watchOpts := &bind.WatchOpts{
|
||||
Start: nil,
|
||||
Context: context.Background(),
|
||||
}
|
||||
sub1, err := WatchLogs[events.CBasic1](&boundContract, *abi, watchOpts, events.CBasic1EventID(), unpackBasic, newCBasic1Ch)
|
||||
sub2, err := WatchLogs[events.CBasic2](&boundContract, *abi, watchOpts, events.CBasic2EventID(), unpackBasic2, newCBasic2Ch)
|
||||
sub1, err := WatchLogs(&boundContract, *abi, watchOpts, events.CBasic1EventID(), func(raw *types.Log) error {
|
||||
event := &events.CBasic1{
|
||||
Id: (new(big.Int)).SetBytes(raw.Topics[0].Bytes()),
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}
|
||||
newCBasic1Ch <- event
|
||||
return nil
|
||||
})
|
||||
sub2, err := WatchLogs(&boundContract, *abi, watchOpts, events.CBasic2EventID(), func(raw *types.Log) error {
|
||||
event := &events.CBasic2{
|
||||
Flag: false, // TODO: how to unpack different types to go types? this should be exposed via abi package.
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}
|
||||
newCBasic2Ch <- event
|
||||
return nil
|
||||
})
|
||||
defer sub1.Unsubscribe()
|
||||
defer sub2.Unsubscribe()
|
||||
|
||||
|
@ -452,6 +454,18 @@ done:
|
|||
Start: 0,
|
||||
Context: context.Background(),
|
||||
}
|
||||
unpackBasic := func(raw *types.Log) (*events.CBasic1, error) {
|
||||
return &events.CBasic1{
|
||||
Id: (new(big.Int)).SetBytes(raw.Topics[0].Bytes()),
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}, nil
|
||||
}
|
||||
unpackBasic2 := func(raw *types.Log) (*events.CBasic2, error) {
|
||||
return &events.CBasic2{
|
||||
Flag: false, // TODO: how to unpack different types to go types? this should be exposed via abi package.
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}, nil
|
||||
}
|
||||
// TODO: test that returning error from unpack prevents event from being received by sink.
|
||||
it, err := FilterLogs[events.CBasic1](crtctInstance, filterOpts, events.CBasic1EventID(), unpackBasic)
|
||||
if err != nil {
|
||||
|
@ -518,23 +532,25 @@ func TestEventsUnpackFailure(t *testing.T) {
|
|||
backend,
|
||||
}
|
||||
|
||||
unpackBasic := func(raw *types.Log) (*events.CBasic1, error) {
|
||||
return nil, fmt.Errorf("this error should stop the filter that uses this unpack.")
|
||||
}
|
||||
unpackBasic2 := func(raw *types.Log) (*events.CBasic2, error) {
|
||||
return &events.CBasic2{
|
||||
Flag: false, // TODO: how to unpack different types to go types? this should be exposed via abi package.
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}, nil
|
||||
}
|
||||
newCBasic1Ch := make(chan *events.CBasic1)
|
||||
newCBasic2Ch := make(chan *events.CBasic2)
|
||||
unpackBasic := func(raw *types.Log) error {
|
||||
return fmt.Errorf("this error should stop the filter that uses this unpack.")
|
||||
}
|
||||
unpackBasic2 := func(raw *types.Log) error {
|
||||
newCBasic2Ch <- &events.CBasic2{
|
||||
Flag: false, // TODO: how to unpack different types to go types? this should be exposed via abi package.
|
||||
Data: (new(big.Int)).SetBytes(raw.Data),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
watchOpts := &bind.WatchOpts{
|
||||
Start: nil,
|
||||
Context: context.Background(),
|
||||
}
|
||||
sub1, err := WatchLogs[events.CBasic1](&boundContract, *abi, watchOpts, events.CBasic1EventID(), unpackBasic, newCBasic1Ch)
|
||||
sub2, err := WatchLogs[events.CBasic2](&boundContract, *abi, watchOpts, events.CBasic2EventID(), unpackBasic2, newCBasic2Ch)
|
||||
sub1, err := WatchLogs(&boundContract, *abi, watchOpts, events.CBasic1EventID(), unpackBasic)
|
||||
sub2, err := WatchLogs(&boundContract, *abi, watchOpts, events.CBasic2EventID(), unpackBasic2)
|
||||
defer sub1.Unsubscribe()
|
||||
defer sub2.Unsubscribe()
|
||||
|
||||
|
|
Loading…
Reference in New Issue