Skip to content

Commit

Permalink
Merge PR: add backend rest api (#549)
Browse files Browse the repository at this point in the history
* add backend rest api

* add timestamp params
  • Loading branch information
ilovers authored Jan 12, 2021
1 parent 529491d commit 950faee
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 0 deletions.
71 changes: 71 additions & 0 deletions x/backend/client/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/deals", dealHandler(cliCtx)).Methods("GET")
r.HandleFunc("/fees", feeDetailListHandler(cliCtx)).Methods("GET")
r.HandleFunc("/order/list/{openOrClosed}", orderListHandler(cliCtx)).Methods("GET")
r.HandleFunc("/orders/{orderID}", orderHandler(cliCtx)).Methods("GET")
r.HandleFunc("/accounts/{address}/orders", accountOrdersHandler(cliCtx)).Methods("GET")
r.HandleFunc("/block_tx_hashes/{blockHeight}", blockTxHashesHandler(cliCtx)).Methods("GET")
r.HandleFunc("/transactions", txListHandler(cliCtx)).Methods("GET")
r.HandleFunc("/latestheight", latestHeightHandler(cliCtx)).Methods("GET")
Expand Down Expand Up @@ -330,6 +332,75 @@ func orderListHandler(cliCtx context.CLIContext) http.HandlerFunc {
}
}

func orderHandler(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
orderID := vars["orderID"]
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/backend/%s/%s", types.QueryOrderByID, orderID), nil)
if err != nil {
sdkErr := common.ParseSDKError(err.Error())
common.HandleErrorMsg(w, cliCtx, sdkErr.Code, sdkErr.Message)
return
}

rest.PostProcessResponse(w, cliCtx, res)
}
}

func accountOrdersHandler(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
address := vars["address"]
pageStr := r.URL.Query().Get("page")
perPageStr := r.URL.Query().Get("per_page")
startStr := r.URL.Query().Get("start")
endStr := r.URL.Query().Get("end")

// validate request
if address == "" {
common.HandleErrorMsg(w, cliCtx, types.CodeAddressIsRequired, "bad request: address is required")
return
}

page, perPage, err := common.Paginate(pageStr, perPageStr)
if err != nil {
common.HandleErrorMsg(w, cliCtx, common.CodeStrconvFailed, err.Error())
return
}

var start, end int64
if startStr == "" {
startStr = "0"
}
if endStr == "" {
endStr = "0"
}
start, errStart := strconv.ParseInt(startStr, 10, 64)
end, errEnd := strconv.ParseInt(endStr, 10, 64)
mErr := types.NewErrorsMerged(errStart, errEnd)
if mErr != nil {
common.HandleErrorMsg(w, cliCtx, common.CodeStrconvFailed, mErr.Error())
return
}

params := types.NewQueryAccountOrdersParams(address, start, end, page, perPage)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
common.HandleErrorMsg(w, cliCtx, common.CodeMarshalJSONFailed, err.Error())
return
}

res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/backend/%s", types.QueryAccountOrders), bz)
if err != nil {
sdkErr := common.ParseSDKError(err.Error())
common.HandleErrorMsg(w, cliCtx, sdkErr.Code, sdkErr.Message)
return
}

rest.PostProcessResponse(w, cliCtx, res)
}
}

func txListHandler(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
addr := r.URL.Query().Get("address")
Expand Down
49 changes: 49 additions & 0 deletions x/backend/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func NewQuerier(keeper Keeper) sdk.Querier {
res, err = queryFeeDetails(ctx, path[1:], req, keeper)
case types.QueryOrderList:
res, err = queryOrderList(ctx, path[1:], req, keeper)
case types.QueryOrderByID:
res, err = queryOrderByID(ctx, path[1:], req, keeper)
case types.QueryAccountOrders:
res, err = queryAccountOrders(ctx, path[1:], req, keeper)
case types.QueryTxList:
res, err = queryTxList(ctx, path[1:], req, keeper)
case types.QueryCandleList:
Expand Down Expand Up @@ -443,6 +447,51 @@ func queryOrderList(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
return bz, nil
}

func queryOrderByID(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
if len(path) == 0 {
return nil, types.ErrOrderIdIsRequired()
}
orderID := path[0]
order := keeper.Orm.GetOrderByID(orderID)
response := common.GetBaseResponse(order)
bz, err := json.Marshal(response)
if err != nil {
return nil, common.ErrMarshalJSONFailed(err.Error())
}
return bz, nil
}

func queryAccountOrders(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params types.QueryAccountOrdersParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, common.ErrUnMarshalJSONFailed(err.Error())
}
if params.Address != "" {
_, err := sdk.AccAddressFromBech32(params.Address)
if err != nil {
return nil, common.ErrCreateAddrFromBech32Failed(params.Address, err.Error())
}
}
if params.Page < 0 || params.PerPage < 0 {
return nil, common.ErrInvalidPaginateParam(params.Page, params.PerPage)
}

offset, limit := common.GetPage(params.Page, params.PerPage)
orders, total := keeper.Orm.GetAccountOrders(params.Address, params.Start, params.End, offset, limit)
var response *common.ListResponse
if len(orders) > 0 {
response = common.GetListResponse(total, params.Page, params.PerPage, orders)
} else {
response = common.GetEmptyListResponse(total, params.Page, params.PerPage)
}
bz, err := json.Marshal(response)
if err != nil {
return nil, common.ErrMarshalJSONFailed(err.Error())
}
return bz, nil
}

func queryTxList(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params types.QueryTxListParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
Expand Down
18 changes: 18 additions & 0 deletions x/backend/orm/orm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,24 @@ func (orm *ORM) GetOrderList(address, product, side string, open bool, offset, l
return orders, total
}

func (orm *ORM) GetAccountOrders(address string, startTS, endTS int64, offset, limit int) ([]types.Order, int) {
var orders []types.Order

if endTS == 0 {
endTS = time.Now().Unix()
}

query := orm.db.Model(types.Order{}).Where("sender = ? AND timestamp >= ? AND timestamp < ?", address, startTS, endTS)
var total int
query.Count(&total)
if offset >= total {
return orders, total
}

query.Order("timestamp desc").Offset(offset).Limit(limit).Find(&orders)
return orders, total
}

// AddTransactions insert into transactions, return count
func (orm *ORM) AddTransactions(transactions []*types.Transaction) (addedCnt int, err error) {
orm.singleEntryLock.Lock()
Expand Down
7 changes: 7 additions & 0 deletions x/backend/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
Expand Down Expand Up @@ -29,6 +30,7 @@ const (
CodeMarketkeeperNotInitialized uint32 = 62016
CodeGetInvalidateGranularity uint32 = 62017
CodeGetInvalidTickerByProducts uint32 = 62018
CodeOrderIdIsRequired uint32 = 62019
)

// invalid param side, must be buy or sell
Expand Down Expand Up @@ -73,3 +75,8 @@ func ErrGetInvalidateGranularity(msg string, key string, field string) sdk.Envel
func ErrGetInvalidTickerByProducts(key string) sdk.EnvelopedErr {
return sdk.EnvelopedErr{Err: sdkerrors.New(DefaultCodespace, CodeGetInvalidTickerByProducts, fmt.Sprintf("No value found for key: %s", key))}
}

// orderId is required
func ErrOrderIdIsRequired() sdk.EnvelopedErr {
return sdk.EnvelopedErr{Err: sdkerrors.New(DefaultCodespace, CodeOrderIdIsRequired, "invalid params: orderId is required")}
}
2 changes: 2 additions & 0 deletions x/backend/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const (
QueryDealList = "deals"
QueryFeeDetails = "fees"
QueryOrderList = "orders"
QueryOrderByID = "orderByID"
QueryAccountOrders = "accountOrders"
QueryTxList = "txs"
QueryCandleList = "candles"
QueryTickerList = "tickers"
Expand Down
24 changes: 24 additions & 0 deletions x/backend/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,30 @@ func NewQueryOrderListParams(addr, product, side string, page, perPage int, star
}
}

// nolint
type QueryAccountOrdersParams struct {
Address string
Start int64
End int64
Page int
PerPage int
}

// NewQueryAccountOrdersParams creates a new instance of QueryAccountOrdersParams
func NewQueryAccountOrdersParams(address string, start int64, end int64, page, perPage int) QueryAccountOrdersParams {
if page == 0 && perPage == 0 {
page = DefaultPage
perPage = DefaultPerPage
}
return QueryAccountOrdersParams{
Address: address,
Start: start,
End: end,
Page: page,
PerPage: perPage,
}
}

// nolint
type QueryTxListParams struct {
Address string
Expand Down

0 comments on commit 950faee

Please sign in to comment.