lib/coinpare/commands/coins.rb
# frozen_string_literal: true
require "pastel"
require "tty-pager"
require "tty-spinner"
require "tty-table"
require "timers"
require_relative "../command"
require_relative "../fetcher"
module Coinpare
module Commands
class Coins < Coinpare::Command
def initialize(names, options)
@names = names
@options = options
@pastel = Pastel.new
@timers = Timers::Group.new
@spinner = TTY::Spinner.new(":spinner Fetching data...",
format: :dots, clear: true)
end
def execute(output: $stdout)
pager = TTY::Pager.new(output: output)
@spinner.auto_spin
if @options["watch"]
output.print cursor.hide
interval = @options["watch"].to_f > 0 ? @options["watch"].to_f : DEFAULT_INTERVAL
@timers.now_and_every(interval) { display_coins(output, pager) }
loop { @timers.wait }
else
display_coins(output, pager)
end
ensure
@spinner.stop
if @options["watch"]
@timers.cancel
output.print cursor.clear_screen_down
output.print cursor.show
end
end
private
def display_coins(output, pager)
if @names.empty? # no coins provided
@names = setup_top_coins
end
response = Fetcher.fetch_prices(@names.map(&:upcase).join(","),
@options["base"].upcase, @options)
return unless response
table = setup_table(response["RAW"], response["DISPLAY"])
@spinner.stop
lines = banner(@options).lines.size + 1 + table.rows_size + 3
clear_output(output, lines) { print_results(table, output, pager) }
end
def clear_output(output, lines)
output.print cursor.clear_screen_down if @options["watch"]
yield if block_given?
output.print cursor.up(lines) if @options["watch"]
end
def print_results(table, output, pager)
output.puts banner(@options)
lines = banner(@options).lines.size + 1 + (table.rows_size + 3)
rendered = table.render(:unicode, padding: [0, 1], alignment: :right)
if lines >= screen.height
pager.page rendered
else
output.print rendered
end
output.puts
end
def setup_top_coins
response = Fetcher.fetch_top_coins_by_volume(@options["base"].upcase,
@options)
return unless response
response["Data"].map { |coin| coin["CoinInfo"]["Name"] }[0...@options["top"]]
end
def setup_table(raw_data, display_data)
table = TTY::Table.new(header: [
{ value: "Coin", alignment: :left },
"Price",
"Chg. 24H",
"Chg.% 24H",
"Open 24H",
"High 24H",
"Low 24H",
"Direct Vol. 24H",
"Total Vol. 24H",
"Market Cap"
])
@names.each do |name|
coin_data = display_data[name.upcase][@options["base"].upcase]
coin_raw_data = raw_data[name.upcase][@options["base"].upcase]
change24h = coin_raw_data["CHANGE24HOUR"]
coin_details = [
{ value: add_color(name.upcase, :yellow), alignment: :left },
add_color(coin_data["PRICE"], pick_color(change24h)),
add_color("#{pick_arrow(change24h)} #{coin_data['CHANGE24HOUR']}",
pick_color(change24h)),
add_color("#{pick_arrow(change24h)} #{coin_data['CHANGEPCT24HOUR']}%",
pick_color(change24h)),
coin_data["OPEN24HOUR"],
coin_data["HIGH24HOUR"],
coin_data["LOW24HOUR"],
coin_data["VOLUME24HOURTO"],
coin_data["TOTALVOLUME24HTO"],
coin_data["MKTCAP"]
]
table << coin_details
end
table
end
end # Coins
end # Commands
end # Coinpare