Forex - European Central Bank (ECB) exchange rates for Elixir

Hey, just released a small library called Forex, to retrieve the European Central Bank daily exchange rates.

The idea behind the library is to provide a simple, no API keys, no authentication, no rate limits, just a simple Elixir library that fetches the data from the European Central Bank and caches it for later use.

With this said take into account this is not aimed at building any type of transactional app, financial applications or any type of application that relies on to the second foreign exchange rates. The reference rates from the ECB are usually updated at around 16:00 CET every working day. This is useful for information purposes, for example, you might want to show on your job board how much is the role salary range in the user’s local currency, etc.

Usage

By default the base currency is the Euro (EUR), the same as the European Central Bank,
but you can change the base currency by passing the base option to the relevant functions.

Sample Usage

To fetch the latest exchange rates, you can use the current_rates/1 function:

iex> Forex.current_rates()
{:ok,
  %{
    base: :eur,
    date: ~D[2025-03-12],
    rates: %{
      usd: Decimal.new("1.1234"),
      jpy: Decimal.new("120.1234"),
      ...
      zar: Decimal.new("24.1442")
    }}
  }

If you use it and found a bug or have any suggestion, don’t hesitate to create an issue or post here. :slight_smile:

Thanks,

Nuno F.

Hex: forex | Hex
Repo:

10 Likes

Forex.base_currency_rate/0 is not documented. Looks like it’s used by other functions. Should it be defp instead or maybe @doc false (in case you use it in other modules too)?


I would rather suggest to return structs instead of maps in case you already know what keys and values you have to expect. This would save lots of time on debugging for trivial typos.


You should consider using typespecs now. I’ve got that’s not supposed to be a 1.0.0 release and it does not need to be a top #1 priority, but it would definitely affect the documentation. For example let’s take a look at Forex.options/1.

With a spec like:

@spec options(Keyword.t()) :: options
# or even
@spec options(input_options) :: options

You can define options type, move all options documentation there and finally use options type in spec for other functions. This way you don’t have to copy-paste same documentation as developers interested what options are supported would simply hover or click on the options type link in the function spec.

@spec current_rates(input_options | options) :: map

In this example both options types are just Keyword.t(), but with different @typedoc. The input_options only have to mention that options/1 function would be used to get validated options. This way documentation would be much easier to read.


Please do not use spaces before header syntax in markdown, see: Forex — forex v0.1.1


You should change this line:

to:

    source_ref: "v" <> @version,

This is because your tags have v before version (which is not bad at all) and you don’t have a branch with this version. I guess you have copy-pasted a “working” configuration, but forgot to work in the branch. Because of that tiny mistake all links to the source code does not work.


You may be interested in adding badges to your README.md file, see:


It would be amazing to have a function like Forex.exchange_historic_rate(historic_date). This way people can create an example sites (like shop template) with a real prices. In many cases there would be no need to update the prices because of inflation which may be especially useful if in such template are used base products like food.


Please keep in mind that’s a public post. You may already know what I wrote, but it may be helpful for others.

1 Like

That’s actually quite nice. Usually that stuff comes with all of those limits. Also daily updates is actually fine for a lot of stuff.

2 Likes

Thanks for your suggestions! This was just a first release, I actually forgot to delete the application mod, the library is supposed to be started in the supervision tree, of course.
So already doing some changes.

1 Like