153 lines
4.6 KiB
Go
153 lines
4.6 KiB
Go
|
package bind
|
||
|
|
||
|
import (
|
||
|
"github.com/ethereum/go-ethereum"
|
||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||
|
"github.com/ethereum/go-ethereum/common"
|
||
|
"github.com/ethereum/go-ethereum/core/types"
|
||
|
"github.com/ethereum/go-ethereum/crypto"
|
||
|
"github.com/ethereum/go-ethereum/event"
|
||
|
)
|
||
|
|
||
|
func DeployContract2(opts *TransactOpts, bytecode []byte, input []byte, backend ContractBackend) (common.Address, *types.Transaction, error) {
|
||
|
c := NewBoundContract(common.Address{}, abi.ABI{}, backend, backend, backend)
|
||
|
tx, err := c.transact(opts, nil, append(bytecode, input...))
|
||
|
if err != nil {
|
||
|
return common.Address{}, nil, err
|
||
|
}
|
||
|
address := crypto.CreateAddress(opts.From, tx.Nonce())
|
||
|
return address, tx, nil
|
||
|
}
|
||
|
|
||
|
func Call2[T any](opts *CallOpts, addr common.Address, input []byte, backend ContractBackend, unpack func([]byte) (T, error)) (arg T, err error) {
|
||
|
var data []byte
|
||
|
data, err = CallRaw(opts, addr, input, backend)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
return unpack(data)
|
||
|
}
|
||
|
|
||
|
func CallRaw(opts *CallOpts, addr common.Address, input []byte, backend ContractBackend) ([]byte, error) {
|
||
|
c := NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||
|
return c.call(opts, input)
|
||
|
}
|
||
|
|
||
|
func Transact2(opts *TransactOpts, addr common.Address, input []byte, backend ContractBackend) (*types.Transaction, error) {
|
||
|
c := NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||
|
return c.transact(opts, &addr, input)
|
||
|
}
|
||
|
|
||
|
func Transfer2(opts *TransactOpts, addr common.Address, backend ContractBackend) (*types.Transaction, error) {
|
||
|
c := NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||
|
return c.Transfer(opts)
|
||
|
}
|
||
|
|
||
|
func FilterLogs[T any](opts *FilterOpts, addr common.Address, backend ContractBackend, eventID common.Hash, unpack func(types.Log) (*T, error), topics ...[]any) (*EventIterator[T], error) {
|
||
|
c := NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||
|
logs, sub, err := c.filterLogs(opts, eventID, topics...)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &EventIterator[T]{unpack: unpack, logs: logs, sub: sub}, nil
|
||
|
}
|
||
|
|
||
|
func WatchLogs[T any](opts *WatchOpts, addr common.Address, backend ContractBackend, eventID common.Hash, unpack func(types.Log) (*T, error), sink chan<- *T, topics ...[]any) (event.Subscription, error) {
|
||
|
c := NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||
|
logs, sub, err := c.watchLogs(opts, eventID, 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
|
||
|
}
|