accounts/abi/bind/v2: improvement on the previous commit: remove all publicly-exported member methods from v2 BoundContract. Most of these are only needed to implement the contract interaction methods in accounts/abi/bind/v2/lib.go . Add 'Transact' method to the contract interaction API.

This commit is contained in:
Jared Wasinger 2025-02-03 20:00:45 -08:00
parent 028ef2f263
commit 6c70418313
6 changed files with 46 additions and 38 deletions

View File

@ -69,7 +69,7 @@ var (
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *{{.Type}}) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
func (c *{{.Type}}) Instance(backend bind.ContractBackend, addr common.Address) bind.BoundContract {
return bind.NewContractInstance(backend, addr, c.abi)
}

View File

@ -19,6 +19,7 @@ package bind
import (
"context"
"errors"
"github.com/ethereum/go-ethereum/event"
"math/big"
"strings"
"sync"
@ -121,21 +122,34 @@ func (m *MetaData) ParseABI() (*abi.ABI, error) {
return m.parsedABI, nil
}
// BoundContract is the base wrapper object that reflects a contract on the
// Ethereum network. It contains a collection of methods that are used by the
// higher level contract bindings to operate.
type BoundContract struct {
address common.Address // Deployment address of the contract on the Ethereum blockchain
abi abi.ABI // Reflect based ABI to access the correct Ethereum methods
backend ContractBackend
// BoundContract represents a contract deployed on-chain. It does not export any methods, and is used in the low-level
// contract interaction API methods provided in the v2 package.
type BoundContract interface {
filterLogs(opts *FilterOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error)
watchLogs(opts *WatchOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error)
rawCreationTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error)
call(opts *CallOpts, input []byte) ([]byte, error)
transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error)
addr() common.Address
}
// NewBoundContract creates a low level contract interface through which calls
// and transactions may be made through.
func NewBoundContract(backend ContractBackend, address common.Address, abi abi.ABI) *BoundContract {
return &BoundContract{
address,
abi,
backend,
}
// NewBoundContract creates a new BoundContract instance.
func NewBoundContract(backend ContractBackend, address common.Address, abi abi.ABI) BoundContract {
return NewBoundContractV1(address, abi, backend, backend, backend)
}
func (c *BoundContractV1) filterLogs(opts *FilterOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
return c.FilterLogs(opts, name, query...)
}
func (c *BoundContractV1) watchLogs(opts *WatchOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
return c.WatchLogs(opts, name, query...)
}
func (c *BoundContractV1) rawCreationTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
return c.RawCreationTransact(opts, calldata)
}
func (c *BoundContractV1) addr() common.Address {
return c.address
}

View File

@ -168,7 +168,7 @@ func (c *BoundContractV1) RawTransact(opts *TransactOpts, calldata []byte) (*typ
return c.transact(opts, &c.address, calldata)
}
// RawTransact initiates a contract-creation transaction with the given raw calldata as the input.
// RawCreationTransact initiates a contract-creation transaction with the given raw calldata as the input.
func (c *BoundContractV1) RawCreationTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
return c.transact(opts, nil, calldata)
}

View File

@ -47,7 +47,7 @@ type DeploymentResult struct {
}
// DeployFn deploys a contract given a deployer and optional input. It returns
// the address and a pending transaction, or an error if the deployment failed.
// the address of the deployed contract and the deployment transaction, or an error if the deployment failed.
type DeployFn func(input, deployer []byte) (common.Address, *types.Transaction, error)
// depTreeDeployer is responsible for taking a dependency, deploying-and-linking its components in the proper

View File

@ -28,7 +28,7 @@ import (
)
// TODO: remove this and use NewBoundContract directly
func NewContractInstance(backend ContractBackend, addr common.Address, abi abi.ABI) *BoundContract {
func NewContractInstance(backend ContractBackend, addr common.Address, abi abi.ABI) BoundContract {
return NewBoundContract(backend, addr, abi)
}
@ -38,10 +38,9 @@ type ContractEvent interface {
}
// FilterEvents returns an EventIterator instance for filtering historical events based on the event id and a block range.
func FilterEvents[Ev ContractEvent](c *BoundContract, opts *FilterOpts, unpack func(*types.Log) (*Ev, error), topics ...[]any) (*EventIterator[Ev], error) {
func FilterEvents[Ev ContractEvent](c BoundContract, opts *FilterOpts, unpack func(*types.Log) (*Ev, error), topics ...[]any) (*EventIterator[Ev], error) {
var e Ev
v1Instance := BoundContractV1{c.address, c.abi, c.backend, c.backend, c.backend}
logs, sub, err := v1Instance.FilterLogs(opts, e.ContractEventName(), topics...)
logs, sub, err := c.filterLogs(opts, e.ContractEventName(), topics...)
if err != nil {
return nil, err
}
@ -52,10 +51,9 @@ func FilterEvents[Ev ContractEvent](c *BoundContract, opts *FilterOpts, unpack f
// contract to be intercepted, unpacked, and forwarded to sink. If
// unpack returns an error, the returned subscription is closed with the
// error.
func WatchEvents[Ev ContractEvent](c *BoundContract, opts *WatchOpts, unpack func(*types.Log) (*Ev, error), sink chan<- *Ev, topics ...[]any) (event.Subscription, error) {
func WatchEvents[Ev ContractEvent](c BoundContract, opts *WatchOpts, unpack func(*types.Log) (*Ev, error), sink chan<- *Ev, topics ...[]any) (event.Subscription, error) {
var e Ev
v1Instance := BoundContractV1{c.address, c.abi, c.backend, c.backend, c.backend}
logs, sub, err := v1Instance.WatchLogs(opts, e.ContractEventName(), topics...)
logs, sub, err := c.watchLogs(opts, e.ContractEventName(), topics...)
if err != nil {
return nil, err
}
@ -162,10 +160,9 @@ func (it *EventIterator[T]) Close() error {
//
// To call a function that doesn't return any output, pass nil as the unpack function.
// This can be useful if you just want to check that the function doesn't revert.
func Call[T any](c *BoundContract, opts *CallOpts, packedInput []byte, unpack func([]byte) (T, error)) (T, error) {
func Call[T any](c BoundContract, opts *CallOpts, packedInput []byte, unpack func([]byte) (T, error)) (T, error) {
var defaultResult T
v1Instance := BoundContractV1{c.address, c.abi, c.backend, c.backend, c.backend}
packedOutput, err := v1Instance.CallRaw(opts, packedInput)
packedOutput, err := c.call(opts, packedInput)
if err != nil {
return defaultResult, err
}
@ -182,11 +179,15 @@ func Call[T any](c *BoundContract, opts *CallOpts, packedInput []byte, unpack fu
return res, err
}
// Transact initiates a transaction with the given raw calldata as the input.
func Transact(c BoundContract, opt *TransactOpts, packedInput []byte) (*types.Transaction, error) {
addr := c.addr()
return c.transact(opt, &addr, packedInput)
}
// DeployContractRaw deploys a contract onto the Ethereum blockchain and binds the
// deployment address with a Go wrapper. It expects its parameters to be abi-encoded
// bytes.
//
// TODO: remove address return? we can calculate it from the returned tx
func DeployContractRaw(opts *TransactOpts, bytecode []byte, backend ContractBackend, packedParams []byte) (common.Address, *types.Transaction, error) {
c := NewBoundContractV1(common.Address{}, abi.ABI{}, backend, backend, backend)
tx, err := c.RawCreationTransact(opts, append(bytecode, packedParams...))
@ -196,10 +197,3 @@ func DeployContractRaw(opts *TransactOpts, bytecode []byte, backend ContractBack
address := crypto.CreateAddress(opts.From, tx.Nonce())
return address, tx, nil
}
// RawTransact initiates a transaction with the given raw calldata as the input.
// It's usually used to initiate transactions for invoking **Fallback** function.
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
v1Instance := BoundContractV1{c.address, c.abi, c.backend, c.backend, c.backend}
return v1Instance.RawTransact(opts, calldata)
}

View File

@ -245,7 +245,7 @@ func TestEvents(t *testing.T) {
defer sub2.Unsubscribe()
packedInput := c.PackEmitMulti()
tx, err := instance.RawTransact(txAuth, packedInput)
tx, err := bind.Transact(instance, txAuth, packedInput)
if err != nil {
t.Fatalf("failed to send transaction: %v", err)
}