Skip to content

Commit 008028e

Browse files
committed
isolate V2 contract interaction API into its own package
1 parent 332c188 commit 008028e

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

accounts/abi/bind/v2/lib.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package v2
2+
3+
import (
4+
"github.com/ethereum/go-ethereum"
5+
"github.com/ethereum/go-ethereum/accounts/abi"
6+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
7+
"github.com/ethereum/go-ethereum/common"
8+
"github.com/ethereum/go-ethereum/core/types"
9+
"github.com/ethereum/go-ethereum/event"
10+
)
11+
12+
func FilterLogs[T any](instance bind.ContractInstance, opts *bind.FilterOpts, eventID common.Hash, unpack func(*types.Log) (*T, error), topics ...[]any) (*EventIterator[T], error) {
13+
backend := instance.Backend()
14+
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend)
15+
logs, sub, err := c.FilterLogs(opts, eventID.String(), topics...)
16+
if err != nil {
17+
return nil, err
18+
}
19+
return &EventIterator[T]{unpack: unpack, logs: logs, sub: sub}, nil
20+
}
21+
22+
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) {
23+
backend := instance.Backend()
24+
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend)
25+
logs, sub, err := c.WatchLogs(opts, eventID.String(), topics...)
26+
if err != nil {
27+
return nil, err
28+
}
29+
return event.NewSubscription(func(quit <-chan struct{}) error {
30+
defer sub.Unsubscribe()
31+
for {
32+
select {
33+
case log := <-logs:
34+
// New log arrived, parse the event and forward to the user
35+
ev, err := unpack(&log)
36+
if err != nil {
37+
return err
38+
}
39+
40+
select {
41+
case sink <- ev:
42+
case err := <-sub.Err():
43+
return err
44+
case <-quit:
45+
return nil
46+
}
47+
case err := <-sub.Err():
48+
return err
49+
case <-quit:
50+
return nil
51+
}
52+
}
53+
}), nil
54+
}
55+
56+
// EventIterator is returned from FilterLogs and is used to iterate over the raw logs and unpacked data for events.
57+
type EventIterator[T any] struct {
58+
Event *T // Event containing the contract specifics and raw log
59+
60+
unpack func(*types.Log) (*T, error) // Unpack function for the event
61+
62+
logs chan types.Log // Log channel receiving the found contract events
63+
sub ethereum.Subscription // Subscription for errors, completion and termination
64+
done bool // Whether the subscription completed delivering logs
65+
fail error // Occurred error to stop iteration
66+
}
67+
68+
// Next advances the iterator to the subsequent event, returning whether there
69+
// are any more events found. In case of a retrieval or parsing error, false is
70+
// returned and Error() can be queried for the exact failure.
71+
func (it *EventIterator[T]) Next() bool {
72+
// If the iterator failed, stop iterating
73+
if it.fail != nil {
74+
return false
75+
}
76+
// If the iterator completed, deliver directly whatever's available
77+
if it.done {
78+
select {
79+
case log := <-it.logs:
80+
res, err := it.unpack(&log)
81+
if err != nil {
82+
it.fail = err
83+
return false
84+
}
85+
it.Event = res
86+
return true
87+
88+
default:
89+
return false
90+
}
91+
}
92+
// Iterator still in progress, wait for either a data or an error event
93+
select {
94+
case log := <-it.logs:
95+
res, err := it.unpack(&log)
96+
if err != nil {
97+
it.fail = err
98+
return false
99+
}
100+
it.Event = res
101+
return true
102+
103+
case err := <-it.sub.Err():
104+
it.done = true
105+
it.fail = err
106+
return it.Next()
107+
}
108+
}
109+
110+
// Error returns any retrieval or parsing error occurred during filtering.
111+
func (it *EventIterator[T]) Error() error {
112+
return it.fail
113+
}
114+
115+
// Close terminates the iteration process, releasing any pending underlying
116+
// resources.
117+
func (it *EventIterator[T]) Close() error {
118+
it.sub.Unsubscribe()
119+
return nil
120+
}
121+
122+
func Transact(instance bind.ContractInstance, opts *bind.TransactOpts, input []byte) (*types.Transaction, error) {
123+
var (
124+
addr = instance.Address()
125+
backend = instance.Backend()
126+
)
127+
c := bind.NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
128+
return c.RawTransact(opts, input)
129+
}
130+
131+
func Transfer(instance bind.ContractInstance, opts *bind.TransactOpts) (*types.Transaction, error) {
132+
backend := instance.Backend()
133+
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend)
134+
return c.Transfer(opts)
135+
}

0 commit comments

Comments
 (0)