-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement eth_feeHistory endpoint #502
Conversation
09f6075
to
bbe0ba6
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #502 +/- ##
==========================================
+ Coverage 58.59% 59.04% +0.44%
==========================================
Files 39 40 +1
Lines 4229 4380 +151
==========================================
+ Hits 2478 2586 +108
- Misses 1545 1572 +27
- Partials 206 222 +16 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
Metamask uses eth_feeHistory to calculate the different transaction priorities for gas price. See metamask source: This doesn't include the current txpool as BTC fee estimation does. Recently we had a situation where many transactions were queued up, and we were not sure if the fee estimation was returning accurate data, or if the 'Speed Up' button in MetaMask would work correctly. If |
0533998
to
7c10b2e
Compare
606a775
to
c3fd2da
Compare
c3fd2da
to
f35d9e9
Compare
@@ -146,6 +146,26 @@ func TestEth_GasPrice(t *testing.T) { | |||
t.Logf("gas price: %v", price) | |||
} | |||
|
|||
func TestEth_FeeHistory(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a suggestion, maybe we can test with additional arguments here.
For example
{ name: "Basic query with percentiles", blockCount: 10, lastBlock: nil, percentiles: []float64{0.25, 0.5, 0.75, 1}, expectErr: false, },
{ name: "Query with no reward percentiles", blockCount: 5, lastBlock: nil, percentiles: nil, expectErr: false, },
{ name: "Query specific block range", blockCount: 3, lastBlock: big.NewInt(5), percentiles: []float64{0.5}, expectErr: false, },
{ name: "Invalid block count", blockCount: 0, lastBlock: nil, percentiles: []float64{0.5}, expectErr: true, },
{ name: "Invalid percentile", blockCount: 5, lastBlock: nil, percentiles: []float64{1.5}, // Invalid percentile > 1 expectErr: true, },
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion, added!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
gas/backend_test.go
Outdated
@@ -185,4 +190,6 @@ func TestGasPriceOracle(t *testing.T) { | |||
|
|||
require.EqualValues(coreClient.minGasPrice.ToBigInt(), gasPriceOracle.GasPrice(), "oracle should return gas reported by the node query") | |||
gasPriceOracle.Stop() | |||
|
|||
// TODO: emit blocks with transactions, to test fee history. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a difference testing it here compared to rpc_test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a lettover comment, removed
gas/fee_history.go
Outdated
) | ||
|
||
// feeHistoryWindowSize is the number of recent blocks to store for the fee history query. | ||
const feeHistoryWindowSize = 20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this configurable? How did you come up with 20?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arbitrarily chosen, mostly because computing the response is not the most effective, as you must go through all requested blocks. I can make it configurable, but I would keep the default low, unless there is a use case for a larger default.
Most API's I have looked at have a limit of 1024, but they always mention that the node can return less than the requested range if not all blocks are available. The reasonable usages of eth_feeHistory
for gas estimation usually use small values:
- web3-py uses 10 blocks for gas estimation
- multichain uses 10 blocks for gas estimation
- Infura used to have a note that only 4 blocks are guaranteed to be available (although, as I see, this note is now gone) and they support up to 1024 blocks (with the note that it could return less)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now also configurable via config.
// No transactions in the block. | ||
if len(d.sortedTxs) == 0 { | ||
for i := range rewards { | ||
rewards[i] = (*hexutil.Big)(common.Big0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be the minimum required gas price for Sapphire (0.0000001 per gas unit) instead of 0? I'm not sure if there's another EVM call to fetch that info and dApps will fail otherwise on fresh chains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered by feehistory.BaseFee
(not via the rewards field), and is handled correctly even if there's no transactions in recent blocks.
// Query fee history. | ||
feeHistory, err := ec.FeeHistory(context.Background(), 10, nil, []float64{0.25, 0.5, 0.75, 1}) | ||
require.NoError(t, err, "get fee history") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check that the fees were not zero. (the minimum gas price is set to 0.0000001 in the test docker image, so the fees should also be non-zero)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a check to ensure the returnedfeeHistory.BaseFee
's are > 0.
6e9d31b
to
eca135b
Compare
eca135b
to
1ca1883
Compare
Fixes #501
Implements eth_feeHistory endpoint. The query supports returning the history for the maximum last 20 (configurable) blocks (this arbitrarily set limit is allowed as per spec: Requested range of blocks. Clients will return less than the requested range if not all blocks are available.)
To avoid fetching multiple blocks, transactions, and receipts from DB on every fee_history query (which can be expensive) the fee_history for last 20 (configurable) blocks is continuously pre-computed in the gas oracle (only the percentiles are computed on the fly).
TODO: