sharkdp / numbat

A statically typed programming language for scientific computations with first class support for physical dimensions and units
https://numbat.dev
Apache License 2.0
1.29k stars 53 forks source link

Add currencies to the web version #177

Closed sharkdp closed 1 year ago

sharkdp commented 1 year ago

The way we do this for the CLI is not straightforward:

https://github.com/sharkdp/numbat/blob/c666cd7e94e4e962c9485a6997a989faf195634e/numbat-cli/src/main.rs#L163-L178

We can hopefully do something similar for the WASM version

archisman-panigrahi commented 1 year ago

How exactly does numbat web version get the conversion rates? Do you manually update them regularly on a module file? Is there a GitHub CI that fetches it from somewhere and saves them to a module file?

sharkdp commented 1 year ago

Yeah, currencies are a bit special :smile:

In the CLI version, we fetch currency exchange rates from the European Central Bank (https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml). We do this asynchronousy, so as not to slow down the startup of numbat. Once the request comes back, we parse the XML respone here:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat-exchange-rates/src/lib.rs#L8-L34

and then update the exchange rate cache here:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat/src/currency.rs#L23-L28

Once that is done, we load the units::currencies module asynchronously (while the Numbat CLI is already running):

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat-cli/src/main.rs#L162-L178

The units::currencies module defines units like so:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat/modules/units/currencies.nbt#L18-L19

Here, the exchange_rate_USD() -> Scalar function is a so-called foreign function that is not implemented in Numbat code, but in Rust:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat/src/ffi.rs#L283-L292

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat/src/ffi.rs#L632-L639

For the web version, we do this in a similar way, except that we fetch that file from JavaScript:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat-wasm/www/index.js#L3-L16

and then pass it into the Rust code (in order to fill the cache, and store the proper values for functions like exchange_rate_USD()). Here, we do not fetch the file from the ECB directly, because that results in a cross-origin (CORS) error. Instead, we fetch https://numbat.dev/ecb-exchange-rates.php, which is basically just a cached proxy of that ECB XML file:

https://github.com/sharkdp/numbat/blob/257c5deea7cfb8827e80f48eed34149f5641b4fa/numbat-wasm/www/ecb-exchange-rates.php#L1-L24

How exactly does numbat web version get the conversion rates? Do you manually update them regularly on a module file? Is there a GitHub CI that fetches it from somewhere and saves them to a module file?

No, there is no need to do that fortunately. Exchange rates are always up to date (ECB updates them once per day and we fetch them at least once per day).

Note that this approach has some downsides, but I have some ideas on how to improve it. For more details, see https://github.com/sharkdp/numbat/issues/107

archisman-panigrahi commented 1 year ago

Just to clarify, suppose I have installed the .deb installer. Does it update the exchange rates automatically, or does it retain the values from when this version was compiled?

sharkdp commented 1 year ago

Does it update the exchange rates automatically

it does.