Transfer-me
It is an API designed to perform internal transfers between digital bank accounts.
This application allows you to: create an account, list accounts, consult the account balance, be authenticated and make transfers to other accounts.
Based on Clean architecture
transfer-me/
┣ app/
┃ ┣ domain/
┃ ┃ ┣ account/
┃ ┃ ┣ authentication/
┃ ┃ ┣ entities/
┃ ┃ ┣ transfer/
┃ ┃ ┗ vos/
┃ ┗ gateways/
┃ ┣ db/
┃ ┗ http/
┣ cmd/
┃ ┗ main
┗ Dockerfile
Project Overview
Endpoints
Create Accounts
Create an account
Request
- Path:
/accounts
- Method:
POST
- Request body
{
"name": "gopher",
"cpf": "12345678910",
"secret": "mySecret"
}
Response successful
Response error
- 400 Bad Request
-
When request body has invalid fields
{
"error": "invalid cpf"
}
-
When request body has invalid field types
{
"error": "invalid request payload"
}
-
When body is empty
{
"error": "invalid fields"
}
-
When account already exist
{
"error": "account already exist"
}
List Accounts
Get the list of accounts
Request
- Path:
/accounts
- Method:
GET
Response successful
Response error
Get Balance
Get account balance
Request
- Path:
/accounts/{account_id}/balance
- Method:
GET
Response successful
- 200 OK
{
"balance": 100
}
Response errors
Login
Authenticate the user with jwt token
Request
- Path:
/login
- Method:
POST
- Request body:
{
"cpf": "12345678910",
"secret": "mySecret"
}
Response successful
Response errors
Create Transfers
Transfers from one Account to another.
Request
- Path:
/transfers
- Method:
POST
- Request body:
{
"account_destination_id" : "7f3412f2-97cd-46de-afa5-35f72f34f3d3",
"amount": 30
}
{
"Authorization" : "Bearer Token"
}
Response errors
-
400 Bad Request
- When authorization header is empty
{
"error": "empty authorization header"
}
- When access token is empty
{
"error": "empty token"
}
- When the authentication method is wrong
{
"error": "invalid auth method"
}
- When request body has invalid field types
{
"error": "invalid request payload"
}
- When request body is empty
{
"error": "invalid fields"
}
- When destination cpf is not found
{
"error": "invalid transfer data"
}
- When amount is invalid
{
"error": "the amount must be greater than zero"
}
-
403 Forbidden
{
"error": "invalid token"
}
-
500 Internal server error
{
"error": "something went wrong"
}
List Transfers
Get the list of transfers from the authenticated user.
Request
-
Path: http://localhost:8000/transfers
-
Method: GET
-
200 OK
{
"id": "7f3412f2-97cd-46de-afa5-35f72f34f3d3",
"amount": 50,
"account_origin_id": "014918d1-577c-4045-a415-a325bee3b1bd",
"account_destination_id": "6a00ac20-e07f-455f-a53c-37088c7b4277",
"created_at": "2021-09-23T11:20:55.774779-03:00"
}
Response error
Environment variables
The existing environment variables in the application are listed below followed by their descriptions:
Name |
Description |
ACCESS_SECRET |
sign key to generate jwt |
API_PORT |
port to start application |
DB_USER |
database user |
DB_PASSWORD |
database secret |
DB_NAME |
database name |
DB_HOST |
database host |
DB_PORT |
database port |
DB_SSLMODE |
database SSL mode |
LOG_LEVEL |
application structured log level |
Stack
To download it with Go previously downloaded:
$ go mod download
Starting (Docker required)
You can use the makefile to make it easier to build and run the application.
A typical day to day would be:
$ make postgres
$ make createdb
$ make build (local)
$ make build-image (docker)
$ make run
$ make test
Hands On with Moq
We're using moq to mock use cases.
How to use:
- Indicate the interface you want to mock inserting a "//go:generate" instruction inside the code, like this:
package account
//go:generate moq -stub -out use_case_mock.go . UseCase
type UseCase interface {
Method1() error
Method2(i int)
}
- Run
go generate
indicating the location of the interface you want to mock, like this:
go generate ./app/domain/account/usecase.go
Unit Tests
Run the command:
$ make test
To see the coverage run the command at the root of the project:
$ go test -cover ./...
License
MIT
Acknowledgments
Special thanks to all the authors of the libraries we use and the contents, videos and articles, on which I based this application.
Thanks also to my mentors and code reviewers.