currency-rate 0.4.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -4
  3. data/README.md +41 -53
  4. data/VERSION +1 -1
  5. data/currency-rate.gemspec +92 -78
  6. data/lib/adapter.rb +37 -83
  7. data/lib/adapters/crypto/bitfinex_adapter.rb +17 -0
  8. data/lib/adapters/crypto/bitpay_adapter.rb +14 -0
  9. data/lib/adapters/crypto/bitstamp_adapter.rb +19 -0
  10. data/lib/adapters/crypto/btc_china_adapter.rb +11 -0
  11. data/lib/adapters/crypto/btc_e_adapter.rb +18 -0
  12. data/lib/adapters/crypto/coinbase_adapter.rb +14 -0
  13. data/lib/adapters/crypto/huobi_adapter.rb +17 -0
  14. data/lib/adapters/crypto/kraken_adapter.rb +29 -0
  15. data/lib/adapters/crypto/localbitcoins_adapter.rb +14 -0
  16. data/lib/adapters/crypto/okcoin_adapter.rb +19 -0
  17. data/lib/adapters/fiat/fixer_adapter.rb +16 -0
  18. data/lib/adapters/fiat/forge_adapter.rb +23 -0
  19. data/lib/adapters/fiat/yahoo_adapter.rb +35 -0
  20. data/lib/configuration.rb +21 -0
  21. data/lib/currency_rate.rb +52 -48
  22. data/lib/fetcher.rb +71 -0
  23. data/lib/storage/file_storage.rb +29 -0
  24. data/lib/storage/serializers/yaml_serializer.rb +15 -0
  25. data/lib/synchronizer.rb +31 -0
  26. data/spec/fixtures/adapters/bitfinex_adapter.yml +18 -0
  27. data/spec/fixtures/adapters/bitpay_adapter.yml +486 -0
  28. data/spec/fixtures/adapters/bitstamp_adapter.yml +30 -0
  29. data/spec/fixtures/adapters/btc_china_adapter.yml +11 -0
  30. data/spec/fixtures/adapters/btce_adapter.yml +60 -0
  31. data/spec/fixtures/adapters/coinbase_adapter.yml +680 -0
  32. data/spec/fixtures/adapters/fixer_adapter.yml +34 -0
  33. data/spec/fixtures/adapters/forge_adapter.yml +75 -0
  34. data/spec/fixtures/adapters/huobi_adapter.yml +22 -0
  35. data/spec/fixtures/adapters/kraken_adapter.yml +124 -0
  36. data/spec/fixtures/adapters/localbitcoins_adapter.yml +381 -0
  37. data/spec/fixtures/adapters/normalized/bitfinex_adapter.yml +2 -0
  38. data/spec/fixtures/adapters/normalized/bitpay_adapter.yml +161 -0
  39. data/spec/fixtures/adapters/normalized/bitstamp_adapter.yml +3 -0
  40. data/spec/fixtures/adapters/normalized/btc_china_adapter.yml +1 -0
  41. data/spec/fixtures/adapters/normalized/btce_adapter.yml +5 -0
  42. data/spec/fixtures/adapters/normalized/coinbase_adapter.yml +680 -0
  43. data/spec/fixtures/adapters/normalized/fixer_adapter.yml +32 -0
  44. data/spec/fixtures/adapters/normalized/forge_adapter.yml +16 -0
  45. data/spec/fixtures/adapters/normalized/huobi_adapter.yml +2 -0
  46. data/spec/fixtures/adapters/normalized/kraken_adapter.yml +4 -0
  47. data/spec/fixtures/adapters/normalized/localbitcoins_adapter.yml +57 -0
  48. data/spec/fixtures/adapters/normalized/okcoin_adapter.yml +4 -0
  49. data/spec/fixtures/adapters/normalized/yahoo_adapter.yml +160 -0
  50. data/spec/fixtures/adapters/okcoin_adapter.yml +40 -0
  51. data/spec/fixtures/adapters/yahoo_adapter.yml +1119 -0
  52. data/spec/lib/adapter_spec.rb +54 -0
  53. data/spec/lib/adapters/crypto/bitfinex_adapter_spec.rb +13 -0
  54. data/spec/lib/adapters/crypto/bitpay_adapter_spec.rb +13 -0
  55. data/spec/lib/adapters/crypto/bitstamp_adapter_spec.rb +13 -0
  56. data/spec/lib/adapters/crypto/btc_china_adapter_spec.rb +13 -0
  57. data/spec/lib/adapters/crypto/btc_e_adapter_spec.rb +13 -0
  58. data/spec/lib/adapters/crypto/coinbase_adapter_spec.rb +13 -0
  59. data/spec/lib/adapters/crypto/huobi_adapter_spec.rb +13 -0
  60. data/spec/lib/adapters/crypto/kraken_adapter_spec.rb +13 -0
  61. data/spec/lib/adapters/crypto/localbitcoins_adapter_spec.rb +13 -0
  62. data/spec/lib/adapters/crypto/okcoin_adapter_spec.rb +13 -0
  63. data/spec/lib/adapters/fiat/fixer_adapter_spec.rb +13 -0
  64. data/spec/lib/adapters/fiat/forge_adapter_spec.rb +23 -0
  65. data/spec/lib/adapters/fiat/yahoo_adapter_spec.rb +13 -0
  66. data/spec/lib/currency_rate_spec.rb +9 -0
  67. data/spec/lib/fetcher_spec.rb +156 -0
  68. data/spec/lib/storage/file_storage_spec.rb +38 -0
  69. data/spec/lib/synchronizer_spec.rb +65 -0
  70. data/spec/spec_helper.rb +23 -8
  71. data/spec/support/matchers/eq_any_of.rb +3 -0
  72. metadata +67 -64
  73. data/Gemfile.lock +0 -93
  74. data/lib/core_ext/deep_get.rb +0 -11
  75. data/lib/crypto_adapter.rb +0 -19
  76. data/lib/crypto_adapters/average_rate_adapter.rb +0 -54
  77. data/lib/crypto_adapters/bitfinex_adapter.rb +0 -40
  78. data/lib/crypto_adapters/bitpay_adapter.rb +0 -33
  79. data/lib/crypto_adapters/bitstamp_adapter.rb +0 -44
  80. data/lib/crypto_adapters/btcchina_adapter.rb +0 -19
  81. data/lib/crypto_adapters/btce_adapter.rb +0 -44
  82. data/lib/crypto_adapters/coinbase_adapter.rb +0 -23
  83. data/lib/crypto_adapters/huobi_adapter.rb +0 -40
  84. data/lib/crypto_adapters/kraken_adapter.rb +0 -42
  85. data/lib/crypto_adapters/localbitcoins_adapter.rb +0 -30
  86. data/lib/crypto_adapters/okcoin_adapter.rb +0 -43
  87. data/lib/fiat_adapter.rb +0 -17
  88. data/lib/fiat_adapters/fixer_adapter.rb +0 -38
  89. data/lib/fiat_adapters/yahoo_adapter.rb +0 -51
  90. data/lib/storage.rb +0 -20
  91. data/spec/currency_rate_spec.rb +0 -52
  92. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/average_rate_adapter.yml +0 -567
  93. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/bitfinex_adapter.yml +0 -121
  94. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/bitpay_adapter.yml +0 -272
  95. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/btcchina_adapter.yml +0 -55
  96. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/btce_adapter.yml +0 -223
  97. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/coinbase_adapter.yml +0 -96
  98. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/huobi_adapter.yml +0 -83
  99. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/kraken_adapter.yml +0 -179
  100. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/localbitcoins_adapter.yml +0 -133
  101. data/spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/okcoin_adapter.yml +0 -223
  102. data/spec/fixtures/vcr/exchange_rate_adapters/fiat_adapters/fixer_adapter.yml +0 -85
  103. data/spec/fixtures/vcr/exchange_rate_adapters/fiat_adapters/yahoo_adapter.yml +0 -48
  104. data/spec/lib/crypto_adapter_spec.rb +0 -56
  105. data/spec/lib/crypto_adapters/average_rate_adapter_spec.rb +0 -46
  106. data/spec/lib/crypto_adapters/bitfinex_adapter_spec.rb +0 -38
  107. data/spec/lib/crypto_adapters/bitpay_adapter_spec.rb +0 -40
  108. data/spec/lib/crypto_adapters/bitstamp_adapter_spec.rb +0 -44
  109. data/spec/lib/crypto_adapters/btcchina_adapter_spec.rb +0 -36
  110. data/spec/lib/crypto_adapters/btce_adapter_spec.rb +0 -42
  111. data/spec/lib/crypto_adapters/coinbase_adapter_spec.rb +0 -39
  112. data/spec/lib/crypto_adapters/huobi_adapter_spec.rb +0 -38
  113. data/spec/lib/crypto_adapters/kraken_adapter_spec.rb +0 -38
  114. data/spec/lib/crypto_adapters/localbitcoins_adapter_spec.rb +0 -36
  115. data/spec/lib/crypto_adapters/okcoin_adapter_spec.rb +0 -43
  116. data/spec/lib/fiat_adapters/fixer_adapter_spec.rb +0 -25
  117. data/spec/lib/fiat_adapters/yahoo_adapter_spec.rb +0 -25
  118. data/spec/lib/storage_spec.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79218290bd3f6500ee88e69ccdc23821c6adb75c
4
- data.tar.gz: 456f45fce8cf8c35b4cb37eabeda9036b9059028
3
+ metadata.gz: a3676983c63a5f579c68cde5320507f1ae2865e8
4
+ data.tar.gz: da1012848a17db8f389d10201d26e66aed2ac93b
5
5
  SHA512:
6
- metadata.gz: e8f7ea0bd8b66fac3d31b891d75c3b5dcda6c1d772f9362ca2ea17092508f4be58986918e31ee0eca365b0480fc2e8df1e9b3b790c94f5921f167d94dca75f28
7
- data.tar.gz: fc34de9e4638d599bd8a5710fe5c6aa847591c9c15a8172cb15509afc31521364d81cc3a299445e806d8bc31d7d66725e13a26e3fed4e0e3e46714baf12cda79
6
+ metadata.gz: d5b015e4587fee54369ecaa39345485f2c9acdb81581fcd4f62655ec235472ef3158dd774c52a5f66b8dadcc2e49206e8c1036017c0421d6ac591aa7785448dd
7
+ data.tar.gz: 707067690373ce67e6cb2cd6697ac1271e7f615ff533bb73d25c196fcc987054258092524621a9773df62043408107f2b9c598da95da91352c32664b674a126f
data/Gemfile CHANGED
@@ -1,11 +1,10 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'satoshi-unit'
3
+ gem "http"
4
4
 
5
5
  group :development do
6
- gem "bundler", "~> 1.0"
7
6
  gem "jeweler", "~> 2.3.7", git: 'git@github.com:technicalpickles/jeweler.git'
8
7
  gem "rspec"
9
- gem 'webmock'
10
- gem 'vcr'
8
+ gem "webmock"
9
+ gem "byebug"
11
10
  end
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  currency-rate
2
2
  =============
3
3
 
4
- Converter for fiat and crypto currencies
4
+ Converter for fiat and crypto currencies. Currently supports BTC and LTC.
5
5
 
6
6
  Installation
7
7
  ------------
@@ -12,66 +12,54 @@ or in Gemfile
12
12
 
13
13
  gem "currency-rate"
14
14
 
15
- Usage
16
- -----
17
- Basically, all you'll need is to use the top level class to fetch any rates you want.
18
- For example:
19
-
20
- CurrencyRate.convert('Bitstamp', amount: 5, from: 'BTC', to: 'USD')
21
- CurrencyRate.convert('Bitstamp', amount: 2750, from: 'USD', to: 'BTC')
22
- CurrencyRate.convert('Bitstamp', amount: 1000, from: 'USD', to: 'EUR')
23
-
24
- In the third case, because Bitstamp doesn't really support direct conversion from
25
- USD to EUR, the 1000 will first be converted to BTC, then the BTC amount will be converted to EUR.
26
-
27
- This introduced the concept of anchor currency. For all Btc adapters in this lib, it's set to BTC
28
- by default. For all Fiat adapters it's set to USD by default. To specify anchor currency manually,
29
- simply pass it as another argument, for example:
30
-
31
- CurrencyRate.convert('Bitstamp', amount: 1000, from: 'USD', to: 'EUR', anchor_currency: 'BTC')
32
-
33
- You can also use `#get` method to get just the rate. It basically works as `#convert`, but only returns the rate and the method signature (attributes passed) is different - attributes are not named:
15
+ Configuration
16
+ -------------
17
+ ```ruby
18
+ CurrencyRate.configure do |config|
19
+ # Now only ForgeAdapter requires api key to fetch rates
20
+ # Empty array by default
21
+ config.api_keys["ForgeAdapter"] = "forge_api_key"
34
22
 
35
- CurrencyRate.get('Bitstamp', 'BTC', 'USD') # => 750
36
- CurrencyRate.get('Bitstamp', 'USD', 'BTC') # => 0.001818182
23
+ # CurrencyRate::FileStorage configuration has only 'path' attribute
24
+ config.file_storage[:path] = "/home/user/data" # default: ""
37
25
 
38
- In the second case, we are trying to get the exchange rate for USD/BTC pair, which literally means
39
- "how much in BTC would 1 USD be?". If the source (Bitstamp, in this case) doesn't provide the
40
- inverted rate, the Adapter inverts the rate itself using the exchange rate for BTC/USD.
26
+ # CurrencyRate uses default Logger from Ruby core library
27
+ # It can be replaced with any compatible object
28
+ # All logger values listed below are default
29
+ config.logger[:device] = $stdout
30
+ config.logger[:level] = :info
31
+ config.logger[:formatter] = nil
41
32
 
42
- You can also use `anchor_currency` argument with `#get`:
33
+ # Cryptocurrency exchange adapters to fetch
34
+ config.crypto_adapters = ["Kraken", "Localbitcoins"]
43
35
 
44
- CurrencyRate.get('Bitstamp', 'USD', 'EUR', anchor_currency: 'BTC')
36
+ # Fiat exchange adapters to fetch
37
+ config.fiat_adapters = ["Yahoo"]
38
+ end
39
+ ```
45
40
 
46
- For a list of available adapters, please see
47
- [lib/btc_adapters](https://github.com/snitko/currency-rate/tree/master/lib/btc_adapters)
48
- and [lib/fiat_adapters](https://github.com/snitko/currency-rate/tree/master/lib/fiat_adapters).
49
- To specify an adapter for `#convert` or `#get`, remove the last `Adapter` part from its name.
41
+ Usage
42
+ -----
50
43
 
51
- Caching and Storage
52
- -------------------
44
+ To fetch rates from exchanges into file storage (the only supported at this moment):
45
+ ```ruby
46
+ CurrencyRate.sync!
47
+ ```
48
+ This method will load all available data from exchanges and put into `yml` files. Failed exchanges will not create new / update exsisting files.
53
49
 
54
- By default, a simple in-memory caching mechanism with a timeout of 1800 seconds is set.
55
- To change the default timeout and also implement your very own caching mechanism you can
56
- try reloading `CurrencyRate::Storage` methods and writing your own functionality,
57
- storing data in Redis, for example.
50
+ To get rates for Crypto/Fiat currency pair use:
51
+ ```ruby
52
+ CurrencyRate.fetch_crypto("Bitstamp", "BTC", "USD")
53
+ ```
58
54
 
59
- While I agree it'd be nicer to have the timeout set somewhere in `CurrencyRate` class,
60
- for simplicity reasons I've avoided that. It also makes sense that the `Storage` class is responsible
61
- for how and when to store/fetch data, not other classes.
55
+ For fetching Fiat/Fiat pair:
56
+ ```ruby
57
+ CurrencyRate.fetch_fiat("CNY", "USD")
58
+ ```
62
59
 
63
- Credits
60
+ Details
64
61
  -------
65
- This gem was extracted from [straight gem](https://github.com/MyceliumGear/straight), thanks to all the people who added various exchange rate adapters and contributed code.
66
-
67
- TODO
68
- ----
69
-
70
- 1. Remove code duplication in Adapters, specifically for
71
- `#rate_for`, `#invert_rate` and `#currency_pair_rate` methods.
72
-
73
- 2. Allow both lower case and upper case currency codes.
74
-
75
- 3. Clean up tests, I have a feeling there some completely useless ones.
76
62
 
77
- 4. Adapters should have a default "to" currency. For example, everyone knows Bitfinex trades BTC for USD mostly.
63
+ `CurrencyRate` contains two parts that can work independently: Synchronizer and Fetcher.
64
+ `CurrencyRate::Synchronizer` loads data from selected exchanges using adapters and saves it into FileStorage in normalized format.
65
+ `CurrencyRate::Fetch` reads data from FileStorage and returns rate for requested pair and exchange.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 1.0.0
@@ -2,18 +2,18 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: currency-rate 0.3.8 ruby lib
5
+ # stub: currency-rate 1.0.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
- s.name = "currency-rate"
9
- s.version = "0.3.8"
8
+ s.name = "currency-rate".freeze
9
+ s.version = "1.0.0"
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["Roman Snitko"]
14
- s.date = "2017-08-24"
15
- s.description = "Fetches exchange rates from various sources and does the conversion"
16
- s.email = "roman.snitko@gmail.com"
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Roman Snitko".freeze]
14
+ s.date = "2017-10-30"
15
+ s.description = "Fetches exchange rates from various sources and does the conversion".freeze
16
+ s.email = "roman.snitko@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE.txt",
19
19
  "README.md"
@@ -22,91 +22,105 @@ Gem::Specification.new do |s|
22
22
  ".document",
23
23
  ".rspec",
24
24
  "Gemfile",
25
- "Gemfile.lock",
26
25
  "LICENSE.txt",
27
26
  "README.md",
28
27
  "Rakefile",
29
28
  "VERSION",
30
29
  "currency-rate.gemspec",
31
30
  "lib/adapter.rb",
32
- "lib/core_ext/deep_get.rb",
33
- "lib/crypto_adapter.rb",
34
- "lib/crypto_adapters/average_rate_adapter.rb",
35
- "lib/crypto_adapters/bitfinex_adapter.rb",
36
- "lib/crypto_adapters/bitpay_adapter.rb",
37
- "lib/crypto_adapters/bitstamp_adapter.rb",
38
- "lib/crypto_adapters/btcchina_adapter.rb",
39
- "lib/crypto_adapters/btce_adapter.rb",
40
- "lib/crypto_adapters/coinbase_adapter.rb",
41
- "lib/crypto_adapters/huobi_adapter.rb",
42
- "lib/crypto_adapters/kraken_adapter.rb",
43
- "lib/crypto_adapters/localbitcoins_adapter.rb",
44
- "lib/crypto_adapters/okcoin_adapter.rb",
31
+ "lib/adapters/crypto/bitfinex_adapter.rb",
32
+ "lib/adapters/crypto/bitpay_adapter.rb",
33
+ "lib/adapters/crypto/bitstamp_adapter.rb",
34
+ "lib/adapters/crypto/btc_china_adapter.rb",
35
+ "lib/adapters/crypto/btc_e_adapter.rb",
36
+ "lib/adapters/crypto/coinbase_adapter.rb",
37
+ "lib/adapters/crypto/huobi_adapter.rb",
38
+ "lib/adapters/crypto/kraken_adapter.rb",
39
+ "lib/adapters/crypto/localbitcoins_adapter.rb",
40
+ "lib/adapters/crypto/okcoin_adapter.rb",
41
+ "lib/adapters/fiat/fixer_adapter.rb",
42
+ "lib/adapters/fiat/forge_adapter.rb",
43
+ "lib/adapters/fiat/yahoo_adapter.rb",
44
+ "lib/configuration.rb",
45
45
  "lib/currency_rate.rb",
46
- "lib/fiat_adapter.rb",
47
- "lib/fiat_adapters/fixer_adapter.rb",
48
- "lib/fiat_adapters/yahoo_adapter.rb",
49
- "lib/storage.rb",
50
- "spec/currency_rate_spec.rb",
51
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/average_rate_adapter.yml",
52
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/bitfinex_adapter.yml",
53
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/bitpay_adapter.yml",
54
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/btcchina_adapter.yml",
55
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/btce_adapter.yml",
56
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/coinbase_adapter.yml",
57
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/huobi_adapter.yml",
58
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/kraken_adapter.yml",
59
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/localbitcoins_adapter.yml",
60
- "spec/fixtures/vcr/exchange_rate_adapters/btc_adapters/okcoin_adapter.yml",
61
- "spec/fixtures/vcr/exchange_rate_adapters/fiat_adapters/fixer_adapter.yml",
62
- "spec/fixtures/vcr/exchange_rate_adapters/fiat_adapters/yahoo_adapter.yml",
63
- "spec/lib/crypto_adapter_spec.rb",
64
- "spec/lib/crypto_adapters/average_rate_adapter_spec.rb",
65
- "spec/lib/crypto_adapters/bitfinex_adapter_spec.rb",
66
- "spec/lib/crypto_adapters/bitpay_adapter_spec.rb",
67
- "spec/lib/crypto_adapters/bitstamp_adapter_spec.rb",
68
- "spec/lib/crypto_adapters/btcchina_adapter_spec.rb",
69
- "spec/lib/crypto_adapters/btce_adapter_spec.rb",
70
- "spec/lib/crypto_adapters/coinbase_adapter_spec.rb",
71
- "spec/lib/crypto_adapters/huobi_adapter_spec.rb",
72
- "spec/lib/crypto_adapters/kraken_adapter_spec.rb",
73
- "spec/lib/crypto_adapters/localbitcoins_adapter_spec.rb",
74
- "spec/lib/crypto_adapters/okcoin_adapter_spec.rb",
75
- "spec/lib/fiat_adapters/fixer_adapter_spec.rb",
76
- "spec/lib/fiat_adapters/yahoo_adapter_spec.rb",
77
- "spec/lib/storage_spec.rb",
78
- "spec/spec_helper.rb"
46
+ "lib/fetcher.rb",
47
+ "lib/storage/file_storage.rb",
48
+ "lib/storage/serializers/yaml_serializer.rb",
49
+ "lib/synchronizer.rb",
50
+ "spec/fixtures/adapters/bitfinex_adapter.yml",
51
+ "spec/fixtures/adapters/bitpay_adapter.yml",
52
+ "spec/fixtures/adapters/bitstamp_adapter.yml",
53
+ "spec/fixtures/adapters/btc_china_adapter.yml",
54
+ "spec/fixtures/adapters/btce_adapter.yml",
55
+ "spec/fixtures/adapters/coinbase_adapter.yml",
56
+ "spec/fixtures/adapters/fixer_adapter.yml",
57
+ "spec/fixtures/adapters/forge_adapter.yml",
58
+ "spec/fixtures/adapters/huobi_adapter.yml",
59
+ "spec/fixtures/adapters/kraken_adapter.yml",
60
+ "spec/fixtures/adapters/localbitcoins_adapter.yml",
61
+ "spec/fixtures/adapters/normalized/bitfinex_adapter.yml",
62
+ "spec/fixtures/adapters/normalized/bitpay_adapter.yml",
63
+ "spec/fixtures/adapters/normalized/bitstamp_adapter.yml",
64
+ "spec/fixtures/adapters/normalized/btc_china_adapter.yml",
65
+ "spec/fixtures/adapters/normalized/btce_adapter.yml",
66
+ "spec/fixtures/adapters/normalized/coinbase_adapter.yml",
67
+ "spec/fixtures/adapters/normalized/fixer_adapter.yml",
68
+ "spec/fixtures/adapters/normalized/forge_adapter.yml",
69
+ "spec/fixtures/adapters/normalized/huobi_adapter.yml",
70
+ "spec/fixtures/adapters/normalized/kraken_adapter.yml",
71
+ "spec/fixtures/adapters/normalized/localbitcoins_adapter.yml",
72
+ "spec/fixtures/adapters/normalized/okcoin_adapter.yml",
73
+ "spec/fixtures/adapters/normalized/yahoo_adapter.yml",
74
+ "spec/fixtures/adapters/okcoin_adapter.yml",
75
+ "spec/fixtures/adapters/yahoo_adapter.yml",
76
+ "spec/lib/adapter_spec.rb",
77
+ "spec/lib/adapters/crypto/bitfinex_adapter_spec.rb",
78
+ "spec/lib/adapters/crypto/bitpay_adapter_spec.rb",
79
+ "spec/lib/adapters/crypto/bitstamp_adapter_spec.rb",
80
+ "spec/lib/adapters/crypto/btc_china_adapter_spec.rb",
81
+ "spec/lib/adapters/crypto/btc_e_adapter_spec.rb",
82
+ "spec/lib/adapters/crypto/coinbase_adapter_spec.rb",
83
+ "spec/lib/adapters/crypto/huobi_adapter_spec.rb",
84
+ "spec/lib/adapters/crypto/kraken_adapter_spec.rb",
85
+ "spec/lib/adapters/crypto/localbitcoins_adapter_spec.rb",
86
+ "spec/lib/adapters/crypto/okcoin_adapter_spec.rb",
87
+ "spec/lib/adapters/fiat/fixer_adapter_spec.rb",
88
+ "spec/lib/adapters/fiat/forge_adapter_spec.rb",
89
+ "spec/lib/adapters/fiat/yahoo_adapter_spec.rb",
90
+ "spec/lib/currency_rate_spec.rb",
91
+ "spec/lib/fetcher_spec.rb",
92
+ "spec/lib/storage/file_storage_spec.rb",
93
+ "spec/lib/synchronizer_spec.rb",
94
+ "spec/spec_helper.rb",
95
+ "spec/support/matchers/eq_any_of.rb"
79
96
  ]
80
- s.homepage = "http://github.com/snitko/currency-rate"
81
- s.licenses = ["MIT"]
82
- s.rubygems_version = "2.5.1"
83
- s.summary = "Converter for fiat and crypto currencies"
97
+ s.homepage = "http://github.com/snitko/currency-rate".freeze
98
+ s.licenses = ["MIT".freeze]
99
+ s.rubygems_version = "2.6.14".freeze
100
+ s.summary = "Converter for fiat and crypto currencies".freeze
84
101
 
85
102
  if s.respond_to? :specification_version then
86
103
  s.specification_version = 4
87
104
 
88
105
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
89
- s.add_runtime_dependency(%q<satoshi-unit>, [">= 0"])
90
- s.add_development_dependency(%q<bundler>, ["~> 1.0"])
91
- s.add_development_dependency(%q<jeweler>, ["~> 2.3.7"])
92
- s.add_development_dependency(%q<rspec>, [">= 0"])
93
- s.add_development_dependency(%q<webmock>, [">= 0"])
94
- s.add_development_dependency(%q<vcr>, [">= 0"])
106
+ s.add_runtime_dependency(%q<http>.freeze, [">= 0"])
107
+ s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.3.7"])
108
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
109
+ s.add_development_dependency(%q<webmock>.freeze, [">= 0"])
110
+ s.add_development_dependency(%q<byebug>.freeze, [">= 0"])
95
111
  else
96
- s.add_dependency(%q<satoshi-unit>, [">= 0"])
97
- s.add_dependency(%q<bundler>, ["~> 1.0"])
98
- s.add_dependency(%q<jeweler>, ["~> 2.3.7"])
99
- s.add_dependency(%q<rspec>, [">= 0"])
100
- s.add_dependency(%q<webmock>, [">= 0"])
101
- s.add_dependency(%q<vcr>, [">= 0"])
112
+ s.add_dependency(%q<http>.freeze, [">= 0"])
113
+ s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.7"])
114
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
115
+ s.add_dependency(%q<webmock>.freeze, [">= 0"])
116
+ s.add_dependency(%q<byebug>.freeze, [">= 0"])
102
117
  end
103
118
  else
104
- s.add_dependency(%q<satoshi-unit>, [">= 0"])
105
- s.add_dependency(%q<bundler>, ["~> 1.0"])
106
- s.add_dependency(%q<jeweler>, ["~> 2.3.7"])
107
- s.add_dependency(%q<rspec>, [">= 0"])
108
- s.add_dependency(%q<webmock>, [">= 0"])
109
- s.add_dependency(%q<vcr>, [">= 0"])
119
+ s.add_dependency(%q<http>.freeze, [">= 0"])
120
+ s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.7"])
121
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
122
+ s.add_dependency(%q<webmock>.freeze, [">= 0"])
123
+ s.add_dependency(%q<byebug>.freeze, [">= 0"])
110
124
  end
111
125
  end
112
126
 
data/lib/adapter.rb CHANGED
@@ -2,105 +2,59 @@ module CurrencyRate
2
2
  class Adapter
3
3
  include Singleton
4
4
 
5
- class FetchingFailed < StandardError; end
6
- class CurrencyNotSupported < StandardError; end
5
+ FETCH_URL = nil
6
+ API_KEY_PARAM = nil
7
7
 
8
- DECIMAL_PRECISION = nil
8
+ def name
9
+ self.class.name.gsub /^.*::/, ""
10
+ end
9
11
 
10
- attr_accessor :try_storage_on_fetching_failed
11
- attr_reader :storage
12
+ def fetch_rates
13
+ begin
14
+ normalize exchange_data
15
+ rescue StandardError => e
16
+ CurrencyRate.logger.error("Error in #{self.name}#fetch_rates")
17
+ CurrencyRate.logger.error(e)
18
+ nil
19
+ end
20
+ end
12
21
 
13
- def initialize
14
- @storage = Storage.new(adapter_name: self.class.to_s)
22
+ def normalize(data)
23
+ if data.nil?
24
+ CurrencyRate.logger.warn("#{self.name}#normalize: data is nil")
25
+ return nil
26
+ end
27
+ true
15
28
  end
16
29
 
17
- def fetch_rates!
30
+ def exchange_data
18
31
  raise "FETCH_URL is not defined!" unless self.class::FETCH_URL
32
+
19
33
  begin
20
34
  if self.class::FETCH_URL.kind_of?(Hash)
21
- @rates = {}
22
- self.class::FETCH_URL.each do |name, url|
23
- uri = URI.parse(url)
24
- @rates[name] = JSON.parse(uri.read(read_timeout: 4))
35
+ self.class::FETCH_URL.reduce({}) do |result, (name, url)|
36
+ result[name] = request url
37
+ result
25
38
  end
26
39
  else
27
- uri = URI.parse(self.class::FETCH_URL)
28
- @rates = JSON.parse(uri.read(read_timeout: 4))
40
+ request self.class::FETCH_URL
29
41
  end
30
- @rates_updated_at = Time.now
31
- @rates
32
- rescue Exception => e
33
- raise FetchingFailed
42
+ rescue StandardError => e
43
+ CurrencyRate.logger.error("Error in #{self.name}#exchange_data")
44
+ CurrencyRate.logger.error(e)
45
+ nil
34
46
  end
35
47
  end
36
48
 
37
- def rate_for(from,to)
38
- begin
39
- @rates = self.storage.fetch(self.class.to_s) { self.fetch_rates! }
40
- rescue FetchingFailed => e
41
- if @try_storage_on_fetching_failed
42
- @rates = self.storage.data[self.class.to_s][:content]
43
- else
44
- raise e
45
- end
46
- end
47
-
48
- unless supports_currency_pair?(from,to)
49
- raise CurrencyNotSupported, "Unsupported currencies (one or both) are: #{from} -> #{to}"
49
+ def request(url)
50
+ fetch_url = url
51
+ if self.class::API_KEY_PARAM
52
+ api_key = CurrencyRate.configuration.api_keys[self.name]
53
+ fetch_url << "&#{self.class::API_KEY_PARAM}=#{api_key}" if api_key
50
54
  end
51
-
52
- # This method is further reloaded in Adapter classes, that's why
53
- # here it doesn't really return anything useful!
54
-
55
+ http_client = HTTP.timeout(connect: 4, read: 4)
56
+ JSON.parse(http_client.get(fetch_url).to_s)
55
57
  end
56
58
 
57
- def supports_currency_pair?(c1,c2)
58
- supported_currency_pairs.include?("#{c1}/#{c2}".upcase) || supported_currency_pairs.include?("#{c2}/#{c1}".upcase)
59
- end
60
-
61
- # This method is supposed to be implemented for each individual adapter because the format of
62
- # the contents of the @rate variable is specific to each adapter. It would parse @rates and
63
- # extract currency pairs. Returns an array of supported currency pairs: ["USD/BTC", "EUR/BTC"]
64
- #
65
- # If you're implementing this method please note that you don't need to return a reversed pair
66
- # that is ["USD/BTC", "BTC/USD"] would be excessive and just ["USD/BTC"] would work,
67
- # because it is assumed that the adapter supports a reverse pair (see #rate_for implementation above).
68
- #
69
- # It would also be wise to use caching when implementing, that is:
70
- #
71
- # return @supported_currency_pairs if @supported_currency_pairs
72
- #
73
- # Which would make this method parse @rates only once.
74
- def supported_currency_pairs
75
- raise "Please implement #supported_currency_pairs in your Adapter"
76
- end
77
-
78
- def cache_supported_currency_pairs
79
- return @supported_currency_pairs if @supported_currency_pairs
80
- @supported_currency_pairs = []
81
- yield
82
- @supported_currency_pairs
83
- end
84
-
85
- # Must be implemented inside every descendant class
86
- # because storage format may be completely different
87
- def get_rate_value_from_source(rates_hash, *keys)
88
- raise "Please implement this method in your Adapter"
89
- end
90
-
91
- # We dont want to have false positive rate, because nil.to_f is 0.0
92
- # This method checks that rate value is not nil
93
- def rate_to_f(rate)
94
- rate ? rate.to_f : raise(CurrencyNotSupported)
95
- end
96
-
97
-
98
- private
99
-
100
- def _invert_rate(rate)
101
- r = (BigDecimal.new('1')/BigDecimal.new(rate.to_s))
102
- r = r.round(self.class::DECIMAL_PRECISION) if self.class::DECIMAL_PRECISION
103
- r
104
- end
105
59
  end
106
60
  end