mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-30 08:33:45 +00:00
add test coverage for events watching
This commit is contained in:
parent
1e8aca95e9
commit
cd18d99180
7 changed files with 425 additions and 13 deletions
|
|
@ -404,7 +404,6 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad
|
|||
}
|
||||
res, err := c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
||||
if err != nil {
|
||||
fmt.Printf("msg data is %x\n", msg.Data)
|
||||
panic(err)
|
||||
}
|
||||
return res, nil
|
||||
|
|
@ -519,6 +518,12 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
|
|||
return c.watchLogs(opts, c.abi.Events[name].ID, query...)
|
||||
}
|
||||
|
||||
// WatchLogsForId filters subscribes to contract logs for future blocks, returning a
|
||||
// subscription object that can be used to tear down the watcher.
|
||||
func (c *BoundContract) WatchLogsForId(opts *WatchOpts, id common.Hash, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
|
||||
return c.watchLogs(opts, id, query...)
|
||||
}
|
||||
|
||||
func (c *BoundContract) watchLogs(opts *WatchOpts, eventID common.Hash, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
|
||||
// Don't crash on a lazy user
|
||||
if opts == nil {
|
||||
|
|
|
|||
140
accounts/abi/bind/testdata/v2/events/bindings.go
vendored
Normal file
140
accounts/abi/bind/testdata/v2/events/bindings.go
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
// Code generated via abigen V2 - DO NOT EDIT.
|
||||
// This file is a generated binding and any manual changes will be lost.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var (
|
||||
_ = errors.New
|
||||
_ = big.NewInt
|
||||
_ = bind.Bind
|
||||
_ = common.Big1
|
||||
_ = types.BloomLookup
|
||||
_ = abi.ConvertType
|
||||
)
|
||||
|
||||
var CLibraryDeps = []*bind.MetaData{}
|
||||
|
||||
// TODO: convert this type to value type after everything works.
|
||||
// CMetaData contains all meta data concerning the C contract.
|
||||
var CMetaData = &bind.MetaData{
|
||||
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic2\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EmitMulti\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EmitOne\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
|
||||
Pattern: "55ef3c19a0ab1c1845f9e347540c1e51f5",
|
||||
Bin: "0x6080604052348015600e575f80fd5b506101a08061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f80fd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212203624d263fed93ccf2a175b7c701e773f413c64394a51928aa2b1968299798fe664736f6c634300081a0033",
|
||||
}
|
||||
|
||||
// C is an auto generated Go binding around an Ethereum contract.
|
||||
type C struct {
|
||||
abi abi.ABI
|
||||
}
|
||||
|
||||
// NewC creates a new instance of C.
|
||||
func NewC() (*C, error) {
|
||||
parsed, err := CMetaData.GetAbi()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &C{abi: *parsed}, nil
|
||||
}
|
||||
|
||||
// TODO: create custom exported types where unpack would generate a struct return.
|
||||
|
||||
// TODO: test constructor with inputs
|
||||
func (_C *C) PackConstructor() ([]byte, error) {
|
||||
return _C.abi.Pack("")
|
||||
}
|
||||
|
||||
// EmitMulti is a free data retrieval call binding the contract method 0xcb493749.
|
||||
//
|
||||
// Solidity: function EmitMulti() returns()
|
||||
func (_C *C) PackEmitMulti() ([]byte, error) {
|
||||
return _C.abi.Pack("EmitMulti")
|
||||
}
|
||||
|
||||
// EmitOne is a free data retrieval call binding the contract method 0xe8e49a71.
|
||||
//
|
||||
// Solidity: function EmitOne() returns()
|
||||
func (_C *C) PackEmitOne() ([]byte, error) {
|
||||
return _C.abi.Pack("EmitOne")
|
||||
}
|
||||
|
||||
// CBasic1 represents a Basic1 event raised by the C contract.
|
||||
type CBasic1 struct {
|
||||
Id *big.Int
|
||||
Data *big.Int
|
||||
Raw *types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
func CBasic1EventID() common.Hash {
|
||||
return common.HexToHash("0x8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207")
|
||||
}
|
||||
|
||||
func (_C *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) {
|
||||
event := "Basic1"
|
||||
if log.Topics[0] != _C.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(CBasic1)
|
||||
if len(log.Data) > 0 {
|
||||
if err := _C.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var indexed abi.Arguments
|
||||
for _, arg := range _C.abi.Events[event].Inputs {
|
||||
if arg.Indexed {
|
||||
indexed = append(indexed, arg)
|
||||
}
|
||||
}
|
||||
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.Raw = log
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CBasic2 represents a Basic2 event raised by the C contract.
|
||||
type CBasic2 struct {
|
||||
Flag bool
|
||||
Data *big.Int
|
||||
Raw *types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
func CBasic2EventID() common.Hash {
|
||||
return common.HexToHash("0x3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e")
|
||||
}
|
||||
|
||||
func (_C *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) {
|
||||
event := "Basic2"
|
||||
if log.Topics[0] != _C.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(CBasic2)
|
||||
if len(log.Data) > 0 {
|
||||
if err := _C.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var indexed abi.Arguments
|
||||
for _, arg := range _C.abi.Events[event].Inputs {
|
||||
if arg.Indexed {
|
||||
indexed = append(indexed, arg)
|
||||
}
|
||||
}
|
||||
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.Raw = log
|
||||
return out, nil
|
||||
}
|
||||
|
||||
1
accounts/abi/bind/testdata/v2/events/combined-abi.json
vendored
Normal file
1
accounts/abi/bind/testdata/v2/events/combined-abi.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"flag","type":"bool"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic2","type":"event"},{"inputs":[],"name":"EmitMulti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"EmitOne","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bin":"6080604052348015600e575f80fd5b506101a08061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f80fd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212203624d263fed93ccf2a175b7c701e773f413c64394a51928aa2b1968299798fe664736f6c634300081a0033"}},"version":"0.8.26+commit.8a97fa7a.Darwin.appleclang"}
|
||||
|
|
@ -2,5 +2,36 @@
|
|||
pragma solidity ^0.8.26;
|
||||
|
||||
contract C {
|
||||
event basic1(
|
||||
uint256 indexed id,
|
||||
uint256 data
|
||||
);
|
||||
event basic2(
|
||||
bool indexed flag,
|
||||
uint256 data
|
||||
);
|
||||
|
||||
// TODO: consider log test where data is hashed? maybe not necessary for v2 coverage
|
||||
function EmitOne() public {
|
||||
emit basic1(
|
||||
uint256(1),
|
||||
uint256(2));
|
||||
}
|
||||
|
||||
// emit multiple events, different types
|
||||
function EmitMulti() public {
|
||||
emit basic1(
|
||||
uint256(1),
|
||||
uint256(2));
|
||||
emit basic1(
|
||||
uint256(3),
|
||||
uint256(4));
|
||||
emit basic2(
|
||||
false,
|
||||
uint256(1));
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// do something with these
|
||||
}
|
||||
}
|
||||
6
accounts/abi/bind/testdata/v2/simple/contract.sol
vendored
Normal file
6
accounts/abi/bind/testdata/v2/simple/contract.sol
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.26;
|
||||
|
||||
contract C {
|
||||
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// TODO: it's weird to have a mirror interface of this in the bind package...
|
||||
type ContractInstance struct {
|
||||
Address common.Address
|
||||
Backend bind.ContractBackend
|
||||
|
|
@ -233,10 +234,10 @@ func FilterLogs[T any](instance *ContractInstance, opts *bind.FilterOpts, eventI
|
|||
}
|
||||
|
||||
// TODO: adding docs soon (jwasinger)
|
||||
func WatchLogs[T any](instance *ContractInstance, opts *bind.WatchOpts, eventID common.Hash, unpack func(*types.Log) (*T, error), sink chan<- *T, topics ...[]any) (event.Subscription, 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) {
|
||||
backend := instance.Backend
|
||||
c := bind.NewBoundContract(instance.Address, abi.ABI{}, backend, backend, backend)
|
||||
logs, sub, err := c.WatchLogs(opts, eventID.String(), topics...)
|
||||
c := bind.NewBoundContract(instance.Address, abi, backend, backend, backend)
|
||||
logs, sub, err := c.WatchLogsForId(opts, eventID, topics...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -335,10 +336,10 @@ func (it *EventIterator[T]) Close() error {
|
|||
|
||||
// Transact creates and submits a transaction to the bound contract instance
|
||||
// using the provided abi-encoded input (or nil).
|
||||
func Transact(instance bind.ContractInstance, opts *bind.TransactOpts, input []byte) (*types.Transaction, error) {
|
||||
func Transact(instance *ContractInstance, opts *bind.TransactOpts, input []byte) (*types.Transaction, error) {
|
||||
var (
|
||||
addr = instance.Address()
|
||||
backend = instance.Backend()
|
||||
addr = instance.Address
|
||||
backend = instance.Backend
|
||||
)
|
||||
c := bind.NewBoundContract(addr, abi.ABI{}, backend, backend, backend)
|
||||
return c.RawTransact(opts, input)
|
||||
|
|
@ -346,8 +347,8 @@ func Transact(instance bind.ContractInstance, opts *bind.TransactOpts, input []b
|
|||
|
||||
// Call performs an eth_call on the given bound contract instance, using the
|
||||
// provided abi-encoded input (or nil).
|
||||
func Call(instance bind.ContractInstance, opts *bind.CallOpts, input []byte) ([]byte, error) {
|
||||
backend := instance.Backend()
|
||||
c := bind.NewBoundContract(instance.Address(), abi.ABI{}, backend, backend, backend)
|
||||
func Call(instance *ContractInstance, opts *bind.CallOpts, input []byte) ([]byte, error) {
|
||||
backend := instance.Backend
|
||||
c := bind.NewBoundContract(instance.Address, abi.ABI{}, backend, backend, backend)
|
||||
return c.CallRaw(opts, input)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/testdata/v2/events"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/testdata/v2/nested_libraries"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
|
@ -35,6 +36,7 @@ import (
|
|||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
|
|
@ -67,7 +69,7 @@ func testSetup() (*bind.TransactOpts, *backends.SimulatedBackend, error) {
|
|||
}
|
||||
|
||||
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
|
||||
opts := bind.TransactOpts{
|
||||
opts := &bind.TransactOpts{
|
||||
From: testAddr,
|
||||
Nonce: nil,
|
||||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||
|
|
@ -92,12 +94,17 @@ func testSetup() (*bind.TransactOpts, *backends.SimulatedBackend, error) {
|
|||
Backend: backend,
|
||||
Client: backend.Client(),
|
||||
}
|
||||
return &opts, &bindBackend, nil
|
||||
return opts, &bindBackend, nil
|
||||
}
|
||||
|
||||
// test deployment and interaction for a basic contract with no library deps
|
||||
func TestDeployment(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// test that deploying a contract with library dependencies works,
|
||||
// verifying by calling the deployed contract.
|
||||
func TestDeployment(t *testing.T) {
|
||||
func TestDeploymentLibraries(t *testing.T) {
|
||||
opts, bindBackend, err := testSetup()
|
||||
if err != nil {
|
||||
t.Fatalf("err setting up test: %v", err)
|
||||
|
|
@ -278,6 +285,227 @@ func TestDeploymentWithOverrides(t *testing.T) {
|
|||
}
|
||||
*/
|
||||
|
||||
// note to self: see how to filter logs in eth_call.
|
||||
|
||||
func TestEvents(t *testing.T) {
|
||||
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
|
||||
txAuth, backend, err := testSetup()
|
||||
if err != nil {
|
||||
t.Fatalf("error setting up testing env: %v", err)
|
||||
}
|
||||
|
||||
deploymentParams := DeploymentParams{
|
||||
Contracts: []ContractDeployParams{
|
||||
{
|
||||
Meta: events.CMetaData,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
res, err := LinkAndDeploy(txAuth, backend, deploymentParams)
|
||||
if err != nil {
|
||||
t.Fatalf("error deploying contract for testing: %v", err)
|
||||
}
|
||||
|
||||
backend.Commit()
|
||||
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[events.CMetaData.Pattern]); err != nil {
|
||||
t.Fatalf("WaitDeployed failed %v", err)
|
||||
}
|
||||
|
||||
ctrct, err := events.NewC()
|
||||
if err != nil {
|
||||
t.Fatalf("error instantiating contract instance: %v", err)
|
||||
}
|
||||
|
||||
abi, err := events.CMetaData.GetAbi()
|
||||
if err != nil {
|
||||
t.Fatalf("error getting contract abi: %v", err)
|
||||
}
|
||||
|
||||
// TODO: why did I introduce separate type, and not just use bound contract?
|
||||
boundContract := ContractInstance{
|
||||
res.Addrs[events.CMetaData.Pattern],
|
||||
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)
|
||||
defer sub1.Unsubscribe()
|
||||
defer sub2.Unsubscribe()
|
||||
fmt.Printf("watching for event with id %x\n", events.CBasic1EventID())
|
||||
fmt.Printf("watching for event with id %x\n", events.CBasic2EventID())
|
||||
//wtf do I do with this subscriptions??
|
||||
_ = sub1
|
||||
_ = sub2
|
||||
|
||||
crtctInstance := &ContractInstance{
|
||||
Address: res.Addrs[events.CMetaData.Pattern],
|
||||
Backend: backend,
|
||||
}
|
||||
_ = ctrct
|
||||
packedCall, err := ctrct.PackEmitMulti()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to pack EmitMulti arguments")
|
||||
}
|
||||
tx, err := Transact(crtctInstance, txAuth, packedCall)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to send transaction...")
|
||||
}
|
||||
backend.Commit()
|
||||
if _, err := bind.WaitMined(context.Background(), backend, tx); err != nil {
|
||||
t.Fatalf("error waiting for tx to be mined: %v", err)
|
||||
}
|
||||
|
||||
timeout := time.NewTimer(2 * time.Second)
|
||||
e1Count := 0
|
||||
e2Count := 0
|
||||
for {
|
||||
select {
|
||||
case _ = <-newCBasic1Ch:
|
||||
e1Count++
|
||||
case _ = <-newCBasic2Ch:
|
||||
e2Count++
|
||||
case _ = <-timeout.C:
|
||||
goto done
|
||||
}
|
||||
if e1Count == 2 && e2Count == 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
done:
|
||||
if e1Count != 2 {
|
||||
t.Fatalf("expected event type 1 count to be 2. got %d", e1Count)
|
||||
}
|
||||
if e2Count != 1 {
|
||||
t.Fatalf("expected event type 2 count to be 1. got %d", e2Count)
|
||||
}
|
||||
// commit a few blocks...
|
||||
// now filter for the previously-emitted events.
|
||||
|
||||
// TODO: test that returning error from unpack prevents event from being received by sink.
|
||||
}
|
||||
|
||||
func TestEventsUnpackFailure(t *testing.T) {
|
||||
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
|
||||
txAuth, backend, err := testSetup()
|
||||
if err != nil {
|
||||
t.Fatalf("error setting up testing env: %v", err)
|
||||
}
|
||||
|
||||
deploymentParams := DeploymentParams{
|
||||
Contracts: []ContractDeployParams{
|
||||
{
|
||||
Meta: events.CMetaData,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
res, err := LinkAndDeploy(txAuth, backend, deploymentParams)
|
||||
if err != nil {
|
||||
t.Fatalf("error deploying contract for testing: %v", err)
|
||||
}
|
||||
|
||||
backend.Commit()
|
||||
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[events.CMetaData.Pattern]); err != nil {
|
||||
t.Fatalf("WaitDeployed failed %v", err)
|
||||
}
|
||||
|
||||
ctrct, err := events.NewC()
|
||||
if err != nil {
|
||||
t.Fatalf("error instantiating contract instance: %v", err)
|
||||
}
|
||||
|
||||
abi, err := events.CMetaData.GetAbi()
|
||||
if err != nil {
|
||||
t.Fatalf("error getting contract abi: %v", err)
|
||||
}
|
||||
|
||||
// TODO: why did I introduce separate type, and not just use bound contract?
|
||||
boundContract := ContractInstance{
|
||||
res.Addrs[events.CMetaData.Pattern],
|
||||
backend,
|
||||
}
|
||||
|
||||
unpackBasic := func(raw *types.Log) (*events.CBasic1, error) {
|
||||
return nil, fmt.Errorf("could not unpack event")
|
||||
}
|
||||
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)
|
||||
defer sub1.Unsubscribe()
|
||||
defer sub2.Unsubscribe()
|
||||
//wtf do I do with this subscriptions??
|
||||
_ = sub1
|
||||
_ = sub2
|
||||
|
||||
crtctInstance := &ContractInstance{
|
||||
Address: res.Addrs[events.CMetaData.Pattern],
|
||||
Backend: backend,
|
||||
}
|
||||
_ = ctrct
|
||||
packedCall, err := ctrct.PackEmitMulti()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to pack EmitMulti arguments")
|
||||
}
|
||||
tx, err := Transact(crtctInstance, txAuth, packedCall)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to send transaction...")
|
||||
}
|
||||
backend.Commit()
|
||||
if _, err := bind.WaitMined(context.Background(), backend, tx); err != nil {
|
||||
t.Fatalf("error waiting for tx to be mined: %v", err)
|
||||
}
|
||||
|
||||
timeout := time.NewTimer(2 * time.Second)
|
||||
e1Count := 0
|
||||
e2Count := 0
|
||||
for {
|
||||
select {
|
||||
case _ = <-newCBasic1Ch:
|
||||
e1Count++
|
||||
case _ = <-newCBasic2Ch:
|
||||
e2Count++
|
||||
case _ = <-timeout.C:
|
||||
goto done
|
||||
}
|
||||
if e1Count == 2 && e2Count == 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
done:
|
||||
if e1Count != 0 {
|
||||
t.Fatalf("expected event type 1 count to be 0. got %d", e1Count)
|
||||
}
|
||||
if e2Count != 1 {
|
||||
t.Fatalf("expected event type 2 count to be 1. got %d", e2Count)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue