-
Notifications
You must be signed in to change notification settings - Fork 86
/
feemgr.go
95 lines (82 loc) · 2.53 KB
/
feemgr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package dex
import (
"strconv"
"sync/atomic"
"decred.org/dcrdex/server/asset"
"decred.org/dcrdex/server/market"
)
// FeeManager manages fee fetchers and a fee cache.
type FeeManager struct {
assets map[uint32]*asset.BackedAsset
cache map[uint32]*uint64
}
var _ market.FeeSource = (*FeeManager)(nil)
// NewFeeManager is the constructor for a FeeManager.
func NewFeeManager() *FeeManager {
return &FeeManager{
assets: make(map[uint32]*asset.BackedAsset),
cache: make(map[uint32]*uint64),
}
}
// AddFetcher adds a fee fetcher (a *BackedAsset) and primes the cache. The
// asset's MaxFeeRate are used to limit the rates returned by the LastRate
// method as well as the rates returned by child FeeFetchers.
func (m *FeeManager) AddFetcher(asset *asset.BackedAsset) {
rate, err := asset.Backend.FeeRate()
if err != nil {
log.Warnf("Error priming fee cache for %s: %v", asset.Symbol, err)
}
if rate > asset.MaxFeeRate {
rate = asset.MaxFeeRate
}
m.cache[asset.ID] = &rate
m.assets[asset.ID] = asset
}
// FeeFetcher creates and returns an asset-specific fetcher that satisfies
// market.FeeFetcher, implemented by *feeFetcher.
func (m *FeeManager) FeeFetcher(assetID uint32) market.FeeFetcher {
asset := m.assets[assetID]
if asset == nil {
panic("no fetcher for " + strconv.Itoa(int(assetID)))
}
return newFeeFetcher(asset, m.cache[assetID])
}
// LastRate is the last rate cached for the specified asset.
func (m *FeeManager) LastRate(assetID uint32) uint64 {
r := m.cache[assetID]
if r == nil {
return 0
}
return atomic.LoadUint64(r)
}
// feeFetcher implements market.FeeFetcher and updates the last fee rate cache.
type feeFetcher struct {
*asset.BackedAsset
lastRate *uint64
}
var _ market.FeeFetcher = (*feeFetcher)(nil)
// newFeeFetcher is the constructor for a *feeFetcher.
func newFeeFetcher(asset *asset.BackedAsset, lastRate *uint64) *feeFetcher {
return &feeFetcher{
BackedAsset: asset,
lastRate: lastRate,
}
}
// FeeRate fetches a new fee rate and updates the cache.
func (f *feeFetcher) FeeRate() uint64 {
r, err := f.Backend.FeeRate()
if err != nil {
log.Errorf("Error retrieving fee rate for %s: %v", f.Symbol, err)
}
if r > f.Asset.MaxFeeRate {
r = f.Asset.MaxFeeRate
}
atomic.StoreUint64(f.lastRate, r)
return r
}
// MaxFeeRate is a getter for the BackedAsset's dex.Asset.MaxFeeRate. This is
// provided so consumers that operate on the returned FeeRate can respect the
// configured limit e.g. ScaleFeeRate in (*Market).processReadyEpoch.
func (f *feeFetcher) MaxFeeRate() uint64 {
return f.Asset.MaxFeeRate
}