ScroogeMcDuckCurrencyApi is a multi currency support application, that allows the user to:
- Convert amounts from a currencie to anothers
- Creates it's own currency based on dollar exchange rate
- Execute basic RestFull methods, such as: Find, update, and delete.
This API was built with Flask APP and Flask-restx, therefore it can be used integrated with Swagger.ui interface.
Since Currency ratios are constantly getting updated, it is not possible for a humanbeeing to keep updating all currencies data, in order to convert amounts dynamically. For that reason, ScroogeMcDuckCurrencyApi is integrated with OpenExchangeAPI free Api currency service.
Howerver, once the user checks for a currency or whatever methods, ScroogeMcDuckCurrencyApi will not directly consult OpenExchange, but it's own database. Data that comes from OpenExchange is dynamically updated according to system scheduling configuration, to be explained in configuration section.
ScroogeMcDuckCurrencyApi works based on dollar conversion rate, thus every currency must be converted from its value to dollar, before getting converted into another currency.
Let's make an example:
If you want to convert Scrooge McDuck's own currency into BRL (Brazilian's currency), you must have McDuck's currency dollar conversion rate, or how many McDuck's coins you need to make it into a doller.
Let's say McDuck's dollar conversion rate is 2 (which is not possible since he is way too much rich), then you need 2 McDuck's coins to make a dollar. Nowadays (and this is impressively scary), the dollar conversion rate from BRL to USD(Dollar universal identifier) is 5.22. To convert 5 McDuck's into Reais, we do:
(5/2)*5.22 = 13.05 Reais
In order to use dependency injection concepts and tools, this API uses python Injector. I had to come around with some logics to make it work fine wich performed, IMHO, just fine and looks pretty well.
ScroogeMcDuckCurrencyApi perform cronologic operations to update the database with OpenExchange api.
Dispite the fact that python has planty of libraries for scheduling and queueing, such as: schedule,Croniter or flask-cronjob
, this service does not use such tools, intenting to look for a leanest approach.
ScroogeMcDuckCurrencyApi has a mongoDb database to store data from OpenExchange and inputed by users.
Using mongo makes easy to use the fantastic mongoengine python ORM package, since it provides a much better view of the code with object models.
ScroogeMcDuckCurrencyApi has a pretty nice interface and performs just fine given it's objective, however it does not perform automatic updates for currencies that are not provided by OpenExchange API, in that way, in order to update custom currencies, the user must keep it up to date manually or create a provider to perform updates on the API from its source.
ScroogeMcDuckCurrencyApi source code has some worth looking comments that you can check, by looking for NOTES:
Despite the fact that this application only uses free resources, life is not always a bed of roses, we have some secrets to hide π΅οΈ and some config to do.
In fact, we only have one secret, to be explained as it follows.
OpenExchange provides a Free to use API, but, in order to use this API, you must have an account at open exchange. For that:
- Go to OpenExchange Sign in Page
- Create your account
- Check for your APP ID at APP IDs page
- Replace the field
{YOUR_OPENEXCHANGE_APP_ID_COMES_HERE}
at docker-compose file
Obs: If you intent to run this application using a IDE, just save your Open Exchange app id as an environment variable with name OPENEXCHANGE_APP_ID
.
By default, the API updates the database with openExchange api every 10 minutes, but if you want to increase or decrease (who knows?) this delay, just replace the value of UPDATE_CURRENCIES_MINUTES_SCHEDULE
at docker-compose file
Obs: Just like the previous section, if you are running the api locally in your IDE, update the environment variable UPDATE_CURRENCIES_MINUTES_SCHEDULE
.
First of all, clone the repository:
git clone git@github.com:raul-macedo-freire/currency-challenge-bravo-api.git
In order to run the api, you have two options:
- Run with docker-compose
- Run with an IDE
If you are not used to work with docker, take a look at the docs and install docker-compose.
After getting used to docker, configure the docker-compose file, according to the Api Configuration Section
In the project Folder, run:
docker compose up
Check the application interface at : https://localhost:5000/swagger
Save the environment variables according to the Api Configuration Observations.
If you are not using a dependency manager, I strongly recommend using something like pytest.
If you don't want to use pyenv and go for it installing dependencies into global python environment(who knows?), skip to Installing Dependencies section.
This project uses python 3.10.6, I'll consider that you're using pyenv for python version management, if you're not, check for you dependencies manager configuration and follow the steps below in a equivalent way.
Check the python version:
python --version
If you're not using version 3.10.6, check if you have it installed, with:
pyenv versions
If you don't, install the version with:
pyenv install -v 3.10.6
Then set the version locally:
pyenv local 3.10.6
In the API root directory, create a new python environment:
python -m venv <virtual-env-name>
Activate the virtual environment
source <virtual-env-name>/bin/activate
if you're using windows access the virtual environment with:
.\venv\Scripts\activate
pip install -r requirements.txt
If you're using VSCODE, I have already provided a Run script with a launch file, so if it's the case:
- Save the environment variables in a
.env
file - Run the
run application
script with F5 shortcut.
If you're not using VSCODE, start using it, take a look at your IDE configuration and run the app from the run.py
root file and don't forget to save the environment variables in configuration.
Check the application interface at : https://localhost:5000/swagger
!!!NOTE!!!: If you run the app like this, you won't be able to run api requests, since the database won't be running.
To run all unit tests, use:
python -m pytest
This application uses k6.io tool to perform stress tests. Check the k6 documentation to install the tool.
To run the test, from the application root, enter the tests folder:
cd ./tests
And run the test:
k6 run sovietic_attack.js
Obs1: Don't forget to have the application up and running before running the test
Obs2: In order to performe more accurate the tests for the API, each endpoint must be tested individually, following the considerations, if you want to test each endpoint, uncomment the endpoint and comment the rest (or not, nobody rules you Β―\_(γ)_/Β―
).
If you are really bad with examples and don't know how to start trying the API, take a look at postman_examples. If you don't know postman, I strongly advise you to give it a try :D
currency-challenge-bravo-api
ββ .github
β ββ workflows
β ββ readme.yml
β ββ Tests.yml
ββ .gitignore
ββ .vscode
β ββ launch.json
β ββ settings.json
ββ app
β ββ api.py
β ββ config
β β ββ config.ini
β β ββ config_helper.py
β ββ controllers
β β ββ base_controller.py
β β ββ currencies_controller.py
β β ββ currency_controller.py
β β ββ currency_converter_controller.py
β β ββ __init__.py
β ββ core
β β ββ entities
β β β ββ currency.py
β β β ββ __init__.py
β β ββ exceptions
β β β ββ base_exceptions.py
β β β ββ client_errors
β β β β ββ currency_not_found.py
β β β β ββ parameters_missing_error.py
β β β β ββ validation_error.py
β β β β ββ __init__.py
β β β ββ server_errors
β β β β ββ configuration_error.py
β β β β ββ external_service_error.py
β β β β ββ infra_service_unauthorized.py
β β β β ββ __init__.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ infra
β β ββ models
β β β ββ currency_model.py
β β β ββ __init__.py
β β ββ repositories
β β β ββ currency_repository.py
β β β ββ interfaces
β β β β ββ abstract_currency_repository.py
β β β β ββ __init__.py
β β β ββ __init__.py
β β ββ services
β β β ββ interfaces
β β β β ββ abstract_external_currency_service.py
β β β β ββ __init__.py
β β β ββ open_exchanges_api_service.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ ioc.py
β ββ middleware
β β ββ exception_middleware.py
β β ββ __init__.py
β ββ models
β β ββ input_model
β β β ββ base_input_model.py
β β β ββ currency_converter_query_parameters_input_model.py
β β β ββ currency_input_model.py
β β β ββ update_currency_input_model.py
β β β ββ __init__.py
β β ββ view_model
β β β ββ base_view_model.py
β β β ββ get_currencies_view_model.py
β β β ββ get_currency_view_model.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ scheduler.py
β ββ services
β β ββ converter_service.py
β β ββ currency_service.py
β β ββ interfaces
β β β ββ abstract_converter_service.py
β β β ββ abstract_currency_service.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ update_db_worker.py
β ββ __init__.py
ββ docker-compose.yml
ββ Dockerfile
ββ LICENSE
ββ mongo-init.js
ββ README.es.md
ββ README.md
ββ README.pt.md
ββ requirements.txt
ββ run.py
ββ tests
ββ app
β ββ core
β β ββ entities
β β β ββ test_currency.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ infra
β β ββ repositories
β β β ββ test_currency_repository.py
β β β ββ __init__.py
β β ββ services
β β β ββ test_open_exchanges_api_service.py
β β β ββ __init__.py
β β ββ __init__.py
β ββ services
β β ββ test_converter_service.py
β β ββ test_currency_service.py
β β ββ __ini__.py
β ββ __init__.py
ββ sovietic_attack.js
ββ tests_helper
β ββ factory
β β ββ factory.py
β β ββ __init__.py
β ββ requests_mock.py
β ββ __init__.py
ββ __init__.py