l1client.go 5.83 KB
Newer Older
1 2 3 4 5 6 7
package mock

import (
	"context"
	"math/big"
	"sync"

8
	"github.com/ethereum/go-ethereum"
9 10 11 12 13 14 15
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
)

// L1ClientConfig houses the internal methods that are executed by the mock
// L1Client. Any members left as nil will panic on execution.
type L1ClientConfig struct {
16 17 18
	// BlockNumber returns the most recent block number.
	BlockNumber func(context.Context) (uint64, error)

19 20 21 22 23 24 25
	// EstimateGas tries to estimate the gas needed to execute a specific
	// transaction based on the current pending state of the backend blockchain.
	// There is no guarantee that this is the true gas limit requirement as
	// other transactions may be added or removed by miners, but it should
	// provide a basis for setting a reasonable default.
	EstimateGas func(context.Context, ethereum.CallMsg) (uint64, error)

26 27 28
	// HeaderByNumber returns a block header from the current canonical chain.
	// If number is nil, the latest known header is returned.
	HeaderByNumber func(context.Context, *big.Int) (*types.Header, error)
29 30 31 32 33 34 35 36 37 38 39 40

	// NonceAt returns the account nonce of the given account. The block number
	// can be nil, in which case the nonce is taken from the latest known block.
	NonceAt func(context.Context, common.Address, *big.Int) (uint64, error)

	// SendTransaction injects a signed transaction into the pending pool for
	// execution.
	//
	// If the transaction was a contract creation use the TransactionReceipt
	// method to get the contract address after the transaction has been mined.
	SendTransaction func(context.Context, *types.Transaction) error

41 42 43 44
	// SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559
	// to allow a timely execution of a transaction.
	SuggestGasTipCap func(context.Context) (*big.Int, error)

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
	// TransactionReceipt returns the receipt of a transaction by transaction
	// hash. Note that the receipt is not available for pending transactions.
	TransactionReceipt func(context.Context, common.Hash) (*types.Receipt, error)
}

// L1Client represents a mock L1Client.
type L1Client struct {
	cfg L1ClientConfig
	mu  sync.RWMutex
}

// NewL1Client returns a new L1Client using the mocked methods in the
// L1ClientConfig.
func NewL1Client(cfg L1ClientConfig) *L1Client {
	return &L1Client{
		cfg: cfg,
	}
}

64 65 66 67 68 69 70 71
// BlockNumber returns the most recent block number.
func (c *L1Client) BlockNumber(ctx context.Context) (uint64, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.BlockNumber(ctx)
}

72 73 74 75 76 77 78 79 80 81 82 83
// EstimateGas tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
func (c *L1Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.EstimateGas(ctx, msg)
}

84 85 86
// HeaderByNumber returns a block header from the current canonical chain. If
// number is nil, the latest known header is returned.
func (c *L1Client) HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*types.Header, error) {
87 88 89
	c.mu.RLock()
	defer c.mu.RUnlock()

90
	return c.cfg.HeaderByNumber(ctx, blockNumber)
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
}

// NonceAt executes the mock NonceAt method.
func (c *L1Client) NonceAt(ctx context.Context, addr common.Address, blockNumber *big.Int) (uint64, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.NonceAt(ctx, addr, blockNumber)
}

// SendTransaction executes the mock SendTransaction method.
func (c *L1Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.SendTransaction(ctx, tx)
}

109 110 111 112 113 114 115 116 117
// SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to
// allow a timely execution of a transaction.
func (c *L1Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.SuggestGasTipCap(ctx)
}

118 119 120 121 122 123 124 125
// TransactionReceipt executes the mock TransactionReceipt method.
func (c *L1Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return c.cfg.TransactionReceipt(ctx, txHash)
}

126 127 128 129 130 131 132 133 134 135
// SetBlockNumberFunc overwrites the mock BlockNumber method.
func (c *L1Client) SetBlockNumberFunc(
	f func(context.Context) (uint64, error)) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.BlockNumber = f
}

136 137 138 139 140 141 142 143 144 145
// SetEstimateGasFunc overwrites the mock EstimateGas method.
func (c *L1Client) SetEstimateGasFunc(
	f func(context.Context, ethereum.CallMsg) (uint64, error)) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.EstimateGas = f
}

146 147 148
// SetHeaderByNumberFunc overwrites the mock HeaderByNumber method.
func (c *L1Client) SetHeaderByNumberFunc(
	f func(ctx context.Context, blockNumber *big.Int) (*types.Header, error)) {
149 150 151 152

	c.mu.Lock()
	defer c.mu.Unlock()

153
	c.cfg.HeaderByNumber = f
154 155
}

156
// SetNonceAtFunc overwrites the mock NonceAt method.
157 158 159 160 161 162 163 164 165
func (c *L1Client) SetNonceAtFunc(
	f func(context.Context, common.Address, *big.Int) (uint64, error)) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.NonceAt = f
}

166
// SetSendTransactionFunc overwrites the mock SendTransaction method.
167 168 169 170 171 172 173 174 175
func (c *L1Client) SetSendTransactionFunc(
	f func(context.Context, *types.Transaction) error) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.SendTransaction = f
}

176 177 178 179 180 181 182 183 184 185
// SetSuggestGasTipCapFunc overwrites themock SuggestGasTipCap method.
func (c *L1Client) SetSuggestGasTipCapFunc(
	f func(context.Context) (*big.Int, error)) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.SuggestGasTipCap = f
}

186 187 188 189 190 191 192 193 194
// SetTransactionReceiptFunc overwrites the mock TransactionReceipt method.
func (c *L1Client) SetTransactionReceiptFunc(
	f func(context.Context, common.Hash) (*types.Receipt, error)) {

	c.mu.Lock()
	defer c.mu.Unlock()

	c.cfg.TransactionReceipt = f
}