currency-rate 2.0.0 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. metadata +8 -119
  3. data/.document +0 -5
  4. data/.gitignore +0 -20
  5. data/.rspec +0 -1
  6. data/Gemfile +0 -6
  7. data/Gemfile.lock +0 -68
  8. data/LICENSE.txt +0 -20
  9. data/README.md +0 -73
  10. data/Rakefile +0 -43
  11. data/currency-rate.gemspec +0 -41
  12. data/lib/adapter.rb +0 -100
  13. data/lib/adapters/crypto/binance_adapter.rb +0 -42
  14. data/lib/adapters/crypto/bitfinex_adapter.rb +0 -41
  15. data/lib/adapters/crypto/bitpay_adapter.rb +0 -29
  16. data/lib/adapters/crypto/bitstamp_adapter.rb +0 -26
  17. data/lib/adapters/crypto/coin_market_cap_adapter.rb +0 -29
  18. data/lib/adapters/crypto/coinbase_adapter.rb +0 -30
  19. data/lib/adapters/crypto/exmo_adapter.rb +0 -27
  20. data/lib/adapters/crypto/hit_BTC_adapter.rb +0 -64
  21. data/lib/adapters/crypto/huobi_adapter.rb +0 -25
  22. data/lib/adapters/crypto/kraken_adapter.rb +0 -46
  23. data/lib/adapters/crypto/localbitcoins_adapter.rb +0 -25
  24. data/lib/adapters/crypto/okcoin_adapter.rb +0 -17
  25. data/lib/adapters/crypto/paxful_adapter.rb +0 -18
  26. data/lib/adapters/crypto/poloniex_adapter.rb +0 -33
  27. data/lib/adapters/crypto/yadio_adapter.rb +0 -19
  28. data/lib/adapters/fiat/bonbast_adapter.rb +0 -23
  29. data/lib/adapters/fiat/coinmonitor_adapter.rb +0 -13
  30. data/lib/adapters/fiat/currency_layer_adapter.rb +0 -31
  31. data/lib/adapters/fiat/fixer_adapter.rb +0 -17
  32. data/lib/adapters/fiat/forge_adapter.rb +0 -34
  33. data/lib/adapters/fiat/free_forex_adapter.rb +0 -36
  34. data/lib/container.rb +0 -203
  35. data/lib/currency_rate.rb +0 -41
  36. data/lib/currency_rate/version.rb +0 -3
  37. data/lib/exceptions.rb +0 -9
  38. data/lib/storage/file_storage.rb +0 -34
  39. data/lib/storage/serializers/yaml_serializer.rb +0 -15
  40. data/lib/utils/string_extensions.rb +0 -19
@@ -1,25 +0,0 @@
1
- module CurrencyRate
2
- class LocalbitcoinsAdapter < Adapter
3
- # No need to use it for fetching, just additional information about supported currencies
4
- SUPPORTED_CURRENCIES = %w(
5
- AED AOA ARS AUD BDT BRL BYN CAD CHF CLP CNY COP CRC CZK DKK DOP EGP ETH
6
- EUR GBP GEL GHS HKD HUF IDR ILS INR IRR JOD JPY KES KRW KWD KZT LKR LTC
7
- MAD MWK MXN MYR NGN NOK NZD OMR PAB PEN PHP PKR PLN QAR RON RSD RUB RWF
8
- SAR SEK SGD SZL THB TRY TWD TZS UAH UGX USD UYU VES VND XAF XMR XOF XRP
9
- ZAR ZMW
10
- )
11
-
12
- ANCHOR_CURRENCY = "BTC"
13
-
14
- FETCH_URL = 'https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/'
15
-
16
- def normalize(data)
17
- return nil unless data = super
18
- data.reduce({ "anchor" => ANCHOR_CURRENCY }) do |result, (fiat, value)|
19
- result["#{fiat.upcase}"] = BigDecimal(value["rates"]["last"].to_s)
20
- result
21
- end
22
- end
23
-
24
- end
25
- end
@@ -1,17 +0,0 @@
1
- module CurrencyRate
2
- class OkcoinAdapter < Adapter
3
- FETCH_URL = {
4
- 'LTC_USD' => 'https://www.okcoin.com/api/spot/v3/instruments/LTC-USD/ticker',
5
- 'BTC_USD' => 'https://www.okcoin.com/api/spot/v3/instruments/BTC-USD/ticker',
6
- }
7
-
8
- def normalize(data)
9
- return nil unless data = super
10
- data.reduce({}) do |result, (pair, value)|
11
- result[pair] = BigDecimal(value["last"].to_s)
12
- result
13
- end
14
- end
15
-
16
- end
17
- end
@@ -1,18 +0,0 @@
1
- module CurrencyRate
2
- class PaxfulAdapter < Adapter
3
- SUPPORTED_CURRENCIES = %w(USD)
4
-
5
- ANCHOR_CURRENCY = "BTC"
6
-
7
- FETCH_URL = "https://paxful.com/api/currency/btc"
8
-
9
- def normalize(data)
10
- return nil unless data = super
11
-
12
- {
13
- "anchor" => ANCHOR_CURRENCY,
14
- "USD" => BigDecimal(data["price"].to_s)
15
- }
16
- end
17
- end
18
- end
@@ -1,33 +0,0 @@
1
- module CurrencyRate
2
- class PoloniexAdapter < Adapter
3
- SUPPORTED_CURRENCIES = %w(BTS DASH DOGE LTC NXT STR XEM XMR XRP USDT
4
- ETH SC DCR LSK STEEM ETC REP ARDR ZEC STRAT
5
- GNT ZRX CVC OMG GAS STORJ EOS SNT KNC BAT
6
- LOOM QTUM USDC MANA BNT BCHABC BCHSV FOAM
7
- NMR POLY LPT ATOM TRX ETHBNT LINK XTZ PAX
8
- USDJ SNX MATIC MKR DAI NEO SWFTC FXC AVA
9
- CHR BNB BUSD MDT XFIL LEND REN LRC WRX SXP
10
- STPT SWAP EXE).freeze
11
-
12
- ANCHOR_CURRENCY = "BTC".freeze
13
-
14
- FETCH_URL = "https://poloniex.com/public?command=returnTicker".freeze
15
-
16
- def normalize(data)
17
- return nil unless data = super
18
-
19
- data.each_with_object({ "anchor" => ANCHOR_CURRENCY }) do |(pair_name, pair_info), result|
20
- next unless pair_name.include?(ANCHOR_CURRENCY)
21
-
22
- key = pair_name.sub(ANCHOR_CURRENCY, "").sub("_", "")
23
-
24
- result[key] =
25
- if pair_name.index(ANCHOR_CURRENCY) == 0
26
- 1 / BigDecimal(pair_info["last"])
27
- else
28
- BigDecimal(pair_info["last"])
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,19 +0,0 @@
1
- module CurrencyRate
2
- class YadioAdapter < Adapter
3
- SUPPORTED_CURRENCIES = %w(VES)
4
-
5
- ANCHOR_CURRENCY = "BTC"
6
-
7
- FETCH_URL = "https://api.yadio.io/rate/BTC"
8
-
9
- def normalize(data)
10
- return nil unless data = super
11
-
12
- {
13
- "anchor" => ANCHOR_CURRENCY,
14
- "USD" => BigDecimal(data["usd"].to_s),
15
- "VES" => BigDecimal(data["rate"].to_s),
16
- }
17
- end
18
- end
19
- end
@@ -1,23 +0,0 @@
1
- module CurrencyRate
2
- class BonbastAdapter < Adapter
3
- # No need to use it for fetching, just additional information about supported currencies
4
- SUPPORTED_CURRENCIES = %w(USD IRR)
5
- ANCHOR_CURRENCY = "USD"
6
- FETCH_URL = "https://www.bonbast.com/"
7
-
8
- def normalize(data)
9
- sell = data.match(/<td id="usd1"[^>]*>(\d+)<\/td>/)[1].to_f
10
- buy = data.match(/<td id="usd2"[^>]*>(\d+)<\/td>/)[1].to_f
11
- { "anchor" => self.class::ANCHOR_CURRENCY, "IRR" => BigDecimal(([buy, sell].reduce(:+).fdiv(2)*10).to_s) }
12
- end
13
-
14
- def request(url)
15
- http_client = HTTP.timeout(
16
- connect: @container.connect_timeout,
17
- read: @container.read_timeout
18
- )
19
- http_client.get(url).to_s
20
- end
21
-
22
- end
23
- end
@@ -1,13 +0,0 @@
1
- module CurrencyRate
2
- class CoinmonitorAdapter < Adapter
3
- # No need to use it for fetching, just additional information about supported currencies
4
- SUPPORTED_CURRENCIES = %w(ARS)
5
- ANCHOR_CURRENCY = "USD"
6
- FETCH_URL = "https://ar.coinmonitor.info/data_ar.json"
7
-
8
- def normalize(data)
9
- return nil unless data = super
10
- { "anchor" => ANCHOR_CURRENCY }.merge({ SUPPORTED_CURRENCIES.first => BigDecimal(data["BTC_avr_ars"].to_s) })
11
- end
12
- end
13
- end
@@ -1,31 +0,0 @@
1
- module CurrencyRate
2
- class CurrencyLayerAdapter < Adapter
3
- # No need to use it for fetching, just additional information about supported currencies
4
- SUPPORTED_CURRENCIES = %w(
5
- AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN
6
- BHD BIF BMD BND BOB BRL BSD BTC BTN BWP BYN BYR BZD CAD
7
- CDF CHF CLF CLP CNY COP CRC CUC CUP CVE CZK DJF DKK DOP
8
- DZD EGP ERN ETB EUR FJD FKP GBP GEL GGP GHS GIP GMD GNF
9
- GTQ GYD HKD HNL HRK HTG HUF IDR ILS IMP INR IQD IRR ISK
10
- JEP JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK
11
- LBP LKR LRD LSL LTL LVL LYD MAD MDL MGA MKD MMK MNT MOP
12
- MRO MUR MVR MWK MXN MYR MZN NAD NGN NIO NOK NPR NZD OMR
13
- PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD
14
- SCR SDG SEK SGD SHP SLL SOS SRD STD SVC SYP SZL THB TJS
15
- TMT TND TOP TRY TTD TWD TZS UAH UGX USD UYU UZS VEF VND
16
- VUV WST XAF XAG XAU XCD XDR XOF XPF YER ZAR ZMK ZMW ZWL
17
- )
18
-
19
- ANCHOR_CURRENCY = "USD"
20
- FETCH_URL = "http://apilayer.net/api/live?access_key=__API_KEY__"
21
-
22
- def normalize(data)
23
- return nil unless data = super
24
- rates = { "anchor" => self.class::ANCHOR_CURRENCY }
25
- data["quotes"].each do |key, value|
26
- rates[key.sub(self.class::ANCHOR_CURRENCY, "")] = BigDecimal(value.to_s)
27
- end
28
- rates
29
- end
30
- end
31
- end
@@ -1,17 +0,0 @@
1
- module CurrencyRate
2
- class FixerAdapter < Adapter
3
- # EUR is the only currency available as a base on free plan
4
- ANCHOR_CURRENCY = "EUR"
5
- FETCH_URL = "http://data.fixer.io/api/latest?access_key=__API_KEY__&base=#{ANCHOR_CURRENCY}"
6
-
7
- def normalize(data)
8
- return nil unless data = super
9
- rates = { "anchor" => ANCHOR_CURRENCY }
10
- data["rates"].each do |k,v|
11
- rates[k] = BigDecimal(v.to_s)
12
- end
13
- rates
14
- end
15
-
16
- end
17
- end
@@ -1,34 +0,0 @@
1
- module CurrencyRate
2
- class ForgeAdapter < Adapter
3
- SUPPORTED_CURRENCIES = %w(
4
- AED AFN ALL AMD ANG AOA ARE ARS AUD AUN AWG BAM BBD BDT BGN BHD BIF BMD
5
- BND BOB BRI BRL BSD BTN BWP BYN BZD CAD CDF CHF CLF CLP CLY CNH CNY COP
6
- CRC CUP CVE CYP CZK DJF DKK DOE DOP DZD EGP ETB EUR FJD FRN GBP GEL GHS
7
- GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY
8
- KES KHR KMF KRU KRW KWD KYD KZT LAK LBP LFX LKR LRD LSL LTL LYD M5P MAD
9
- MAL MDL MGA MKD MMK MOP MRU MTL MUR MVR MWK MXN MYR MZN NAD NBL NGN NIO
10
- NOK NPR NSO NZD OMR OSO PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF
11
- SAR SBD SCR SDG SEK SGD SHP SLL SOS SRD STN SVC SZL THB TJS TMT TND TOP
12
- TRY TTD TWD TZS UAH UGX USD UYU UZS VES VND VRL VRN XAG XAGK XAU XAUK XCD
13
- XDR XOF XPD XPDK XPF XPT XPTK YER ZAR ZMW ZWD
14
- )
15
-
16
- ANCHOR_CURRENCY = "USD"
17
- currency_pairs_request = SUPPORTED_CURRENCIES.map { |c| "#{ANCHOR_CURRENCY}/#{c}" }.join(",")
18
- FETCH_URL = "https://api.1forge.com/quotes?pairs=#{currency_pairs_request}&api_key=__API_KEY__"
19
-
20
- def normalize(data)
21
- return nil unless data = super
22
- rates = { "anchor" => self.class::ANCHOR_CURRENCY }
23
- data.each do |rate|
24
- if rate["error"]
25
- @container.logger.error("Forge exchange returned error")
26
- return nil
27
- end
28
- rates[rate["s"].sub("#{self.class::ANCHOR_CURRENCY}/", "")] = BigDecimal(rate["p"].to_s) if rate["p"]
29
- end
30
- rates
31
- end
32
-
33
- end
34
- end
@@ -1,36 +0,0 @@
1
- module CurrencyRate
2
-
3
- # Beware, freeforexapi.com doesn't normally work and you need to place
4
- # a small banner on your website so they'd list your websites IP address.
5
- # More info here: http://freeforexapi.com/Home/Api
6
- class FreeForexAdapter < Adapter
7
- SUPPORTED_CURRENCIES = %w(
8
- AED AFN ALL AMD ANG AOA ARS ATS AUD AWG AZM AZN BAM BBD BDT
9
- BEF BGN BHD BIF BMD BND BOB BRL BSD BTN BWP BYN BYR BZD CAD
10
- CDF CLP CNH CNY COP CRC CUC CUP CVE CYP CZK DEM DJF DKK DOP
11
- DZD EEK EGP ERN ESP ETB EUR FIM FJD FKP FRF GBP GEL GGP GHC
12
- GHS GIP GMD GNF GRD GTQ GYD HKD HNL HRK HTG HUF IDR IEP ILS
13
- IMP INR IQD IRR ISK ITL JEP JMD JOD KES KGS KHR KMF KPW KRW
14
- KWD KYD KZT LAK LBP LKR LRD LSL LTL LUF LVL LYD MAD MDL MGA
15
- MGF MKD MMK MNT MOP MRO MRU MTL MUR MVR MWK MXN MYR MZM MZN
16
- NAD NGN NIO NLG NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PTE
17
- PYG QAR ROL RON RSD RUB RWF SAR SBD SCR SDD SDG SEK SGD SHP
18
- SIT SKK SLL SOS SPL SRD SRG STD STN SVC SYP SZL THB TJS TMM
19
- TMT TND TOP TRL TRY TTD TVD TWD TZS UAH UGX UYU UZS VAL VEB
20
- VEF VES VND VUV WST XAF XAG XAU XBT XCD XDR XOF XPD XPF XPT
21
- YER ZAR ZMK ZMW ZWD
22
- )
23
-
24
- ANCHOR_CURRENCY = "USD"
25
- FETCH_URL = "https://www.freeforexapi.com/api/live?pairs=" + SUPPORTED_CURRENCIES.map { |c| "USD#{c}"}.join(",")
26
-
27
- def normalize(data)
28
- return nil unless data = super
29
- rates = { "anchor" => self.class::ANCHOR_CURRENCY }
30
- data["rates"].each do |pair, payload|
31
- rates[pair.sub(self.class::ANCHOR_CURRENCY, "")] = BigDecimal(payload["rate"].to_s)
32
- end
33
- rates
34
- end
35
- end
36
- end
data/lib/container.rb DELETED
@@ -1,203 +0,0 @@
1
- class CurrencyRate::Container
2
-
3
- attr_accessor :api_keys
4
- attr_accessor :logger
5
- attr_accessor :adapters
6
- attr_accessor :connect_timeout
7
- attr_accessor :read_timeout
8
- attr_accessor :storage
9
- attr_accessor :logger_callbacks
10
- attr_accessor :limit_adapters_for_pairs
11
-
12
- def initialize(
13
- api_keys: {},
14
- adapter_type: nil,
15
- adapter_names: nil,
16
- limit_adapters_for_pairs: {},
17
- storage_settings: CurrencyRate.default_config[:storage_settings],
18
- connect_timeout: CurrencyRate.default_config[:connect_timeout],
19
- read_timeout: CurrencyRate.default_config[:read_timeout],
20
- logger_settings: CurrencyRate.default_config[:logger_settings],
21
- logger_callbacks: CurrencyRate.default_config[:logger_callbacks]
22
- )
23
-
24
- logger_settigns = CurrencyRate.default_config[:logger_settings].merge(logger_settings)
25
- storage_settigns = CurrencyRate.default_config[:storage_settings].merge(storage_settings)
26
-
27
- method(__method__).parameters.map do |_, name|
28
- value = binding.local_variable_get(name)
29
- instance_variable_set("@#{name}", value)
30
- end
31
-
32
- _logger_callbacks = {}
33
- @logger_callbacks.each do |k,v|
34
- _logger_callbacks[Logger::Severity.const_get(k.to_s.upcase)] = v
35
- end
36
- @logger_callbacks = _logger_callbacks
37
-
38
- _limit_adapters_for_pairs = {}
39
- @limit_adapters_for_pairs.each do |k,v|
40
- _limit_adapters_for_pairs[k] = CurrencyRate.const_get(v.to_s.to_camel_case + "Adapter").instance
41
- end
42
- @limit_adapters_for_pairs = _limit_adapters_for_pairs
43
-
44
- @storage = CurrencyRate.const_get(storage_settigns[:type].to_s.to_camel_case + "Storage").new(
45
- path: storage_settings[:path],
46
- container: self,
47
- serializer: storage_settings[:serializer]
48
- )
49
-
50
- load_adapters!(names: adapter_names, type: adapter_type)
51
- end
52
-
53
- def method_missing(m, *args, &block)
54
- if m.to_s.end_with? "_adapters"
55
- self.send(:adapters, m[0..-10])
56
- else
57
- super
58
- end
59
- end
60
-
61
- def logger
62
- return @logger if @logger
63
- @logger = Logger.new(@logger_settings[:device])
64
- @logger.progname = "CurrencyRate"
65
- @logger.level = @logger_settings[:level]
66
- @logger.formatter = @logger_settings[:formatter] if @logger_settings[:formatter]
67
- @logger
68
- end
69
-
70
- # This method doesn't make any requests. It merely reads normalized data
71
- # from the selected storage. Contrary to what one might assume,
72
- # it doesn't call CurrencyRate::Container.sync! if storage for a particular
73
- # adapter doesn't exist - that's because those are two separate tasks
74
- # and you might not want to make that external http(s) request even if
75
- # the rates in storage are not found.
76
- #
77
- # It also uses a 3 different strategies to calculate rates before they are returned:
78
- #
79
- # 1. If only one adapter is specified and/or available, it will return the rate for the
80
- # pair using the data from the storage for this particular adapter.
81
- #
82
- # 2. If two or more adapters are specified and available, it will return the average rate
83
- # based on the the rates from all of those adapters.
84
- #
85
- # 3. If `strategy: :majority` flag is set and an odd number of adapters (say, 3)
86
- # is passed and/or available it will look at the rates from all, separate them
87
- # into two groups based on how close their rates are and return the average of the rates
88
- # that are closest in the group that is the largest.
89
- #
90
- # It will also check @limit_adapters_for_pairs hash for the request pair
91
- # and if the key exists it will exclude adapters that are not listed in the array
92
- # under that key.
93
- def get_rate(from, to, use_adapters=@adapter_names, strategy: :average)
94
- adapters_for_pair = @limit_adapters_for_pairs["#{from}/#{to}"]
95
- _adapters = adapters.select { |a| use_adapters.include?(a.name(:camel_case)) }
96
- _adapters = _adapters.select { |a| adapters_for_pair.include?(a.name(:camel_case)) } if adapters_for_pair
97
-
98
- warning_loggers = []
99
- rates = _adapters.map do |a|
100
- rate = [a.name(:camel_case), a.get_rate(from, to)]
101
- warning_loggers.push -> { self.log(:warn, "No rate for pair #{from}/#{to} found in #{a.name(:camel_case)} adapter") if rate[1].nil? }
102
- rate
103
- end.select { |r| !r[1].nil? }
104
-
105
- if rates.empty?
106
- self.log(:error,
107
- "No rate for pair #{from}/#{to} is found in any of the available adapters " +
108
- "(#{_adapters.map { |a| a.name(:camel_case) }.join(", ")})"
109
- )
110
- else
111
- warning_loggers.each { |wl| wl.call }
112
- end
113
-
114
- if rates.size == 1
115
- rates[0][1]
116
- else
117
- if strategy == :majority && rates.size.odd?
118
- rates.sort! { |r1, r2| r1[1] <=> r2[1] }
119
-
120
- largest_discrepancy_rate_index = 0
121
- last_discrepancy = 0
122
-
123
- rates.each_with_index do |r,i|
124
- if i > 0
125
- discrepancy = r[1] - rates[i-1][1]
126
- if discrepancy > last_discrepancy
127
- last_discrepancy = discrepancy
128
- largest_discrepancy_rate_index = i
129
- end
130
- end
131
- end
132
-
133
- rates_group_1 = rates[0...largest_discrepancy_rate_index]
134
- rates_group_2 = rates[largest_discrepancy_rate_index..rates.size-1]
135
- rates = [rates_group_1, rates_group_2].max { |g1,g2| g1.size <=> g2.size }
136
- end
137
- rates.inject(BigDecimal(0)) { |sum, i| sum + i[1] } / BigDecimal(rates.size)
138
- end
139
-
140
- end
141
-
142
- def sync!
143
- successfull = []
144
- failed = []
145
- @adapters.each do |adapter|
146
- adapter_name = adapter.class.to_s.sub("CurrencyRate::", "")
147
- begin
148
- rates = adapter.fetch_rates
149
- unless rates
150
- self.log(:warn, "Trying to sync rates for #{adapter_name}, rates not found, but http(s) request did not return any error.")
151
- failed << adapter_name
152
- next
153
- end
154
- @storage.write(adapter_name.to_snake_case.sub("_adapter", ""), rates)
155
- successfull << adapter_name
156
- rescue StandardError => e
157
- failed << adapter_name
158
- self.log(:error, e)
159
- next
160
- end
161
- end
162
- [successfull, failed]
163
- end
164
-
165
- def log(level, message)
166
- severity = Logger::Severity.const_get(level.to_s.upcase)
167
- logger.send(level, message)
168
- if @logger_callbacks[severity]
169
- @logger_callbacks[severity].call(level, message)
170
- else
171
- @logger_callbacks.keys.sort.each do |k|
172
- @logger_callbacks[k].call(level, message) && break if k < severity
173
- end
174
- end
175
- end
176
-
177
- private
178
-
179
- def load_adapters!(names: nil, type: :all)
180
- if names
181
- names = [names] if names.kind_of?(String)
182
- @adapters = names.map do |name|
183
- CurrencyRate.const_get(name + "Adapter").instance
184
- end
185
- else
186
- crypto_adapter_files = Dir[File.join CurrencyRate.root, "lib/adapters/crypto/*"]
187
- fiat_adapter_files = Dir[File.join CurrencyRate.root, "lib/adapters/fiat/*"]
188
- adapter_files = case type
189
- when :crypto then crypto_adapter_files
190
- when :fiat then fiat_adapter_files
191
- else crypto_adapter_files + fiat_adapter_files
192
- end
193
- @adapters = adapter_files.map do |file|
194
- CurrencyRate.const_get(File.basename(file, ".rb").to_camel_case).instance
195
- end
196
- end
197
- @adapters.each { |a| a.container = self; a.api_key = @api_keys[a.name] }
198
- @adapter_names = @adapters.map { |a| a.name(:camel_case) }
199
- @adapters
200
- end
201
-
202
-
203
- end