1# frozen_string_literal: true
2
3require "em-http"
4require "money/bank/open_exchange_rates_bank"
5require "nokogiri"
6
7require_relative "em"
8
9class BTCSellPrices
10 def initialize(redis, oxr_app_id)
11 @redis = redis
12 @oxr = Money::Bank::OpenExchangeRatesBank.new(
13 Money::RatesStore::Memory.new
14 )
15 @oxr.app_id = oxr_app_id
16 end
17
18 def cad
19 fetch_canadianbitcoins.then do |http|
20 canadianbitcoins = Nokogiri::HTML.parse(http.response)
21
22 bitcoin_row = canadianbitcoins.at("#ticker > table > tbody > tr")
23 raise "Bitcoin row has moved" unless bitcoin_row.at("td").text == "Bitcoin"
24
25 BigDecimal.new(
26 bitcoin_row.at("td:nth-of-type(3)").text.match(/^\$(\d+\.\d+)/)[1]
27 )
28 end
29 end
30
31 def usd
32 EMPromise.all([cad, cad_to_usd]).then { |(a, b)| a * b }
33 end
34
35protected
36
37 def fetch_canadianbitcoins
38 EM::HttpRequest.new(
39 "https://www.canadianbitcoins.com",
40 tls: { verify_peer: true }
41 ).get
42 end
43
44 def cad_to_usd
45 @redis.get("cad_to_usd").then do |rate|
46 next rate.to_f if rate
47
48 EM.promise_defer {
49 # OXR gem is not async, so defer to threadpool
50 oxr.update_rates
51 oxr.get_rate("CAD", "USD")
52 }.then do |orate|
53 @redis.set("cad_to_usd", orate, ex: 60 * 60).then { orate }
54 end
55 end
56 end
57end