-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgastracker.go
118 lines (111 loc) · 2.63 KB
/
gastracker.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package main
import (
"time"
"sync"
"log"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
var (
ETHER_TRANSFER_GAS = big.NewInt(21000)
)
type GasTracker struct {
tokens *TokenNotifier
prices *PriceTracker
influx *Influx
// process flow
quit chan struct{}
wg sync.WaitGroup
}
// Start the main gastracker module.
// It will start submodules TokenNotifier, PriceTracker and InfluxDB
func StartGasTracker(rpcEndpoint string) (*GasTracker, error) {
// price tracker
pt := StartPriceTracker(time.Minute)
// influxDB
influx, err := StartInflux()
if err != nil {
return nil, err
}
lastBlock, err := influx.GetLatestPointBlock()
log.Printf("Latest block in DB: %v\n", lastBlock)
if err != nil || lastBlock <= 0 {
if err != nil {
log.Printf("ERROR retrieving last block number: %s", err)
}
lastBlock = 2500000 // approx a month ago
}
// token notifier
tn, err := StartTokenNotifier(rpcEndpoint, lastBlock)
if err != nil {
return nil, err
}
// done
gt := &GasTracker{
tokens: tn,
prices: pt,
influx: influx,
quit: make(chan struct{}),
}
go gt.run()
return gt, nil
}
func (gt *GasTracker) run() {
gt.wg.Add(1)
defer gt.wg.Done()
// subscribe to token txs
for {
select {
case txs := <-gt.tokens.TokenStream:
gt.handleTxs(txs)
case <-gt.quit:
log.Println("Gas Tracker is closing...")
return
}
}
}
func (gt *GasTracker) handleTxs(txs []*TokenTx) {
var points []*TxPoint
for _, tx := range txs {
log.Printf("New tx for token %s\n", tx.Token.Name)
etherWei := (&big.Float{}).SetInt(common.Ether)
// token stats
tokenWeiFee := (&big.Float{}).SetInt(tx.Fee())
tokenEtherFee, _ := tokenWeiFee.Quo(tokenWeiFee, etherWei).Float64()
// separately track gas price expressed in fee for ether transfer
etherWeiFee := (&big.Float{}).SetInt((&big.Int{}).Mul(ETHER_TRANSFER_GAS, tx.GasPrice))
etherEtherFee, _ := etherWeiFee.Quo(etherWeiFee, etherWei).Float64()
points = append(points,
&TxPoint{
Time: tx.Time,
Token: tx.Token.Name,
Gas: tx.Gas.Uint64(),
FeeMap: map[string]float64{
"ETH": tokenEtherFee,
"USD": tokenEtherFee * gt.prices.Get("USD"),
"EUR": tokenEtherFee * gt.prices.Get("EUR"),
},
Block: tx.Block,
},
&TxPoint{
Time: tx.Time,
Token: "ETH",
Gas: ETHER_TRANSFER_GAS.Uint64(),
FeeMap: map[string]float64{
"ETH": etherEtherFee,
"USD": etherEtherFee * gt.prices.Get("USD"),
"EUR": etherEtherFee * gt.prices.Get("EUR"),
},
Block: tx.Block,
},
)
}
gt.influx.AddTxPoints(points)
}
func (gt *GasTracker) Stop() {
gt.prices.Stop()
gt.tokens.Stop()
gt.influx.Stop()
gt.quit <- struct{}{}
gt.wg.Wait()
}