Skip to content

Commit

Permalink
Encapsulate gasfee API (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
windycrypto authored Jan 22, 2025
1 parent 83299af commit 52aa783
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 39 deletions.
38 changes: 0 additions & 38 deletions .github/workflows/ci.yml

This file was deleted.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/DeBankDeFi/etherlib

go 1.17
go 1.22

require (
github.com/ethereum/go-ethereum v1.13.14
Expand Down
12 changes: 12 additions & 0 deletions pkg/gasfeesvc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## 说明

为方便查阅各个链的 gas fee 预估实现, 以及避免每条链一个分支, 所有链的 gas fee 预估实现都在 `pkg/gasfeesvc/` 目录下, 节点代码引用此包时使用条件编译决定要编译哪条链的实现代码.

若新链与现有某条链的实现一直, 可以直接复用现有实现, 但是在实现顶部一定要添加对应链的 build tag. 这将作为后续查询某个实现已被用于哪些链的依据, 防止修改某个实现意外影响其它链.

比如, op 的 gas fee 预估逻辑也适用于 base, 则 `op.go` 实现文件顶部一定要同时包含 op base 两个 build tag, 且关系为或.

```
//go:build op || base
// +build op base
```
17 changes: 17 additions & 0 deletions pkg/gasfeesvc/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gasfeesvc

type EstimatedGasFee struct {
MaxPriorityFeePerGas float64 `json:"maxPriorityFeePerGas"`
MaxFeePerGas float64 `json:"maxFeePerGas"`
}

type SuggestedGasFees struct {
BaseBlock int64 `json:"baseBlock"`
NextBaseFee float64 `json:"nextBaseFee"`
GasUsedRatio []float64 `json:"gasUsedRatio"`
HistoricalBaseFees []float64 `json:"historicalBaseFees,omitempty"`
HistoricalRewards []float64 `json:"historicalRewards,omitempty"`
RegulatedHistoricalRewards []float64 `json:"regulatedHistoricalRewards,omitempty"`
StdDevThreshold float64 `json:"stdDevThreshold,omitempty"`
EstimatedGasFees map[string]*EstimatedGasFee `json:"estimatedGasFees"`
}
88 changes: 88 additions & 0 deletions pkg/gasfeesvc/eth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//go:build eth
// +build eth

package gasfeesvc

import (
"context"
"math"
"math/big"
"sort"

"github.com/ethereum/go-ethereum/rpc"
"github.com/gonum/stat"
)

type FeeHistory func(ctx context.Context, blocks uint64, lastBlock *rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error)

func SuggestGasFees(ctx context.Context, lastBlock *rpc.BlockNumber, feeHistory FeeHistory) (*SuggestedGasFees, error) {
// query the past 10 blocks
blocks := 10
stdDevThreshold := 1.0
baseFeeIncreateRatio := []float64{1.0, 1.45, 2.35} // metamask is: 1, 1.43, 2.3
tipFeePercentiles := []float64{0.1, 0.5, 0.9}
levels := []string{"normal", "fast", "instant"}

// firstly we get all percentiles, we will do preprocessing on the returned data and pickup 3 percentiles as the normal, fast, instant levels
rewardPercentiles := []float64{}
for i := range 100 {
rewardPercentiles = append(rewardPercentiles, float64(i))
}

if lastBlock == nil {
lastBlock = new(rpc.BlockNumber)
*lastBlock = rpc.LatestBlockNumber
}
oldest, rewards, baseFees, gasUsedRatios, err := feeHistory(ctx, uint64(blocks), lastBlock, rewardPercentiles)
if err != nil {
return nil, err
}

// pre process the original data from the Oracle
// 1. convert the original data unit "wei" to "gwei"
// 2. remove the exceptional rewards that deviate too much from the mean
results := &SuggestedGasFees{
BaseBlock: oldest.Int64() + int64(blocks) - 1,
GasUsedRatio: gasUsedRatios,
StdDevThreshold: stdDevThreshold,
EstimatedGasFees: make(map[string]*EstimatedGasFee, 3),
}
for _, baseFee := range baseFees {
if bf, accuracy := new(big.Float).SetInt(baseFee).Float64(); accuracy == 0 {
results.HistoricalBaseFees = append(results.HistoricalBaseFees, bf/1_000_000_000)
results.NextBaseFee = bf / 1_000_000_000 // set the next block's base fee here too
}
}
for _, rewardsIn1Blk := range rewards {
for _, txReward := range rewardsIn1Blk {
if rwd, accuracy := new(big.Float).SetInt(txReward).Float64(); accuracy == 0 {
results.HistoricalRewards = append(results.HistoricalRewards, rwd/1_000_000_000)
}
}
}

// remove the rewards that 1x from the Standard Deviation
mean, stdDev := stat.MeanStdDev(results.HistoricalRewards, nil)
regulated := []float64{}
for _, num := range results.HistoricalRewards {
if math.Abs(num-mean) <= stdDevThreshold*stdDev {
regulated = append(regulated, num)
}
}
sort.Float64s(regulated)
results.RegulatedHistoricalRewards = regulated

for i, level := range levels {
percentile := tipFeePercentiles[i]
baseFeeRatio := baseFeeIncreateRatio[i]

idx := int(percentile * float64(len(regulated)))
tip := regulated[idx]

results.EstimatedGasFees[level] = &EstimatedGasFee{
MaxPriorityFeePerGas: tip,
MaxFeePerGas: results.NextBaseFee*baseFeeRatio + tip,
}
}
return results, nil
}
4 changes: 4 additions & 0 deletions pkg/gasfeesvc/op.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//go:build op || base
// +build op base

package gasfeesvc

0 comments on commit 52aa783

Please sign in to comment.