mirror of
https://github.com/miguelmota/cointop
synced 2024-11-05 00:00:14 +00:00
parent
65faa8b0a3
commit
75b86fcee4
114
Gopkg.lock
generated
Normal file
114
Gopkg.lock
generated
Normal file
@ -0,0 +1,114 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/anaskhan96/soup"
|
||||
packages = ["."]
|
||||
revision = "cd07662ec9300d16d2ece1c24b0b29ad89f65ff4"
|
||||
version = "v1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/bradfitz/slice"
|
||||
packages = ["."]
|
||||
revision = "d9036e2120b5ddfa53f3ebccd618c4af275f47da"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/dustin/go-humanize"
|
||||
packages = ["."]
|
||||
revision = "bb3d318650d48840a39aa21a027c6630e198e626"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/color"
|
||||
packages = ["."]
|
||||
revision = "507f6050b8568533fb3f5504de8e5205fa62a114"
|
||||
version = "v1.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gizak/termui"
|
||||
packages = ["."]
|
||||
revision = "24acd523c756fd9728824cdfac66aad9d8982fb7"
|
||||
version = "v2.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jroimartin/gocui"
|
||||
packages = ["."]
|
||||
revision = "4f518eddb04b8f73870836b6d1941e8aa3c06637"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/maruel/panicparse"
|
||||
packages = ["stack"]
|
||||
revision = "785840568bdc7faa0dfb1cd6c643207f03271f64"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-runewidth"
|
||||
packages = ["."]
|
||||
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
|
||||
version = "v0.0.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/miguelmota/go-coinmarketcap"
|
||||
packages = ["."]
|
||||
revision = "05fd2d0c45f763462f90e630da2ddc0392d2cdd3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-wordwrap"
|
||||
packages = ["."]
|
||||
revision = "ad45545899c7b13c020ea92b2072220eefad42b8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/nsf/termbox-go"
|
||||
packages = ["."]
|
||||
revision = "e2050e41c8847748ec5288741c0b19a8cb26d084"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/willf/pad"
|
||||
packages = ["."]
|
||||
revision = "b3d7806010228b1a954b4d9c4ee4cf6cb476b063"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "go4.org"
|
||||
packages = ["reflectutil"]
|
||||
revision = "e6a7f04a962e05f288f348eec6de20fe93b6b292"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"html",
|
||||
"html/atom"
|
||||
]
|
||||
revision = "6078986fec03a1dcc236c34816c71b0e05018fda"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "378d26f46672a356c46195c28f61bdb4c0a781dd"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "ff54fa52bac3cde3f10f5c237dad28da497594584e4291356b5efd040501fe4e"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
58
Gopkg.toml
Normal file
58
Gopkg.toml
Normal file
@ -0,0 +1,58 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/bradfitz/slice"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/dustin/go-humanize"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fatih/color"
|
||||
version = "1.6.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gizak/termui"
|
||||
version = "2.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jroimartin/gocui"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/miguelmota/go-coinmarketcap"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/willf/pad"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
@ -7,7 +7,7 @@
|
||||
Make sure to have [golang](https://golang.org/) installed, then do:
|
||||
|
||||
```bash
|
||||
go get -u github.com/miguelmota/cointop/cointop
|
||||
go get -u github.com/miguelmota/cointop
|
||||
```
|
||||
|
||||
## License
|
||||
|
500
cointop.go
Normal file
500
cointop.go
Normal file
@ -0,0 +1,500 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bradfitz/slice"
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gizak/termui"
|
||||
"github.com/jroimartin/gocui"
|
||||
"github.com/miguelmota/cointop/table"
|
||||
cmc "github.com/miguelmota/go-coinmarketcap"
|
||||
"github.com/willf/pad"
|
||||
)
|
||||
|
||||
var (
|
||||
white = color.New(color.FgWhite).SprintFunc()
|
||||
green = color.New(color.FgGreen).SprintFunc()
|
||||
red = color.New(color.FgRed).SprintFunc()
|
||||
cyan = color.New(color.FgCyan).SprintFunc()
|
||||
)
|
||||
|
||||
var (
|
||||
oneMinute int64 = 60
|
||||
oneHour = oneMinute * 60
|
||||
oneDay = oneHour * 24
|
||||
oneWeek = oneDay * 7
|
||||
oneMonth = oneDay * 30
|
||||
oneYear = oneDay * 365
|
||||
)
|
||||
|
||||
// Cointop cointop
|
||||
type Cointop struct {
|
||||
g *gocui.Gui
|
||||
chartview *gocui.View
|
||||
chartpoints [][]termui.Cell
|
||||
headersview *gocui.View
|
||||
tableview *gocui.View
|
||||
table *table.Table
|
||||
sortdesc bool
|
||||
currentsort string
|
||||
coins []*cmc.Coin
|
||||
}
|
||||
|
||||
func (ct *Cointop) chartPoints(maxX int, coin string) error {
|
||||
chart := termui.NewLineChart()
|
||||
chart.Height = 10
|
||||
chart.AxesColor = termui.ColorWhite
|
||||
chart.LineColor = termui.ColorCyan
|
||||
chart.Border = false
|
||||
|
||||
now := time.Now()
|
||||
secs := now.Unix()
|
||||
start := secs - oneDay
|
||||
end := secs
|
||||
|
||||
_ = coin
|
||||
//graphData, err := cmc.GetCoinGraphData(coin, start, end)
|
||||
graphData, err := cmc.GetGlobalMarketGraphData(start, end)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var data []float64
|
||||
/*
|
||||
for i := range graphData.PriceUSD {
|
||||
data = append(data, graphData.PriceUSD[i][1])
|
||||
}
|
||||
*/
|
||||
for i := range graphData.MarketCapByAvailableSupply {
|
||||
data = append(data, graphData.MarketCapByAvailableSupply[i][1])
|
||||
}
|
||||
chart.Data = data
|
||||
termui.Body = termui.NewGrid()
|
||||
termui.Body.Width = maxX
|
||||
termui.Body.AddRows(
|
||||
termui.NewRow(
|
||||
termui.NewCol(12, 0, chart),
|
||||
),
|
||||
)
|
||||
|
||||
var points [][]termui.Cell
|
||||
// calculate layout
|
||||
termui.Body.Align()
|
||||
w := termui.Body.Width
|
||||
h := 10
|
||||
row := termui.Body.Rows[0]
|
||||
b := row.Buffer()
|
||||
for i := 0; i < h; i = i + 1 {
|
||||
var rowpoints []termui.Cell
|
||||
for j := 0; j < w; j = j + 1 {
|
||||
p := b.At(j, i)
|
||||
rowpoints = append(rowpoints, p)
|
||||
}
|
||||
points = append(points, rowpoints)
|
||||
}
|
||||
|
||||
ct.chartpoints = points
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
g, err := gocui.NewGui(gocui.Output256)
|
||||
if err != nil {
|
||||
log.Fatalf("new gocui: %v", err)
|
||||
}
|
||||
defer g.Close()
|
||||
g.Cursor = true
|
||||
g.Mouse = true
|
||||
g.Highlight = true
|
||||
|
||||
ct := Cointop{
|
||||
g: g,
|
||||
}
|
||||
g.SetManagerFunc(ct.layout)
|
||||
|
||||
if err := ct.keybindings(g); err != nil {
|
||||
log.Fatalf("keybindings: %v", err)
|
||||
}
|
||||
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Fatalf("main loop: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ct *Cointop) quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
}
|
||||
|
||||
func (ct *Cointop) keybindings(g *gocui.Gui) error {
|
||||
if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, ct.cursorDown); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'j', gocui.ModNone, ct.cursorDown); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, ct.cursorUp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'k', gocui.ModNone, ct.cursorUp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, ct.pageDown); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlU, gocui.ModNone, ct.pageUp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'r', gocui.ModNone, ct.sort("rank", false)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'n', gocui.ModNone, ct.sort("name", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 's', gocui.ModNone, ct.sort("symbol", false)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'p', gocui.ModNone, ct.sort("price", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'm', gocui.ModNone, ct.sort("marketcap", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'v', gocui.ModNone, ct.sort("24hvolume", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '1', gocui.ModNone, ct.sort("1hchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '2', gocui.ModNone, ct.sort("24hchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '7', gocui.ModNone, ct.sort("7dchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 't', gocui.ModNone, ct.sort("totalsupply", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'a', gocui.ModNone, ct.sort("availablesupply", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'l', gocui.ModNone, ct.sort("lastupdated", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, ct.quit); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'q', gocui.ModNone, ct.quit); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyEsc, gocui.ModNone, ct.quit); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) sort(sortby string, desc bool) func(g *gocui.Gui, v *gocui.View) error {
|
||||
return func(g *gocui.Gui, v *gocui.View) error {
|
||||
if ct.currentsort == sortby {
|
||||
ct.sortdesc = !ct.sortdesc
|
||||
} else {
|
||||
ct.currentsort = sortby
|
||||
ct.sortdesc = desc
|
||||
}
|
||||
slice.Sort(ct.coins[:], func(i, j int) bool {
|
||||
if ct.sortdesc {
|
||||
i, j = j, i
|
||||
}
|
||||
a := ct.coins[i]
|
||||
b := ct.coins[j]
|
||||
switch sortby {
|
||||
case "rank":
|
||||
return a.Rank < b.Rank
|
||||
case "name":
|
||||
return a.Name < b.Name
|
||||
case "symbol":
|
||||
return a.Symbol < b.Symbol
|
||||
case "price":
|
||||
return a.PriceUSD < b.PriceUSD
|
||||
case "marketcap":
|
||||
return a.MarketCapUSD < b.MarketCapUSD
|
||||
case "24hvolume":
|
||||
return a.USD24HVolume < b.USD24HVolume
|
||||
case "1hchange":
|
||||
return a.PercentChange1H < b.PercentChange1H
|
||||
case "24hchange":
|
||||
return a.PercentChange24H < b.PercentChange24H
|
||||
case "7dchange":
|
||||
return a.PercentChange7D < b.PercentChange7D
|
||||
case "totalsupply":
|
||||
return a.TotalSupply < b.TotalSupply
|
||||
case "availablesupply":
|
||||
return a.AvailableSupply < b.AvailableSupply
|
||||
case "lastupdated":
|
||||
return a.LastUpdated < b.LastUpdated
|
||||
default:
|
||||
return a.Rank < b.Rank
|
||||
}
|
||||
})
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
ct.tableview.Clear()
|
||||
ct.setTable()
|
||||
return nil
|
||||
})
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
ct.chartview.Clear()
|
||||
maxX, _ := g.Size()
|
||||
_, cy := ct.chartview.Cursor()
|
||||
coin := "ethereum"
|
||||
ct.chartPoints(maxX, coin)
|
||||
ct.setChart()
|
||||
fmt.Fprint(v, cy)
|
||||
return nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (ct *Cointop) cursorDown(g *gocui.Gui, v *gocui.View) error {
|
||||
if ct.tableview == nil {
|
||||
return nil
|
||||
}
|
||||
_, y := ct.tableview.Origin()
|
||||
cx, cy := ct.tableview.Cursor()
|
||||
numRows := len(ct.coins) - 1
|
||||
//fmt.Fprint(v, cy)
|
||||
if (cy + y + 1) > numRows {
|
||||
return nil
|
||||
}
|
||||
if err := ct.tableview.SetCursor(cx, cy+1); err != nil {
|
||||
ox, oy := ct.tableview.Origin()
|
||||
if err := ct.tableview.SetOrigin(ox, oy+1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) cursorUp(g *gocui.Gui, v *gocui.View) error {
|
||||
if ct.tableview == nil {
|
||||
return nil
|
||||
}
|
||||
ox, oy := ct.tableview.Origin()
|
||||
cx, cy := ct.tableview.Cursor()
|
||||
//fmt.Fprint(v, oy)
|
||||
if err := ct.tableview.SetCursor(cx, cy-1); err != nil && oy > 0 {
|
||||
if err := ct.tableview.SetOrigin(ox, oy-1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) pageDown(g *gocui.Gui, v *gocui.View) error {
|
||||
if ct.tableview == nil {
|
||||
return nil
|
||||
}
|
||||
_, y := ct.tableview.Origin()
|
||||
cx, cy := ct.tableview.Cursor()
|
||||
numRows := len(ct.coins) - 1
|
||||
_, sy := ct.tableview.Size()
|
||||
rows := sy
|
||||
if (cy + y + rows) > numRows {
|
||||
// go to last row
|
||||
ct.tableview.SetCursor(cx, numRows)
|
||||
ox, _ := ct.tableview.Origin()
|
||||
ct.tableview.SetOrigin(ox, numRows)
|
||||
return nil
|
||||
}
|
||||
if err := ct.tableview.SetCursor(cx, cy+rows); err != nil {
|
||||
ox, oy := ct.tableview.Origin()
|
||||
if err := ct.tableview.SetOrigin(ox, oy+rows); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) pageUp(g *gocui.Gui, v *gocui.View) error {
|
||||
if ct.tableview == nil {
|
||||
return nil
|
||||
}
|
||||
ox, oy := v.Origin()
|
||||
cx, cy := v.Cursor()
|
||||
_, sy := v.Size()
|
||||
rows := sy
|
||||
//fmt.Fprint(v, oy)
|
||||
if err := v.SetCursor(cx, cy-rows); err != nil && oy > 0 {
|
||||
if err := v.SetOrigin(ox, oy-rows); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchData() ([]*cmc.Coin, error) {
|
||||
limit := 100
|
||||
result := []*cmc.Coin{}
|
||||
coins, err := cmc.GetAllCoinData(int(limit))
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
for i := range coins {
|
||||
coin := coins[i]
|
||||
result = append(result, &coin)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) layout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
|
||||
chartHeight := 10
|
||||
if v, err := g.SetView("chart", 0, 0, maxX, chartHeight); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
v.Frame = false
|
||||
ct.chartview = v
|
||||
ct.setChart()
|
||||
}
|
||||
|
||||
if v, err := g.SetView("header", 0, chartHeight, maxX, maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
t := table.New().SetWidth(maxX)
|
||||
|
||||
headers := []string{
|
||||
pad.Right("[r]ank", 13, " "),
|
||||
pad.Right("[n]ame", 13, " "),
|
||||
pad.Right("[s]ymbol", 8, " "),
|
||||
pad.Left("[p]rice", 10, " "),
|
||||
pad.Left("[m]arket cap", 17, " "),
|
||||
pad.Left("24H [v]olume", 15, " "),
|
||||
pad.Left("[1]H%", 9, " "),
|
||||
pad.Left("[2]4H%", 9, " "),
|
||||
pad.Left("[7]D%", 9, " "),
|
||||
pad.Left("[t]otal supply", 20, " "),
|
||||
pad.Left("[a]vailable supply", 19, " "),
|
||||
pad.Left("[l]ast updated", 17, " "),
|
||||
}
|
||||
for _, h := range headers {
|
||||
t.AddCol(h)
|
||||
}
|
||||
|
||||
t.Format().Fprint(v)
|
||||
v.Highlight = true
|
||||
v.SelBgColor = gocui.ColorGreen
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
v.Frame = false
|
||||
}
|
||||
|
||||
if v, err := g.SetView("table", 0, chartHeight+1, maxX, maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
v.Highlight = true
|
||||
v.SelBgColor = gocui.ColorCyan
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
v.Frame = false
|
||||
ct.tableview = v
|
||||
ct.setTable()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) setChart() error {
|
||||
maxX, _ := ct.g.Size()
|
||||
if len(ct.chartpoints) == 0 {
|
||||
ct.chartPoints(maxX, "bitcoin")
|
||||
}
|
||||
|
||||
for i := range ct.chartpoints {
|
||||
var s string
|
||||
for j := range ct.chartpoints[i] {
|
||||
p := ct.chartpoints[i][j]
|
||||
s = fmt.Sprintf("%s%c", s, p.Ch)
|
||||
}
|
||||
fmt.Fprintln(ct.chartview, s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct *Cointop) setTable() error {
|
||||
maxX, _ := ct.g.Size()
|
||||
ct.table = table.New().SetWidth(maxX)
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.AddCol("")
|
||||
ct.table.HideColumHeaders = true
|
||||
var err error
|
||||
if len(ct.coins) == 0 {
|
||||
ct.coins, err = fetchData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, coin := range ct.coins {
|
||||
unix, _ := strconv.ParseInt(coin.LastUpdated, 10, 64)
|
||||
lastUpdated := time.Unix(unix, 0).Format("15:04:05 Jan 02")
|
||||
colorprice := cyan
|
||||
color1h := white
|
||||
color24h := white
|
||||
color7d := white
|
||||
if coin.PercentChange1H > 0 {
|
||||
color1h = green
|
||||
}
|
||||
if coin.PercentChange1H < 0 {
|
||||
color1h = red
|
||||
}
|
||||
if coin.PercentChange24H > 0 {
|
||||
color24h = green
|
||||
}
|
||||
if coin.PercentChange24H < 0 {
|
||||
color24h = red
|
||||
}
|
||||
if coin.PercentChange7D > 0 {
|
||||
color7d = green
|
||||
}
|
||||
if coin.PercentChange7D < 0 {
|
||||
color7d = red
|
||||
}
|
||||
ct.table.AddRow(
|
||||
pad.Left(fmt.Sprint(coin.Rank), 4, " "),
|
||||
pad.Right(coin.Name, 22, " "),
|
||||
pad.Right(coin.Symbol, 6, " "),
|
||||
colorprice(pad.Left(humanize.Commaf(coin.PriceUSD), 12, " ")),
|
||||
pad.Left(humanize.Commaf(coin.MarketCapUSD), 17, " "),
|
||||
pad.Left(humanize.Commaf(coin.USD24HVolume), 15, " "),
|
||||
color1h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange1H), 9, " ")),
|
||||
color24h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange24H), 9, " ")),
|
||||
color7d(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange7D), 9, " ")),
|
||||
pad.Left(humanize.Commaf(coin.TotalSupply), 20, " "),
|
||||
pad.Left(humanize.Commaf(coin.AvailableSupply), 18, " "),
|
||||
pad.Left(fmt.Sprintf("%s", lastUpdated), 18, " "),
|
||||
// add %percent of cap
|
||||
)
|
||||
}
|
||||
|
||||
ct.table.Format().Fprint(ct.tableview)
|
||||
return nil
|
||||
}
|
@ -1,614 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bradfitz/slice"
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gizak/termui"
|
||||
"github.com/jroimartin/gocui"
|
||||
"github.com/miguelmota/cointop/table"
|
||||
cmc "github.com/miguelmota/go-coinmarketcap"
|
||||
"github.com/willf/pad"
|
||||
)
|
||||
|
||||
var white = color.New(color.FgWhite).SprintFunc()
|
||||
var cyan = color.New(color.FgCyan).SprintFunc()
|
||||
var red = color.New(color.FgRed).SprintFunc()
|
||||
var green = color.New(color.FgGreen).SprintFunc()
|
||||
|
||||
func fmtTime(v interface{}) string {
|
||||
t := v.(time.Time)
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
func ltTime(a interface{}, b interface{}) bool {
|
||||
return a.(time.Time).Before(b.(time.Time))
|
||||
}
|
||||
|
||||
func round(num float64) int {
|
||||
return int(num + math.Copysign(0.5, num))
|
||||
}
|
||||
|
||||
func toFixed(num float64, precision int) float64 {
|
||||
output := math.Pow(10, float64(precision))
|
||||
return float64(round(num*output)) / output
|
||||
}
|
||||
|
||||
func chartCells(maxX int, coin string) [][]termui.Cell {
|
||||
//_ = termui.Init()
|
||||
//defer termui.Close()
|
||||
|
||||
// quit on Ctrl-c
|
||||
/*
|
||||
termui.Handle("/sys/kbd/C-c", func(termui.Event) {
|
||||
termui.StopLoop()
|
||||
})
|
||||
*/
|
||||
chart := termui.NewLineChart()
|
||||
//chart.DataLabels = []string{""}
|
||||
chart.Height = 10
|
||||
chart.AxesColor = termui.ColorWhite
|
||||
chart.LineColor = termui.ColorCyan //| termui.AttrBold
|
||||
chart.Border = false
|
||||
|
||||
var (
|
||||
oneMinute int64 = 60
|
||||
oneHour = oneMinute * 60
|
||||
oneDay = oneHour * 24
|
||||
//oneWeek = oneDay * 7
|
||||
//oneMonth = oneDay * 30
|
||||
//oneYear = oneDay * 365
|
||||
)
|
||||
|
||||
now := time.Now()
|
||||
secs := now.Unix()
|
||||
start := secs - oneDay
|
||||
end := secs
|
||||
|
||||
_ = coin
|
||||
//graphData, err := cmc.GetCoinGraphData(coin, start, end)
|
||||
graphData, err := cmc.GetGlobalMarketGraphData(start, end)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var data []float64
|
||||
/*
|
||||
for i := range graphData.PriceUSD {
|
||||
data = append(data, graphData.PriceUSD[i][1])
|
||||
}
|
||||
*/
|
||||
for i := range graphData.MarketCapByAvailableSupply {
|
||||
data = append(data, graphData.MarketCapByAvailableSupply[i][1])
|
||||
}
|
||||
chart.Data = data
|
||||
//h := chart.InnerHeight()
|
||||
//w := chart.InnerWidth()
|
||||
|
||||
// add grid rows and columns
|
||||
termui.Body = termui.NewGrid()
|
||||
//termui.Body.Rows = termui.Body.Rows[:0]
|
||||
termui.Body.Width = maxX
|
||||
termui.Body.AddRows(
|
||||
termui.NewRow(
|
||||
termui.NewCol(12, 0, chart),
|
||||
),
|
||||
)
|
||||
|
||||
var points [][]termui.Cell
|
||||
|
||||
// calculate layout
|
||||
termui.Body.Align()
|
||||
// render to terminal
|
||||
//termui.Render(termui.Body)
|
||||
w := termui.Body.Width
|
||||
h := 10
|
||||
row := termui.Body.Rows[0]
|
||||
b := row.Buffer()
|
||||
for i := 0; i < h; i = i + 1 {
|
||||
var rowpoints []termui.Cell
|
||||
for j := 0; j < w; j = j + 1 {
|
||||
_ = b
|
||||
p := b.At(j, i)
|
||||
c := p
|
||||
rowpoints = append(rowpoints, c)
|
||||
}
|
||||
points = append(points, rowpoints)
|
||||
}
|
||||
//termui.Loop()
|
||||
|
||||
return points
|
||||
}
|
||||
|
||||
var points [][]termui.Cell
|
||||
|
||||
func main() {
|
||||
g, err := gocui.NewGui(gocui.Output256)
|
||||
if err != nil {
|
||||
log.Fatalf("new gocui: %v", err)
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
g.Cursor = true
|
||||
g.Mouse = true
|
||||
g.Highlight = true
|
||||
g.SetManagerFunc(layout)
|
||||
|
||||
if err := keybindings(g); err != nil {
|
||||
log.Fatalf("keybindings: %v", err)
|
||||
}
|
||||
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Fatalf("main loop: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
}
|
||||
|
||||
func keybindings(g *gocui.Gui) error {
|
||||
if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", 'j', gocui.ModNone, cursorDown); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", 'k', gocui.ModNone, cursorUp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, pageDown); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlU, gocui.ModNone, pageUp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", 'r', gocui.ModNone, sort("rank", false)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'n', gocui.ModNone, sort("name", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 's', gocui.ModNone, sort("symbol", false)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'p', gocui.ModNone, sort("price", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'm', gocui.ModNone, sort("marketcap", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'v', gocui.ModNone, sort("24hvolume", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '1', gocui.ModNone, sort("1hchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '2', gocui.ModNone, sort("24hchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", '7', gocui.ModNone, sort("7dchange", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 't', gocui.ModNone, sort("totalsupply", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'a', gocui.ModNone, sort("availablesupply", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'l', gocui.ModNone, sort("lastupdated", true)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", 'q', gocui.ModNone, quit); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyEsc, gocui.ModNone, quit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type strategy func(g *gocui.Gui, v *gocui.View) error
|
||||
|
||||
var sortDesc bool
|
||||
var currentsort string
|
||||
|
||||
func sort(sortBy string, desc bool) strategy {
|
||||
return func(g *gocui.Gui, v *gocui.View) error {
|
||||
|
||||
if currentsort == sortBy {
|
||||
sortDesc = !sortDesc
|
||||
} else {
|
||||
currentsort = sortBy
|
||||
sortDesc = desc
|
||||
}
|
||||
|
||||
slice.Sort(coins[:], func(i, j int) bool {
|
||||
if sortDesc == true {
|
||||
i, j = j, i
|
||||
}
|
||||
a := coins[i]
|
||||
b := coins[j]
|
||||
switch sortBy {
|
||||
case "rank":
|
||||
return a.Rank < b.Rank
|
||||
case "name":
|
||||
return a.Name < b.Name
|
||||
case "symbol":
|
||||
return a.Symbol < b.Symbol
|
||||
case "price":
|
||||
return a.PriceUSD < b.PriceUSD
|
||||
case "marketcap":
|
||||
return a.MarketCapUSD < b.MarketCapUSD
|
||||
case "24hvolume":
|
||||
return a.USD24HVolume < b.USD24HVolume
|
||||
case "1hchange":
|
||||
return a.PercentChange1H < b.PercentChange1H
|
||||
case "24hchange":
|
||||
return a.PercentChange24H < b.PercentChange24H
|
||||
case "7dchange":
|
||||
return a.PercentChange7D < b.PercentChange7D
|
||||
case "totalsupply":
|
||||
return a.TotalSupply < b.TotalSupply
|
||||
case "availablesupply":
|
||||
return a.AvailableSupply < b.AvailableSupply
|
||||
case "lastupdated":
|
||||
return a.LastUpdated < b.LastUpdated
|
||||
default:
|
||||
return a.Rank < b.Rank
|
||||
}
|
||||
})
|
||||
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
v, _ = g.View("table")
|
||||
v.Clear()
|
||||
setTable(g)
|
||||
return nil
|
||||
})
|
||||
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
v, _ = g.View("chart")
|
||||
v.Clear()
|
||||
|
||||
maxX, _ := g.Size()
|
||||
_, cy := v.Cursor()
|
||||
coin := "ethereum"
|
||||
points = chartCells(maxX, coin)
|
||||
setChart(g, v)
|
||||
fmt.Fprint(v, cy)
|
||||
return nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var coins []*cmc.Coin
|
||||
|
||||
func cursorDown(g *gocui.Gui, v *gocui.View) error {
|
||||
v, _ = g.View("table")
|
||||
if v != nil {
|
||||
_, y := v.Origin()
|
||||
cx, cy := v.Cursor()
|
||||
numRows := len(coins) - 1
|
||||
//fmt.Fprint(v, cy)
|
||||
if (cy + y + 1) > numRows {
|
||||
return nil
|
||||
}
|
||||
if err := v.SetCursor(cx, cy+1); err != nil {
|
||||
ox, oy := v.Origin()
|
||||
if err := v.SetOrigin(ox, oy+1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cursorUp(g *gocui.Gui, v *gocui.View) error {
|
||||
v, _ = g.View("table")
|
||||
if v != nil {
|
||||
ox, oy := v.Origin()
|
||||
cx, cy := v.Cursor()
|
||||
//fmt.Fprint(v, oy)
|
||||
if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
|
||||
if err := v.SetOrigin(ox, oy-1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pageDown(g *gocui.Gui, v *gocui.View) error {
|
||||
v, _ = g.View("table")
|
||||
if v != nil {
|
||||
_, y := v.Origin()
|
||||
cx, cy := v.Cursor()
|
||||
numRows := len(coins) - 1
|
||||
_, sy := v.Size()
|
||||
rows := sy
|
||||
if (cy + y + rows) > numRows {
|
||||
// go to last row
|
||||
v.SetCursor(cx, numRows)
|
||||
ox, _ := v.Origin()
|
||||
v.SetOrigin(ox, numRows)
|
||||
return nil
|
||||
}
|
||||
if err := v.SetCursor(cx, cy+rows); err != nil {
|
||||
ox, oy := v.Origin()
|
||||
if err := v.SetOrigin(ox, oy+rows); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pageUp(g *gocui.Gui, v *gocui.View) error {
|
||||
v, _ = g.View("table")
|
||||
if v != nil {
|
||||
ox, oy := v.Origin()
|
||||
cx, cy := v.Cursor()
|
||||
_, sy := v.Size()
|
||||
rows := sy
|
||||
//fmt.Fprint(v, oy)
|
||||
if err := v.SetCursor(cx, cy-rows); err != nil && oy > 0 {
|
||||
if err := v.SetOrigin(ox, oy-rows); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchData() ([]*cmc.Coin, error) {
|
||||
limit := 100
|
||||
result := []*cmc.Coin{}
|
||||
coins, err := cmc.GetAllCoinData(int(limit))
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
for i := range coins {
|
||||
coin := coins[i]
|
||||
result = append(result, &coin)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func layout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
|
||||
chartHeight := 10
|
||||
if v, err := g.SetView("chart", 0, 0, maxX, chartHeight); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
//v.Frame = false
|
||||
setChart(g, v)
|
||||
}
|
||||
|
||||
if v, err := g.SetView("header", 0, chartHeight, maxX, maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
t := table.New().SetWidth(maxX)
|
||||
|
||||
headers := []string{
|
||||
pad.Right("[r]ank", 13, " "),
|
||||
pad.Right("[n]ame", 13, " "),
|
||||
pad.Right("[s]ymbol", 8, " "),
|
||||
pad.Left("[p]rice", 10, " "),
|
||||
pad.Left("[m]arket cap", 17, " "),
|
||||
pad.Left("24H [v]olume", 15, " "),
|
||||
pad.Left("[1]H%", 9, " "),
|
||||
pad.Left("[2]4H%", 9, " "),
|
||||
pad.Left("[7]D%", 9, " "),
|
||||
pad.Left("[t]otal supply", 20, " "),
|
||||
pad.Left("[a]vailable supply", 19, " "),
|
||||
pad.Left("[l]ast updated", 17, " "),
|
||||
}
|
||||
for _, h := range headers {
|
||||
t.AddCol(h)
|
||||
}
|
||||
|
||||
t.Format().Fprint(v)
|
||||
v.Highlight = true
|
||||
v.SelBgColor = gocui.ColorGreen
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
v.Frame = false
|
||||
}
|
||||
|
||||
if v, err := g.SetView("table", 0, chartHeight+1, maxX, maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
_ = v
|
||||
_ = maxY
|
||||
setTable(g)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setChart(g *gocui.Gui, v *gocui.View) error {
|
||||
v.Frame = false
|
||||
/*
|
||||
tm.Clear()
|
||||
tm.MoveCursor(0, 0)
|
||||
chart := tm.NewLineChart(maxX/2, 9)
|
||||
//chart.Flags = tm.DRAW_INDEPENDENT
|
||||
chart.Flags = tm.DRAW_RELATIVE
|
||||
data := new(tm.DataTable)
|
||||
data.AddColumn("")
|
||||
data.AddColumn("")
|
||||
|
||||
var (
|
||||
oneMinute int64 = 60
|
||||
oneHour = oneMinute * 60
|
||||
oneDay = oneHour * 24
|
||||
//oneWeek = oneDay * 7
|
||||
oneMonth = oneDay * 30
|
||||
//oneYear = oneDay * 365
|
||||
)
|
||||
|
||||
now := time.Now()
|
||||
secs := now.Unix()
|
||||
//start := secs - oneDay
|
||||
start := secs - oneMonth
|
||||
end := secs
|
||||
|
||||
coin := "ethereum"
|
||||
graphData, err := cmc.GetCoinGraphData(coin, start, end)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var dt []float64
|
||||
for i := range graphData.PriceUSD {
|
||||
dt = append(dt, graphData.PriceUSD[i][1])
|
||||
}
|
||||
|
||||
for i, d := range dt {
|
||||
_ = d
|
||||
_ = i
|
||||
data.AddRow(float64(i), d)
|
||||
}
|
||||
_ = dt
|
||||
|
||||
out := chart.Draw(data, []int{0, 6})
|
||||
fmt.Fprint(v, out)
|
||||
//tm.Println(out)
|
||||
var buf bytes.Buffer
|
||||
tm.Output = bufio.NewWriter(&buf)
|
||||
//tm.Output = bufio.NewWriter(v)
|
||||
_ = buf
|
||||
tm.Flush()
|
||||
_ = v
|
||||
//buf.WriteTo(v)
|
||||
//buf.WriteTo(os.Stdout)
|
||||
*/
|
||||
|
||||
maxX, _ := g.Size()
|
||||
if len(points) == 0 {
|
||||
points = chartCells(maxX, "bitcoin")
|
||||
}
|
||||
|
||||
for i := range points {
|
||||
var s string
|
||||
for j := range points[i] {
|
||||
p := points[i][j]
|
||||
s = fmt.Sprintf("%s%c", s, p.Ch)
|
||||
}
|
||||
fmt.Fprintln(v, s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setTable(g *gocui.Gui) error {
|
||||
maxX, _ := g.Size()
|
||||
v, _ := g.View("table")
|
||||
t := table.New().SetWidth(maxX)
|
||||
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.AddCol("")
|
||||
t.HideColumHeaders = true
|
||||
|
||||
var err error
|
||||
if len(coins) == 0 {
|
||||
coins, err = fetchData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, coin := range coins {
|
||||
unix, _ := strconv.ParseInt(coin.LastUpdated, 10, 64)
|
||||
lastUpdated := time.Unix(unix, 0).Format("15:04:05 Jan 02")
|
||||
colorprice := cyan
|
||||
color1h := white
|
||||
color24h := white
|
||||
color7d := white
|
||||
if coin.PercentChange1H > 0 {
|
||||
color1h = green
|
||||
}
|
||||
if coin.PercentChange1H < 0 {
|
||||
color1h = red
|
||||
}
|
||||
if coin.PercentChange24H > 0 {
|
||||
color24h = green
|
||||
}
|
||||
if coin.PercentChange24H < 0 {
|
||||
color24h = red
|
||||
}
|
||||
if coin.PercentChange7D > 0 {
|
||||
color7d = green
|
||||
}
|
||||
if coin.PercentChange7D < 0 {
|
||||
color7d = red
|
||||
}
|
||||
_ = color7d
|
||||
t.AddRow(
|
||||
pad.Left(fmt.Sprint(coin.Rank), 4, " "),
|
||||
pad.Right(coin.Name, 22, " "),
|
||||
pad.Right(coin.Symbol, 6, " "),
|
||||
colorprice(pad.Left(humanize.Commaf(coin.PriceUSD), 12, " ")),
|
||||
pad.Left(humanize.Commaf(coin.MarketCapUSD), 17, " "),
|
||||
pad.Left(humanize.Commaf(coin.USD24HVolume), 15, " "),
|
||||
color1h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange1H), 9, " ")),
|
||||
color24h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange24H), 9, " ")),
|
||||
color7d(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange7D), 9, " ")),
|
||||
pad.Left(humanize.Commaf(coin.TotalSupply), 20, " "),
|
||||
pad.Left(humanize.Commaf(coin.AvailableSupply), 18, " "),
|
||||
pad.Left(fmt.Sprintf("%s", lastUpdated), 18, " "),
|
||||
// add %percent of cap
|
||||
)
|
||||
}
|
||||
|
||||
//t.SortAsc("Name").SortDesc("Age").Sort().Format().Fprint(v)
|
||||
t.Format().Fprint(v)
|
||||
//v.Editable = true
|
||||
//v.SetCursor(0, 2)
|
||||
v.Highlight = true
|
||||
v.SelBgColor = gocui.ColorCyan
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
v.Frame = false
|
||||
//v.Autoscroll = true
|
||||
|
||||
//buffer := ln.Buffer()
|
||||
//buffer.
|
||||
|
||||
// Sort by time
|
||||
// t.SortAscFn("Created", ltTime).Sort().Format().Fprint(v)
|
||||
return nil
|
||||
}
|
0
services/api/interface.go
Normal file
0
services/api/interface.go
Normal file
Loading…
Reference in New Issue
Block a user