| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
FetchRate is a historical currency and cryptocurrency exchange rate tool. Given an amount, a source currency or crypto symbol, and a date, it returns the equivalent value in a target currency using rates from that specific day.
It provides three interfaces for the same service: a CLI, a REST API, and a web UI.
Stack: Java 17 · Spring Boot 4 · SQLite · Thymeleaf · Maven
Requirements (local build): Java 17+, Maven 3.9+
mvn package -DskipTestsCLI:
java -jar target/FetchRate-0.5.jar convert --amount 100 --input-currency USD --date 2024-01-15HTTP server (web UI at http://localhost:8000, REST API at /convert):
java -jar target/FetchRate-0.5.jar start_http_server
# Custom port:
java -jar target/FetchRate-0.5.jar start_http_server --port 9090The HTTP server binds to 127.0.0.1 (loopback only) by default. To expose it on the network (for example, behind a reverse proxy), set server.address=0.0.0.0 in fetchrate.properties.
Docker:
docker compose upRate data is persisted to ./data/ on the host. The container binds to 127.0.0.1 by default; to expose it on the network, override the port binding in your compose file. To pass a crypto API key:
FETCHRATE_API_KEY=your_key docker compose upThe image also supports CLI usage. Build the image first, then run:
docker compose build
docker run --rm -v ./data:/app/data fetchrate convert -a 100 -c USD -d 2024-01-15Docker API key note: The config --set-key command writes to fetchrate.properties inside the container, which is not persisted across restarts. When running via Docker, set the API key using the FETCHRATE_API_KEY environment variable or through the web UI (the web UI stores it in the database volume, which is persisted).
For a full list of commands and options:
java -jar target/FetchRate-0.5.jar --helpjava -jar FetchRate-0.5.jar convert -a <amount> -c <symbol> -d <YYYY-MM-DD> [--to <symbol>] [--exchange <symbol>]
| Flag | Short | Description |
|---|---|---|
| --amount | -a | Amount to convert. Commas and underscores accepted as thousand separators (e.g. 1,000 or 1_000). |
| --input-currency | -c | Source currency or crypto symbol (e.g. USD, BTC). Case-insensitive. |
| --date | -d | Date in YYYY-MM-DD format. Must not be in the future. |
| --to | -t | (Optional) Target fiat currency (e.g. USD, GBP, JPY). Defaults to EUR. Cannot be combined with --exchange. |
| --exchange | -e | (Optional) Target cryptocurrency (e.g. ETH, SOL). Cannot be combined with --to. |
Examples:
# Convert to EUR (default)
java -jar FetchRate-0.5.jar convert -a 100 -c USD -d 2024-01-15
# Convert to a different fiat currency
java -jar FetchRate-0.5.jar convert -a 100 -c USD -d 2024-01-15 --to GBP
java -jar FetchRate-0.5.jar convert -a 1 -c BTC -d 2024-01-15 --to JPY
# Exchange for another cryptocurrency
java -jar FetchRate-0.5.jar convert -a 1 -c BTC -d 2024-01-15 --exchange ETH
java -jar FetchRate-0.5.jar convert -a 100 -c USD -d 2024-01-15 --exchange SOLAll results are printed to stdout as JSON. Errors are also returned as JSON.
Default output (EUR):
{
"input": {
"amount": "100",
"currencySymbol": "USD",
"date": "2024-01-15"
},
"output": {
"inEuro": "91.37"
}
}With --to or --exchange:
{
"input": {
"amount": "100",
"currencySymbol": "USD",
"date": "2024-01-15"
},
"output": {
"amount": "78.65",
"currency": "GBP"
}
}Fiat output is rounded to 2 decimal places. Cryptocurrency output (--exchange) is rounded to 8 decimal places.
java -jar FetchRate-0.5.jar config --set-key YOUR_API_KEY # Save crypto data provider API key
java -jar FetchRate-0.5.jar config --set-url https://... # Override crypto data provider URL
java -jar FetchRate-0.5.jar config --add-symbol XRP # Add symbol to daily update list
java -jar FetchRate-0.5.jar config --remove-symbol DOGE # Remove symbol from daily update list
java -jar FetchRate-0.5.jar config --list-symbols # Show current tracked symbol listGET /convert?amount=<n>&input_currency=<symbol>&date=<YYYY-MM-DD>[&output_currency=<symbol>]
Returns a JSON response on success, or an error field with an appropriate HTTP status on failure.
The optional output_currency parameter accepts any ECB-tracked fiat currency or cryptocurrency symbol. When omitted or set to EUR, the response uses the default inEuro format. When set to any other currency, the response uses the amount + currency format (same as the CLI --to / --exchange output).
GET /health
Returns {"status": "ok"}.
GET /settings
Returns the current runtime settings: apiKeyConfigured (boolean), providerUrl (string or null), trackedSymbols (array), and trackedSymbolsCustomized (boolean).
POST /settings Content-Type: application/json
Updates one or more runtime settings. Accepted fields: apiKey, providerUrl, addSymbol, removeSymbol. Returns {"status":"saved"} on success or {"error":"..."} on validation failure. This is the programmatic equivalent of the web UI settings panel.
Once the HTTP server is running, a browser interface is available at /.
The web UI supports selecting an output currency via a dropdown (any ECB fiat currency or tracked cryptocurrency). The default output is EUR.
Rates are sourced from the European Central Bank. All 30 ECB-tracked currencies are supported as both input and output:
USD JPY BGN CZK DKK GBP HUF PLN RON SEK CHF ISK NOK TRY AUD BRL CAD CNY HKD IDR ILS INR KRW MXN MYR NZD PHP SGD THB ZAR
The ECB publishes rates on business days only. Requests on a weekend return an error with the nearest Friday suggested. Requests on a public holiday return a not-found error.
Default tracked symbols: BTC, LTC, DOGE, SOL, USDT.
Crypto rates require a compatible data provider API. An API key is required for automatic daily updates and on-demand fetching; without one, only rates loaded from local CSV files are available. Additional symbols can be added via config --add-symbol. Unlike fiat, crypto rates are available for every calendar day including weekends.
The application ships with LiveCoinWatch pre-configured as the default endpoint because it currently offers a free API tier. FetchRate is not affiliated with or endorsed by LiveCoinWatch; it is simply one example of a compatible provider. Any service implementing the same API contract can be used instead (see Custom Provider below).
When the output currency is not EUR, FetchRate uses EUR as an intermediate pivot:
input amount → EUR → output currency
This applies to both --to (fiat output) and --exchange (crypto output).
For fiat output, the ECB rate for the output currency is used. If the requested date falls on a weekend or holiday, the most recent available business day rate is used automatically.
For crypto output, the stored EUR-equivalent rate for that coin on the requested date is used.
Note for tax purposes: This two-step EUR-pivot methodology is consistent with guidance from major tax authorities:
The small rounding difference that may arise from the two-step pivot (versus a direct market rate) is considered immaterial under the "reasonable and consistently applied methodology" standard accepted by all of the above authorities.
The application maintains a local SQLite database in the data/ directory.
| Table | Columns | Purpose |
|---|---|---|
| fiat_rates | date, currency, rate | ECB daily rates (1 EUR = N foreign units) |
| crypto_rates | date, symbol, rate | Crypto rates in EUR per 1 coin |
| meta | key, value | Runtime state: last update timestamps, API key, provider URL |
| tracked_symbols | symbol | Custom crypto symbol list (empty = default list in effect) |
All bulk writes use INSERT ... ON CONFLICT DO UPDATE (upsert), so re-running an update is always safe. The schema is created automatically on first startup.
Rates are refreshed once per day on the first request of the day:
If all sources fail (e.g. no network), the timestamp is not advanced and the next request retries.
If a crypto rate for the requested date is not in the database, the application fetches it on demand and returns the result immediately. The fetched rate is cached in the local database for future requests. If the on-demand fetch also fails (e.g. no API key configured, symbol not found), an error is returned.
Place .csv files in data/crypto/ to seed historical crypto rates without using API credits. The filename must match the coin symbol (e.g. BTC.csv). The supported format is the export from CoinCodex.
FetchRate ships with LiveCoinWatch pre-configured as the default endpoint. If you want to use it, free API keys are available at livecoinwatch.com/tools/api. To use a different provider instead, see Custom Provider below; only the API key and endpoint URL need to change.
Option 1 - Properties file (recommended): create fetchrate.properties next to the jar:
fetchrate.api-key=your_api_key_here
Option 2 - CLI:
java -jar FetchRate-0.5.jar config --set-key your_api_key_here
java -jar FetchRate-0.5.jar config --set-url https://your-provider/endpointOption 3 - Environment variable:
export FETCHRATE_API_KEY=your_api_key_hereWhen running in HTTP mode, the API key and provider URL can also be configured from the web UI under ⚙ API Settings.
CLI vs HTTP settings: The config command and properties file write values that take effect on the next startup. The web UI (HTTP mode) stores values in the local database and they take effect immediately without a restart. If both are configured, the database value takes priority.
The provider URL is fully configurable, so you can swap LiveCoinWatch for any other service or self-hosted proxy, as long as it implements the same API contract:
{"currency":"EUR","code":"BTC","start":<epoch_ms>,"end":<epoch_ms>,"meta":false}{"code":"BTC","history":[{"date":<epoch_ms>,"rate":<eur_price>}, ...]}Set the endpoint via any of the methods above (--set-url, fetchrate.provider-url, or the web UI). The API key field accepts whatever credential the replacement service requires.
The daily update fetches rates for the default set: BTC, LTC, DOGE, SOL, USDT. This list can be customised:
java -jar FetchRate-0.5.jar config --list-symbols
java -jar FetchRate-0.5.jar config --add-symbol XRP
java -jar FetchRate-0.5.jar config --remove-symbol DOGEThe first add or remove seeds the list from the current defaults, so no existing symbols are lost. In HTTP mode the list is also manageable from the web UI.
Copyright (c) 2026 Simon D. All rights reserved. No permission is granted to use, copy, modify, or distribute this project without a written license.
Contact: simon.d.dev@proton.me
| Back | FazBrowse Home | New Git URL |