[R4R] feat: Fetch auctions from historical state (#649)

* feat: query old blocks for auctions

* fix: add next auction id to querier

* fix: set boolean when found

* fix: use correct query route and params

* apply suggestions from review comments
This commit is contained in:
Kevin Davis 2020-09-16 14:58:11 -04:00 committed by GitHub
parent 7085253ac9
commit 15a7dc610e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 28 deletions

View File

@ -17,6 +17,8 @@ const (
AttributeKeyLot = types.AttributeKeyLot
AttributeKeyMaxBid = types.AttributeKeyMaxBid
AttributeValueCategory = types.AttributeValueCategory
CollateralAuctionType = types.CollateralAuctionType
DebtAuctionType = types.DebtAuctionType
DefaultBidDuration = types.DefaultBidDuration
DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration
DefaultNextAuctionID = types.DefaultNextAuctionID
@ -24,13 +26,17 @@ const (
EventTypeAuctionBid = types.EventTypeAuctionBid
EventTypeAuctionClose = types.EventTypeAuctionClose
EventTypeAuctionStart = types.EventTypeAuctionStart
ForwardAuctionPhase = types.ForwardAuctionPhase
ModuleName = types.ModuleName
QuerierRoute = types.QuerierRoute
QueryGetAuction = types.QueryGetAuction
QueryGetAuctions = types.QueryGetAuctions
QueryGetParams = types.QueryGetParams
QueryNextAuctionID = types.QueryNextAuctionID
ReverseAuctionPhase = types.ReverseAuctionPhase
RouterKey = types.RouterKey
StoreKey = types.StoreKey
SurplusAuctionType = types.SurplusAuctionType
)
var (
@ -52,6 +58,7 @@ var (
NewMsgPlaceBid = types.NewMsgPlaceBid
NewParams = types.NewParams
NewQueryAllAuctionParams = types.NewQueryAllAuctionParams
NewQueryAuctionParams = types.NewQueryAuctionParams
NewSurplusAuction = types.NewSurplusAuction
NewWeightedAddresses = types.NewWeightedAddresses
ParamKeyTable = types.ParamKeyTable

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/auction/client/common"
"github.com/kava-labs/kava/x/auction/types"
)
@ -54,22 +55,12 @@ func QueryGetAuctionCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if err != nil {
return fmt.Errorf("auction-id '%s' not a valid uint", args[0])
}
bz, err := cdc.MarshalJSON(types.QueryAuctionParams{
AuctionID: id,
})
auction, height, err := common.QueryAuctionByID(cliCtx, cdc, queryRoute, id)
if err != nil {
return err
}
// Query
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetAuction), bz)
if err != nil {
return err
}
// Decode and print results
var auction types.Auction
cdc.MustUnmarshalJSON(res, &auction)
auctionWithPhase := types.NewAuctionWithPhase(auction)
cliCtx = cliCtx.WithHeight(height)

View File

@ -0,0 +1,94 @@
package common
import (
"fmt"
"strings"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
"github.com/kava-labs/kava/x/auction/types"
)
const (
defaultPage = 1
defaultLimit = 100
)
// QueryAuctionByID returns an auction from state if present or falls back to searching old blocks
func QueryAuctionByID(cliCtx context.CLIContext, cdc *codec.Codec, queryRoute string, auctionID uint64) (types.Auction, int64, error) {
bz, err := cdc.MarshalJSON(types.NewQueryAuctionParams(auctionID))
if err != nil {
return nil, 0, err
}
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetAuction), bz)
if err == nil {
var auction types.Auction
cdc.MustUnmarshalJSON(res, &auction)
return auction, height, nil
}
if err != nil && !strings.Contains(err.Error(), "auction not found") {
return nil, 0, err
}
res, height, err = cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryNextAuctionID), nil)
if err != nil {
return nil, 0, err
}
var nextAuctionID uint64
cdc.MustUnmarshalJSON(res, &nextAuctionID)
if auctionID >= nextAuctionID {
return nil, 0, sdkerrors.Wrapf(types.ErrAuctionNotFound, "%d", auctionID)
}
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, "place_bid"),
fmt.Sprintf("%s.%s='%s'", types.EventTypeAuctionBid, types.AttributeKeyAuctionID, []byte(fmt.Sprintf("%d", auctionID))),
}
// if the auction is closed, query for previous bid transactions
// note, will only fetch a maximum of 100 bids, so if an auction had more than that this
// query may fail to retreive the final state of the auction
searchResult, err := utils.QueryTxsByEvents(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return nil, 0, err
}
maxHeight := int64(0)
found := false
for _, info := range searchResult.Txs {
for _, msg := range info.Tx.GetMsgs() {
if msg.Type() == "place_bid" {
found = true
if info.Height > maxHeight {
maxHeight = info.Height
}
}
}
}
if !found {
return nil, 0, sdkerrors.Wrapf(types.ErrAuctionNotFound, "%d", auctionID)
}
queryCLIContext := cliCtx.WithHeight(maxHeight)
res, height, err = queryCLIContext.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetAuction), bz)
if err != nil {
return nil, 0, err
}
// Decode and print results
var auction types.Auction
cdc.MustUnmarshalJSON(res, &auction)
return auction, height, nil
}

View File

@ -11,6 +11,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/kava-labs/kava/x/auction/client/common"
"github.com/kava-labs/kava/x/auction/types"
)
@ -41,28 +42,13 @@ func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
if !ok {
return
}
bz, err := cliCtx.Codec.MarshalJSON(types.QueryAuctionParams{AuctionID: auctionID})
auction, height, err := common.QueryAuctionByID(cliCtx, cliCtx.Codec, types.ModuleName, auctionID)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// Query
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryGetAuction), bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
// Decode and return results
cliCtx = cliCtx.WithHeight(height)
var auction types.Auction
err = cliCtx.Codec.UnmarshalJSON(res, &auction)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
auctionWithPhase := types.NewAuctionWithPhase(auction)
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionWithPhase))
}

View File

@ -21,6 +21,8 @@ func NewQuerier(keeper Keeper) sdk.Querier {
return queryAuctions(ctx, req, keeper)
case types.QueryGetParams:
return queryGetParams(ctx, req, keeper)
case types.QueryNextAuctionID:
return queryNextAuctionID(ctx, req, keeper)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName)
}
@ -122,3 +124,13 @@ func filterAuctions(ctx sdk.Context, auctions types.Auctions, params types.Query
return filteredAuctions
}
func queryNextAuctionID(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
nextAuctionID, _ := keeper.GetNextAuctionID(ctx)
bz, err := types.ModuleCdc.MarshalJSON(nextAuctionID)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
return bz, nil
}

View File

@ -7,6 +7,8 @@ const (
QueryGetAuctions = "auctions"
// QueryGetParams is the query path for querying the global auction params
QueryGetParams = "params"
// QueryNextAuctionID is the query path for querying the id of the next auction
QueryNextAuctionID = "next-auction-id"
)
// QueryAuctionParams params for query /auction/auction
@ -14,6 +16,13 @@ type QueryAuctionParams struct {
AuctionID uint64
}
// NewQueryAuctionParams returns a new QueryAuctionParams
func NewQueryAuctionParams(id uint64) QueryAuctionParams {
return QueryAuctionParams{
AuctionID: id,
}
}
// QueryAllAuctionParams is the params for an auctions query
type QueryAllAuctionParams struct {
Page int `json:"page" yaml:"page"`