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.
transfer-me/
┣ app/
┃ ┣ domain/
┃ ┃ ┣ account/
┃ ┃ ┣ authentication/
┃ ┃ ┣ entities/
┃ ┃ ┣ transfer/
┃ ┃ ┗ vos/
┃ ┗ gateways/
┃ ┣ db/
┃ ┗ http/
┣ cmd/
┃ ┗ main
┗ Dockerfile
Create an account
- Path:
/accounts
- Method:
POST
- Request body
{
"name": "gopher",
"cpf": "12345678910",
"secret": "mySecret"
}
- 201 Created
{ "id": "7f3412f2-97cd-46de-afa5-35f72f34f3d3", "name": "gopher" }
- 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" }
-
Get the list of accounts
- Path:
/accounts
- Method:
GET
- 200 OK
{ "id": "7f3412f2-97cd-46de-afa5-35f72f34f3d3", "name": "gopher", "cpf": "12345678910" }
- 500 Internal server error
{ "error": "something went wrong" }
Get account balance
- Path:
/accounts/{account_id}/balance
- Method:
GET
- 200 OK
{ "balance": 100 }
-
404 Not Found
{ "error": "not found" }
-
500 Internal server error
{ "error": "something went wrong" }
Authenticate the user with jwt token
- Path:
/login
- Method:
POST
- Request body:
{
"cpf": "12345678910",
"secret": "mySecret"
}
- 201 Created
{ "Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzA5NTI5MjQsImlhdCI6MTYzMDk1MjAyNCwiaWQiOiI5OTRmZDJhOC1kMjJmLTQ2OTMtYWVkYS00Zjk1YmQ4MjIwMjUiLCJpc3MiOiJKV1QiLCJuYW1lIjoiZ29waGVyIiwic3ViIjoiODI0MmU4NWYtYzRhZS00MzY5LWI1Y2YtNTFmNWNlZjlmMzMwIn0.PYcE5gnv7qCBn153HMVnU0lAN7kI95YnugKmqNVhQU0" }
-
400 Bad Request
- When the name or password is incorrect
{ "error": "incorrect username or password" }
- When request body has invalid field types
{ "error": "invalid request payload" }
- When body is empty
{ "error": "invalid fields" }
- When the name or password is incorrect
-
500 Internal server error
{ "error": "unexpected error" }
Transfers from one Account to another.
- Path:
/transfers
- Method:
POST
- Request body:
{
"account_destination_id" : "7f3412f2-97cd-46de-afa5-35f72f34f3d3",
"amount": 30
}
- Header Params:
{
"Authorization" : "Bearer Token"
}
- 201 Created
{ "id": "7f3412f2-97cd-46de-afa5-35f72f34f3d3" }
-
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" }
- When authorization header is empty
-
403 Forbidden
{ "error": "invalid token" }
-
500 Internal server error
{ "error": "something went wrong" }
Get the list of transfers from the authenticated user.
-
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" }
- 500 Internal server error
{ "error": "something went wrong" }
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 |
To download it with Go previously downloaded:
$ go mod download
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
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
Run the command:
$ make test
To see the coverage run the command at the root of the project:
$ go test -cover ./...
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.