initial implementation
This commit is contained in:
parent
d6349081c6
commit
be7651f415
73
client/client.go
Normal file
73
client/client.go
Normal file
@ -0,0 +1,73 @@
|
||||
package client
|
||||
|
||||
import "github.com/gorilla/websocket"
|
||||
|
||||
type Block struct {
|
||||
Hash string `json:"hash"`
|
||||
Height int `json:"height"`
|
||||
NTx int `json:"nTx"`
|
||||
Size int `json:"size"`
|
||||
Time int `json:"time"`
|
||||
Weight int `json:"weight"`
|
||||
Fees float64 `json:"fees"`
|
||||
MinFee float64 `json:"minFee"`
|
||||
MaxFee float64 `json:"maxFee"`
|
||||
MedianFee float64 `json:"medianFee"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
MempoolInfo struct {
|
||||
Size int `json:"size"`
|
||||
Bytes int `json:"bytes"`
|
||||
} `json:"mempoolInfo"`
|
||||
|
||||
Block Block `json:"block"`
|
||||
Blocks []Block `json:"blocks"`
|
||||
|
||||
ProjectedBlocks []struct {
|
||||
BlockSize int `json:"blockSize"`
|
||||
BlockWeight int `json:"blockWeight"`
|
||||
NTx int `json:"nTx"`
|
||||
MinFee float64 `json:"minFee"`
|
||||
MaxFee float64 `json:"maxFee"`
|
||||
MinWeigthFee float64 `json:"minWeigthFee"`
|
||||
MaxWeigthFee float64 `json:"maxWeigthFee"`
|
||||
MedianFee float64 `json:"medianFee"`
|
||||
Fees float64 `json:"fees"`
|
||||
HasMyTx bool `json:"hasMytx"`
|
||||
} `json:"projectedBlocks"`
|
||||
|
||||
TxPerSecond float64 `json:"txPerSecond"`
|
||||
VBytesPerSecond int `json:"vBytesPerSecond"`
|
||||
Conversions struct {
|
||||
BTC float64 `json:"BTC"`
|
||||
USD float64 `json:"USD"`
|
||||
} `json:"conversions"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
conn *websocket.Conn
|
||||
}
|
||||
|
||||
func New() (*Client, error) {
|
||||
dialer := websocket.Dialer{}
|
||||
conn, _, err := dialer.Dial("wss://mempool.space/ws", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(
|
||||
`{"action":"want","data":["stats","blocks","projected-blocks"]}`,
|
||||
)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Client{conn: conn}, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read() (*Response, error) {
|
||||
var resp Response
|
||||
if err := c.conn.ReadJSON(&resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
17
go.mod
Normal file
17
go.mod
Normal file
@ -0,0 +1,17 @@
|
||||
module github.com/gchaincl/mempool
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/gizak/termui v3.1.0+incompatible
|
||||
github.com/gizak/termui/v3 v3.1.0
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/jroimartin/gocui v0.4.0
|
||||
github.com/kr/pretty v0.2.0
|
||||
github.com/mattn/go-runewidth v0.0.8 // indirect
|
||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be // indirect
|
||||
github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c
|
||||
google.golang.org/grpc v1.27.1 // indirect
|
||||
)
|
||||
74
go.sum
Normal file
74
go.sum
Normal file
@ -0,0 +1,74 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/gizak/termui v3.1.0+incompatible h1:N3CFm+j087lanTxPpHOmQs0uS3s5I9TxoAFy6DqPqv8=
|
||||
github.com/gizak/termui v3.1.0+incompatible/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
|
||||
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
|
||||
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/jroimartin/gocui v0.4.0 h1:52jnalstgmc25FmtGcWqa0tcbMEWS6RpFLsOIO+I+E8=
|
||||
github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
|
||||
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be h1:yzmWtPyxEUIKdZg4RcPq64MfS8NA6A5fNOJgYhpR9EQ=
|
||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
36
main.go
Normal file
36
main.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/gchaincl/mempool/client"
|
||||
"github.com/gchaincl/mempool/ui"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c, err := client.New()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
gui, err := ui.New()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer gui.Close()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
resp, err := c.Read()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
gui.Render(resp)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := gui.Loop(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
228
ui/ui.go
Normal file
228
ui/ui.go
Normal file
@ -0,0 +1,228 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/gchaincl/mempool/client"
|
||||
"github.com/jroimartin/gocui"
|
||||
)
|
||||
|
||||
const (
|
||||
BLOCK_WIDTH = 22
|
||||
BLOCKS_TO_DISPLAY = 4
|
||||
)
|
||||
|
||||
type UI struct {
|
||||
gui *gocui.Gui
|
||||
}
|
||||
|
||||
func New() (*UI, error) {
|
||||
gui, err := gocui.NewGui(gocui.Output256)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gui.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit)
|
||||
|
||||
return &UI{gui: gui}, nil
|
||||
}
|
||||
|
||||
func quit(*gocui.Gui, *gocui.View) error { return gocui.ErrQuit }
|
||||
|
||||
func (ui *UI) Close() { ui.gui.Close() }
|
||||
|
||||
func (ui *UI) Loop() error {
|
||||
err := ui.gui.MainLoop()
|
||||
// Mask ErrQuit
|
||||
if err == gocui.ErrQuit {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (ui *UI) Render(resp *client.Response) {
|
||||
ui.gui.Update(func(g *gocui.Gui) error {
|
||||
return ui.update(g, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func (ui *UI) update(g *gocui.Gui, resp *client.Response) error {
|
||||
x, y := g.Size()
|
||||
|
||||
// whether or not use vertical layout
|
||||
vertical := BLOCK_WIDTH*5 > x
|
||||
|
||||
// draw projected blocks (mempool)
|
||||
for i, _ := range resp.ProjectedBlocks {
|
||||
name := fmt.Sprintf("projected-block-%d", i)
|
||||
var x0, x1, y0, y1 int
|
||||
if vertical {
|
||||
x0 = x - (x/4)*(i+1)
|
||||
x1 = x0 + BLOCK_WIDTH
|
||||
y0 = (y / 2) - 12
|
||||
y1 = (y / 2) - 2
|
||||
} else {
|
||||
x0 = x/2 - BLOCK_WIDTH*(i+1)
|
||||
x1 = x0 + BLOCK_WIDTH - 2
|
||||
y0 = (y / 2) - 5
|
||||
y1 = (y / 2) + 5
|
||||
}
|
||||
|
||||
v, err := g.SetView(name, x0, y0, x1, y1)
|
||||
if err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Clear()
|
||||
if _, err := v.Write(printProjectedBlock(i, resp)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := ui.separator(g, x, y, vertical); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy the last BLOCKS_TO_DISPLAY blocks to a slice
|
||||
nBlocks := len(resp.Blocks)
|
||||
if nBlocks > BLOCKS_TO_DISPLAY {
|
||||
nBlocks = BLOCKS_TO_DISPLAY
|
||||
}
|
||||
blocks := make([]*client.Block, nBlocks)
|
||||
for i := 0; i < nBlocks; i++ {
|
||||
blocks[i] = &resp.Blocks[len(resp.Blocks)-1-i]
|
||||
}
|
||||
|
||||
// draw blockchain blocks
|
||||
for i, block := range blocks {
|
||||
name := fmt.Sprintf("block-%d", i)
|
||||
var x0, x1, y0, y1 int
|
||||
if vertical {
|
||||
x0 = x - (x/4)*(i+1)
|
||||
x1 = x0 + BLOCK_WIDTH
|
||||
y0 = (y / 2) + 2
|
||||
y1 = (y / 2) + 12
|
||||
} else {
|
||||
x0 = (x / 2) + (BLOCK_WIDTH*i + 1) + 1
|
||||
x1 = x0 + BLOCK_WIDTH - 2
|
||||
y0 = (y / 2) - 5
|
||||
y1 = (y / 2) + 5
|
||||
}
|
||||
|
||||
v, err := g.SetView(name, x0, y0, x1, y1)
|
||||
if err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Title = fmt.Sprintf("#%d", block.Height)
|
||||
v.Clear()
|
||||
if _, err := v.Write(printBlock(i, blocks)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ui *UI) separator(g *gocui.Gui, x, y int, vertical bool) error {
|
||||
var x0, x1, y0, y1 int
|
||||
if vertical {
|
||||
x0, x1 = 0, x
|
||||
y0, y1 = y/2-1, y/2+1
|
||||
} else {
|
||||
x0, x1 = x/2-1, x/2+1
|
||||
y0, y1 = 0, y
|
||||
}
|
||||
|
||||
v, err := g.SetView("separtor", x0, y0, x1, y1)
|
||||
if err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
v.Frame = false
|
||||
v.Wrap = true
|
||||
}
|
||||
|
||||
v.Clear()
|
||||
if vertical {
|
||||
fmt.Fprintf(v, strings.Repeat("-", x))
|
||||
} else {
|
||||
fmt.Fprintf(v, strings.Repeat("|", y))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
white = color.New(color.FgWhite).SprintfFunc()
|
||||
yellow = color.New(color.FgYellow).SprintfFunc()
|
||||
)
|
||||
|
||||
func printProjectedBlock(n int, resp *client.Response) []byte {
|
||||
block := resp.ProjectedBlocks[n]
|
||||
|
||||
lines := []string{
|
||||
white(" ~%.3f sat/vB ", block.MedianFee),
|
||||
yellow(" %.0f - %.0f sat/vB ", math.Ceil(block.MinFee), math.Ceil(block.MaxFee)),
|
||||
" ",
|
||||
white(" %.2f MB ", float64(block.BlockSize)/(1000*1000)),
|
||||
white(" %4d transactions ", block.NTx),
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
}
|
||||
|
||||
if n < 3 {
|
||||
lines[8] = white(" in ~%2d minutes ", (n+1)*10)
|
||||
bg := color.New(color.BgRed).SprintfFunc()
|
||||
offset := 9 - int(
|
||||
float64(block.BlockWeight)/4000000.0*10,
|
||||
)
|
||||
for i := offset; i < len(lines); i++ {
|
||||
lines[i] = bg("%s", lines[i])
|
||||
}
|
||||
} else {
|
||||
bw := math.Ceil(float64(block.BlockWeight) / 4000000.0)
|
||||
lines[8] = white(" +%d blocks", int(bw))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
fmt.Fprintf(buf, strings.Join(lines, "\n"))
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func printBlock(n int, blocks []*client.Block) []byte {
|
||||
block := blocks[n]
|
||||
|
||||
ago := time.Now().Unix() - int64(block.Time)
|
||||
lines := []string{
|
||||
white(" ~%.3f sat/Vb ", block.MedianFee),
|
||||
yellow(" %.0f - %.0f sat/vB ", math.Ceil(block.MinFee), math.Ceil(block.MaxFee)),
|
||||
" ",
|
||||
white(" %.2f MB ", float64(block.Size)/(1000*1000)),
|
||||
white(" %4d transactions ", block.NTx),
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
white(" %d secs ago ", ago),
|
||||
" ",
|
||||
}
|
||||
|
||||
bg := color.New(color.BgBlue).SprintFunc()
|
||||
for i, l := range lines {
|
||||
lines[i] = bg(l)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
fmt.Fprintf(buf, strings.Join(lines, "\n"))
|
||||
return buf.Bytes()
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user