Code Monkey home page Code Monkey logo

simple-wallet's Introduction

Simple Wallet RESTful API

The name of the project is pretty much descriptive enough. To add a little more on the name, the application does the stuff you need from a digital wallet i.e.

  1. Registration and Login
  2. Account Deposit
  3. Account Withdrawal
  4. Balance Enquiry
  5. Mini Statement

PS. This is fully a backend application with no front end client whatsoever. You can use curl, postman or your favourite http tool to interact with the application.

You can follow the below steps to install and setup the application.

Installation

To begin with the application uses postgres as the backend database.

Database Installation

The application uses postgres as the database server. So here are instructions on how to setup postgresql on your machine using docker.

Get the official postgres docker image.

$ docker pull postgres

Then create a container from the image with the following variables

$ docker create \
--name wallet-db \
-e POSTGRES_USER=wallet \
-e POSTGRES_PASSWORD=wallet \
-p 5432:5432 \
postgres

Run the following command to start the container

$ docker start wallet-db

Simple Wallet Installation

Running the application is as simple as running any other go application but first we need to copy and create our configuration.

Lets begin. Cloning ...

$ git clone https://github.com/SirWaithaka/simple-wallet.git

Configuring

$ cd simple-wallet
$ cp config.yml.example config.yml

This configuration file looks something like this

database:
  host: "127.0.0.1"
  port: "5432"
  user: "wallet"
  password: "wallet"
  dbname: "wallet"

app_secret_key: "eQig7GS4cHO2su"

You can change the config variables depending on your database setup, here i choose to follow the default setup shown at database installation step.

Building and running

Using the Binary
$ cd main
$ go build wallet-server.go
$ ./wallet-server

It will install all dependencies required and produce a binary for your platform.

Using the Dockerfile

Make sure you have docker installed and working properly.

$ docker build -t simple-wallet:latest .
$ docker container create --name wallet-server -p 6700:6700 --restart unless-stopped simple-wallet
$ docker container start wallet-server

The server will start at port 6700.

Enjoy.

API

A description of the api.

Endpoints

All the routes exposed in the application are all defined in this function

func apiRouteGroup(g fiber.Router, domain *registry.Domain, config app.Config) {

	g.Post("/login", user_handlers.Authenticate(domain.User, config))
	g.Post("/user", user_handlers.Register(domain.User))

	g.Get("/account/balance", middleware.AuthByBearerToken(config.Secret), account_handlers.BalanceEnquiry(domain.Account))
	g.Post("/account/deposit", middleware.AuthByBearerToken(config.Secret), account_handlers.Deposit(domain.Account))
	g.Post("/account/withdrawal", middleware.AuthByBearerToken(config.Secret), account_handlers.Withdraw(domain.Account))
	g.Post("/account/withdraw", middleware.AuthByBearerToken(config.Secret), account_handlers.Withdraw(domain.Account))

	g.Get("/account/statement", middleware.AuthByBearerToken(config.Secret), account_handlers.MiniStatement(domain.Transaction))
}

The routes are mounted on the prefix /api so your requests should point to

POST /api/login
POST /api/user # for registration
GET /api/account/balance
POST /api/account/deposit
POST /api/account/withdrawal
GET /api/account/statement

To Register

A user can be registered to the api with the following POST parameters firstName, lastName, email, phoneNumber, password

Curl request example

curl --request POST \
  --url http://localhost:6700/api/user \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data firstName=Sir \
  --data lastName=Waithaka \
  --data [email protected] \
  --data phoneNumber=254700000000 \
  --data password=mnbvcxz

Response example

{
    "status": "success",
    "message": "user created",
    "user": {
        "email": "[email protected]",
        "userId": "b4b00501-ba22-49fb-827d-b25d969c58bb"
    }
}

To Login

You can use email and password or phoneNumber and password

Curl request example

curl --request POST \
  --url http://localhost:6700/api/login \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data password=mnbvcxz \
  --data phoneNumber=254700000000

Response example

{
    "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6Ijg0ODA5YTAyLTkwODItNGFlMy05MDQ3LTM4NDA5NDhjNTdjZiIsImVtYWlsIjoiaGFsbEBlbWFpbC5jb20ifSwiZXhwIjoxNTg0MDI0NTQ0LCJpYXQiOjE1ODQwMDI5NDR9.qZHLJWtYK7_ClgnaPJbGuaiPW8ssd1Ra9xFJWdg6iwE"
}

NOTE: The remaining endpoints require the token acquired above for authentication

To Deposit

You only need the amount parameter

Curl request example

curl --request POST \
  --url http://localhost:6700/api/account/deposit \
  --header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6Ijk4YmNmMmY1LWRiY2ItNDk1NS04NTU0LTc0OWYxMTVhZjU5OCIsImVtYWlsIjoiIn0sImV4cCI6MTYwNDA2Mjg0NiwiaWF0IjoxNjA0MDQxMjQ2fQ.Z0oFwOV3wEiQzpwLg4LH5NZIBUsllDhcJefgvceMiHw' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data amount=1000

Response example

{
  "balance": 1000,
  "message": "Amount successfully deposited new balance 1000",
  "userId": "98bcf2f5-dbcb-4955-8554-749f115af598"
}

To Withdraw

You only need the amount parameter

Curl request example

curl --request POST \
  --url http://localhost:6700/api/account/withdrawal \
  --header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6Ijk4YmNmMmY1LWRiY2ItNDk1NS04NTU0LTc0OWYxMTVhZjU5OCIsImVtYWlsIjoiIn0sImV4cCI6MTYwNDA2OTE0MywiaWF0IjoxNjA0MDQ3NTQzfQ.IYyclrC66aweehs_A4Sigmc83a27udmPofM2yOeut9Q' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data amount=40

Response example

{
  "balance": 880,
  "message": "Amount successfully withdrawn. New balance 880",
  "userId": "98bcf2f5-dbcb-4955-8554-749f115af598"
}

To Query Balance

This is just a GET request, no params

Curl request example

curl --request GET \
  --url http://localhost:6700/api/account/balance \
  --header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6Ijk4YmNmMmY1LWRiY2ItNDk1NS04NTU0LTc0OWYxMTVhZjU5OCIsImVtYWlsIjoiIn0sImV4cCI6MTYwNDA2Mjg0NiwiaWF0IjoxNjA0MDQxMjQ2fQ.Z0oFwOV3wEiQzpwLg4LH5NZIBUsllDhcJefgvceMiHw'

Response example

{
    "message": "Your current balance is 4700",
    "balance": 4700
}

To Get Mini Statement

This is just a GET request, no params

Curl request example

curl --request GET \
  --url http://localhost:6700/api/account/statement \
  --header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6Ijk4YmNmMmY1LWRiY2ItNDk1NS04NTU0LTc0OWYxMTVhZjU5OCIsImVtYWlsIjoiIn0sImV4cCI6MTYwNDA2OTE0MywiaWF0IjoxNjA0MDQ3NTQzfQ.IYyclrC66aweehs_A4Sigmc83a27udmPofM2yOeut9Q'

Response example

{
    "message": "ministatement retrieved for the past 5 transactions",
    "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
    "transactions": [
        {
            "transactionId": "1088b880-1aa1-4cf0-929b-dfab01c52c13",
            "transactionType": "balance_enquiry",
            "timestamp": "2020-03-12T13:11:09.863693Z",
            "amount": 4700,
            "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
            "accountId": "fd1ce4e4-e467-4eac-8ea0-ea0c9d4f76fe"
        },
        {
            "transactionId": "8b64ca58-b869-47b6-964a-0846957d4c7f",
            "transactionType": "withdrawal",
            "timestamp": "2020-03-12T12:30:37.355034Z",
            "amount": 4700,
            "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
            "accountId": "fd1ce4e4-e467-4eac-8ea0-ea0c9d4f76fe"
        },
        {
            "transactionId": "4514a94c-f303-4324-b010-a4e7c3dd3f77",
            "transactionType": "withdrawal",
            "timestamp": "2020-03-12T12:30:36.278053Z",
            "amount": 4710,
            "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
            "accountId": "fd1ce4e4-e467-4eac-8ea0-ea0c9d4f76fe"
        },
        {
            "transactionId": "871035ad-456a-4467-8260-414b464b6d86",
            "transactionType": "withdrawal",
            "timestamp": "2020-03-12T12:30:35.446227Z",
            "amount": 4720,
            "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
            "accountId": "fd1ce4e4-e467-4eac-8ea0-ea0c9d4f76fe"
        },
        {
            "transactionId": "c3c3a19a-fc3a-4080-9b52-5d3e19853cd7",
            "transactionType": "withdrawal",
            "timestamp": "2020-03-12T12:30:34.646326Z",
            "amount": 4730,
            "userId": "84809a02-9082-4ae3-9047-3840948c57cf",
            "accountId": "fd1ce4e4-e467-4eac-8ea0-ea0c9d4f76fe"
        }
    ]
}

Testing

Tests have not been written for the application but i have very important talks i would share here that i cant recommend enough about how to go about testing the application.

  1. Ian Cooper - TDD, Where Did It All Go Wrong

An approach to testing this application would be something in the following lines.

  1. Test the code in the interactor files
  2. Test the code in the repository files

The above files carry the bulk of the behaviour of the whole application, they are the business logic of the application. The rest of the files are just implementation details that could change rapidly and the tests written for them would certainly fail after change.

e.g. the http handler functions in the application use gofiber, writing unit tests for them is good but not desired, because gofiber can be replaced with mux easily and that would break your tests.

simple-wallet's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

simple-wallet's Issues

Change build script directory

Hello Sir Waithaka? You did an amazing job with this repository. Just to mention that the Readme file has a typing error which could easily confuse any person that is following. The application build script is inside the cmd directory but your instructions point to main directory which does not exist. Maybe you could change that too

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.