aboutsummaryrefslogtreecommitdiffstats
path: root/ethclient
diff options
context:
space:
mode:
authortamirms <tamir@trello.com>2018-11-08 20:26:47 +0800
committerFelix Lange <fjl@users.noreply.github.com>2018-11-08 20:26:47 +0800
commitb16cc501a88eb7c36cfd8ee9be1c0c985ef4a7d9 (patch)
tree02a92c1f7669d11c66337e32abf5f7d0ad1d178b /ethclient
parent9313fa63f959f8a5c3609c187120711a484a4c57 (diff)
downloadgo-tangerine-b16cc501a88eb7c36cfd8ee9be1c0c985ef4a7d9.tar.gz
go-tangerine-b16cc501a88eb7c36cfd8ee9be1c0c985ef4a7d9.tar.zst
go-tangerine-b16cc501a88eb7c36cfd8ee9be1c0c985ef4a7d9.zip
ethclient: include block hash from FilterQuery (#17996)
ethereum/go-ethereum#16734 introduced BlockHash to the FilterQuery struct. However, ethclient was not updated to include BlockHash in the actual RPC request.
Diffstat (limited to 'ethclient')
-rw-r--r--ethclient/ethclient.go36
-rw-r--r--ethclient/ethclient_test.go120
2 files changed, 145 insertions, 11 deletions
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index b40837c8c..f3163e19b 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -365,26 +365,42 @@ func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumb
// FilterLogs executes a filter query.
func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
var result []types.Log
- err := ec.c.CallContext(ctx, &result, "eth_getLogs", toFilterArg(q))
+ arg, err := toFilterArg(q)
+ if err != nil {
+ return nil, err
+ }
+ err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg)
return result, err
}
// SubscribeFilterLogs subscribes to the results of a streaming filter query.
func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
- return ec.c.EthSubscribe(ctx, ch, "logs", toFilterArg(q))
+ arg, err := toFilterArg(q)
+ if err != nil {
+ return nil, err
+ }
+ return ec.c.EthSubscribe(ctx, ch, "logs", arg)
}
-func toFilterArg(q ethereum.FilterQuery) interface{} {
+func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
arg := map[string]interface{}{
- "fromBlock": toBlockNumArg(q.FromBlock),
- "toBlock": toBlockNumArg(q.ToBlock),
- "address": q.Addresses,
- "topics": q.Topics,
+ "address": q.Addresses,
+ "topics": q.Topics,
}
- if q.FromBlock == nil {
- arg["fromBlock"] = "0x0"
+ if q.BlockHash != nil {
+ arg["blockHash"] = *q.BlockHash
+ if q.FromBlock != nil || q.ToBlock != nil {
+ return nil, fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock")
+ }
+ } else {
+ if q.FromBlock == nil {
+ arg["fromBlock"] = "0x0"
+ } else {
+ arg["fromBlock"] = toBlockNumArg(q.FromBlock)
+ }
+ arg["toBlock"] = toBlockNumArg(q.ToBlock)
}
- return arg
+ return arg, nil
}
// Pending State
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
index 178eb2be9..3e8bf974c 100644
--- a/ethclient/ethclient_test.go
+++ b/ethclient/ethclient_test.go
@@ -16,7 +16,15 @@
package ethclient
-import "github.com/ethereum/go-ethereum"
+import (
+ "fmt"
+ "math/big"
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+)
// Verify that Client implements the ethereum interfaces.
var (
@@ -32,3 +40,113 @@ var (
// _ = ethereum.PendingStateEventer(&Client{})
_ = ethereum.PendingContractCaller(&Client{})
)
+
+func TestToFilterArg(t *testing.T) {
+ blockHashErr := fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock")
+ addresses := []common.Address{
+ common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"),
+ }
+ blockHash := common.HexToHash(
+ "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb",
+ )
+
+ for _, testCase := range []struct {
+ name string
+ input ethereum.FilterQuery
+ output interface{}
+ err error
+ }{
+ {
+ "without BlockHash",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ FromBlock: big.NewInt(1),
+ ToBlock: big.NewInt(2),
+ Topics: [][]common.Hash{},
+ },
+ map[string]interface{}{
+ "address": addresses,
+ "fromBlock": "0x1",
+ "toBlock": "0x2",
+ "topics": [][]common.Hash{},
+ },
+ nil,
+ },
+ {
+ "with nil fromBlock and nil toBlock",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ Topics: [][]common.Hash{},
+ },
+ map[string]interface{}{
+ "address": addresses,
+ "fromBlock": "0x0",
+ "toBlock": "latest",
+ "topics": [][]common.Hash{},
+ },
+ nil,
+ },
+ {
+ "with blockhash",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ BlockHash: &blockHash,
+ Topics: [][]common.Hash{},
+ },
+ map[string]interface{}{
+ "address": addresses,
+ "blockHash": blockHash,
+ "topics": [][]common.Hash{},
+ },
+ nil,
+ },
+ {
+ "with blockhash and from block",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ BlockHash: &blockHash,
+ FromBlock: big.NewInt(1),
+ Topics: [][]common.Hash{},
+ },
+ nil,
+ blockHashErr,
+ },
+ {
+ "with blockhash and to block",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ BlockHash: &blockHash,
+ ToBlock: big.NewInt(1),
+ Topics: [][]common.Hash{},
+ },
+ nil,
+ blockHashErr,
+ },
+ {
+ "with blockhash and both from / to block",
+ ethereum.FilterQuery{
+ Addresses: addresses,
+ BlockHash: &blockHash,
+ FromBlock: big.NewInt(1),
+ ToBlock: big.NewInt(2),
+ Topics: [][]common.Hash{},
+ },
+ nil,
+ blockHashErr,
+ },
+ } {
+ t.Run(testCase.name, func(t *testing.T) {
+ output, err := toFilterArg(testCase.input)
+ if (testCase.err == nil) != (err == nil) {
+ t.Fatalf("expected error %v but got %v", testCase.err, err)
+ }
+ if testCase.err != nil {
+ if testCase.err.Error() != err.Error() {
+ t.Fatalf("expected error %v but got %v", testCase.err, err)
+ }
+ } else if !reflect.DeepEqual(testCase.output, output) {
+ t.Fatalf("expected filter arg %v but got %v", testCase.output, output)
+ }
+ })
+ }
+}