/gopher-trade

Currency Conversion API

Primary LanguageGoMIT LicenseMIT

Gopher Trade

Gopher Trade is a currency conversion API built in Go. It works by getting live default currencies (BTC, ETH, EUR and BRL) rates on startup and setting it to cache (with a hard coded TTL of 5 minutes). Custom currencies can be created and persisted in the server database. After cache expires, the first request for a conversion involving a default rate will get its value from an external API and set it to cache. References are scattered as links through this README.

Contents

Features

Project (development) and product (API) features:

Development

  • CI (GitHub Actions) - Runs tests, linters and compares generated files on Pull Requests to main (which is a protected branch);
  • Lint (golangci-lint) - Enforces style and best practices;
  • Makefile - Simplifies running tests, dependencies and application.
  • Docker Compose - Runs API and dependencies with no configuration and on any OS/arch
  • Load testing - Includes ddosify load testing tool configuration.

API

Gopher Trade allows users to register custom currency rates based on USD, get conversions from and to custom or default (USD, BRL, EUR, ETH, BTC) currencies. In the default currencies case, external APIs (Exchange Rate and Crypto Compare) are used.

On the client.http file in the root of this repository you can find examples of how to use the available endpoints. You can also view and try out available endpoints on Swagger UI. After running the app, access http://localhost:3000/swagger (if you ran with default config).

Future improvements

This project was developed with a 10 day deadline, so some features/implementations had to be left out:

  • Set env var for cache timeout;
  • Create .env file to run project locally (for development);
  • Structured logging;
  • Unit tests for clients;
  • End to end tests;
  • Refactor error payloads;
  • Endpoint to list all available currencies;
  • Fallback for when an external API is unavailable;
  • Assess the use of Strategy pattern for conversion use case (to decide to get conversion from repository or client);
  • Implement authentication and authorization (only allow currency creator to edit its value).

Testing

This project does not aim to have 100% test coverage. Also, its development did not follow strict TDD doctrine, instead it aimed to test behaviour.

To run all automated tests (unit and integration):

make test

There is a preconfigured load test tool in the load_test directory at the root of this folder. To install and run, (with the api running - see running locally section below) just enter

make load-test

in your terminal. The tool is preconfigured to make 1000 requests in 1 second to each available endpoint. To adjust values, check out the ddosify docs.

Locally tests are resulting 100% success rate.

Running locally

Just enter:

make api

in your terminal and voilĂ ! It will run an image of a postgres db and the Gopher Trade API on docker containers. To stop you can use:

make stop

And to see the db and app logs:

make logs

Application Dependencies

This project imports external packages (list does not include development tools installed in some makefile commands):

Tech Specs

Architecture

Aiming to make this project more scalable and maintainable, it is being developed based on Clean Architecture.

Number types

The first idea in this project was to use integer values for monetary values (representing in cents), for simplicity. However, specificities of currency exchange made this a bad alternative, i.e., non-fiat currencies (such as criptocurrencies) and exchange rates being commonly measured and represented with more than 2 decimal points.

Considering the floating-point arithmetic problem, the decimal package was used (initially using the standard lib math/big package was considered, but given the scope of the project and the time constraint, using an external lib was considered the best trade-off).

Workflow

A very basic Kanban board was used to keep track of priorities and deadline for the project. It was kept simples since the project is being developed by one person. For this purpose, GitHub Projects showed to be enough.

Given the time constraint (deadline and hours available during the day), an MVP was planned, an some improvements indicated in the Backlog.

The conventional commits standard was followed during the development of the project. Pull Requests were opened for each feature (although without code review, but for the sake of having a stable main branch - and prettier commit log), mocking a trunk-based development.