Skip to content

Commit

Permalink
feat: add estimate fees endpoint for cosmos
Browse files Browse the repository at this point in the history
  • Loading branch information
kaladinlight committed Dec 5, 2023
1 parent 355b58e commit 7068756
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 0 deletions.
20 changes: 20 additions & 0 deletions go/coinstacks/cosmos/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func New(httpClient *cosmos.HTTPClient, grpcClient *cosmos.GRPCClient, wsClient

v1Gas := v1.PathPrefix("/gas").Subrouter()
v1Gas.HandleFunc("/estimate", a.EstimateGas).Methods("POST")
v1Gas.HandleFunc("/fees", a.Fees).Methods("GET")

v1ValidatorsRoot := v1.PathPrefix("/validators").Subrouter()
v1ValidatorsRoot.HandleFunc("", a.GetValidators).Methods("GET")
Expand Down Expand Up @@ -206,3 +207,22 @@ func (a *API) ValidatorTxHistory(w http.ResponseWriter, r *http.Request) {

api.HandleResponse(w, http.StatusOK, txHistory)
}

// swagger:route GET /api/v1/gas/fees v1 Fees
//
// Get current fees.
//
// responses:
//
// 200: Fees
// 400: BadRequestError
// 500: InternalServerError
func (a *API) Fees(w http.ResponseWriter, r *http.Request) {
fees, err := a.handler.GetFees()
if err != nil {
api.HandleError(w, http.StatusInternalServerError, err.Error())
return
}

api.HandleResponse(w, http.StatusOK, fees)
}
28 changes: 28 additions & 0 deletions go/coinstacks/cosmos/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,31 @@ func (h *Handler) getAPRData() (*APRData, error) {

return aprData, nil
}

// Contains info about the current fees
// swagger:model Fees
type Fees map[string]string

func (h *Handler) GetFees() (*Fees, error) {
globalMinGasPrices, err := h.HTTPClient.GetGlobalMinimumGasPrices()
if err != nil {
return nil, errors.Wrap(err, "failed to get global minimum gas prices")
}

localMinGasPrice, err := h.HTTPClient.GetLocalMinimumGasPrices()
if err != nil {
return nil, errors.Wrap(err, "failed to get local minimum gas prices")
}

minGasPrices := make(Fees)
for k, global := range globalMinGasPrices {
minGasPrices[k] = global.String()
if local, ok := localMinGasPrice[k]; ok {
if local.GT(global) {
minGasPrices[k] = local.String()
}
}
}

return &minGasPrices, nil
}
37 changes: 37 additions & 0 deletions go/coinstacks/cosmos/api/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,35 @@
}
}
},
"/api/v1/gas/fees": {
"get": {
"tags": [
"v1"
],
"summary": "Get current fees.",
"operationId": "Fees",
"responses": {
"200": {
"description": "Fees",
"schema": {
"$ref": "#/definitions/Fees"
}
},
"400": {
"description": "BadRequestError",
"schema": {
"$ref": "#/definitions/BadRequestError"
}
},
"500": {
"description": "InternalServerError",
"schema": {
"$ref": "#/definitions/InternalServerError"
}
}
}
}
},
"/api/v1/info": {
"get": {
"tags": [
Expand Down Expand Up @@ -678,6 +707,14 @@
},
"x-go-package": "github.com/shapeshift/unchained/pkg/cosmos"
},
"Fees": {
"description": "Contains info about the current fees",
"type": "object",
"additionalProperties": {
"type": "string"
},
"x-go-package": "github.com/shapeshift/unchained/coinstacks/cosmos/api"
},
"GasAmount": {
"type": "string",
"x-go-package": "github.com/shapeshift/unchained/pkg/api"
Expand Down
93 changes: 93 additions & 0 deletions go/pkg/cosmos/fees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package cosmos

import (
"encoding/json"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/pkg/errors"
)

func (c *HTTPClient) GetGlobalMinimumGasPrices() (map[string]sdk.Dec, error) {
gasPrices := make(map[string]sdk.Dec)

var res struct {
Param struct {
Amount string `json:"subspace"`
Key string `json:"key"`
Value string `json:"value"`
} `json:"param"`
}

e := &ErrorResponse{}

queryParams := map[string]string{
"subspace": "globalfee",
"key": "MinimumGasPricesParam",
}

r, err := c.LCD.R().SetResult(&res).SetError(e).SetQueryParams(queryParams).Get("/cosmos/params/v1beta1/params")
if err != nil {
return gasPrices, errors.Wrap(err, "failed to get globalfee params")
}

if r.Error() != nil {
return gasPrices, errors.Errorf("failed to get globalfee params: %s", e.Msg)
}

values := []struct {
Denom string `json:"denom"`
Amount string `json:"amount"`
}{}

err = json.Unmarshal([]byte(res.Param.Value), &values)
if err != nil {
return gasPrices, errors.Wrapf(err, "failed to unmarshal value: %s", res.Param.Value)
}

for _, value := range values {
coinStr := fmt.Sprintf("%s%s", value.Amount, value.Denom)

coin, err := sdk.ParseDecCoin(coinStr)
if err != nil {
logger.Errorf("failed to parse dec coin: %s: %v", coinStr, err)
continue
}

gasPrices[coin.GetDenom()] = coin.Amount
}

return gasPrices, nil
}

func (c *HTTPClient) GetLocalMinimumGasPrices() (map[string]sdk.Dec, error) {
gasPrices := make(map[string]sdk.Dec)

var res struct {
MinimumGasPrice string `json:"minimum_gas_price"`
}

e := &ErrorResponse{}

r, err := c.LCD.R().SetResult(&res).SetError(e).Get("/cosmos/base/node/v1beta1/config")
if err != nil {
return gasPrices, errors.Wrap(err, "failed to get base node config")
}

if r.Error() != nil {
return gasPrices, errors.Errorf("failed to get base node config: %s", e.Msg)
}

coins, err := sdk.ParseDecCoins(res.MinimumGasPrice)
if err != nil {
return gasPrices, errors.Wrap(err, "failed to parse coins")
}

for _, coin := range coins {
gasPrices[coin.GetDenom()] = coin.Amount
}

gasPrices["uatom"] = sdk.NewDec(1)

return gasPrices, nil
}

0 comments on commit 7068756

Please sign in to comment.