Packages
ex_money
3.2.3
6.1.1
6.1.0
6.0.0
6.0.0-rc.0
5.24.2
5.24.1
5.24.0
retired
5.23.0
5.22.0
5.21.0
5.20.0
5.19.2
5.19.1
5.19.0
5.18.0
5.17.2
5.17.1
5.17.0
5.16.1
5.16.0
5.15.4
5.15.3
5.15.2
5.15.1
5.15.0
5.14.1
5.13.0
5.12.4
5.12.3
5.12.2
5.12.1
5.12.0
5.11.0
5.10.0
5.9.0
5.8.0
5.7.4
5.7.3
5.7.2
5.7.1
5.7.0
5.6.0
5.5.5
5.5.4
5.5.3
5.5.2
5.5.1
5.5.0
5.4.1
5.4.0
5.4.0-rc.0
5.3.2
5.3.1
5.3.0
5.2.1
5.2.0
5.1.0
5.0.2
5.0.1
5.0.0
retired
4.4.3
4.4.2
retired
4.4.1
4.4.0
4.3.0
4.2.2
4.2.1
4.2.0
4.1.0
4.0.0
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.1
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.0
3.0.0
2.12.2
2.12.1
retired
2.12.0
retired
2.11.0
2.10.0
2.9.1
2.9.0
2.8.0
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.0
2.4.0
2.3.0
2.2.2
2.2.1
2.2.0
2.1.0
2.1.0-rc.1
retired
2.1.0-rc.0
retired
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.3
1.1.2
1.1.1
retired
1.1.0
1.0.0
1.0.0-rc.0
retired
0.9.0
retired
0.8.5
retired
0.8.4
retired
0.8.3
retired
0.8.2
retired
0.8.1
retired
0.8.0
retired
0.7.0
retired
0.6.2
retired
0.6.1
retired
0.6.0
retired
0.5.3
retired
0.5.2
retired
0.5.1
retired
0.5.0
retired
0.4.3
retired
0.4.2
retired
0.4.1
retired
0.4.0
retired
0.3.0
retired
0.2.0
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
0.1.3
retired
0.1.2
retired
0.1.1
retired
0.1.0
retired
0.0.16
retired
0.0.15
retired
0.0.14
retired
0.0.13
retired
0.0.12
retired
0.0.11
retired
0.0.10
retired
0.0.9
retired
0.0.7
retired
0.0.6
retired
0.0.5
retired
0.0.4
retired
0.0.3
retired
0.0.2
retired
Money functions for operations on and localization of a money data type with support for ISO 4217 currencies and ISO 24165 digial tokens (crypto currencies).
Current section
Files
Jump to
Current section
Files
lib/money/exchange_rates/open_exchange_rates.ex
defmodule Money.ExchangeRates.OpenExchangeRates do
@moduledoc """
Implements the `Money.ExchangeRates` for the Open Exchange
Rates service.
## Required configuration:
The configuration key `:open_exchange_rates_app_id` should be
set to your `app_id`. for example:
config :ex_money,
open_exchange_rates_app_id: "your_app_id"
or configure it via environment variable:
config :ex_money,
open_exchange_rates_app_id: {:system, "OPEN_EXCHANGE_RATES_APP_ID"}
It is also possible to configure an alternative base url for this
service in case it changes in the future. For example:
config :ex_money,
open_exchange_rates_app_id: "your_app_id"
open_exchange_rates_url: "https://openexchangerates.org/alternative_api"
"""
require Logger
alias Money.ExchangeRates.Retriever
@behaviour Money.ExchangeRates
@open_exchange_rate_url "https://openexchangerates.org/api"
@doc """
Update the retriever configuration to include the requirements
for Open Exchange Rates. This function is invoked when the
exchange rate service starts up, just after the ets table
:exchange_rates is created.
* `default_config` is the configuration returned by `Money.ExchangeRates.default_config/0`
Returns the configuration either unchanged or updated with
additional configuration specific to this exchange
rates retrieval module.
"""
def init(default_config) do
url = Money.get_env(:open_exchange_rates_url, @open_exchange_rate_url)
app_id = Money.get_env(:open_exchange_rates_app_id, nil)
Map.put(default_config, :retriever_options, %{url: url, app_id: app_id})
end
def decode_rates(body) do
%{"base" => _base, "rates" => rates} = Money.json_library().decode!(body)
rates
|> Cldr.Map.atomize_keys()
|> Enum.map(fn
{k, v} when is_float(v) -> {k, Decimal.from_float(v)}
{k, v} when is_integer(v) -> {k, Decimal.new(v)}
end)
|> Enum.into(%{})
end
@doc """
Retrieves the latest exchange rates from Open Exchange Rates site.
* `config` is the retrieval configuration. When invoked from the
exchange rates services this will be the config returned from
`Money.ExchangeRates.config/0`
Returns:
* `{:ok, rates}` if the rates can be retrieved
* `{:error, reason}` if rates cannot be retrieved
Typically this function is called by the exchange rates retrieval
service although it can be called outside that context as
required.
"""
@spec get_latest_rates(Money.ExchangeRates.Config.t()) :: {:ok, map()} | {:error, String.t()}
def get_latest_rates(config) do
url = config.retriever_options.url
app_id = config.retriever_options.app_id
retrieve_latest_rates(url, app_id, config)
end
defp retrieve_latest_rates(_url, nil, _config) do
{:error, app_id_not_configured()}
end
@latest_rates "/latest.json"
defp retrieve_latest_rates(url, app_id, config) do
Retriever.retrieve_rates(url <> @latest_rates <> "?app_id=" <> app_id, config)
end
@doc """
Retrieves the historic exchange rates from Open Exchange Rates site.
* `date` is a date returned by `Date.new/3` or any struct with the
elements `:year`, `:month` and `:day`.
* `config` is the retrieval configuration. When invoked from the
exchange rates services this will be the config returned from
`Money.ExchangeRates.config/0`
Returns:
* `{:ok, rates}` if the rates can be retrieved
* `{:error, reason}` if rates cannot be retrieved
Typically this function is called by the exchange rates retrieval
service although it can be called outside that context as
required.
"""
def get_historic_rates(date, config) do
url = config.retriever_options.url
app_id = config.retriever_options.app_id
retrieve_historic_rates(date, url, app_id, config)
end
defp retrieve_historic_rates(_date, _url, nil, _config) do
{:error, app_id_not_configured()}
end
@historic_rates "/historical/"
defp retrieve_historic_rates(%Date{calendar: Calendar.ISO} = date, url, app_id, config) do
date_string = Date.to_string(date)
Retriever.retrieve_rates(
url <> @historic_rates <> "#{date_string}.json" <> "?app_id=" <> app_id,
config
)
end
defp retrieve_historic_rates(%{year: year, month: month, day: day}, url, app_id, config) do
case Date.new(year, month, day) do
{:ok, date} -> retrieve_historic_rates(date, url, app_id, config)
error -> error
end
end
defp app_id_not_configured do
"Open Exchange Rates app_id is not configured. Rates are not retrieved."
end
end