diff --git a/pkg/eth/api.go b/pkg/eth/api.go index 9cdd3e20..0e923cca 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -480,6 +480,84 @@ func (pea *PublicEthAPI) GetRawTransactionByHash(ctx context.Context, hash commo return nil, err } +// accessListResult returns an optional accesslist +// Its the result of the `debug_createAccessList` RPC call. +// It contains an error if the transaction itself failed. +type accessListResult struct { + Accesslist *types.AccessList `json:"accessList"` + Error string `json:"error,omitempty"` + GasUsed hexutil.Uint64 `json:"gasUsed"` +} + +// CreateAccessList creates a EIP-2930 type AccessList for the given transaction. +// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state. +func (pea *PublicEthAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) { + if pea.rpc != nil { + var res *accessListResult + if err := pea.rpc.CallContext(ctx, &res, "eth_createAccessList", args, blockNrOrHash); err != nil { + return nil, err + } + return res, nil + } + return nil, RequiresProxyError{method: "eth_createAccessList"} +} + +type feeHistoryResult struct { + OldestBlock *hexutil.Big `json:"oldestBlock"` + Reward [][]*hexutil.Big `json:"reward,omitempty"` + BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` + GasUsedRatio []float64 `json:"gasUsedRatio"` +} + +// FeeHistory returns the fee market history. +func (pea *PublicEthAPI) FeeHistory(ctx context.Context, blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) { + if pea.rpc != nil { + var res *feeHistoryResult + if err := pea.rpc.CallContext(ctx, &res, "eth_feeHistory", blockCount, lastBlock, rewardPercentiles); err != nil { + return nil, err + } + return res, nil + } + return nil, RequiresProxyError{method: "eth_feeHistory"} +} + +// EstimateGas returns an estimate of the amount of gas needed to execute the +// given transaction against the current pending block. +func (pea *PublicEthAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) { + if pea.rpc != nil { + var res hexutil.Uint64 + if err := pea.rpc.CallContext(ctx, &res, "eth_estimateGas", args, blockNrOrHash); err != nil { + return hexutil.Uint64(0), err + } + return res, nil + } + return hexutil.Uint64(0), RequiresProxyError{method: "eth_estimateGas"} +} + +// GasPrice returns a suggestion for a gas price for legacy transactions. +func (pea *PublicEthAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) { + if pea.rpc != nil { + var res *hexutil.Big + if err := pea.rpc.CallContext(ctx, &res, "eth_gasPrice"); err != nil { + return nil, err + } + return res, nil + } + return nil, RequiresProxyError{method: "eth_gasPrice"} +} + +// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. +func (pea *PublicEthAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) { + if pea.rpc != nil { + var res *hexutil.Big + if err := pea.rpc.CallContext(ctx, &res, "eth_maxPriorityFeePerGas"); err != nil { + return nil, err + } + return res, nil + } + return nil, RequiresProxyError{method: "eth_maxPriorityFeePerGas"} +} + /* Receipts and Logs diff --git a/pkg/eth/errors.go b/pkg/eth/errors.go new file mode 100644 index 00000000..7b6ac0a8 --- /dev/null +++ b/pkg/eth/errors.go @@ -0,0 +1,17 @@ +package eth + +import "fmt" + +type RequiresProxyError struct { + method string +} + +var _ error = RequiresProxyError{} + +func (e RequiresProxyError) SetMethod(method string) { + e.method = method +} + +func (e RequiresProxyError) Error() string { + return fmt.Sprintf("%s requires a configured proxy geth node", e.method) +} diff --git a/pkg/eth/transaction_arguments.go b/pkg/eth/transaction_arguments.go new file mode 100644 index 00000000..f837c500 --- /dev/null +++ b/pkg/eth/transaction_arguments.go @@ -0,0 +1,49 @@ +package eth + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +) + +// TransactionArgs represents the arguments to construct a new transaction +// or a message call. +type TransactionArgs struct { + From *common.Address `json:"from"` + To *common.Address `json:"to"` + Gas *hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` + MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` + Value *hexutil.Big `json:"value"` + Nonce *hexutil.Uint64 `json:"nonce"` + + // We accept "data" and "input" for backwards-compatibility reasons. + // "input" is the newer name and should be preferred by clients. + // Issue detail: https://github.com/ethereum/go-ethereum/issues/15628 + Data *hexutil.Bytes `json:"data"` + Input *hexutil.Bytes `json:"input"` + + // Introduced by AccessListTxType transaction. + AccessList *types.AccessList `json:"accessList,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` +} + +// from retrieves the transaction sender address. +func (args *TransactionArgs) from() common.Address { + if args.From == nil { + return common.Address{} + } + return *args.From +} + +// data retrieves the transaction calldata. Input field is preferred. +func (args *TransactionArgs) data() []byte { + if args.Input != nil { + return *args.Input + } + if args.Data != nil { + return *args.Data + } + return nil +}