2022-09-30 20:04:34 +00:00
|
|
|
package requests
|
|
|
|
|
|
|
|
import (
|
2022-10-31 10:46:49 +00:00
|
|
|
"bytes"
|
2022-09-30 20:04:34 +00:00
|
|
|
"fmt"
|
2022-10-31 02:20:58 +00:00
|
|
|
|
2023-01-13 18:12:18 +00:00
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
"github.com/ledgerwatch/erigon/common/hexutil"
|
2022-10-31 10:46:49 +00:00
|
|
|
"github.com/ledgerwatch/erigon/core/types"
|
2022-09-30 20:04:34 +00:00
|
|
|
)
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
type EthBlockNumber struct {
|
|
|
|
CommonResponse
|
|
|
|
Number hexutil.Uint64 `json:"result"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type EthBlockByNumber struct {
|
|
|
|
CommonResponse
|
|
|
|
Result *EthBlockByNumberResult `json:"result"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type EthBlockByNumberResult struct {
|
|
|
|
Difficulty hexutil.Big `json:"difficulty"`
|
|
|
|
Miner libcommon.Address `json:"miner"`
|
|
|
|
Transactions []EthTransaction `json:"transactions"`
|
|
|
|
TxRoot libcommon.Hash `json:"transactionsRoot"`
|
|
|
|
Hash libcommon.Hash `json:"hash"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type EthGetTransactionCount struct {
|
|
|
|
CommonResponse
|
|
|
|
Result hexutil.Uint64 `json:"result"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type EthSendRawTransaction struct {
|
|
|
|
CommonResponse
|
|
|
|
TxnHash libcommon.Hash `json:"result"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reqGen *RequestGenerator) BlockNumber() (uint64, error) {
|
|
|
|
var b EthBlockNumber
|
2023-03-30 21:49:28 +00:00
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
method, body := reqGen.blockNumber()
|
|
|
|
res := reqGen.call(method, body, &b)
|
2023-03-30 21:49:28 +00:00
|
|
|
number := uint64(b.Number)
|
|
|
|
|
|
|
|
if res.Err != nil {
|
|
|
|
return number, fmt.Errorf("error getting current block number: %v", res.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return number, nil
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
func (req *RequestGenerator) blockNumber() (RPCMethod, string) {
|
|
|
|
const template = `{"jsonrpc":"2.0","method":%q,"id":%d}`
|
|
|
|
return Methods.ETHBlockNumber, fmt.Sprintf(template, Methods.ETHBlockNumber, req.reqID)
|
|
|
|
}
|
2023-01-10 17:43:58 +00:00
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
func (reqGen *RequestGenerator) GetBlockByNumber(blockNum uint64, withTxs bool) (EthBlockByNumber, error) {
|
|
|
|
var b EthBlockByNumber
|
2023-01-10 17:43:58 +00:00
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
method, body := reqGen.getBlockByNumber(blockNum, withTxs)
|
|
|
|
res := reqGen.call(method, body, &b)
|
2023-01-10 17:43:58 +00:00
|
|
|
if res.Err != nil {
|
|
|
|
return b, fmt.Errorf("error getting block by number: %v", res.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.Error != nil {
|
|
|
|
return b, fmt.Errorf("error populating response object: %v", b.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
func (req *RequestGenerator) getBlockByNumber(blockNum uint64, withTxs bool) (RPCMethod, string) {
|
|
|
|
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x",%t],"id":%d}`
|
|
|
|
return Methods.ETHGetBlockByNumber, fmt.Sprintf(template, Methods.ETHGetBlockByNumber, blockNum, withTxs, req.reqID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (req *RequestGenerator) getBlockByNumberI(blockNum string, withTxs bool) (RPCMethod, string) {
|
|
|
|
const template = `{"jsonrpc":"2.0","method":%q,"params":["%s",%t],"id":%d}`
|
|
|
|
return Methods.ETHGetBlockByNumber, fmt.Sprintf(template, Methods.ETHGetBlockByNumber, blockNum, withTxs, req.reqID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reqGen *RequestGenerator) GetBlockByNumberDetails(blockNum string, withTxs bool) (map[string]interface{}, error) {
|
2023-03-02 10:25:11 +00:00
|
|
|
var b struct {
|
2023-06-04 19:53:05 +00:00
|
|
|
CommonResponse
|
2023-03-02 10:25:11 +00:00
|
|
|
Result interface{} `json:"result"`
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
method, body := reqGen.getBlockByNumberI(blockNum, withTxs)
|
|
|
|
res := reqGen.call(method, body, &b)
|
2023-03-02 10:25:11 +00:00
|
|
|
if res.Err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting block by number: %v", res.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.Error != nil {
|
|
|
|
return nil, fmt.Errorf("error populating response object: %v", b.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
m, ok := b.Result.(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("cannot convert type")
|
|
|
|
}
|
|
|
|
|
|
|
|
return m, nil
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
func (reqGen *RequestGenerator) GetTransactionCount(address libcommon.Address, blockNum BlockNumber) (EthGetTransactionCount, error) {
|
|
|
|
var b EthGetTransactionCount
|
2022-10-31 10:46:49 +00:00
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
method, body := reqGen.getTransactionCount(address, blockNum)
|
|
|
|
if res := reqGen.call(method, body, &b); res.Err != nil {
|
2022-10-31 10:46:49 +00:00
|
|
|
return b, fmt.Errorf("error getting transaction count: %v", res.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.Error != nil {
|
|
|
|
return b, fmt.Errorf("error populating response object: %v", b.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
func (req *RequestGenerator) getTransactionCount(address libcommon.Address, blockNum BlockNumber) (RPCMethod, string) {
|
|
|
|
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x","%v"],"id":%d}`
|
|
|
|
return Methods.ETHGetTransactionCount, fmt.Sprintf(template, Methods.ETHGetTransactionCount, address, blockNum, req.reqID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reqGen *RequestGenerator) SendTransaction(signedTx *types.Transaction) (*libcommon.Hash, error) {
|
|
|
|
var b EthSendRawTransaction
|
2022-10-31 10:46:49 +00:00
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
if err := (*signedTx).MarshalBinary(&buf); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to marshal binary: %v", err)
|
|
|
|
}
|
|
|
|
|
2023-06-04 19:53:05 +00:00
|
|
|
method, body := reqGen.sendRawTransaction(buf.Bytes())
|
|
|
|
if res := reqGen.call(method, body, &b); res.Err != nil {
|
2022-10-31 10:46:49 +00:00
|
|
|
return nil, fmt.Errorf("could not make to request to eth_sendRawTransaction: %v", res.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &b.TxnHash, nil
|
|
|
|
}
|
2023-06-04 19:53:05 +00:00
|
|
|
|
|
|
|
func (req *RequestGenerator) sendRawTransaction(signedTx []byte) (RPCMethod, string) {
|
|
|
|
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x"],"id":%d}`
|
|
|
|
return Methods.ETHSendRawTransaction, fmt.Sprintf(template, Methods.ETHSendRawTransaction, signedTx, req.reqID)
|
|
|
|
}
|