omni_exchange 1.6.0 → 1.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf795bf43c3ede8973124f10ff3afa6190a4c6af4705ecc481bf2a1112477f33
4
- data.tar.gz: 4b8fc48b43b3cbcb9e118d8e1ee5238c71c9ddfceca7aa1cf1034a78fa693691
3
+ metadata.gz: a9e96486f0fec5e014b79827ca801fc70c717ad3f3c36a333fc2d1248ea7b3f6
4
+ data.tar.gz: f52a460e18ad19a5cfeefe507dbce77563faf8e81ad5c2b23701fa7fec058190
5
5
  SHA512:
6
- metadata.gz: a42a179b5435a78d4aacd65c04e4c26223c1115c53b3160963ace5c8175dce8252a1ae7fc2272e758d16c0264c99294ac3a84763f0fa1f4cf5a51d08746327c3
7
- data.tar.gz: 58186c5c5697ef71566e41ad717b4c76362e2650edc1bd72da11ff0964bc76e7e5936f656969b58e37f69f6f34e640c1f09cba2041eeeb25a73ad27fae037ef3
6
+ metadata.gz: e948110df897320119664e7dadd069a9b32a74c9f683f21d9af48c4166eda64dfd6494fee2719c11c670088b91276de8f8659e7248aa324297219981ae18865f
7
+ data.tar.gz: 218e427ae203f24f0eeb4e74235b63fadaf47638061d6735f52d854b9413d5bfbcb08d5e541365cfcdeb9e4dfc481b2aedba145f6bfcf1f69b4a880a0e1451e9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- omni_exchange (1.6.0)
4
+ omni_exchange (1.7.0)
5
5
  faraday (< 2)
6
6
  money (~> 6.13.1)
7
7
 
@@ -13,7 +13,7 @@ GEM
13
13
  concurrent-ruby (1.1.10)
14
14
  diff-lcs (1.5.0)
15
15
  dotenv (2.8.1)
16
- faraday (1.10.2)
16
+ faraday (1.10.3)
17
17
  faraday-em_http (~> 1.0)
18
18
  faraday-em_synchrony (~> 1.0)
19
19
  faraday-excon (~> 1.1)
@@ -41,7 +41,7 @@ GEM
41
41
  method_source (1.0.0)
42
42
  money (6.13.8)
43
43
  i18n (>= 0.6.4, <= 2)
44
- multipart-post (2.2.3)
44
+ multipart-post (2.3.0)
45
45
  parallel (1.22.1)
46
46
  parser (3.1.2.1)
47
47
  ast (~> 2.4.1)
@@ -49,7 +49,7 @@ GEM
49
49
  coderay (~> 1.1)
50
50
  method_source (~> 1.0)
51
51
  rainbow (3.1.1)
52
- rake (10.5.0)
52
+ rake (12.3.3)
53
53
  regexp_parser (2.5.0)
54
54
  rexml (3.2.5)
55
55
  rspec (3.11.0)
@@ -89,7 +89,7 @@ DEPENDENCIES
89
89
  dotenv
90
90
  omni_exchange!
91
91
  pry
92
- rake (~> 10.0)
92
+ rake (~> 12.3)
93
93
  rspec (~> 3.0)
94
94
  rubocop (~> 0.80)
95
95
  vcr
@@ -36,7 +36,7 @@ module OmniExchange
36
36
 
37
37
  # Each provider class should inherit from Provider and have a .get_exchange_rates method. If a provider class
38
38
  # doesn't have a .get_exchange_rates method, the method below will be called and an error will be raised.
39
- def self.get_exchange_rate
39
+ def self.get_exchange_rate(base_currency:, target_currency:) # rubocop:disable Lint/UnusedMethodArgument
40
40
  raise 'method not implemented...'
41
41
  end
42
42
 
@@ -4,42 +4,67 @@ require 'omni_exchange'
4
4
 
5
5
  module OmniExchange
6
6
  class OpenExchangeRates < Provider
7
- ENDPOINT_URL = 'https://openexchangerates.org/api/latest.json'
8
-
9
- # This method returns the exchange rate, the rate at which the smallest unit of one currency (the base currency)
10
- # will be exchanged for another currency (the target currency), from Open Exchange Rate's API.
11
- # This method is called in the OmniExchange.exchange_currency method.
12
- #
13
- # @param base_currency: [String] the ISO Currency Code of the currency that you're exchanging from. ie. "USD", "JPY"
14
- # @param target_currency: [String] the ISO Currency Code of the currency that you're exchanging to. ie. "EUR", "KRW"
15
- # @ return [BigDecimal] an exchange rate is returned as a BigDecimal for precise calculation since this exchange
16
- # rate will be used to calculate an convert an exchange of currencies. However, an exception will be raised
17
- # if there is a timeout while connecting to xe.com or a timeout while reading Open Exchange Rate's API.
18
- def self.get_exchange_rate(base_currency:, target_currency:)
19
- config = OmniExchange.configuration.provider_config[:open_exchange_rates]
20
- app_id = config[:app_id]
21
-
22
- api = Faraday.new(OmniExchange::OpenExchangeRates::ENDPOINT_URL)
23
-
24
- begin
25
- response = api.get do |req|
26
- req.url "?app_id=#{app_id}&base=#{base_currency}"
27
- req.options.timeout = config[:read_timeout] || OmniExchange::Configuration::DEFAULT_READ_TIMEOUT
28
- req.options.open_timeout = config[:connect_timeout] || OmniExchange::Configuration::DEFAULT_CONNECTION_TIMEOUT
7
+ ENDPOINT_URL = 'https://openexchangerates.org/api/'
8
+
9
+ class << self
10
+ # This method returns the exchange rate, the rate at which the smallest unit of one currency (the base currency)
11
+ # will be exchanged for another currency (the target currency), from Open Exchange Rate's API.
12
+ # This method is called in the OmniExchange.exchange_currency method.
13
+ #
14
+ # @param base_currency: [String] the ISO Currency Code of the currency that you're exchanging from. ie. "USD", "JPY"
15
+ # @param target_currency: [String] the ISO Currency Code of the currency that you're exchanging to. ie. "EUR", "KRW"
16
+ # @ return [BigDecimal] an exchange rate is returned as a BigDecimal for precise calculation since this exchange
17
+ # rate will be used to calculate an convert an exchange of currencies. However, an exception will be raised
18
+ # if there is a timeout while connecting to xe.com or a timeout while reading Open Exchange Rate's API.
19
+ def get_exchange_rate(base_currency:, target_currency:)
20
+ body = api_get do |req|
21
+ req.url 'latest.json'
22
+ req.params['base'] = base_currency
23
+ req.params['symbols'] = target_currency
29
24
  end
30
- rescue *EXCEPTIONS => e
31
- raise e.class, 'Open Exchange Rates has timed out.'
25
+
26
+ exchange_rate = body['rates'][target_currency].to_d
27
+ currency_unit = get_currency_unit(base_currency).to_d
28
+
29
+ (exchange_rate * currency_unit).to_d
32
30
  end
33
31
 
34
- begin
35
- exchange_rate = JSON.parse(response.body, symbolize_names: true)[:rates][target_currency.to_sym].to_d
36
- rescue JSON::ParserError => e
37
- raise e.class, 'JSON::ParserError in OmniExchange::OpenExchangeRates'
32
+ def get_historic_rate(base_currency:, target_currencies:, date:)
33
+ body = api_get do |req|
34
+ req.url "historical/#{date.strftime('%Y-%m-%d')}.json"
35
+
36
+ req.params['base'] = base_currency
37
+ req.params['symbols'] = target_currencies.join(',')
38
+ end
39
+
40
+ currency_unit = get_currency_unit(base_currency).to_d
41
+ body['rates'].transform_values do |rate|
42
+ (rate * currency_unit).to_d
43
+ end
38
44
  end
39
45
 
40
- currency_unit = get_currency_unit(base_currency).to_d
46
+ private
47
+
48
+ def api_get(&blk)
49
+ api = Faraday.new(OmniExchange::OpenExchangeRates::ENDPOINT_URL)
41
50
 
42
- (exchange_rate * currency_unit).to_d
51
+ response = api.get do |req|
52
+ blk.call(req)
53
+
54
+ req.params['app_id'] = config[:app_id]
55
+
56
+ req.options.timeout = config[:read_timeout] ||
57
+ OmniExchange::Configuration::DEFAULT_READ_TIMEOUT
58
+ req.options.open_timeout = config[:connect_timeout] ||
59
+ OmniExchange::Configuration::DEFAULT_CONNECTION_TIMEOUT
60
+ end
61
+
62
+ JSON.parse(response.body)
63
+ end
64
+
65
+ def config
66
+ OmniExchange.configuration.provider_config[:open_exchange_rates]
67
+ end
43
68
  end
44
69
 
45
70
  # when this file is required at the top of lib/omni_exchange.rb, this method call is run and allows
@@ -6,45 +6,89 @@ module OmniExchange
6
6
  class Xe < Provider
7
7
  ENDPOINT_URL = 'https://xecdapi.xe.com/'
8
8
 
9
- # This method returns the exchange rate, the rate at which the smallest unit of one currency (the base currency)
10
- # will be exchanged for another currency (the target currency), from xe.com's API.
11
- # This method is called in the OmniExchange.exchange_currency method.
12
- #
13
- # @param base_currency: [String] the ISO Currency Code of the currency that you're exchanging from. ie. "USD", "JPY"
14
- # @param target_currency: [String] the ISO Currency Code of the currency that you're exchanging to. ie. "EUR", "KRW"
15
- # @ return [BigDecimal] an exchange rate is returned as a BigDecimal for precise calculation since this exchange
16
- # rate will be used to calculate an convert an exchange of currencies. However, an exception will be raised
17
- # if there is a timeout while connecting to xe.com or a timeout while reading xe.com's API.
18
- def self.get_exchange_rate(base_currency:, target_currency:)
19
- config = OmniExchange.configuration.provider_config[:xe]
20
- api_id = config[:api_id]
21
- api_key = config[:api_key]
22
- currency_unit = get_currency_unit(base_currency)
23
-
24
- api = Faraday.new(OmniExchange::Xe::ENDPOINT_URL) do |f|
25
- f.request :basic_auth, api_id, api_key
26
- f.adapter :net_http
9
+ class << self
10
+ # This method returns the exchange rate, the rate at which the smallest unit of one currency (the base currency)
11
+ # will be exchanged for another currency (the target currency), from xe.com's API.
12
+ # This method is called in the OmniExchange.exchange_currency method.
13
+ #
14
+ # @param base_currency: [String] the ISO Currency Code of the currency that you're exchanging from. ie. "USD", "JPY"
15
+ # @param target_currency: [String] the ISO Currency Code of the currency that you're exchanging to. ie. "EUR", "KRW"
16
+ # @ return [BigDecimal] an exchange rate is returned as a BigDecimal for precise calculation since this exchange
17
+ # rate will be used to calculate an convert an exchange of currencies. However, an exception will be raised
18
+ # if there is a timeout while connecting to xe.com or a timeout while reading xe.com's API.
19
+ def get_exchange_rate(base_currency:, target_currency:)
20
+ currency_unit = get_currency_unit(base_currency)
21
+
22
+ body = api_get do |req|
23
+ req.url 'v1/convert_from.json'
24
+
25
+ req.params['from'] = base_currency
26
+ req.params['to'] = target_currency
27
+ req.params['amount'] = currency_unit
28
+ end
29
+
30
+ body[:to][0][:mid].to_d
27
31
  end
28
32
 
29
- begin
30
- response = api.get do |req|
31
- req.url "v1/convert_from.json/?from=#{base_currency}&to=#{target_currency}&amount=#{currency_unit}"
32
- req.options.timeout = config[:read_timeout] || OmniExchange::Configuration::DEFAULT_READ_TIMEOUT
33
- req.options.open_timeout = config[:connect_timeout] || OmniExchange::Configuration::DEFAULT_CONNECTION_TIMEOUT
33
+ # This method returns the historic exchange rate for multiple currencies for a given date.
34
+ #
35
+ # @param base_currency: [String] the ISO Currency Code of the currency that you're exchanging from.
36
+ # ie. "USD", "JPY"
37
+ # @param target_currencies: [Array] an array of ISO Currency Codes of the currencies that you're
38
+ # exchanging to. ie. ["EUR", "KRW"]
39
+ # @param date: [Date] the date for which you want the historic exchange rate.
40
+ def get_historic_rate(base_currency:, target_currencies:, date:)
41
+ currency_unit = get_currency_unit(base_currency)
42
+
43
+ body = api_get do |req|
44
+ req.url 'v1/historic_rate.json'
45
+
46
+ req.params['from'] = base_currency
47
+ req.params['to'] = target_currencies.join(',')
48
+ req.params['amount'] = currency_unit
49
+ req.params['date'] = date.strftime('%Y-%m-%d')
50
+ end
51
+
52
+ rates = {}
53
+ body[:to].each do |rate|
54
+ rates[rate[:quotecurrency]] = rate[:mid].to_d
34
55
  end
35
- rescue *EXCEPTIONS => e
36
- raise e.class, 'xe.com has timed out.'
56
+
57
+ rates
37
58
  end
38
59
 
39
- begin
60
+ private
61
+
62
+ def api_get(&blk)
63
+ response = api.get do |req|
64
+ blk.call(req)
65
+
66
+ req.options.timeout = config[:read_timeout] ||
67
+ OmniExchange::Configuration::DEFAULT_READ_TIMEOUT
68
+ req.options.open_timeout = config[:connect_timeout] ||
69
+ OmniExchange::Configuration::DEFAULT_CONNECTION_TIMEOUT
70
+ end
71
+
40
72
  body = JSON.parse(response.body, symbolize_names: true)
41
- rescue JSON::ParserError => e
42
- raise e.class, 'JSON::ParserError in OmniExchange::Xe'
73
+
74
+ raise OmniExchange::XeMonthlyLimit, 'Xe.com monthly limit has been exceeded' if body[:code] == 3
75
+
76
+ body
43
77
  end
44
78
 
45
- raise OmniExchange::XeMonthlyLimit, 'Xe.com monthly limit has been exceeded' if body[:code] == 3
79
+ def api
80
+ api_id = config[:api_id]
81
+ api_key = config[:api_key]
46
82
 
47
- body[:to][0][:mid].to_d
83
+ Faraday.new(OmniExchange::Xe::ENDPOINT_URL) do |f|
84
+ f.request :basic_auth, api_id, api_key
85
+ f.adapter :net_http
86
+ end
87
+ end
88
+
89
+ def config
90
+ OmniExchange.configuration.provider_config[:xe]
91
+ end
48
92
  end
49
93
 
50
94
  # when this file is required at the top of lib/omni_exchange.rb, this method call is run and allows
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniExchange
4
- VERSION = '1.6.0'
4
+ VERSION = '1.7.0'
5
5
  end
data/lib/omni_exchange.rb CHANGED
@@ -34,7 +34,16 @@ module OmniExchange
34
34
  end
35
35
 
36
36
  # if a provider raises one of these exceptions, OmniExchange will gracefully attempt to use another provider
37
- EXCEPTIONS = [Faraday::Error, Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::SSLError, Net::OpenTimeout, Net::WriteTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError]
37
+ EXCEPTIONS = [
38
+ Faraday::Error,
39
+ Faraday::ConnectionFailed,
40
+ Faraday::TimeoutError,
41
+ Faraday::SSLError,
42
+ Net::OpenTimeout,
43
+ Net::WriteTimeout,
44
+ Net::ReadTimeout,
45
+ OpenSSL::SSL::SSLError
46
+ ]
38
47
 
39
48
  module_function
40
49
 
@@ -76,12 +85,18 @@ module OmniExchange
76
85
 
77
86
  exchanged_amount = rate.to_d * amount.to_d
78
87
 
79
- return { converted_amount: exchanged_amount, exchange_rate: rate, non_subunit_fx_rate: plain_format_rate, provider: OmniExchange::Provider.all.key(klass) }
88
+ return {
89
+ converted_amount: exchanged_amount,
90
+ exchange_rate: rate,
91
+ non_subunit_fx_rate: plain_format_rate,
92
+ provider: OmniExchange::Provider.all.key(klass)
93
+ }
80
94
  rescue *EXCEPTIONS, OmniExchange::XeMonthlyLimit, JSON::ParserError => e
81
95
  error_messages << e.inspect
82
96
  end
83
-
84
- raise OmniExchange::HttpError, "Failed to load #{base_currency}->#{target_currency}:\n#{error_messages.join("\n")}"
97
+
98
+ raise OmniExchange::HttpError, "Failed to load #{base_currency}->#{target_currency}:\n" \
99
+ "#{error_messages.join("\n")}"
85
100
  end
86
101
  end
87
102
  # rubocop:enable Lint/Syntax
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency 'dotenv'
34
34
  spec.add_development_dependency 'pry'
35
- spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rake', '~> 12.3'
36
36
  spec.add_development_dependency 'rspec', '~> 3.0'
37
37
  spec.add_development_dependency 'rubocop', '~> 0.80'
38
38
  spec.add_development_dependency 'vcr'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omni_exchange
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yun Chung
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-31 00:00:00.000000000 Z
11
+ date: 2023-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
75
+ version: '12.3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '10.0'
82
+ version: '12.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
175
  - !ruby/object:Gem::Version
176
176
  version: '0'
177
177
  requirements: []
178
- rubygems_version: 3.2.3
178
+ rubygems_version: 3.2.33
179
179
  signing_key:
180
180
  specification_version: 4
181
181
  summary: OmniExchange converts currencies using up-to-the-minute foreign exchange