Skip to content

Commit

Permalink
feat: contract history
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmagnus committed Dec 6, 2023
1 parent 5f32b6d commit 1d949c3
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 40 deletions.
160 changes: 158 additions & 2 deletions backend/internal/controller/http/v1/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ type contractRoutes struct {
c usecase.ContractUseCase
v usecase.VaultUseCase
as usecase.AssetUseCase
u usecase.UserUseCase
l *logger.Logger
}

func newContractRoutes(handler *gin.RouterGroup, m HTTPControllerMessenger, a usecase.AuthUseCase, c usecase.ContractUseCase, v usecase.VaultUseCase,
as usecase.AssetUseCase, l *logger.Logger,
as usecase.AssetUseCase, u usecase.UserUseCase, l *logger.Logger,
) {
r := &contractRoutes{m, a, c, v, as, l}
r := &contractRoutes{m, a, c, v, as, u, l}
h := handler.Group("/contract").Use(Auth(r.a.ValidateToken()))
{
h.GET("/:id", r.getContractById)
h.POST("", r.createContract)
h.GET("/list", r.getAllContracts)
h.GET("/history/:contractId", r.getContractHistory)
h.POST("/history/", r.addContractHistory)
h.PUT("/history/", r.updateContractHistory)
}
}

Expand All @@ -44,6 +48,16 @@ type CreateContractRequest struct {
Compound int `json:"compound" example:"1"`
}

type AddContractHistoryRequest struct {
DepositAmount float64 `json:"deposit_amount" binding:"required" example:"100"`
ContractId int `json:"contract_id" binding:"required" example:"GSDSC..."`
}

type UpdateContractHistoryRequest struct {
WithdrawAmount float64 `json:"withdraw_amount" binding:"required" example:"100"`
ContractId int `json:"contract_id" binding:"required" example:"GSDSC..."`
}

// @Summary Create a new contract
// @Description Create new contract
// @Tags Contract
Expand Down Expand Up @@ -179,3 +193,145 @@ func (r *contractRoutes) getContractById(c *gin.Context) {

c.JSON(http.StatusOK, contract)
}

// @Summary Get contract history
// @Description Retrieve a list of history of contract
// @Tags ContractHistory
// @Accept json
// @Produce json
// @Param page query int false "Page number for pagination"
// @Param limit query int false "Number of items per page for pagination"
// @Success 200 {object} []entity.Contract
// @Failure 400 {object} response "Invalid query parameters"
// @Failure 500 {object} response "Internal server error"
// @Router /contracts [get]
func (r *contractRoutes) getContractHistory(c *gin.Context) {
contractId := c.Param("contractId")

contract, err := r.c.GetById(contractId)
if err != nil {
errorResponse(c, http.StatusNotFound, "contract not found", err)
}

token := c.Request.Header.Get("Authorization")
user, err := r.a.GetUserByToken(token)
if err != nil {
errorResponse(c, http.StatusNotFound, "user not found", err)
return
}

userID, err := strconv.Atoi(user.ID)

Check failure on line 223 in backend/internal/controller/http/v1/contracts.go

View workflow job for this annotation

GitHub Actions / Code Quality (1.20)

ineffectual assignment to err (ineffassign)
contracts, err := r.c.GetHistory(userID, contract.Id)
if err != nil {
r.l.Error(err, "http - v1 - get history - GetHistory")
errorResponse(c, http.StatusInternalServerError, "error getting history", err)
return
}
c.JSON(http.StatusOK, contracts)
}

// @Summary Add contract history
// @Description Add contract history
// @Tags Contract
// @Accept json
// @Produce json
// @Param request body AddContractHistoryRequest true "History info"
// @Success 200 {object} entity.ContractHistory
// @Failure 400 {object} response
// @Failure 404 {object} response
// @Failure 500 {object} response
// @Router /contract/history [post]
func (r *contractRoutes) addContractHistory(c *gin.Context) {
var request AddContractHistoryRequest
var err error

if err := c.ShouldBindJSON(&request); err != nil {
r.l.Error(err, "http - v1 - add contract history - ShouldBindJSON")
errorResponse(c, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()), err)
return
}

contractId := strconv.Itoa(request.ContractId)
contract, err := r.c.GetById(contractId)
if err != nil {
r.l.Error(err, "http - v1 - add contract history - GetById")
errorResponse(c, http.StatusNotFound, "contract not found", err)
return
}

token := c.Request.Header.Get("Authorization")
user, err := r.u.GetUserByToken(token)
if err != nil {
r.l.Error(err, "http - v1 - create contract - GetById")
errorResponse(c, http.StatusNotFound, "vault not found", err)
return
}

contractHistory := entity.ContractHistory{
Contract: contract,
User: user,
DepositAmount: request.DepositAmount,
}

contractHistory, err = r.c.AddContractHistory(contractHistory)
if err != nil {
r.l.Error(err, "http - v1 - add contract history - Create")
errorResponse(c, http.StatusNotFound, fmt.Sprintf("error: %s", err.Error()), err)
return
}

c.JSON(http.StatusOK, contractHistory)
}

// @Summary Update contract history
// @Description Update contract history
// @Tags Contract
// @Accept json
// @Produce json
// @Param request body UpdateContractHistoryRequest true "History info"
// @Success 200 {object} entity.ContractHistory
// @Failure 400 {object} response
// @Failure 404 {object} response
// @Failure 500 {object} response
// @Router /contract/history [put]
func (r *contractRoutes) updateContractHistory(c *gin.Context) {
var request UpdateContractHistoryRequest
var err error

if err := c.ShouldBindJSON(&request); err != nil {
r.l.Error(err, "http - v1 - add contract history - ShouldBindJSON")
errorResponse(c, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()), err)
return
}

contractId := strconv.Itoa(request.ContractId)
contract, err := r.c.GetById(contractId)
if err != nil {
r.l.Error(err, "http - v1 - add contract history - GetById")
errorResponse(c, http.StatusNotFound, "contract not found", err)
return
}

token := c.Request.Header.Get("Authorization")
user, err := r.u.GetUserByToken(token)
if err != nil {
r.l.Error(err, "http - v1 - create contract - GetById")
errorResponse(c, http.StatusNotFound, "vault not found", err)
return
}

contractHistory := entity.ContractHistory{
Contract: contract,
User: user,
WithdrawAmount: &request.WithdrawAmount,
}

contractHistory, err = r.c.UpdateContractHistory(contractHistory)
if err != nil {
r.l.Error(err, "http - v1 - update contract history - Create")
errorResponse(c, http.StatusNotFound, fmt.Sprintf("error: %s", err.Error()), err)
return
}

c.JSON(http.StatusOK, contractHistory)
}
2 changes: 1 addition & 1 deletion backend/internal/controller/http/v1/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func NewRouter(
newRolePermissionsRoutes(groupV1, rolePermissionUc, messengerController, logger)
newVaultCategoryRoutes(groupV1, messengerController, authUseCase, vaultCategoryUc, logger)
newVaultRoutes(groupV1, messengerController, authUseCase, vaultUc, vaultCategoryUc, walletUseCase, assetUseCase, logger)
newContractRoutes(groupV1, messengerController, authUseCase, contractUc, vaultUc, assetUseCase, logger)
newContractRoutes(groupV1, messengerController, authUseCase, contractUc, vaultUc, assetUseCase, userUseCase, logger)
newLogTransactionsRoutes(groupV1, walletUseCase, assetUseCase, messengerController, logUc, authUseCase, logger)
newSorobanRoutes(groupV1, walletUseCase, messengerController, authUseCase)
newAssetTomlRoutes(groupV1, walletUseCase, assetUseCase, messengerController, authUseCase, logUc, logger)
Expand Down
51 changes: 25 additions & 26 deletions backend/internal/controller/http/v1/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,34 @@ func (r *vaultRoutes) createVault(c *gin.Context) {
}
walletPk := kpRes.PublicKeys[0]

ops := []entity.Operation{
{
Type: entity.CreateAccountOp,
Target: walletPk,
Amount: _startingBalance,
Origin: sponsor.Key.PublicKey,
Sponsor: sponsor.Key.PublicKey,
wallet, err := r.w.Create(entity.Wallet{

Check failure on line 114 in backend/internal/controller/http/v1/vault.go

View workflow job for this annotation

GitHub Actions / Code Quality (1.20)

ineffectual assignment to err (ineffassign)
Type: entity.DistributorType,
Key: entity.Key{
PublicKey: walletPk,
Weight: 1,
},
})

fundRes, err := r.m.SendMessage(entity.HorizonChannel, entity.HorizonRequest{
Id: wallet.Id,
Type: "fundWithFriendbot",
Account: walletPk,
})
if err != nil {
r.l.Error(err, "http - v1 - fund wallet - SendMessage")
errorResponse(c, http.StatusInternalServerError, "messaging problems", err)
}

fundResult := fundRes.Message.(entity.HorizonResponse)

if fundResult.StatusCode != 200 {
r.l.Error(err, "http - v1 - fund wallet - fundRes.StatusCode != 200")
errorResponse(c, http.StatusInternalServerError, "friendbot error", err)
return
}

ops := []entity.Operation{}

for _, assetId := range request.AssetsId {
asset, err := r.as.GetById(strconv.Itoa(assetId))
if err != nil {
Expand Down Expand Up @@ -159,15 +177,6 @@ func (r *vaultRoutes) createVault(c *gin.Context) {
return
}

wallet := entity.Wallet{
Type: entity.DistributorType,
Funded: true,
Key: entity.Key{
PublicKey: walletPk,
Weight: 1,
},
}

vault := entity.Vault{
Name: request.Name,
VaultCategory: &vaultCategory,
Expand Down Expand Up @@ -261,16 +270,6 @@ func (r *vaultRoutes) getVaultById(c *gin.Context) {
return
}

if vault.VaultCategoryId != nil {
vaultCategory, err := r.vc.GetById(*vault.VaultCategoryId)
if err != nil {
errorResponse(c, http.StatusInternalServerError, "error getting vault category", err)
return
}

vault.VaultCategory = &vaultCategory
}

c.JSON(http.StatusOK, vault)
}

Expand Down
11 changes: 11 additions & 0 deletions backend/internal/entity/contract_history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package entity

type ContractHistory struct {
Id int `json:"id" example:"1"`
Contract Contract `json:"contract"`
DepositedAt *string `json:"deposited_at"`
DepositAmount float64 `json:"deposit_amount"`
WithdrawnAt *string `json:"withdrawn_at"`
WithdrawAmount *float64 `json:"withdraw_amount"`
User User `json:"user"`
}
33 changes: 30 additions & 3 deletions backend/internal/usecase/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ func (uc *ContractUseCase) GetAll() ([]entity.Contract, error) {
}

func (uc *ContractUseCase) GetById(id string) (entity.Contract, error) {
asset, err := uc.cRepo.GetContractById(id)
contract, err := uc.cRepo.GetContractById(id)
if err != nil {
return entity.Contract{}, fmt.Errorf("ContractUseCase - Get - uc.repo.GetContractById: %w", err)
return entity.Contract{}, fmt.Errorf("ContractUseCase - GetById - uc.repo.GetContractById: %w", err)
}

return asset, nil
return contract, nil
}

func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity.Contract, error) {
Expand All @@ -51,3 +51,30 @@ func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity.

return contracts, nil
}

func (uc *ContractUseCase) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) {
contractsHistory, err := uc.cRepo.GetHistory(userId, contractId)
if err != nil {
return nil, fmt.Errorf("ContractUseCase - GetHistory - uc.repo.GetHistory: %w", err)
}

return contractsHistory, nil
}

func (uc *ContractUseCase) AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) {
contractsHistory, err := uc.cRepo.AddContractHistory(contractHistory)
if err != nil {
return entity.ContractHistory{}, fmt.Errorf("ContractUseCase - AddContractHistory - uc.repo.AddContractHistory: %w", err)
}

return contractsHistory, nil
}

func (uc *ContractUseCase) UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) {
contractHistory, err := uc.cRepo.UpdateContractHistory(contractHistory)
if err != nil {
return entity.ContractHistory{}, fmt.Errorf("ContractUseCase - UpdateContractHistory - uc.repo.UpdateContractHistory: %w", err)
}

return contractHistory, nil
}
3 changes: 3 additions & 0 deletions backend/internal/usecase/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ type (
CreateContract(entity.Contract) (entity.Contract, error)
GetContractById(id string) (entity.Contract, error)
GetPaginatedContracts(int, int) ([]entity.Contract, error)
GetHistory(userId int, contractId int) ([]entity.ContractHistory, error)
AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error)
UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error)
}

LogTransactionRepoInterface interface {
Expand Down
Loading

0 comments on commit 1d949c3

Please sign in to comment.