coinpare 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'toml'
4
- require 'pastel'
5
- require 'tty-config'
6
- require 'tty-prompt'
7
- require 'tty-spinner'
8
- require 'tty-table'
9
- require 'tty-pie'
10
- require 'timers'
11
-
12
- require_relative '../command'
13
- require_relative '../fetcher'
3
+ require "toml"
4
+ require "pastel"
5
+ require "tty-config"
6
+ require "tty-prompt"
7
+ require "tty-spinner"
8
+ require "tty-table"
9
+ require "tty-pie"
10
+ require "timers"
11
+
12
+ require_relative "../command"
13
+ require_relative "../fetcher"
14
14
 
15
15
  module Coinpare
16
16
  module Commands
@@ -23,16 +23,16 @@ module Coinpare
23
23
  @timers = Timers::Group.new
24
24
  @spinner = TTY::Spinner.new(":spinner Fetching data...",
25
25
  format: :dots, clear: true)
26
- @interval = @options.fetch('watch', DEFAULT_INTERVAL).to_f
27
- config.set('settings', 'color', value: !@options['no-color'])
26
+ @interval = @options.fetch("watch", DEFAULT_INTERVAL).to_f
27
+ config.set("settings", "color", value: !@options["no-color"])
28
28
  end
29
29
 
30
30
  def execute(input: $stdin, output: $stdout)
31
31
  config_saved = config.exist?
32
- if config_saved && @options['edit']
32
+ if config_saved && @options["edit"]
33
33
  editor.open(config.source_file)
34
34
  return
35
- elsif @options['edit']
35
+ elsif @options["edit"]
36
36
  output.puts "Sorry, no holdings configuration found."
37
37
  output.print "Run \""
38
38
  output.print "$ #{add_color('coinpare holdings', :yellow)}\" "
@@ -42,29 +42,29 @@ module Coinpare
42
42
 
43
43
  config.read if config_saved
44
44
 
45
- holdings = config.fetch('holdings')
45
+ holdings = config.fetch("holdings")
46
46
  if holdings.nil? || (holdings && holdings.empty?)
47
47
  info = setup_portfolio(input, output)
48
48
  config.merge(info)
49
- elsif @options['add']
49
+ elsif @options["add"]
50
50
  coin_info = add_coin(input, output)
51
- config.append(coin_info, to: ['holdings'])
52
- elsif @options['remove']
51
+ config.append(coin_info, to: ["holdings"])
52
+ elsif @options["remove"]
53
53
  coin_info = remove_coin(input, output)
54
- config.remove(*coin_info, from: ['holdings'])
55
- elsif @options['clear']
54
+ config.remove(*coin_info, from: ["holdings"])
55
+ elsif @options["clear"]
56
56
  prompt = create_prompt(input, output)
57
- answer = prompt.yes?('Do you want to remove all holdings?')
57
+ answer = prompt.yes?("Do you want to remove all holdings?")
58
58
  if answer
59
- config.delete('holdings')
59
+ config.delete("holdings")
60
60
  output.puts add_color("All holdings removed", :red)
61
61
  end
62
62
  end
63
63
 
64
- holdings = config.fetch('holdings')
64
+ holdings = config.fetch("holdings")
65
65
  no_holdings_left = holdings.nil? || (holdings && holdings.empty?)
66
66
  if no_holdings_left
67
- config.delete('holdings')
67
+ config.delete("holdings")
68
68
  end
69
69
 
70
70
  # Persist current configuration
@@ -77,15 +77,15 @@ module Coinpare
77
77
  end
78
78
 
79
79
  @spinner.auto_spin
80
- settings = config.fetch('settings')
80
+ settings = config.fetch("settings")
81
81
  # command options take precedence over config settings
82
82
  overridden_settings = {}
83
- overridden_settings['exchange'] = @options.fetch('exchange', settings.fetch('exchange'))
84
- overridden_settings['base'] = @options.fetch('base', settings.fetch('base'))
85
- holdings = config.fetch('holdings') { [] }
86
- names = holdings.map { |c| c['name'] }
83
+ overridden_settings["exchange"] = @options.fetch("exchange", settings.fetch("exchange"))
84
+ overridden_settings["base"] = @options.fetch("base", settings.fetch("base"))
85
+ holdings = config.fetch("holdings") { [] }
86
+ names = holdings.map { |c| c["name"] }
87
87
 
88
- if @options['watch']
88
+ if @options["watch"]
89
89
  output.print cursor.hide
90
90
  @timers.now_and_every(@interval) do
91
91
  display_coins(output, names, overridden_settings)
@@ -96,7 +96,7 @@ module Coinpare
96
96
  end
97
97
  ensure
98
98
  @spinner.stop
99
- if @options['watch']
99
+ if @options["watch"]
100
100
  @timers.cancel
101
101
  output.print cursor.clear_screen_down
102
102
  output.print cursor.show
@@ -104,14 +104,14 @@ module Coinpare
104
104
  end
105
105
 
106
106
  def display_coins(output, names, overridden_settings)
107
- response = Fetcher.fetch_prices(names.join(','),
108
- overridden_settings['base'].upcase,
107
+ response = Fetcher.fetch_prices(names.join(","),
108
+ overridden_settings["base"].upcase,
109
109
  overridden_settings)
110
110
  return unless response
111
- table = if @options['pie']
112
- setup_table_with_pies(response['RAW'], response['DISPLAY'])
111
+ table = if @options["pie"]
112
+ setup_table_with_pies(response["RAW"], response["DISPLAY"])
113
113
  else
114
- setup_table(response['RAW'], response['DISPLAY'])
114
+ setup_table(response["RAW"], response["DISPLAY"])
115
115
  end
116
116
 
117
117
  @spinner.stop
@@ -119,7 +119,7 @@ module Coinpare
119
119
  lines = banner(overridden_settings).lines.size + 1 + (table.rows_size + 3)
120
120
  clear_output(output, lines) do
121
121
  output.puts banner(overridden_settings)
122
- if @options['pie']
122
+ if @options["pie"]
123
123
  output.puts table.render(:unicode, padding: [0, 2])
124
124
  else
125
125
  output.puts table.render(:unicode, padding: [0, 1], alignment: :right)
@@ -128,9 +128,9 @@ module Coinpare
128
128
  end
129
129
 
130
130
  def clear_output(output, lines)
131
- output.print cursor.clear_screen_down if @options['watch']
131
+ output.print cursor.clear_screen_down if @options["watch"]
132
132
  yield if block_given?
133
- output.print cursor.up(lines) if @options['watch']
133
+ output.print cursor.up(lines) if @options["watch"]
134
134
  end
135
135
 
136
136
  def create_prompt(input, output)
@@ -138,32 +138,31 @@ module Coinpare
138
138
  prefix: "[#{add_color('c', :yellow)}] ",
139
139
  input: input, output: output,
140
140
  interrupt: -> { puts; exit 1 },
141
- enable_color: !@options['no-color'],
142
- clear: true
141
+ enable_color: !@options["no-color"]
143
142
  )
144
143
  prompt.on(:keypress) { |event|
145
- prompt.trigger(:keydown) if event.value == 'j'
146
- prompt.trigger(:keyup) if event.value == 'k'
144
+ prompt.trigger(:keydown) if event.value == "j"
145
+ prompt.trigger(:keyup) if event.value == "k"
147
146
  }
148
147
  prompt
149
148
  end
150
149
 
151
150
  def ask_coin
152
151
  -> (prompt) do
153
- key('name').ask('What coin do you own?') do |q|
154
- q.default 'BTC'
155
- q.required(true, 'You need to provide a coin')
156
- q.validate(/\w{2,}/, 'Currency can only be chars.')
152
+ key("name").ask("What coin do you own?") do |q|
153
+ q.default "BTC"
154
+ q.required(true, "You need to provide a coin")
155
+ q.validate(/\w{2,}/, "Currency can only be chars.")
157
156
  q.convert ->(coin) { coin.upcase }
158
157
  end
159
- key('amount').ask('What amount?') do |q|
160
- q.required(true, 'You need to provide an amount')
161
- q.validate(/[\d.]+/, 'Invalid amount provided')
158
+ key("amount").ask("What amount?") do |q|
159
+ q.required(true, "You need to provide an amount")
160
+ q.validate(/[\d.]+/, "Invalid amount provided")
162
161
  q.convert ->(am) { am.to_f }
163
162
  end
164
- key('price').ask('At what price per coin?') do |q|
165
- q.required(true, 'You need to provide a price')
166
- q.validate(/[\d.]+/, 'Invalid prince provided')
163
+ key("price").ask("At what price per coin?") do |q|
164
+ q.required(true, "You need to provide a price")
165
+ q.validate(/[\d.]+/, "Invalid prince provided")
167
166
  q.convert ->(p) { p.to_f }
168
167
  end
169
168
  end
@@ -180,8 +179,8 @@ module Coinpare
180
179
 
181
180
  def remove_coin(input, output)
182
181
  prompt = create_prompt(input, output)
183
- holdings = config.fetch('holdings')
184
- data = prompt.multi_select('Which hodlings to remove?') do |menu|
182
+ holdings = config.fetch("holdings")
183
+ data = prompt.multi_select("Which hodlings to remove?") do |menu|
185
184
  holdings.each do |holding|
186
185
  menu.choice "#{holding['name']} (#{holding['amount']})", holding
187
186
  end
@@ -198,26 +197,26 @@ module Coinpare
198
197
  prompt = create_prompt(input, output)
199
198
  context = self
200
199
  data = prompt.collect do
201
- key('settings') do
202
- key('base').ask('What base currency to convert holdings to?') do |q|
200
+ key("settings") do
201
+ key("base").ask("What base currency to convert holdings to?") do |q|
203
202
  q.default "USD"
204
203
  q.convert ->(b) { b.upcase }
205
- q.validate(/\w{3}/, 'Currency code needs to be 3 chars long')
204
+ q.validate(/\w{3}/, "Currency code needs to be 3 chars long")
206
205
  end
207
- key('exchange').ask('What exchange would you like to use?') do |q|
206
+ key("exchange").ask("What exchange would you like to use?") do |q|
208
207
  q.default "CCCAGG"
209
208
  q.required true
210
209
  end
211
210
  end
212
211
 
213
212
  while prompt.yes?("Do you want to add coin to your altfolio?")
214
- key('holdings').values(&context.ask_coin)
213
+ key("holdings").values(&context.ask_coin)
215
214
  end
216
215
  end
217
216
 
218
217
  lines = 4 + # intro
219
218
  2 + # base + exchange
220
- data['holdings'].size * 4 + 1
219
+ data["holdings"].size * 4 + 1
221
220
  output.print cursor.up(lines)
222
221
  output.print cursor.clear_screen_down
223
222
 
@@ -226,24 +225,24 @@ module Coinpare
226
225
 
227
226
  def create_pie_charts(raw_data, display_data)
228
227
  colors = %i[yellow blue green cyan magenta red]
229
- radius = @options['pie'].to_i > 0 ? @options['pie'].to_i : DEFAULT_PIE_RADIUS
230
- base = @options.fetch('base', config.fetch('settings', 'base')).upcase
228
+ radius = @options["pie"].to_i > 0 ? @options["pie"].to_i : DEFAULT_PIE_RADIUS
229
+ base = @options.fetch("base", config.fetch("settings", "base")).upcase
231
230
  to_symbol = nil
232
231
  past_data = []
233
232
  curr_data = []
234
233
 
235
- config.fetch('holdings').each do |coin|
236
- coin_data = raw_data[coin['name']][base]
237
- to_symbol = display_data[coin['name']][base]['TOSYMBOL']
238
- past_price = coin['amount'] * coin['price']
239
- curr_price = coin['amount'] * coin_data['PRICE']
234
+ config.fetch("holdings").each do |coin|
235
+ coin_data = raw_data[coin["name"]][base]
236
+ to_symbol = display_data[coin["name"]][base]["TOSYMBOL"]
237
+ past_price = coin["amount"] * coin["price"]
238
+ curr_price = coin["amount"] * coin_data["PRICE"]
240
239
 
241
- past_data << { name: coin['name'], value: past_price }
242
- curr_data << { name: coin['name'], value: curr_price }
240
+ past_data << { name: coin["name"], value: past_price }
241
+ curr_data << { name: coin["name"], value: curr_price }
243
242
  end
244
243
 
245
244
  options = {
246
- colors: !@options['no-color'] && colors,
245
+ colors: !@options["no-color"] && colors,
247
246
  radius: radius,
248
247
  legend: {
249
248
  left: 2,
@@ -253,8 +252,8 @@ module Coinpare
253
252
  }
254
253
 
255
254
  [
256
- TTY::Pie.new(options.merge(data: past_data)),
257
- TTY::Pie.new(options.merge(data: curr_data)),
255
+ TTY::Pie.new(**options.merge(data: past_data)),
256
+ TTY::Pie.new(**options.merge(data: curr_data)),
258
257
  to_symbol
259
258
  ]
260
259
  end
@@ -273,8 +272,8 @@ module Coinpare
273
272
 
274
273
  table = TTY::Table.new(
275
274
  header: [
276
- {value: header_past, alignment: :center},
277
- {value: header_curr, alignment: :center}
275
+ { value: header_past, alignment: :center },
276
+ { value: header_curr, alignment: :center }
278
277
  ]
279
278
  )
280
279
  past_pie.to_s.split("\n").zip(curr_pie.to_s.split("\n")).each do |past_part, curr_part|
@@ -284,36 +283,36 @@ module Coinpare
284
283
  end
285
284
 
286
285
  def setup_table(raw_data, display_data)
287
- base = @options.fetch('base', config.fetch('settings', 'base')).upcase
286
+ base = @options.fetch("base", config.fetch("settings", "base")).upcase
288
287
  total_buy = 0
289
288
  total = 0
290
289
  to_symbol = nil
291
290
 
292
291
  table = TTY::Table.new(header: [
293
- { value: 'Coin', alignment: :left },
294
- 'Amount',
295
- 'Price',
296
- 'Total Price',
297
- 'Cur. Price',
298
- 'Total Cur. Price',
299
- 'Change',
300
- 'Change%'
292
+ { value: "Coin", alignment: :left },
293
+ "Amount",
294
+ "Price",
295
+ "Total Price",
296
+ "Cur. Price",
297
+ "Total Cur. Price",
298
+ "Change",
299
+ "Change%"
301
300
  ])
302
301
 
303
- config.fetch('holdings').each do |coin|
304
- coin_data = raw_data[coin['name']][base]
305
- coin_display_data = display_data[coin['name']][base]
306
- past_price = coin['amount'] * coin['price']
307
- curr_price = coin['amount'] * coin_data['PRICE']
308
- to_symbol = coin_display_data['TOSYMBOL']
302
+ config.fetch("holdings").each do |coin|
303
+ coin_data = raw_data[coin["name"]][base]
304
+ coin_display_data = display_data[coin["name"]][base]
305
+ past_price = coin["amount"] * coin["price"]
306
+ curr_price = coin["amount"] * coin_data["PRICE"]
307
+ to_symbol = coin_display_data["TOSYMBOL"]
309
308
  change = curr_price - past_price
310
309
  arrow = pick_arrow(change)
311
310
  total_buy += past_price
312
311
  total += curr_price
313
312
 
314
313
  coin_details = [
315
- { value: add_color(coin['name'], :yellow), alignment: :left },
316
- coin['amount'],
314
+ { value: add_color(coin["name"], :yellow), alignment: :left },
315
+ coin["amount"],
317
316
  "#{to_symbol} #{number_to_currency(round_to(coin['price']))}",
318
317
  "#{to_symbol} #{number_to_currency(round_to(past_price))}",
319
318
  add_color("#{to_symbol} #{number_to_currency(round_to(coin_data['PRICE']))}", pick_color(change)),
@@ -328,8 +327,8 @@ module Coinpare
328
327
  arrow = pick_arrow(total_change)
329
328
 
330
329
  table << [
331
- { value: add_color('ALL', :cyan), alignment: :left }, '-', '-',
332
- "#{to_symbol} #{number_to_currency(round_to(total_buy))}", '-',
330
+ { value: add_color("ALL", :cyan), alignment: :left }, "-", "-",
331
+ "#{to_symbol} #{number_to_currency(round_to(total_buy))}", "-",
333
332
  add_color("#{to_symbol} #{number_to_currency(round_to(total))}", pick_color(total_change)),
334
333
  add_color("#{arrow} #{to_symbol} #{number_to_currency(round_to(total_change))}", pick_color(total_change)),
335
334
  add_color("#{arrow} #{round_to(percent_change(total_buy, total))}%", pick_color(total_change))
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pastel'
4
- require 'tty-pager'
5
- require 'tty-spinner'
6
- require 'tty-table'
7
- require 'timers'
3
+ require "pastel"
4
+ require "tty-pager"
5
+ require "tty-spinner"
6
+ require "tty-table"
7
+ require "timers"
8
8
 
9
- require_relative '../command'
10
- require_relative '../fetcher'
9
+ require_relative "../command"
10
+ require_relative "../fetcher"
11
11
 
12
12
  module Coinpare
13
13
  module Commands
@@ -17,7 +17,7 @@ module Coinpare
17
17
  @options = options
18
18
  @pastel = Pastel.new
19
19
  @timers = Timers::Group.new
20
- @spinner = TTY::Spinner.new(':spinner Fetching data...',
20
+ @spinner = TTY::Spinner.new(":spinner Fetching data...",
21
21
  format: :dots, clear: true)
22
22
  end
23
23
 
@@ -25,9 +25,9 @@ module Coinpare
25
25
  pager = TTY::Pager.new(output: output)
26
26
  @spinner.auto_spin
27
27
 
28
- if @options['watch']
28
+ if @options["watch"]
29
29
  output.print cursor.hide
30
- interval = @options['watch'].to_f > 0 ? @options['watch'].to_f : DEFAULT_INTERVAL
30
+ interval = @options["watch"].to_f > 0 ? @options["watch"].to_f : DEFAULT_INTERVAL
31
31
  @timers.now_and_every(interval) { display_markets(output, pager) }
32
32
  loop { @timers.wait }
33
33
  else
@@ -35,7 +35,7 @@ module Coinpare
35
35
  end
36
36
  ensure
37
37
  @spinner.stop
38
- if @options['watch']
38
+ if @options["watch"]
39
39
  @timers.cancel
40
40
  output.print cursor.clear_screen_down
41
41
  output.print cursor.show
@@ -45,7 +45,7 @@ module Coinpare
45
45
  def display_markets(output, pager)
46
46
  to_symbol = fetch_symbol
47
47
  response = Fetcher.fetch_top_exchanges_by_pair(
48
- @name.upcase, @options['base'].upcase, @options)
48
+ @name.upcase, @options["base"].upcase, @options)
49
49
  return unless response
50
50
  table = setup_table(response["Data"]["Exchanges"], to_symbol)
51
51
 
@@ -55,9 +55,9 @@ module Coinpare
55
55
  end
56
56
 
57
57
  def clear_output(output, lines)
58
- output.print cursor.clear_screen_down if @options['watch']
58
+ output.print cursor.clear_screen_down if @options["watch"]
59
59
  yield if block_given?
60
- output.print cursor.up(lines) if @options['watch']
60
+ output.print cursor.up(lines) if @options["watch"]
61
61
  end
62
62
 
63
63
  def print_results(table, output, pager)
@@ -73,10 +73,10 @@ module Coinpare
73
73
  end
74
74
 
75
75
  def fetch_symbol
76
- prices = Fetcher.fetch_prices(
77
- @name.upcase, @options['base'].upcase, @options)
76
+ prices = Fetcher.fetch_prices(@name.upcase, @options["base"].upcase, @options)
78
77
  return unless prices
79
- prices['DISPLAY'][@name.upcase][@options['base'].upcase]['TOSYMBOL']
78
+
79
+ prices["DISPLAY"][@name.upcase][@options["base"].upcase]["TOSYMBOL"]
80
80
  end
81
81
 
82
82
  def banner
@@ -87,20 +87,20 @@ module Coinpare
87
87
 
88
88
  def setup_table(data, to_symbol)
89
89
  table = TTY::Table.new(header: [
90
- { value: 'Market', alignment: :left },
91
- 'Price',
92
- 'Chg. 24H',
93
- 'Chg.% 24H',
94
- 'Open 24H',
95
- 'High 24H',
96
- 'Low 24H',
97
- 'Direct Vol. 24H',
90
+ { value: "Market", alignment: :left },
91
+ "Price",
92
+ "Chg. 24H",
93
+ "Chg.% 24H",
94
+ "Open 24H",
95
+ "High 24H",
96
+ "Low 24H",
97
+ "Direct Vol. 24H"
98
98
  ])
99
99
 
100
100
  data.each do |market|
101
- change24h = market['CHANGE24HOUR']
101
+ change24h = market["CHANGE24HOUR"]
102
102
  market_details = [
103
- { value: add_color(market['MARKET'], :yellow), alignment: :left },
103
+ { value: add_color(market["MARKET"], :yellow), alignment: :left },
104
104
  add_color("#{to_symbol} #{number_to_currency(round_to(market['PRICE']))}", pick_color(change24h)),
105
105
  add_color("#{pick_arrow(change24h)} #{to_symbol} #{number_to_currency(round_to(change24h))}", pick_color(change24h)),
106
106
  add_color("#{pick_arrow(change24h)} #{round_to(market['CHANGEPCT24HOUR'] * 100)}%", pick_color(change24h)),