-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathfee_distribution.go
More file actions
132 lines (106 loc) · 2.63 KB
/
Copy pathfee_distribution.go
File metadata and controls
132 lines (106 loc) · 2.63 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package ui
import (
"context"
"fmt"
"sort"
"sync"
"github.com/fatih/color"
"github.com/jroimartin/gocui"
"github.com/mempool/mempool-cli/client"
)
type FeeDistribution struct {
gui *gocui.Gui
m sync.Mutex
loading bool
isProjected bool
cancelFn context.CancelFunc
fees client.Fees
title string
client *client.Client
}
func NewFeeDistribution(g *gocui.Gui, c *client.Client) *FeeDistribution {
return &FeeDistribution{gui: g, client: c}
}
func (fd *FeeDistribution) newCtx() context.Context {
ctx, cancel := context.WithCancel(context.Background())
fd.cancelFn = cancel
return ctx
}
func (fd *FeeDistribution) FetchProjection(n int) error {
fn := func(ctx context.Context) (client.Fees, error) {
return fd.client.GetMempoolFee(ctx, n)
}
return fd.fetch(fn)
}
func (fd *FeeDistribution) FetchBlock(n int) error {
fn := func(ctx context.Context) (client.Fees, error) {
return fd.client.GetBlockFee(ctx, n)
}
return fd.fetch(fn)
}
func (fd *FeeDistribution) fetch(fn func(ctx context.Context) (client.Fees, error)) error {
fd.m.Lock()
defer fd.m.Unlock()
if fn := fd.cancelFn; fn != nil {
fn()
}
fd.loading = true
ctx := fd.newCtx()
go func() {
fees, err := fn(ctx)
if err != nil {
return
}
fd.fees = fees
fd.loading = false
fd.gui.Update(fd.Layout)
}()
return nil
}
func (fd *FeeDistribution) Layout(g *gocui.Gui) error {
fd.m.Lock()
defer fd.m.Unlock()
if fd.loading == false && (fd.fees == nil || len(fd.fees) == 0) {
return nil
}
x, y := g.Size()
name := "fee_distribution"
v, err := g.SetView(name, x/2-20, y/2-3, x/2+20, y/2+3)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Fee distribution" + fd.title + "('esc' to close)"
g.SetCurrentView(name)
g.SetViewOnTop(name)
g.SetKeybinding(name, gocui.KeyEsc, gocui.ModNone, fd.close)
}
v.Clear()
if fd.loading == true {
fmt.Fprint(v, "Loading...")
return nil
}
sort.Sort(fd.fees)
txs := len(fd.fees)
min, max := fd.fees[0].FPV, fd.fees[txs-1].FPV
var (
white = color.New(color.FgWhite).SprintfFunc()
yellow = color.New(color.FgYellow).SprintfFunc()
)
fmt.Fprintf(v, white("Fee span:")+" %d - %d "+yellow("sat/vByte\n"), ceil(min), ceil(max))
fmt.Fprintf(v, white("Tx count:")+" %d "+white("transactions\n"), txs)
fmt.Fprintf(v, white("Median: ")+" ~%d "+yellow("sat/vBytes\n"), ceil(fd.fees[txs/2].FPV))
return nil
}
func (fd *FeeDistribution) close(g *gocui.Gui, v *gocui.View) error {
fd.m.Lock()
defer fd.m.Unlock()
if fn := fd.cancelFn; fn != nil {
fn()
}
fd.cancelFn = nil
fd.loading = false
fd.fees = nil
g.DeleteView(v.Name())
return nil
}