currency-rate 0.4.1 → 1.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 (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