mirror of https://github.com/ethereum/go-ethereum
parent
332c188c9c
commit
008028e5fd
@ -0,0 +1,135 @@ |
||||
package v2 |
||||
|
||||
import ( |
||||
"github.com/ethereum/go-ethereum" |
||||
"github.com/ethereum/go-ethereum/accounts/abi" |
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind" |
||||
"github.com/ethereum/go-ethereum/common" |
||||
"github.com/ethereum/go-ethereum/core/types" |
||||
"github.com/ethereum/go-ethereum/event" |
||||
) |
||||
|
||||
func FilterLogs[T any](instance bind.ContractInstance, opts *bind.FilterOpts, eventID common.Hash, unpack func(*types.Log) (*T, error), topics ...[]any) (*EventIterator[T], error) { |
||||
backend := instance.Backend() |
||||
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend) |
||||
logs, sub, err := c.FilterLogs(opts, eventID.String(), topics...) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &EventIterator[T]{unpack: unpack, logs: logs, sub: sub}, nil |
||||
} |
||||
|
||||
func WatchLogs[T any](instance bind.ContractInstance, opts *bind.WatchOpts, eventID common.Hash, unpack func(*types.Log) (*T, error), sink chan<- *T, topics ...[]any) (event.Subscription, error) { |
||||
backend := instance.Backend() |
||||
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend) |
||||
logs, sub, err := c.WatchLogs(opts, eventID.String(), topics...) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return event.NewSubscription(func(quit <-chan struct{}) error { |
||||
defer sub.Unsubscribe() |
||||
for { |
||||
select { |
||||
case log := <-logs: |
||||
// New log arrived, parse the event and forward to the user
|
||||
ev, err := unpack(&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: |
||||
return nil |
||||
} |
||||
} |
||||
}), nil |
||||
} |
||||
|
||||
// EventIterator is returned from FilterLogs and is used to iterate over the raw logs and unpacked data for events.
|
||||
type EventIterator[T any] struct { |
||||
Event *T // Event containing the contract specifics and raw log
|
||||
|
||||
unpack func(*types.Log) (*T, error) // Unpack function for the event
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
} |
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *EventIterator[T]) Next() bool { |
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil { |
||||
return false |
||||
} |
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done { |
||||
select { |
||||
case log := <-it.logs: |
||||
res, err := it.unpack(&log) |
||||
if err != nil { |
||||
it.fail = err |
||||
return false |
||||
} |
||||
it.Event = res |
||||
return true |
||||
|
||||
default: |
||||
return false |
||||
} |
||||
} |
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select { |
||||
case log := <-it.logs: |
||||
res, err := it.unpack(&log) |
||||
if err != nil { |
||||
it.fail = err |
||||
return false |
||||
} |
||||
it.Event = res |
||||
return true |
||||
|
||||
case err := <-it.sub.Err(): |
||||
it.done = true |
||||
it.fail = err |
||||
return it.Next() |
||||
} |
||||
} |
||||
|
||||
// Error returns any retrieval or parsing error occurred during filtering.
|
||||
func (it *EventIterator[T]) Error() error { |
||||
return it.fail |
||||
} |
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *EventIterator[T]) Close() error { |
||||
it.sub.Unsubscribe() |
||||
return nil |
||||
} |
||||
|
||||
func Transact(instance bind.ContractInstance, opts *bind.TransactOpts, input []byte) (*types.Transaction, error) { |
||||
var ( |
||||
addr = instance.Address() |
||||
backend = instance.Backend() |
||||
) |
||||
c := bind.NewBoundContract(addr, abi.ABI{}, backend, backend, backend) |
||||
return c.RawTransact(opts, input) |
||||
} |
||||
|
||||
func Transfer(instance bind.ContractInstance, opts *bind.TransactOpts) (*types.Transaction, error) { |
||||
backend := instance.Backend() |
||||
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend) |
||||
return c.Transfer(opts) |
||||
} |
Loading…
Reference in new issue