Module: OmniExchange

Defined in:
lib/omni_exchange.rb,
lib/omni_exchange/error.rb,
lib/omni_exchange/version.rb,
lib/omni_exchange/provider.rb,
lib/omni_exchange/providers/xe.rb,
lib/omni_exchange/configuration.rb,
lib/omni_exchange/providers/open_exchange_rates.rb

Overview

rubocop:disable Lint/Syntax

Defined Under Namespace

Classes: Configuration, Error, HttpError, OpenExchangeRates, Provider, UnknownCurrency, Xe, XeMonthlyLimit

Constant Summary collapse

EXCEPTIONS =

if a provider raises one of these exceptions, OmniExchange will gracefully attempt to use another provider

[
  Faraday::Error,
  Faraday::ConnectionFailed,
  Faraday::TimeoutError,
  Faraday::SSLError,
  Net::OpenTimeout,
  Net::WriteTimeout,
  Net::ReadTimeout,
  OpenSSL::SSL::SSLError
]
VERSION =
'2.0.0'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configurationObject

Returns the value of attribute configuration.



23
24
25
# File 'lib/omni_exchange.rb', line 23

def configuration
  @configuration
end

Class Method Details

.configure {|configuration| ... } ⇒ Object

This method allows you to call OmniExchange.configure with a block that creates a new

instance of OmniExchange::Configuration

Yields:



32
33
34
# File 'lib/omni_exchange.rb', line 32

def self.configure
  yield(configuration)
end

.get_exchange_rate(base_currency:, target_currency:, providers:) ⇒ Object

returns the latest foreign exchange rate from the base currency to the target currency.

@ return [BigDecimal] an exchange rate is returned as a BigDecimal for precise calculation since this exchange

rate will be used to calculate an convert an exchange of currencies.

Parameters:

  • base_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging from. ie. “USD”, “JPY”

  • target_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging to. ie. “EUR”, “KRW”

  • providers: (Array)

    an array of symbols of the providers that will be used to get exchange rates API data. The symbols must be found in the @providers hash in the Provider class (lib/omni_exchange/provider.rb). ie. xe:, :open_exchange_rates

Raises:



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/omni_exchange.rb', line 113

def get_exchange_rate(base_currency:, target_currency:, providers:)
  provider_classes = providers.map { |p| OmniExchange::Provider.load_provider(p) }

  error_messages = []

  provider_classes.each do |klass|
    rate = klass.get_exchange_rate(base_currency: base_currency,
                                   target_currency: target_currency)

    return {
      rate: rate,
      provider: OmniExchange::Provider.all.key(klass)
    }

  rescue *EXCEPTIONS, OmniExchange::XeMonthlyLimit, JSON::ParserError => e
    error_messages << e.inspect
  end

  raise OmniExchange::HttpError, "Failed to get exchange rate:\n" \
                                 "#{error_messages.join("\n")}"
end

.get_fx_data(amount:, base_currency:, target_currency:, providers:) ⇒ Hash

returns foreign exchange data including the amount of money in one country’s currency when exchanged from an

amount of money of another country's currency using exchange rates data from API providers, the exchange
rate used to calculate that amount, and the API provider that supplied that rate.

Parameters:

  • amount: (Integer, #to_d)

    the amount to exchange (in cents, if applicable to the currency). ie. 1, 10, 100

  • base_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging from. ie. “USD”, “JPY”

  • target_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging to. ie. “EUR”, “KRW”

  • providers: (Array)

    an array of symbols of the providers that will be used to get exchange rates API data. The symbols must be found in the @providers hash in the Provider class (lib/omni_exchange/provider.rb). ie. xe:, :open_exchange_rates

Returns:

  • (Hash)

    If none of the providers in the providers hash are able to retrieve data, or if one of the currencies is not valid, an exception is raised.

    • :converted_amount [BigDecimal] the amount of money exchanged from the base currency to the target

      currency as a BigDecimal for precice calculation. ie. 1, 10, 100
      
    • :exchange_rate [BigDecimal] the rate used to calculate the converted_amount as a BigDecimal. ie. 0.95211e1

    • :non_subunit_fx_rate [BigDecimal] a rate that can be used when a currency with subunits is not in cents . ie. 0.95211e3

    • :provider [Symbol] the provider that supplied the exchange_rate data. ie. :xe, :open_exchange_rates

Raises:



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/omni_exchange.rb', line 67

def get_fx_data(amount:, base_currency:, target_currency:, providers:)
  # if one of the currencies is not valid (ie. 'fake_crypto'), an exception is raised.
  begin
    Money::Currency.wrap(base_currency)
    Money::Currency.wrap(target_currency)
  rescue Money::Currency::UnknownCurrency => exception
    raise OmniExchange::UnknownCurrency, "#{exception}"
  end

  error_messages = []

  # Make sure all providers passed exist. If not, a LoadError is raise and not rescued
  provider_classes = providers.map { |p| OmniExchange::Provider.load_provider(p) }

  # Gracefully hit each provider and fail-over to the next one
  provider_classes.each do |klass|
    rate = klass.get_exchange_rate(base_currency: base_currency, target_currency: target_currency)
    plain_format_rate = (rate * Money::Currency.wrap(base_currency).subunit_to_unit).to_d

    exchanged_amount = rate.to_d * amount.to_d

    return {
      converted_amount: exchanged_amount,
      exchange_rate: rate,
      non_subunit_fx_rate: plain_format_rate,
      provider: OmniExchange::Provider.all.key(klass)
    }
  rescue *EXCEPTIONS, OmniExchange::XeMonthlyLimit, JSON::ParserError => e
    error_messages << e.inspect
  end

  raise OmniExchange::HttpError, "Failed to load #{base_currency}->#{target_currency}:\n" \
                                 "#{error_messages.join("\n")}"
end

.get_historic_rate(base_currency:, target_currencies:, date:, providers:) ⇒ Object

returns the historic exchange rate from the base currency to the target currency at a certain date.

ie. Date.new(2018, 12, 25) @ return [Hash]: A hash containing the exchange rates.

Parameters:

  • base_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging from. ie. “USD”, “JPY”

  • target_currency: (String)

    the ISO Currency Code of the currency that you’re exchanging to. ie. “EUR”, “KRW”

  • date: (Date)

    the specific date you want a historic exchange rate for.

  • providers: (Array)

    an array of symbols of the providers that will be used to get exchange rates API data. The symbols must be found in the @providers hash in the Provider class (lib/omni_exchange/provider.rb). ie. xe:, :open_exchange_rates

Raises:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/omni_exchange.rb', line 148

def get_historic_rate(base_currency:, target_currencies:, date:, providers:)
  provider_classes = providers.map { |p| OmniExchange::Provider.load_provider(p) }

  error_messages = []

  provider_classes.each do |klass|
    rates = klass.get_historic_rate(base_currency: base_currency,
                                    target_currencies: target_currencies,
                                    date: date)

    return {
      rates: rates,
      provider: OmniExchange::Provider.all.key(klass)
    }

  rescue *EXCEPTIONS, OmniExchange::XeMonthlyLimit, JSON::ParserError => e
    error_messages << e.inspect
  end

  raise OmniExchange::HttpError, "Failed to get historic rate:\n" \
                                 "#{error_messages.join("\n")}"
end