currency-rate 1.5.3 → 2.0.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/Gemfile.lock +68 -0
  4. data/README.md +2 -2
  5. data/Rakefile +12 -3
  6. data/currency-rate.gemspec +1 -1
  7. data/lib/adapter.rb +56 -22
  8. data/lib/adapters/crypto/binance_adapter.rb +1 -1
  9. data/lib/adapters/crypto/bitfinex_adapter.rb +3 -2
  10. data/lib/adapters/crypto/bitpay_adapter.rb +1 -1
  11. data/lib/adapters/crypto/bitstamp_adapter.rb +1 -1
  12. data/lib/adapters/crypto/coin_market_cap_adapter.rb +2 -4
  13. data/lib/adapters/crypto/coinbase_adapter.rb +3 -3
  14. data/lib/adapters/crypto/exmo_adapter.rb +1 -1
  15. data/lib/adapters/crypto/hit_BTC_adapter.rb +64 -0
  16. data/lib/adapters/crypto/huobi_adapter.rb +17 -9
  17. data/lib/adapters/crypto/kraken_adapter.rb +5 -5
  18. data/lib/adapters/crypto/localbitcoins_adapter.rb +1 -1
  19. data/lib/adapters/crypto/okcoin_adapter.rb +4 -6
  20. data/lib/adapters/crypto/paxful_adapter.rb +18 -0
  21. data/lib/adapters/crypto/poloniex_adapter.rb +33 -0
  22. data/lib/adapters/crypto/yadio_adapter.rb +2 -1
  23. data/lib/adapters/fiat/bonbast_adapter.rb +3 -5
  24. data/lib/adapters/fiat/coinmonitor_adapter.rb +4 -5
  25. data/lib/adapters/fiat/currency_layer_adapter.rb +2 -3
  26. data/lib/adapters/fiat/fixer_adapter.rb +3 -4
  27. data/lib/adapters/fiat/forge_adapter.rb +15 -6
  28. data/lib/adapters/fiat/free_forex_adapter.rb +7 -3
  29. data/lib/container.rb +203 -0
  30. data/lib/currency_rate.rb +20 -63
  31. data/lib/currency_rate/version.rb +1 -1
  32. data/lib/exceptions.rb +9 -0
  33. data/lib/storage/file_storage.rb +15 -10
  34. data/lib/utils/string_extensions.rb +19 -0
  35. metadata +12 -14
  36. data/api_keys.yml.sample +0 -4
  37. data/bin/rake +0 -29
  38. data/bin/rspec +0 -29
  39. data/lib/adapters/crypto/btc_china_adapter.rb +0 -11
  40. data/lib/adapters/crypto/btc_e_adapter.rb +0 -18
  41. data/lib/adapters/fiat/yahoo_adapter.rb +0 -35
  42. data/lib/configuration.rb +0 -29
  43. data/lib/fetcher.rb +0 -78
  44. data/lib/synchronizer.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52b476d5c2345bf38f2e09f6e97e1aa7d6a31fa7ac599be78d3010d51d02bd4e
4
- data.tar.gz: 98ea03b4216397d3a15089d4811707b8dd45a61ad762e97306822139152a564f
3
+ metadata.gz: e33cf57e2389c7faea732bc6a2c1005d1373daa26622d77d07058a157cb408b4
4
+ data.tar.gz: ecdcdf02e7478deb612bebe5fed48c3d46d99916f9f25b4e0666bcf88ed4c1f9
5
5
  SHA512:
6
- metadata.gz: 9022611b0da6b1744aadbbce03134a39fbb8fbafe18eef681b1a544378b92408045af7aef0cc1f88baade2dafe02f9df9b5fc5c75b75f3375648664e882e8697
7
- data.tar.gz: c1db1e408e49c28cd88c44a1c5705daccaf26e79733c6cb6fac2c9baac2143a256814bfd825c56e3de7d07e63d332ef3bdb302ad11b876e12f8c61a09b24342b
6
+ metadata.gz: d6d71b129e93052a97d6e27749531c16818e19eeb1f7b44b6889d67683543094eea7c9cf59f7dc6dae01e1e6e0f570c0709c06d3c786b7c7d275f1b4e60c6e65
7
+ data.tar.gz: 21cd15e77e63eb8df45f4b52904b7c9ac3fb0e0a93838a3373c31165af5a7d115c6982b2e8cdf869898ed24dbe07008bcc817b9464ca0510717cf5a92e359844
data/.gitignore CHANGED
@@ -16,7 +16,5 @@ pkg
16
16
 
17
17
  .byebug_history
18
18
 
19
- Gemfile.lock
20
-
21
19
  # Private API keys for adapters
22
- api_keys.yml
20
+ spec/api_keys.yml
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ currency-rate (1.7.0)
5
+ http (>= 4.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.7.0)
11
+ public_suffix (>= 2.0.2, < 5.0)
12
+ byebug (11.0.1)
13
+ crack (0.4.3)
14
+ safe_yaml (~> 1.0.0)
15
+ diff-lcs (1.3)
16
+ domain_name (0.5.20190701)
17
+ unf (>= 0.0.5, < 1.0.0)
18
+ ffi (1.13.1)
19
+ ffi-compiler (1.0.1)
20
+ ffi (>= 1.0.0)
21
+ rake
22
+ hashdiff (1.0.0)
23
+ http (4.4.1)
24
+ addressable (~> 2.3)
25
+ http-cookie (~> 1.0)
26
+ http-form_data (~> 2.2)
27
+ http-parser (~> 1.2.0)
28
+ http-cookie (1.0.3)
29
+ domain_name (~> 0.5)
30
+ http-form_data (2.3.0)
31
+ http-parser (1.2.1)
32
+ ffi-compiler (>= 1.0, < 2.0)
33
+ public_suffix (4.0.1)
34
+ rake (10.5.0)
35
+ rspec (3.9.0)
36
+ rspec-core (~> 3.9.0)
37
+ rspec-expectations (~> 3.9.0)
38
+ rspec-mocks (~> 3.9.0)
39
+ rspec-core (3.9.0)
40
+ rspec-support (~> 3.9.0)
41
+ rspec-expectations (3.9.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.9.0)
44
+ rspec-mocks (3.9.0)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.9.0)
47
+ rspec-support (3.9.0)
48
+ safe_yaml (1.0.5)
49
+ unf (0.1.4)
50
+ unf_ext
51
+ unf_ext (0.0.7.7)
52
+ webmock (3.7.6)
53
+ addressable (>= 2.3.6)
54
+ crack (>= 0.3.2)
55
+ hashdiff (>= 0.4.0, < 2.0.0)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ byebug
62
+ currency-rate!
63
+ rake (~> 10.0)
64
+ rspec (~> 3.0)
65
+ webmock
66
+
67
+ BUNDLED WITH
68
+ 2.1.2
data/README.md CHANGED
@@ -20,8 +20,8 @@ CurrencyRate.configure do |config|
20
20
  # Empty array by default
21
21
  config.api_keys["ForgeAdapter"] = "forge_api_key"
22
22
 
23
- # CurrencyRate::FileStorage configuration has only 'path' attribute
24
- config.file_storage[:path] = "/home/user/data" # default: ""
23
+ # CurrencyRate::FileStorage is built-in storage provider and has only `path` parameter
24
+ config.storage << CurrencyRate::FileStorage(path: "/home/user/data")
25
25
 
26
26
  # CurrencyRate uses default Logger from Ruby core library
27
27
  # It can be replaced with any compatible object
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ RSpec::Core::RakeTask.new(:spec)
9
9
  task :default => :spec
10
10
 
11
11
  desc "Update rates for specified adapter"
12
- task :update_rates, [:exchange] do |t, args|
12
+ task :update_rates, [:exchange] do |_, args|
13
13
  api_keys = YAML.load_file("api_keys.yml")
14
14
 
15
15
  CurrencyRate.configure do |config|
@@ -20,15 +20,24 @@ task :update_rates, [:exchange] do |t, args|
20
20
 
21
21
  print "Loading data for #{args.exchange}... "
22
22
  exchange_data = adapter.exchange_data
23
- raw_storage = CurrencyRate::FileStorage.new(File.expand_path("spec/fixtures/adapters", __dir__))
23
+ raw_storage = CurrencyRate::FileStorage.new(path: File.expand_path("spec/fixtures/adapters", __dir__))
24
24
  raw_storage.write(args.exchange, exchange_data)
25
25
  puts "Success!"
26
26
 
27
27
  print "Normalizing data for #{args.exchange}..."
28
28
  normalized_data = adapter.normalize exchange_data
29
- normalized_storage = CurrencyRate::FileStorage.new(File.expand_path("spec/fixtures/adapters/normalized", __dir__))
29
+ normalized_storage = CurrencyRate::FileStorage.new(path: File.expand_path("spec/fixtures/adapters/normalized", __dir__))
30
30
  normalized_storage.write(args.exchange, normalized_data)
31
31
  puts "Success!"
32
32
 
33
33
  puts "#{args.exchange} fixtures update finished!"
34
34
  end
35
+
36
+ desc "Update rates for all defined adapters"
37
+ task :update_all_rates do |_, _|
38
+ CurrencyRate.constants.grep(/.Adapter$/).each do |name|
39
+ short_name = name.to_s.sub("Adapter", "")
40
+ Rake::Task[:update_rates].invoke(short_name)
41
+ Rake::Task[:update_rates].reenable
42
+ end
43
+ end
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ["lib"]
33
33
 
34
- spec.add_dependency "http", ">= 0"
34
+ spec.add_dependency "http", ">= 4.3"
35
35
 
36
36
  spec.add_development_dependency "byebug"
37
37
  spec.add_development_dependency "rake", "~> 10.0"
@@ -1,32 +1,44 @@
1
-
2
1
  module CurrencyRate
3
2
  class Adapter
4
3
  include Singleton
5
4
 
6
5
  SUPPORTED_CURRENCIES = []
7
6
  FETCH_URL = nil
8
- API_KEY_PARAM = nil
9
7
 
10
- def name
11
- self.class.name.gsub /^.*::/, ""
8
+ attr_reader :rates
9
+ attr_accessor :container
10
+ attr_accessor :api_key
11
+
12
+ def name(format=:snake_case)
13
+ @camel_case_name ||= self.class.name.gsub(/^.*::/, "").sub("Adapter", "")
14
+ @snake_case_name ||= @camel_case_name.to_snake_case
15
+ format == :camel_case ? @camel_case_name : @snake_case_name
16
+ end
17
+
18
+ def get_rate(from, to)
19
+ @rates = @container.storage.read(self.name) if @rates.nil? && @container.storage.exists?(self.name)
20
+ return BigDecimal(rates[to]) if ANCHOR_CURRENCY == from && rates[to]
21
+ return BigDecimal(1 / rates[from]) if ANCHOR_CURRENCY == to && rates[from]
22
+ return BigDecimal(rates[to] / rates[from]) if rates[from] && rates[to]
23
+ nil
12
24
  end
13
25
 
14
26
  def fetch_rates
15
27
  begin
16
- normalize exchange_data
28
+ @rates = normalize(exchange_data)
17
29
  rescue StandardError => e
18
- CurrencyRate.logger.error("Error in #{self.name}#fetch_rates")
19
- CurrencyRate.logger.error(e)
30
+ @container.log(:error, e)
20
31
  nil
21
32
  end
22
33
  end
23
34
 
24
35
  def normalize(data)
25
- if data.nil?
26
- CurrencyRate.logger.warn("#{self.name}#normalize: data is nil")
36
+ @rates = if data.nil?
37
+ @container.log(:warn, "#{self.name}#normalize: data is nil")
27
38
  return nil
39
+ else
40
+ parse_raw_data(data)
28
41
  end
29
- true
30
42
  end
31
43
 
32
44
  def exchange_data
@@ -38,28 +50,50 @@ module CurrencyRate
38
50
  result[name] = request url
39
51
  end
40
52
  else
41
- request self.class::FETCH_URL
53
+ result = request self.class::FETCH_URL
42
54
  end
43
55
  rescue StandardError => e
44
- CurrencyRate.logger.error("Error in #{self.name}#exchange_data")
45
- CurrencyRate.logger.error(e)
56
+ @container.log(:error, e)
46
57
  nil
47
58
  end
48
59
  end
49
60
 
50
- def request(url)
51
- fetch_url = url
52
- if self.class::API_KEY_PARAM
53
- api_key = CurrencyRate.configuration.api_keys[self.name]
61
+ def url_with_api_key(url)
62
+ if url.include?("__API_KEY__")
54
63
  if api_key.nil?
55
- CurrencyRate.logger.error("API key for #{self.name} not defined")
64
+ @container.log(:error, "API key for #{self.name} is not set")
56
65
  return nil
66
+ else
67
+ url.sub("__API_KEY__", api_key.strip)
68
+ end
69
+ else
70
+ url
71
+ end
72
+ end
73
+
74
+ def request(url)
75
+ unless url = url_with_api_key(url)
76
+ return nil
77
+ end
78
+ http_client = HTTP.timeout(connect: @container.connect_timeout, read: @container.read_timeout)
79
+ http_client
80
+ .headers("Accept" => "application/json; version=1")
81
+ .headers("Content-Type" => "text/plain")
82
+ .get(url)
83
+ .to_s
84
+ end
85
+
86
+ def parse_raw_data(data)
87
+ if data.kind_of?(Hash)
88
+ data.each { |k,v| data[k] = parse_raw_data(v) }
89
+ data
90
+ else
91
+ begin
92
+ return JSON.parse(data)
93
+ rescue JSON::ParserError
94
+ return data
57
95
  end
58
- param_symbol = fetch_url.split("/").last.include?("?") ? "&" : "?"
59
- fetch_url << "#{param_symbol}#{self.class::API_KEY_PARAM}=#{api_key}" if api_key
60
96
  end
61
- http_client = HTTP.timeout(connect: CurrencyRate.configuration.connect_timeout, read: CurrencyRate.configuration.read_timeout)
62
- JSON.parse(http_client.get(fetch_url).to_s)
63
97
  end
64
98
 
65
99
  end
@@ -20,7 +20,7 @@ module CurrencyRate
20
20
  }
21
21
 
22
22
  def normalize(data)
23
- return nil unless super
23
+ return nil unless data = super
24
24
  binance_result = data["Binance"].reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, hash|
25
25
  if hash["symbol"].index(ANCHOR_CURRENCY) == 0
26
26
  result[hash["symbol"].sub(ANCHOR_CURRENCY, "")] = BigDecimal(hash["price"].to_s)
@@ -6,13 +6,14 @@ module CurrencyRate
6
6
  DAD DAI DAT DGB DASH DTA DTH EDO ELF EOS ESS ETC ETH ETP EUR FSN FUN GBP
7
7
  GNT HOT IOS IOT IQX JPY KNC LRC LTC LYM MIT MKR MNA MTN NCA NEO ODE OMG
8
8
  OMNI ORS PAI POA POY QSH QTM RBT RCN RDN REP REQ RLC RRT SAN SEE SEN SNG
9
- SNT SPK STJ TNB TRX USD UTK VEE VET WAX WPR XLM XMR XRP XTZ XVG YYW ZCN
9
+ SNT SPK STJ TNB TRX USD USDT UTK VEE VET WAX WPR XLM XMR XRP XTZ XVG YYW ZCN
10
10
  ZEC ZIL ZRX
11
11
  )
12
12
 
13
13
  ASSET_MAP = {
14
14
  "DSH" => "DASH",
15
15
  "OMN" => "OMNI",
16
+ "UST" => "USDT",
16
17
  }
17
18
 
18
19
  ANCHOR_CURRENCY = "BTC"
@@ -20,7 +21,7 @@ module CurrencyRate
20
21
  FETCH_URL = "https://api.bitfinex.com/v2/tickers?symbols=ALL"
21
22
 
22
23
  def normalize(data)
23
- return nil unless super
24
+ return nil unless data = super
24
25
  data.reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, pair_info|
25
26
  pair_name = pair_info[0].sub("t", "")
26
27
  key = pair_name.sub(ANCHOR_CURRENCY, "")
@@ -18,7 +18,7 @@ module CurrencyRate
18
18
  FETCH_URL = "https://bitpay.com/api/rates"
19
19
 
20
20
  def normalize(data)
21
- return nil unless super
21
+ return nil unless data = super
22
22
  data.reject { |rate| rate["code"] == ANCHOR_CURRENCY }.reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, rate|
23
23
  result["#{rate['code'].upcase}"] = BigDecimal(rate["rate"].to_s)
24
24
  result
@@ -10,7 +10,7 @@ module CurrencyRate
10
10
  FETCH_URL["USD"] = "https://www.bitstamp.net/api/ticker/"
11
11
 
12
12
  def normalize(data)
13
- return nil unless super
13
+ return nil unless data = super
14
14
  data.reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, (key, value)|
15
15
  if key == "USD"
16
16
  result[key] = BigDecimal(value["last"].to_s)
@@ -12,12 +12,10 @@ module CurrencyRate
12
12
  )
13
13
 
14
14
  ANCHOR_CURRENCY = "BTC"
15
-
16
- FETCH_URL = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest"
17
- API_KEY_PARAM = "CMC_PRO_API_KEY"
15
+ FETCH_URL = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?CMC_PRO_API_KEY=__API_KEY__"
18
16
 
19
17
  def normalize(data)
20
- return nil unless super
18
+ return nil unless data = super
21
19
  data["data"].each_with_object({ "anchor" => ANCHOR_CURRENCY }) do |payload, result|
22
20
  if payload["symbol"] == ANCHOR_CURRENCY
23
21
  result["USD"] = BigDecimal(payload["quote"]["USD"]["price"].to_s)
@@ -18,9 +18,9 @@ module CurrencyRate
18
18
 
19
19
  FETCH_URL = "https://api.coinbase.com/v2/exchange-rates?currency=#{ANCHOR_CURRENCY}"
20
20
 
21
- def normalize(response)
22
- return nil unless super
23
- response["data"]["rates"].reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, (currency, rate)|
21
+ def normalize(data)
22
+ return nil unless data = super
23
+ data["data"]["rates"].reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, (currency, rate)|
24
24
  result[currency] = BigDecimal(rate.to_s)
25
25
  result
26
26
  end
@@ -12,7 +12,7 @@ module CurrencyRate
12
12
  FETCH_URL = "https://api.exmo.com/v1/ticker/"
13
13
 
14
14
  def normalize(data)
15
- return nil unless super
15
+ return nil unless data = super
16
16
  data.reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, (key, value)|
17
17
  if key.split("_")[0] == ANCHOR_CURRENCY
18
18
  result[key.sub("#{self.class::ANCHOR_CURRENCY}_", "")] = BigDecimal(value["avg"].to_s)
@@ -0,0 +1,64 @@
1
+ module CurrencyRate
2
+ class HitBTCAdapter < Adapter
3
+ SUPPORTED_CURRENCIES = %w(
4
+ ZRC EDG IHT AEON SOC HBAR ZRX OPT APPC DRGN PTOY
5
+ XDN OKB CHSB NCT GUSD GET FUN EXP EMRX REV GHOST
6
+ BMH SNC DTR ERD SCL HMQ ACT ETC QTUM MTX SBTC
7
+ KIND SMT BTB SWFTC 1ST UTT AXPR NMR EVX IOTA XPRM
8
+ STMX SALT DGB NTK AMM ALGO ORMEUS BDG BQX EKO FYP
9
+ IPX HOT MG BTS ADX CRPT WAXP POA PLBT SHIP HTML
10
+ BOX GNO UBT BTT ZEN VEO POA20 BCPT SRN XPR ETHBNT
11
+ MANA QKC MLN FLP SOLO TRUE VSYS JST GNT BOS PHB
12
+ ZEC ESH SWM NANO VIBE HVN SOLVE ELEC LRC AGI LNC
13
+ WAVES WTC ONT STRAT GNX NEU BCN XPNT ECA ARDR KIN
14
+ LSK USE IOTX CRO IDH LINK OAX CPT NGC XNS KEY TKY
15
+ HSR TNT SMART TRST DCR WINGS GT MKR ONE DOGE ARN
16
+ ACAT BMC RAISE EXM TIME REX FDZ HT MTH SCC BET
17
+ DENT IDRT IPL ZAP CMCT TDP XAUR MTL NEBL SUSDT BAT
18
+ STEEM CUR BYTZ PRO LOOM USD DRG DICE ADK COMP DRT
19
+ XTZ WETH EURS CHZ NEO NPLC XCON LEVL PAX AIM PART
20
+ PRE ERK HEDG FET PAXG DAG AVA CUTE NEXO DAY PITCH
21
+ MITX NXT POWR PLR CVCOIN TUSD MYST DLT REM RLC DNA
22
+ FOTA SBD ELF TEL C20 PNT CND UTK ASI CVC ETP ETH
23
+ ZIL ARPA INK NPXS LEO MESH NIM DATX FXT PBT GST
24
+ BSV GAS CBC MCO SENT GBX XRC POE SUR LOC WIKI PPT
25
+ CVT APM LEND NUT DOV KMD AYA LUN XEM RVN BCD XMR
26
+ NWC USG CLO NLC2 BBTC BERRY ART GRIN VITAE XBP OMG
27
+ MDA KRL BCH POLY PLA BANCA ENJ TRIGX UUU PASS ANT
28
+ LAMB BIZZ RFR AMB ROOBEE BST LCC RCN MIN BUSD DIT
29
+ PPC AE IQ BNK CENNZ SUB OCN DGD VRA STX AERGO HGT
30
+ TRAD IGNIS REP DAPP DNT CDT YCC SNGLS ICX PKT COV
31
+ PAY ABYSS BLZ DAV TKN ERT SPC SEELE XZC MAID AUTO
32
+ REN DATA AUC TV LAVA KAVA DAI DAPS ADA COCOS MITH
33
+ SETH NRG PHX DASH VLX CHAT VET EOSDT ZSC KNC DGTX
34
+ CEL SHORTUSD IOST BNB PBTT XMC EMC VIB BNT STORJ
35
+ ATOM LCX SC FTT BTM XLM TRX CELR BRD DBIX ETN SNT
36
+ MOF HEX XUC PLU FACE TNC SIG PXG BDP BTX TAU DCT
37
+ YOYOW SYBC SWT MAN GLEEC EOS XVG NAV CURE XRP KICK
38
+ BRDG LTC USDC MATIC FTX BTG PMA
39
+ ).freeze
40
+
41
+ ANCHOR_CURRENCY = "BTC".freeze
42
+
43
+ FETCH_URL = "https://api.hitbtc.com/api/2/public/ticker".freeze
44
+
45
+ def normalize(data)
46
+ return nil unless data = super
47
+
48
+ data.each_with_object({ "anchor" => ANCHOR_CURRENCY }) do |pair_info, result|
49
+ pair_name = pair_info["symbol"]
50
+ next unless pair_name.include?(ANCHOR_CURRENCY)
51
+ next unless pair_info["last"]
52
+
53
+ key = pair_name.sub(ANCHOR_CURRENCY, "")
54
+
55
+ result[key] =
56
+ if pair_name.index(ANCHOR_CURRENCY) == 0
57
+ BigDecimal(pair_info["last"])
58
+ else
59
+ 1 / BigDecimal(pair_info["last"])
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,17 +1,25 @@
1
1
  module CurrencyRate
2
2
  class HuobiAdapter < Adapter
3
- FETCH_URL = {
4
- "BTC_CNY" => "http://api.huobi.com/staticmarket/ticker_btc_json.js",
5
- "LTC_CNY" => "http://api.huobi.com/staticmarket/ticker_ltc_json.js"
6
- }
3
+ FETCH_URL = "https://api.huobi.pro/market/tickers".freeze
4
+
5
+ ANCHOR_CURRENCY = "BTC"
7
6
 
8
7
  def normalize(data)
9
- return nil unless super
10
- data.reduce({}) do |result, (pair, value)|
11
- result[pair] = BigDecimal(value["ticker"]["last"].to_s)
12
- result
8
+ return nil unless data = super
9
+
10
+ data["data"].each_with_object({ "anchor" => ANCHOR_CURRENCY }) do |pair_info, result|
11
+ pair_name = pair_info["symbol"].upcase
12
+ next unless pair_name.include?(ANCHOR_CURRENCY)
13
+
14
+ key = pair_name.sub(ANCHOR_CURRENCY, "")
15
+
16
+ result[key] =
17
+ if pair_name.index(ANCHOR_CURRENCY) == 0
18
+ BigDecimal(pair_info["close"].to_s)
19
+ else
20
+ 1 / BigDecimal(pair_info["close"].to_s)
21
+ end
13
22
  end
14
23
  end
15
-
16
24
  end
17
25
  end