This is a simple Rest API for caching fiat-conversion rates from a third-party API, and may potentially serve other useful data in the future. This API is built on Python, Flask, and Redis. Data from a third-party API are stored as a hashmap in Redis with a designated TTL. The client can either use the timestamp of the original third-party request for each token and currency, or the timestamp of the request to this API to determine a sane time to refetch results. Each token and currency combination is requested and cached individually.
# Create a virtual environment
python3 -m venv venv
# Activate the virtual environment
. venv/bin/activate
# Install dependencies
pip install -r requirements.txt
export FLASK_APP=src/api
flask run
# Your server will be available at http://127.0.0.1:5000/
# Make sure to send requests with the x-api-key header value which
# matches the key in your .env file
Create a .env
file with the following keys defined:
# Key used by x-api-key header to authorize protected routes - REQUIRED
API_KEY="THIS_IS_MY_API_KEY"
# Redis authentication - REQUIRED (if your Redis host requires AUTH)
REDIS_PASSWORD="MY_REDIS_SECRET"
# Redis host (if not localhost) - OPTIONAL
REDIS_HOST="domain.of.redishost"
# Redis port (if not default) - OPTIONAL
REDIS_PORT=6379
# Redis db, defaults to 0 - OPTIONAL
REDIS_DB=0
# API KEY for rest.coinapi.io - REQUIRED
THIRD_PARTY_KEY="xxxxxx-xxxx-xxxxxx-xxxxxxxxx-xxxxxxxx"
# Exchange Rate API URL - OPTIONAL
EXCHANGE_RATE_API="https://rest.coinapi.io/v1/exchangerate"
# TTL for cached API queries (third-party), defaults to 7200 (2 hours) - OPTIONAL
TTL = 3600
Additionally, see DEFAULTS
in config.py
for setting default tokens, currencies, etc.
/api/v1
- Version info/api/v1/rates
- Get default conversion rates (GET
|POST
)/api/v1/rates?coins=BTC,ETH,DOT
- Specify coins for which to query. Default currencies will be used./api/v1/rates?currencies=USD,EUR
- Specify currencies. Default coins will be used./api/v1/rates?coins=BTC,ETH,DOT,ATOM¤cies=USD,YEN,EUR
- Specify both coins and currencies, no defaults./api/v1/health
- Health check/api/v1/env
- Environment variables
POST Example with cURL
NOTE You can specify coin
or coins
, currency
or currencies
as the GET
request parameters with similar effect.
NOTE POST
requests can also be sent as JSON data, passing coins
and/or currencies
as JSON parameters. Passing no arguments in a POST
or GET
will return the API default values.
curl --request POST http://127.0.0.1:5000/api/v1/rates --header "X-Api-Key:MY_SECRET_API_KEY" --data "coins=BTC,EUR¤cies=USD,EUR,YEN"
# Optionally, pipe it through jq for formatting JSON
curl --request POST http://127.0.0.1:5000/api/v1/rates --header "X-Api-Key:MY_SECRET_API_KEY" --data "coins=BTC,EUR¤cies=USD,EUR,YEN" | jq
SAMPLE OUTPUT
{
"data": {
"BTC": {
"EUR": {
"coin": "BTC",
"currency": "EUR",
"rate": 23268.18602491288,
"timestamp": "2022-07-20T13:05:06.0000000Z"
},
"USD": {
"coin": "BTC",
"currency": "USD",
"rate": 23838.256582523245,
"timestamp": "2022-07-20T13:05:06.0000000Z"
},
"YEN": {}
},
"EUR": {
"EUR": {
"coin": "EUR",
"currency": "EUR",
"rate": 1.0,
"timestamp": "2022-07-20T13:18:07.6269666Z"
},
"USD": {
"coin": "EUR",
"currency": "USD",
"rate": 1.0245,
"timestamp": "2022-07-20T13:17:57.0000000Z"
},
"YEN": {}
}
},
"timestamp": 1658323087.77571
}
NOTE In this example, no conversion rates were found for YEN
, which results in an empty JSON object. Empty results are not cached, and will be refetched on the next request.
Using redis-cli
, we can inspect the cached values from our third-party requests.
redis-cli
If authentication is required, enter the proper password (as defined in .env
):
AUTH <my-secret-redis-password>
Inspecting the stored keys following a request, you may see something like the following:
127.0.0.1:6379> keys *
1) "DOT/USD/expires"
2) "DOT/USD"
3) "BTC/USD/expires"
4) "BTC/USD"
...
As the API results are cached as hashmaps (which, in Redis, do not accept a TTL), an /expires
key/value is set, expiring when the configured TTL has been reached. These keys are checked to determine when a refetch should occur, which will overwrite the cached hashmaps. We can inspect one of these hashmaps as such:
127.0.0.1:6379> hgetall "BTC/USD"
The value for the /expires
key, e.g., BTC/USD/expires
, is set to TTL it was given:
127.0.0.1:6379> get "BTC/USD/expires"
"7200"
- Use the same format and type for timestamps.
- Any error responses from the third-party API should be passed on to the client for handling.
- Add SimpleCache or Memcached for any non-Redis-cached routes