Open Sierra410 opened 6 months ago
If there is a reliable, free API that we can use, I'm all for adding support for more currencies. Last time I checked, I didn't find anything except for the ECB "API". It's not like I intentionally want to be Europe-centric.
I'm not particularly excited about the idea of storing API credentials somewhere:
So, I've poked at a few currency exchange APIs from that list I've linked.
The one with most currencies (766!) is the creatively named one "Currency-API". However, looking at it, it seems like it's just some guy™ hitting a bunch of APIs, merging the results into one massive lists and caching it on cloudflare. All in a github workflow script too! I'm honestly impressed at the ingenuity, but doesn't seem like a reliable source of currency data.
Now, a few others seem to work too, but I'm going to skip over.
The best candidate, I think, is the Polish National Bank. It has an A and a B currency list (https://api.nbp.pl/api/exchangerates/tables/
{a,b}
) and both combined total up to 149 currencies. The only "issue" with it is that it uses PLN as the base currency, but it's trivial to work around of.
Thank you for doing the research.
The one with most currencies (766!) is the creatively named one "Currency-API". However, looking at it, it seems like it's just some guy™ hitting a bunch of APIs, merging the results into one massive lists and caching it on cloudflare. All in a github workflow script too! I'm honestly impressed at the ingenuity, but doesn't seem like a reliable source of currency data.
In principle, this is what we need. But yeah, I would also be skeptical w.r.t reliability. Especially since there are issues in the linked repo that indicate stability issues (haven't looked into it further though).
The best candidate, I think, is the Polish National Bank. It has an A and a B currency list (
https://api.nbp.pl/api/exchangerates/tables/
{a,b}
) and both combined total up to 149 currencies.
Ok, interesting. It's also XML-based, so we wouldn't need any new dependencies in numbat-exchange-rates
. I'm fine with adding this as an additional backend to numbat-exchange-rates
(I'd like to keep ECB, even if the Polish National Bank is a strict superset), if we can figure out a clean architecture for doing so. Especially concerning priority and error handling (for example: what happens if one or the other backend is not available). Asynchronicity is also an interesting aspect. Imagine we already have the currencies from backend A, but we're still waiting for the results from backend B. Should we already make those currencies from backend A available for the user, or only after the timeout on the second query has been exceeded, etc. I think it would be worth writing this down before we go on an implement this.
One thing that we should also think about is this problem: https://github.com/sharkdp/numbat/blob/da9deb519be2bd353d993b8af135326f7fb54f56/numbat/src/lib.rs#L598C1-L714. It's not strictly related to this issue, but becomes even more apparent if we add new currencies.
The only "issue" with it is that it uses PLN as the base currency, but it's trivial to work around of.
Right. We currently use the Euro as a base currency (because of ECB), but since we have the PLN<->EUR conversion, that should not pose any problems.
Asynchronicity is also an interesting aspect. Imagine we already have the currencies from backend A, but we're still waiting for the results from backend B. Should we already make those currencies from backend A available for the user, or only after the timeout on the second query has been exceeded, etc. I think it would be worth writing this down before we go on an implement this.
Perhaps the backends could have different priority over each other? We obviously want the backend with most currencies, right? So it makes sense to pick favorites, I think.
Assuming the requests are started all at once:
If we get a complete and valid result from our main source (e.g. the Polish bank) we grab it and use it immediately, completely discarding the response from the secondary (ternary, etc) source.
If we get a response from our secondary source first, however, we will wait instead. If our main source succeeds some time after the secondary, we still use the main source and discard the secondary (because we want more currencies). If our main source fails/times out, only then do we use the secondary.
As for amount of time we wait: we could wait for, let's say, 2 or 3 seconds after the secondary request finishes. That way if the user has a poor internet connection and it takes something like 5 seconds to do a single request, the user will either get to use data from our main source in those 5 seconds, or from our secondary source in 7 (if the main source is down).
If the connection is fine, but our main source is down, the program will settle on the secondary source in mere 2.x seconds.
It should be fast enough for smooth UX regardless of whether the data is fetched at startup or at first use that way.
One thing that we should also think about is this problem: https://github.com/sharkdp/numbat/blob/da9deb519be2bd353d993b8af135326f7fb54f56/numbat/src/lib.rs#L598C1-L714. It's not strictly related to this issue, but becomes even more apparent if we add new currencies.
As I understand the issue is that for dynamic loading to work, the currencies need to be known in advance, but we don't know exactly which currencies are going to get returned by the backend, right?
Perhaps the hardcoded list could only contain common aliases (so strings like "dollar", "pound", "$", "₪", etc), but in addition to checking against a list, anything that's three capital letters could be assumed to be a potential currency? So something 69 ABC
or 10 XYZ -> UVW
would trigger loading, because that looks close enough to a currency code, I guess?
It appears to me that there is no (easy) way to change the exchange rate provider.
European Central Bank API returns a list of 30 currencies, meanwhile there are almost 200 currencies in the world. It essentially means that the currency conversion feature is of limited use for anyone residing almost anywhere outside of EU or few EU-friendly countries.
There is, also, an unholy number of various cryptocurrencies which people might want to convert.
If would be nice if the program either:
and/or
."gesmes:Envelope".Cube.Cube.Cube.[] | [."@currency", ."@rate"]
for ECB) to extract the relevant data.