Skip to content

Commit

Permalink
Feature: add fees to transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
aopoltorzhicky committed Dec 9, 2024
1 parent 691c6ac commit 1620af9
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 1 deletion.
27 changes: 27 additions & 0 deletions cmd/api/docs/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions cmd/api/docs/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions cmd/api/docs/swagger.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions cmd/api/handler/responses/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,15 @@ func NewFullFee(fee storage.Fee) FullFee {

return ff
}

type TxFee struct {
Amount string `example:"1000" format:"string" json:"amount" swaggertype:"string"`
Asset string `example:"nria" format:"string" json:"asset" swaggertype:"string"`
}

func NewTxFee(fee storage.Fee) TxFee {
return TxFee{
Asset: fee.Asset,
Amount: fee.Amount.String(),
}
}
1 change: 1 addition & 0 deletions cmd/api/handler/responses/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Tx struct {
ActionTypes []string `example:"rollup_data_submission,transfer" format:"string" json:"action_types" swaggertype:"string"`

Actions []Action `json:"actions,omitempty"`
Fees []TxFee `json:"fees,omitempty"`
}

func NewTx(tx storage.Tx) Tx {
Expand Down
17 changes: 16 additions & 1 deletion cmd/api/handler/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func NewTxHandler(

type getTxRequest struct {
Hash string `param:"hash" validate:"required,hexadecimal,len=64"`

Fee bool `query:"fee" validate:"omitempty"`
}

// Get godoc
Expand All @@ -52,6 +54,7 @@ type getTxRequest struct {
// @Tags transactions
// @ID get-transaction
// @Param hash path string true "Transaction hash in hexadecimal" minlength(64) maxlength(64)
// @Param fee query boolean false "Flag which indicates need join full transaction fees"
// @Produce json
// @Success 200 {object} responses.Tx
// @Success 204
Expand All @@ -73,8 +76,20 @@ func (handler *TxHandler) Get(c echo.Context) error {
if err != nil {
return handleError(c, err, handler.tx)
}
response := responses.NewTx(tx)

if req.Fee {
fees, err := handler.fees.FullTxFee(c.Request().Context(), tx.Id)
if err != nil {
return handleError(c, err, handler.tx)
}
response.Fees = make([]responses.TxFee, len(fees))
for i := range fees {
response.Fees[i] = responses.NewTxFee(fees[i])
}
}

return c.JSON(http.StatusOK, responses.NewTx(tx))
return c.JSON(http.StatusOK, response)
}

type txListRequest struct {
Expand Down
54 changes: 54 additions & 0 deletions cmd/api/handler/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,60 @@ func (s *TxTestSuite) TestGet() {
s.Require().Equal(types.StatusSuccess, tx.Status)
}

func (s *TxTestSuite) TestGetWithFee() {
q := make(url.Values)
q.Add("fee", "true")

req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil)
rec := httptest.NewRecorder()
c := s.echo.NewContext(req, rec)
c.SetPath("/tx/:hash")
c.SetParamNames("hash")
c.SetParamValues(testTxHash)

s.tx.EXPECT().
ByHash(gomock.Any(), testTx.Hash).
Return(testTx, nil).
Times(1)

s.fees.EXPECT().
FullTxFee(gomock.Any(), testTx.Id).
Return([]storage.Fee{
{
Amount: decimal.NewFromInt(100),
Asset: "asset_1",
}, {
Amount: decimal.NewFromInt(200),
Asset: "asset_2",
},
}, nil).
Times(1)

s.Require().NoError(s.handler.Get(c))
s.Require().Equal(http.StatusOK, rec.Code)

var tx responses.Tx
err := json.NewDecoder(rec.Body).Decode(&tx)
s.Require().NoError(err)

s.Require().EqualValues(1, tx.Id)
s.Require().EqualValues(100, tx.Height)
s.Require().Equal(testTime, tx.Time)
s.Require().Equal(testTxHash, tx.Hash)
s.Require().EqualValues(1, tx.Position)
s.Require().EqualValues(1, tx.ActionsCount)
s.Require().EqualValues(10, tx.Nonce)
s.Require().EqualValues(testAddress.Hash, tx.Signer)
s.Require().Equal("codespace", tx.Codespace)
s.Require().Equal(types.StatusSuccess, tx.Status)

s.Require().Len(tx.Fees, 2)
s.Require().Equal("100", tx.Fees[0].Amount)
s.Require().Equal("asset_1", tx.Fees[0].Asset)
s.Require().Equal("200", tx.Fees[1].Amount)
s.Require().Equal("asset_2", tx.Fees[1].Asset)
}

func (s *TxTestSuite) TestGetInvalidTx() {
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
Expand Down
1 change: 1 addition & 0 deletions internal/storage/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type IFee interface {

ByTxId(ctx context.Context, id uint64, limit, offset int) ([]Fee, error)
ByPayerId(ctx context.Context, id uint64, limit, offset int, sort storage.SortOrder) ([]Fee, error)
FullTxFee(ctx context.Context, id uint64) ([]Fee, error)
}

type Fee struct {
Expand Down
39 changes: 39 additions & 0 deletions internal/storage/mock/fee.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions internal/storage/postgres/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,13 @@ func (f *Fee) ByPayerId(ctx context.Context, id uint64, limit, offset int, sort

return
}

func (f *Fee) FullTxFee(ctx context.Context, id uint64) (fees []storage.Fee, err error) {
err = f.DB().NewSelect().
Model(&fees).
ColumnExpr("sum(amount) as amount, asset").
Where("tx_id = ?", id).
Group("asset").
Scan(ctx)
return
}
13 changes: 13 additions & 0 deletions internal/storage/postgres/fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ func (s *StorageTestSuite) TestFeeByPayerId() {
s.Require().NotNil(fee.Tx)
s.Require().NotEmpty(fee.Tx.Hash)
}

func (s *StorageTestSuite) TestFullTxFee() {
ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second)
defer ctxCancel()

fees, err := s.storage.Fee.FullTxFee(ctx, 1)
s.Require().NoError(err)
s.Require().Len(fees, 1)

fee := fees[0]
s.Require().EqualValues("100", fee.Amount.String())
s.Require().EqualValues("nria", fee.Asset)
}

0 comments on commit 1620af9

Please sign in to comment.