From 04e7f833504418ddb7d198f56326cfccfd0ed9f7 Mon Sep 17 00:00:00 2001 From: SpongeBoi <66492212+Shubhaankar-Sharma@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:07:01 +0530 Subject: [PATCH] make a public contract query builder method (#110) --- ethrpc/ethrpc.go | 43 ++++++---------------------------------- ethrpc/methods.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/ethrpc/ethrpc.go b/ethrpc/ethrpc.go index 844506f5..2391304f 100644 --- a/ethrpc/ethrpc.go +++ b/ethrpc/ethrpc.go @@ -11,7 +11,6 @@ import ( "net/http" "sync/atomic" - "github.com/0xsequence/ethkit/ethcoder" "github.com/0xsequence/ethkit/go-ethereum" "github.com/0xsequence/ethkit/go-ethereum/accounts/abi/bind" "github.com/0xsequence/ethkit/go-ethereum/common" @@ -435,42 +434,12 @@ func (p *Provider) ContractQuery(ctx context.Context, contractAddress string, in func (p *Provider) contractQuery(ctx context.Context, contractAddress string, inputAbiExpr, outputAbiExpr string, args interface{}) ([]string, error) { contract := common.HexToAddress(contractAddress) - var ( - calldata []byte - err error - ) - - switch args := args.(type) { - case []string: - calldata, err = ethcoder.AbiEncodeMethodCalldataFromStringValues(inputAbiExpr, args) - if err != nil { - return nil, fmt.Errorf("abi encode failed: %w", err) - } - - case []interface{}: - calldata, err = ethcoder.AbiEncodeMethodCalldata(inputAbiExpr, args) - if err != nil { - return nil, fmt.Errorf("abi encode failed: %w", err) - } - case nil: - calldata, err = ethcoder.AbiEncodeMethodCalldata(inputAbiExpr, nil) - if err != nil { - return nil, fmt.Errorf("abi encode failed: %w", err) - } - } - - msg := ethereum.CallMsg{ - To: &contract, - Data: calldata, - } - - output, err := p.CallContract(ctx, msg, nil) - if err != nil { - return nil, fmt.Errorf("contract call failed: %w", err) - } - resp, err := ethcoder.AbiDecodeExprAndStringify(outputAbiExpr, output) + contractQueryBuilder, err := ContractQuery(contract, inputAbiExpr, outputAbiExpr, args) if err != nil { - return nil, fmt.Errorf("abi decode of response failed: %w", err) + return nil, err } - return resp, nil + + var result []string + _, err = p.Do(ctx, contractQueryBuilder.Into(&result)) + return result, err } diff --git a/ethrpc/methods.go b/ethrpc/methods.go index bb2246aa..12ff6cb1 100644 --- a/ethrpc/methods.go +++ b/ethrpc/methods.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/0xsequence/ethkit/ethcoder" "github.com/0xsequence/ethkit/ethrpc/jsonrpc" "github.com/0xsequence/ethkit/go-ethereum" "github.com/0xsequence/ethkit/go-ethereum/common" @@ -282,6 +283,55 @@ func PendingTransactionCount() CallBuilder[uint] { } } +func ContractQuery(contractAddress common.Address, inputAbiExpr, outputAbiExpr string, args interface{}) (CallBuilder[[]string], error) { + var ( + calldata []byte + err error + ) + + switch args := args.(type) { + case []string: + calldata, err = ethcoder.AbiEncodeMethodCalldataFromStringValues(inputAbiExpr, args) + if err != nil { + return CallBuilder[[]string]{}, fmt.Errorf("abi encode failed: %w", err) + } + + case []interface{}: + calldata, err = ethcoder.AbiEncodeMethodCalldata(inputAbiExpr, args) + if err != nil { + return CallBuilder[[]string]{}, fmt.Errorf("abi encode failed: %w", err) + } + case nil: + calldata, err = ethcoder.AbiEncodeMethodCalldata(inputAbiExpr, nil) + if err != nil { + return CallBuilder[[]string]{}, fmt.Errorf("abi encode failed: %w", err) + } + } + + msg := ethereum.CallMsg{ + To: &contractAddress, + Data: calldata, + } + + return CallBuilder[[]string]{ + method: "eth_call", + params: []any{toCallArg(msg), toBlockNumArg(nil)}, + intoFn: func(message json.RawMessage, ret *[]string) error { + var result hexutil.Bytes + if err := json.Unmarshal(message, &result); err != nil { + return err + } + + resp, err := ethcoder.AbiDecodeExprAndStringify(outputAbiExpr, result) + if err != nil { + return fmt.Errorf("abi decode of response failed: %w", err) + } + *ret = resp + return nil + }, + }, nil +} + func CallContract(msg ethereum.CallMsg, blockNum *big.Int) CallBuilder[[]byte] { return CallBuilder[[]byte]{ method: "eth_call",