Skip to content
This repository has been archived by the owner on Aug 28, 2023. It is now read-only.

jshmrtn/currency-conversion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CurrencyConversion

GitHub license Hex.pm Version Coverage Status

Convert Money Amounts between currencies. This library uses an OTP worker to save current conversion rates.

Installation

The package can be installed by adding currency_conversion to your list of dependencies in mix.exs:

def deps do
  [
    {:currency_conversion, "~> 1.0"},
    {:jason, "~> 1.1"}, # When usig Fixer / Exchange Rates API,
    {:httpotion, "~> 3.1"}, # When usig Fixer / Exchange Rates API
  ]
end

Setup

CurrencyConversion is a wrapper around the currency conversion. We can define an implementation as follows:

defmodule MyApp.CurrencyConversion do
  use CurrencyConversion, otp_app: :my_app
end

If your application was generated with a supervisor (by passing --sup to mix new) you will have a lib/my_app/application.ex file containing the application start callback that defines and starts your supervisor. You just need to edit the start/2 function to start the converter as a supervisor on your application's supervisor:

def start(_type, _args) do
  children = [
    {MyApp.CurrencyConversion, []}
  ]
  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Configuration

  • source - Configure which Data Source Should Be Used.
    • Type: atom
    • Default: CurrencyConversion.Source.ExchangeRatesApi
    • Restrictions: Must implement CurrencyConversion.Source behaviour
    • Given Implementations:
      • CurrencyConversion.Source.Fixer - Fixer
      • CurrencyConversion.Source.ExchangeRatesApi - Exchange Rates API
      • CurrencyConversion.Source.Test - Test Source
  • base_currency - Change the base currency that is requested when fetching rates
    • Type: atom
    • Default: :EUR
  • refresh_interval - Configure how often the data should be refreshed (in ms) or turn auto-refresh off.
    • Type: integer | :manual
    • Default: 86_400_000 (Once per Day)
    • :manual turns auto-refresh off, do refresh yourself
  • seed - Deliver the rates data manually.
    • Type: (Keyword.t() -> {:ok, CurrencyConversion.Rates.t()} | {:error, binary}) | {module :: atom, function :: atom, arity :: 1}
    • Default: Load from source
  • test_rates - Configure rates for CurrencyConversion.Source.Test source
    • Type: {atom, %{atom: float}}
    • Default: see CurrencyConversion.Source.Test.@default_rates
    • Example: {:EUR, %{CHF: 7.0}}
config :my_app, MyApp.CurrencyConversion,
  source: CurrencyConversion.Source.Fixer,
  source_api_key: "FIXER_ACCESS_KEY",
  source_protocol: "https",
  refresh_interval: 86_400_000

Custom Source

A custom source can be implemented by using the behaviour CurrencyConversion.Source and reconfiguring the source config.

It only has to implement the function load/0, which produces a struct of type %CurrencyConversion.Rates{}.

Test

To prevent HTTP calls in the Tests, configure the Test Source. (See the configuration test_rates for custom test rates.)

config :my_app, MyApp.CurrencyConversion,
  source: CurrencyConversion.Source.Test,
  refresh_interval: 86_400_000

Usage

Only the callbacks from CurrencyConversion are exposed to the user. The library money is used to represent money amounts.

Example

Change 7 swiss franks to dollars:

iex> MyApp.CurrencyConversion.convert(Money.new(7_00, :CHF), :USD)
%Money{amount: 10_50, currency: :USD}

Get supported currencies:

iex> MyApp.CurrencyConversion.get_currencies()
[:EUR, :USD, :CHF, ...]

Manually refresh exchange rates:

iex> MyApp.CurrencyConversion.refresh_rates()
:ok