go-crypto

Introduction

Framework

License Maintaned Commits Forks Stars Watchers

This project is the back-end prototype of a crypto wallet application I developed with the Go programming language during my internship at ProxoLab company.

I would also like to mention that I learned the Go programming language alongside this project. Additionally, this project allowed me to learn various DevOps concepts.

When I started writing the project, I had searched for many such examples, but the examples I found always had shortcomings. I am sure that there are many aspects of this project that can be improved. However, I believe it is an excellent example project because I designed it with this year’s most commonly used technologies and best practices.

Table of Contents

To-do List

While working on this project, you can find below the expectations that the company I interned at had from me:

Developer Tips

Getting Started

Docker

As you probably know, running a single Go file is not so hard. But when it comes to running a project with multiple dependencies, it gets a little bit complicated. And Docker comes to the rescue in this situation. You can run the project with a single command using Docker. You also need Docker for deployment purposes.

Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and deploy it as one package.

Docker can get your project up and running in a few minutes. But that’s not enough for a project like this. You need to monitor your project, test it, and more. And for that you need to install some other tools like Prometheus, Grafana, K6, Postgres.

[!NOTE]
Both ways uses Docker Engine to run the project. You can install Docker Engine from here.

Compose Setup

Compose Setup uses Docker Compose to run the project. Which is a tool designed to run multi-container applications. You need to configure a file named “docker-compose.yml” to install all the containers needed and run the project. You can Click here to learn more about Docker Compose.

Go Crypto runs with the following containers:

Container Description
Go-Crypto Runs the main project. Docker file can be found at project directory.
Notifier Runs the micro service that sends the mails.
K6 Runs a script that simulates connection load to test servers.
Postgres Database to store user data.
Prometheus Database to store metric data.
Loki Database to store logs.
Grafana Analytics visualizer interface.
ZooKeeper Micro service manager.
Kafka Queue for micro services.
Kafka UI Interface for kafka. Used for development purposes

These containers all work together to run the project.

Requirements

You need to install the following tools to run the project with Docker Compose:

Installation

Kubernetes Setup

Kubernetes

Kubernetes is an open-source container orchestration platform used for automating the deployment, scaling, and management of containerized applications.

Kubernetes can automatically scale your applications based on demand, ensuring that you have the right amount of resources to handle your workload.

Horizontal vs Verical scaling up

To understand what is Horizontally Scaling, first you should know what is Verical Scaling.

Vertical scaling, aka. scaling up, is a method used to increase the capacity and performance of a single server or machine by adding more resources to it (eg. RAM, CPU).

And Horizontal scaling, aka. scaling out, is a method used to increase the capacity and performance of a system by adding more machines or nodes to a network or cluster.

You can scale out Go-Crypto by the following steps:

And that’s it, you are ready to go! Kubernetes will automatically boot up the containers and scale them based on demand. Altho you will still need to run the other containers with docker-compose.

Here is the list of containers that will be running with Kubernetes:

Beside these containers, you will still need to run the rest of the containers with docker-compose.

Kubectl

Kubectl is a command-line tool that allows you to run commands against Kubernetes clusters. You can use kubectl to deploy applications, inspect and manage cluster resources, and view logs.

You can find some useful commands below:

Lens

Lens is a powerful IDE for Kubernetes. It is a standalone application for MacOS, Windows and Linux operating systems. You can use Lens to monitor your Kubernetes cluster.

Lens

Project Design

This project is a REST API project, and it has been built using the Multitier Architecture design. The Multitier Architecture design is a REST API pattern consisting of layers named Controller (Presentation), Service (Business), and Repository (Persistence).

Technologies

You can find the technologies used in this project below:

Ports

The ports exposed by the project are:

Name Port Description
Fiber 80 Rest API itself.
Swagger 8080 Auto generated documentation for API.
Grafana 3000 Monitoring interface.
Postgres 5432 Database
Prometheus 9090 Metric database.
Loki 3100 Log database.
ZooKeeper 2181 Micro services.
Kafka 9092 Micro services.

Some ports are exposed on development purposes.

Folder Structure

This project follows common designs used in the back-end of web applications. Here is the project tree with comments explaining the modules, files, and their purposes:

.
├── controllers # Endpoints (aka Presentation layer)
   ├── exchanges.go
   ├── user.go
   └── wallet.go
├── core # Core components
   ├── config.go # Retrieve environment variables
   └── database.go # Initialize database connection
├── helpers # Utilities
   ├── database.go # Database utilities
   ├── errors.go # HTTP Errors (e.g 404, 403, 400)
   ├── password.go # Password hashing, comparing
   ├── token.go # JWT utilities
   └── validate.go # Payload validations
├── log
   ├── local.go # Logging functions for local logs.
   └── log.go # Logging functions for Loki.
├── main.go
├── middleware
   ├── auth.go # Authorization with JWT
   ├── json.go # Adds header accepts "application/json"
   ├── metrics.go # Monitoring
   └── websocket.go # Return error if websocket request missing upgrade header.
├── models # Database & API models
   ├── exchanges.go
   ├── transaction.go
   ├── user.go
   └── wallet.go
├── repositories # Repository layer (aka Persistance)
   ├── exchanges.go
   ├── user.go
   └── wallet.go
├── router # Routes
   └── router.go
└── services # Service layer (aka Bussiness layer)
    ├── exchanges.go
    ├── user.go
    └── wallet.go

Models

The module called “Models” is the boilerplate that represents data structures used in the background of web applications. Models are used to introduce raw data into the programming language being used. Here are the models for this project:

Crypto API

Coinbase

Coinbase’s free to use public API (v2) is used to fetch crypto exchange data. Here you can find the endpoint below:

https://api.coinbase.com/v2/exchange-rates?currency=BTC

Auto Documentation

Swagger

Swagger is a tool that helps developers to create document and test APIs (Application Programming Interfaces) for their software applications.

Swaggo

Swagger needs a configuration file to create documents. This configuration is automatically generated by Swaggo from your comment lines.

You can read the documentation from “localhost:8080” once you started docker.

Monitoring

Prometheus and Grafana are tools used for monitoring and analyzing metrics of a web application. With Grafana and Prometheus, you can analyze a wide range of data, from sales metrics to resource utilization and more.

Prometheus

Prometheus is a software that collects “metric” data from the http servers by requesting a specific endpoint at target servers at intervals you specified. The metric data is stored chronologically by the Prometheus. Data can be accessed via web interface or Rest API that Prometheus provides.

Prometheus web interface

Grafana

And Grafana is an open source analytics monitoring tool that provides bunch of visual components like (e.g charts, gauges). Grafana can have multiple data sources and Prometheus is one of them. Grafana can request to API of the Prometheus and visualize your chronologically stored metrics data.

I’ve configured Prometheus to gather default Go Metrics from Go Fiber and visualized some of those metrics in Grafana as can be seen in the picture below:

monitoring

Logging

This project uses two different methods for logging. One is for local logging with simple print functions and the other is for advanced logging for customers.

Traditional Logging

I’ve used traditional local logging functions for the stuff that only concerns developers.

traditional logging

Loki

Loki is an open-source log aggregation system developed by Grafana Labs. It is designed to help you collect, store, and query log data from various sources in a scalable and efficient manner.

In this project, I used Loki for advanced logging. And I used zap-loki library for establishing the connection between Go and Loki.

Monitoring Loki data source in Grafana:

logging

Load Test

The term load testing is used in different ways in the professional software testing community. Load testing generally refers to the practice of modeling the expected usage of a software program by simulating multiple users accessing the program concurrently. (https://en.wikipedia.org/wiki/Load_testing)

I’ve used “Grafana K6” to load test this project. K6 has a very simple interface.

Using K6

First, you should create a JavaScript file for K6, as mentioned, named “scripts/loadtest.js”.

This script, using the framework provided by K6, allows you to quickly send load requests to your web application. You can also perform checks on responses using the functions provided by K6.

K6 is originally designed to export metrics to a data source called InfluxDB. However, you can obtain output for Prometheus using the experimental Prometheus Remote Write module.

Monitoring Test Results

The output obtained from Prometheus can be visualized using the Grafana interface, as explained in the “Monitoring” section.

loadtest monitoring

API

Endpoints

Uncategorised Endpoints

GET /api/exchange-rates/ #### Description Lists the crypto currency exchange rates. #### Response ```json { "currency": "USD", "rates": { "00": 13.651877133105803, "1INCH": 3.898635477582846, "AAVE": 0.0159936025589764, "ABT": 13.708019191226867, "ACH": 64.1148938898506, ... } ```

User Endpoints

POST /api/user/login/ #### Description Returns auth token if matching credentials provided. #### Parameters | Name | Type | Description | |----------|--------|--------------| | mail | string | Mail address | | password | string | Password | #### Response ```json { "status": true, "message": "OK!", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOjF9.HBNfNTMv3Jd9Wf-m3v6buHgGLQL0Srl8zwGro8JHcO4" } ```
POST /api/user/register/ #### Description Creates a new account if provided details are appropriate. If verification code is not provided, it will try to send a verification code to the mail address provided. If the bool named "verificationSent" in response data is true, you must have received the mail address. #### Parameters | Name | Type | Description | |--------------|--------|-------------------| | name | string | First name | | lastName | string | Last name | | mail | string | Mail address | | password | string | Password | | verification | string | Verification code | #### Response ```json { "status": true, "message": "OK!", } ```
GET /api/user/me/ #### Description Returns user information. #### Parameters Auth required #### Response ```json { "id": 1, "lastname": "Batulu", "mail": "[email protected]", "name": "Yahya" } ```

User Wallet Endpoints

GET /api/user/wallet/balance/ #### Description Returns user balance. #### Parameters Auth required #### Response ```json { "BTC": 40990.47869000058, "USD": 995270.5766880848 } ```
POST /api/user/wallet/deposit/ #### Description A money deposit endpoint. Virtual POS not implemented. It's just a prototype. #### Parameters Auth required | Name | Type | Description | |--------|-------|-----------------------------| | amount | float | Amount of money to deposit. | #### Response ```json { "status": true, "newBalance": 64.05993807839195, "message": "OK", } ```
POST /api/user/wallet/withdraw/ #### Description A money withdraw endpoint. #### Parameters Auth required | Name | Type | Description | |--------|-------|------------------------------| | amount | float | Amount of money to withdraw. | #### Response ```json { "status": true, "newBalance": 64.05993807839195, "message": "OK", } ```
POST /api/user/wallet/buy/ #### Description Performs a crypto purchase and returns success or failure depending on the result. #### Parameters Auth required | Name | Type | Description | |----------|--------|--------------------------| | amount | float | Amount of crypto to buy. | | currency | string | Currency to buy | #### Response ```json { "message": "OK!", "status": true, // Success state "Balance": { // New balance "BTC": 1.0053999999999998, "USD": 64.05993807839195 }, "sold_amount": 135.72802500006378, "sold_currency": "USD", "bought_amount": 0.005, "bought_currency": "BTC", } ```
POST /api/user/wallet/sell/ #### Description Performs a crypto selling and returns success or failure depending on the result. #### Parameters Auth required | Name | Type | Description | |----------|--------|---------------------------| | amount | float | Amount of crypto to sell. | | currency | string | Currency to sell. | #### Response ```json { "message": "OK!", "status": true, "Balance": { "BTC": 995270.5766880848, "USD": 40990.47869000058 }, "bought_amount": 135.17072499994828, "bought_currency": "USD", "sold_amount": 0.005, "sold_currency": "BTC", } ```

Websocket

WS /ws/exchange-rates #### Description Returns exchange-rates as it changed. #### Response ```json { "currency": "USD", "rates": { "00": 13.651877133105803, "1INCH": 3.898635477582846, "AAVE": 0.0159936025589764, "ABT": 13.708019191226867, "ACH": 64.1148938898506, ... } ```

Copyright

This project is licensed under the terms of the MIT License.

You are free to use this project in compliance with the MIT License. If you decide to use, modify, or redistribute this software, you must include a copy of the original license and copyright notice in all copies or substantial portions of the software.

For more information about the MIT License, visit: MIT License.