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

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/auction/client/common"
"github.com/kava-labs/kava/x/auction/types" "github.com/kava-labs/kava/x/auction/types"
) )
@ -54,22 +55,12 @@ func QueryGetAuctionCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if err != nil { if err != nil {
return fmt.Errorf("auction-id '%s' not a valid uint", args[0]) 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 { if err != nil {
return err 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) auctionWithPhase := types.NewAuctionWithPhase(auction)
cliCtx = cliCtx.WithHeight(height) 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" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/types/rest"
"github.com/kava-labs/kava/x/auction/client/common"
"github.com/kava-labs/kava/x/auction/types" "github.com/kava-labs/kava/x/auction/types"
) )
@ -41,28 +42,13 @@ func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
if !ok { if !ok {
return return
} }
bz, err := cliCtx.Codec.MarshalJSON(types.QueryAuctionParams{AuctionID: auctionID}) auction, height, err := common.QueryAuctionByID(cliCtx, cliCtx.Codec, types.ModuleName, auctionID)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return 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 // Decode and return results
cliCtx = cliCtx.WithHeight(height) 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) auctionWithPhase := types.NewAuctionWithPhase(auction)
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionWithPhase)) 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) return queryAuctions(ctx, req, keeper)
case types.QueryGetParams: case types.QueryGetParams:
return queryGetParams(ctx, req, keeper) return queryGetParams(ctx, req, keeper)
case types.QueryNextAuctionID:
return queryNextAuctionID(ctx, req, keeper)
default: default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName) 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 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" QueryGetAuctions = "auctions"
// QueryGetParams is the query path for querying the global auction params // QueryGetParams is the query path for querying the global auction params
QueryGetParams = "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 // QueryAuctionParams params for query /auction/auction
@ -14,6 +16,13 @@ type QueryAuctionParams struct {
AuctionID uint64 AuctionID uint64
} }
// NewQueryAuctionParams returns a new QueryAuctionParams
func NewQueryAuctionParams(id uint64) QueryAuctionParams {
return QueryAuctionParams{
AuctionID: id,
}
}
// QueryAllAuctionParams is the params for an auctions query // QueryAllAuctionParams is the params for an auctions query
type QueryAllAuctionParams struct { type QueryAllAuctionParams struct {
Page int `json:"page" yaml:"page"` Page int `json:"page" yaml:"page"`