Class: CoinQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/coinquery.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(autofind: true, dym: true, timeout: 5, filepath: '.', debug: false) ⇒ CoinQuery

Returns a new instance of CoinQuery.



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
# File 'lib/coinquery.rb', line 23

def initialize(autofind: true, dym: true, timeout: 5, filepath: '.', 
               debug: false)

  @autofind, @dym, @timeout, @debug = autofind, dym, timeout, debug
  @filepath = filepath

  @url_base = 'https://api.coingecko.com/api/v3/'
  r = ping()

  if r then

    puts ('CoinQuery').highlight + ' (powered by CoinGecko)'
    puts
    puts ('ping response: ' + r.to_a.first.join(' ')).info

    if autofind then

      file = 'coinquery.dat'

      if not File.exists? file then

        puts ('fetching coins list ...').info  
        @list = api_call 'coins/list'
      

        if @dym then

          puts 'loading did_you_mean ...'.info if @debug          

          @dym = DidYouMean::SpellChecker.new(dictionary: @list.flat_map \
                    {|x| [x['symbol'], x['name']]})
        end

      end


      if not File.exists? file then

        File.open(File.join(@filepath, file), 'w+') do |f|  
         Marshal.dump([@list, @dym], f)  
        end 

      else
      
        puts ('loading coins list ...').info  
        File.open(File.join(@filepath, file)) do |f|  
          @list, @dym = Marshal.load(f)  
        end
  
      end

    end
  end
  
  @table = RecordxSqlite.new(File.join(@filepath, 'coinquery.db'), 
    table: {coins: {id: '', cname: '', price: '', date: 0}})
  

end

Instance Attribute Details

#listObject (readonly)

Returns the value of attribute list.



21
22
23
# File 'lib/coinquery.rb', line 21

def list
  @list
end

Instance Method Details

#archive(limit: 250) ⇒ Object

archives the cryptocurrency prices in a local sqlite database note: intended for archiving prices on a daily basis



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/coinquery.rb', line 86

def archive(limit: 250)    
      
  puts 'archive: fetching coins ...'.info
  a = coins(limit: limit)
  
  puts 'archive: saving to database ...'.info

  a.each do |coin|
    
    uid = coin['id'] + Date.today.to_time.to_i.to_s
    @table.create id: uid.to_s, cname: coin['name'], 
        price: coin['current_price'].to_s, date: Date.today.to_time.to_i
    
  end
  
  puts 'archive: completed'.info
  
end

#coins(limit: 5) ⇒ Object

lists the top coins (limited to 5 by default)



107
108
109
110
# File 'lib/coinquery.rb', line 107

def coins(limit: 5)
  currency = 'usd'
  api_call "coins/markets?vs_currency=#{currency}&per_page=#{limit}"
end

#coins_listObject

lists the names and identifiers of all coins



114
115
116
# File 'lib/coinquery.rb', line 114

def coins_list
  @list
end

#find_coin(coin_name) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/coinquery.rb', line 118

def find_coin(coin_name)

  return coin_name unless @autofind

  s = coin_name.to_s.downcase
  puts 's: ' + s.inspect if @debug
  r = @list.find {|coin| coin['symbol'].downcase == s || coin['name'].downcase == s}
  puts 'r: ' + r.inspect if @debug
  
  if r.nil? then

    if @dym then

      suggestion = @dym.correct coin_name
      raise CoinQueryException, "unknown coin or token name. \n"  \
          + "Did you mean %s?" % [suggestion.first]

    else

      raise CoinQueryException, "unknown coin or token name."

    end

  end

  r

end

#find_id(name) ⇒ Object



147
148
149
150
# File 'lib/coinquery.rb', line 147

def find_id(name)
  r = find_coin(name)
  r['id']
end

#find_name(s) ⇒ Object



152
153
154
155
# File 'lib/coinquery.rb', line 152

def find_name(s)
  r = find_coin s
  r['name']
end

#historical_price(coin, rawdate) ⇒ Object Also known as: history

returns the price of a coin for a given historical date e.g. historical_price(‘Bitcoin’, ‘01-05-2021’)



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/coinquery.rb', line 160

def historical_price(coin, rawdate)

  uc = Unichron.new(rawdate.to_s, :little_endian)
  raise 'invalid date' unless uc.valid?
  date = uc.to_date.strftime("%d-%m-%Y")

  id = find_id coin
  r = api_call "coins/%s/history?date=%s" % [id, date]
  price = r['market_data']['current_price']['usd']
  price < 1 ? price : price.round(2)

end

#pingObject



175
176
177
# File 'lib/coinquery.rb', line 175

def ping
  api_call 'ping'
end

#price(coin) ⇒ Object

returns the price for a given a coin e.g. price(‘Litecoin’)



182
183
184
185
186
187
188
189
190
191
192
# File 'lib/coinquery.rb', line 182

def price(coin)

  currency = 'usd'
  id = find_id coin
  r = api_call("simple/price?ids=#{id}&vs_currencies=#{currency}")

  if r then
    val = r[id][currency]
    val < 1 ? val : val.round(2)
  end
end

#query_archive(coin_name, rawdate) ⇒ Object

use the database archive to query the historical price of a coin e.g. query_archive :btc, ‘1 May 2021’



197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/coinquery.rb', line 197

def query_archive(coin_name, rawdate)

  uc = Unichron.new(rawdate.to_s, :little_endian)
  raise 'invalid date' unless uc.valid?
  date = uc.to_date
  
  coin_id = find_id coin_name    
  
  id = coin_id + date.to_time.to_i.to_s
  r = @table.query "select * from coins where id == '#{id}'"
  r.first if r
  
end