mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
Auction rest fixes (#361)
* auction query fixes * minor formating tweaks * add phase info to debt & surplus auctions * add base auction struct tags * use module name in querier paths * update rest tx endoint to use http body * improve invalid coins error messages * add rest examples * align starting auction ID with gov and cdp * fix cdp test broken by auction ID change * fix all tests broken by ID change
This commit is contained in:
parent
31e185c632
commit
bbc5d3b7a0
16
contrib/rest_examples/auction/place-bid-request.json
Normal file
16
contrib/rest_examples/auction/place-bid-request.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"base_req": {
|
||||||
|
"from": "kava1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj",
|
||||||
|
"memo": "arbitrary text",
|
||||||
|
"chain_id": "testing",
|
||||||
|
"account_number": "0",
|
||||||
|
"sequence": "2",
|
||||||
|
"gas": "500000",
|
||||||
|
"gas_adjustment": "1.0",
|
||||||
|
"simulate": false
|
||||||
|
},
|
||||||
|
"amount": {
|
||||||
|
"denom": "usdx",
|
||||||
|
"amount": "100000000"
|
||||||
|
}
|
||||||
|
}
|
32
contrib/rest_examples/auction/place-bid-response-signed.json
Normal file
32
contrib/rest_examples/auction/place-bid-response-signed.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"type": "cosmos-sdk/StdTx",
|
||||||
|
"value": {
|
||||||
|
"msg": [
|
||||||
|
{
|
||||||
|
"type": "auction/MsgPlaceBid",
|
||||||
|
"value": {
|
||||||
|
"auction_id": "1",
|
||||||
|
"bidder": "kava1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj",
|
||||||
|
"amount": {
|
||||||
|
"denom": "usdx",
|
||||||
|
"amount": "100000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fee": {
|
||||||
|
"amount": [],
|
||||||
|
"gas": "500000"
|
||||||
|
},
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "tendermint/PubKeySecp256k1",
|
||||||
|
"value": "AsBYqm9S7cjIBdG6N/xzAGuEizTt2S2CJuM1FCsgta7u"
|
||||||
|
},
|
||||||
|
"signature": "O3zsB8P61SN7/5C+TNfO9hMaFYWV6hjr2aVigN0GrckR2PQGZhpyEZ03P71A9uK7DFLawzvAHDZRqQu833lAnA=="
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"memo": "arbitrary text"
|
||||||
|
}
|
||||||
|
}
|
24
contrib/rest_examples/auction/place-bid-response.json
Normal file
24
contrib/rest_examples/auction/place-bid-response.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"type": "cosmos-sdk/StdTx",
|
||||||
|
"value": {
|
||||||
|
"msg": [
|
||||||
|
{
|
||||||
|
"type": "auction/MsgPlaceBid",
|
||||||
|
"value": {
|
||||||
|
"auction_id": "1",
|
||||||
|
"bidder": "kava1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj",
|
||||||
|
"amount": {
|
||||||
|
"denom": "usdx",
|
||||||
|
"amount": "100000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fee": {
|
||||||
|
"amount": [],
|
||||||
|
"gas": "500000"
|
||||||
|
},
|
||||||
|
"signatures": null,
|
||||||
|
"memo": "arbitrary text"
|
||||||
|
}
|
||||||
|
}
|
32
contrib/rest_examples/auction/place-bid-txs-request.json
Normal file
32
contrib/rest_examples/auction/place-bid-txs-request.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"tx": {
|
||||||
|
"msg": [
|
||||||
|
{
|
||||||
|
"type": "auction/MsgPlaceBid",
|
||||||
|
"value": {
|
||||||
|
"auction_id": "1",
|
||||||
|
"bidder": "kava1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj",
|
||||||
|
"amount": {
|
||||||
|
"denom": "usdx",
|
||||||
|
"amount": "100000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fee": {
|
||||||
|
"amount": [],
|
||||||
|
"gas": "500000"
|
||||||
|
},
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "tendermint/PubKeySecp256k1",
|
||||||
|
"value": "AsBYqm9S7cjIBdG6N/xzAGuEizTt2S2CJuM1FCsgta7u"
|
||||||
|
},
|
||||||
|
"signature": "O3zsB8P61SN7/5C+TNfO9hMaFYWV6hjr2aVigN0GrckR2PQGZhpyEZ03P71A9uK7DFLawzvAHDZRqQu833lAnA=="
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"memo": "arbitrary text"
|
||||||
|
},
|
||||||
|
"mode": "block"
|
||||||
|
}
|
@ -31,6 +31,7 @@ const (
|
|||||||
DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration
|
DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration
|
||||||
DefaultBidDuration = types.DefaultBidDuration
|
DefaultBidDuration = types.DefaultBidDuration
|
||||||
QueryGetAuction = types.QueryGetAuction
|
QueryGetAuction = types.QueryGetAuction
|
||||||
|
DefaultNextAuctionID = types.DefaultNextAuctionID
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -85,7 +85,7 @@ func QueryGetAuctionsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
|||||||
var auctions types.Auctions
|
var auctions types.Auctions
|
||||||
cdc.MustUnmarshalJSON(res, &auctions)
|
cdc.MustUnmarshalJSON(res, &auctions)
|
||||||
|
|
||||||
var auctionsWithPhase []types.AuctionWithPhase
|
auctionsWithPhase := []types.AuctionWithPhase{} // using empty slice so json returns [] instead of null when there's no auctions
|
||||||
for _, a := range auctions {
|
for _, a := range auctions {
|
||||||
auctionsWithPhase = append(auctionsWithPhase, types.NewAuctionWithPhase(a))
|
auctionsWithPhase = append(auctionsWithPhase, types.NewAuctionWithPhase(a))
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ import (
|
|||||||
"github.com/kava-labs/kava/x/auction/types"
|
"github.com/kava-labs/kava/x/auction/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const RestAuctionID = "auction-id"
|
const restAuctionID = "auction-id"
|
||||||
|
|
||||||
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||||
r.HandleFunc(fmt.Sprintf("/auction/auctions/{%s}", RestAuctionID), queryAuctionHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/{%s}/auctions", types.ModuleName), queryAuctionsHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc("/auction/auctions", queryAuctionsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/{%s}/auctions/{%s}", types.ModuleName, restAuctionID), queryAuctionHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc("/auction/parameters", getParamsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/{%s}/parameters", types.ModuleName), getParamsHandlerFn(cliCtx)).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
||||||
@ -30,12 +30,12 @@ func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
// Prepare params for querier
|
// Prepare params for querier
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
if len(vars[RestAuctionID]) == 0 {
|
if len(vars[restAuctionID]) == 0 {
|
||||||
err := fmt.Errorf("%s required but not specified", RestAuctionID)
|
err := fmt.Errorf("%s required but not specified", restAuctionID)
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
auctionID, ok := rest.ParseUint64OrReturnBadRequest(w, vars[RestAuctionID])
|
auctionID, ok := rest.ParseUint64OrReturnBadRequest(w, vars[restAuctionID])
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -51,17 +51,17 @@ func queryAuctionHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode and return results
|
||||||
|
cliCtx = cliCtx.WithHeight(height)
|
||||||
|
|
||||||
var auction types.Auction
|
var auction types.Auction
|
||||||
err = cliCtx.Codec.UnmarshalJSON(res, &auction)
|
err = cliCtx.Codec.UnmarshalJSON(res, &auction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Decode and return results
|
|
||||||
cliCtx = cliCtx.WithHeight(height)
|
|
||||||
|
|
||||||
auctionWithPhase := types.NewAuctionWithPhase(auction)
|
auctionWithPhase := types.NewAuctionWithPhase(auction)
|
||||||
|
|
||||||
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionWithPhase))
|
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionWithPhase))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,13 +73,15 @@ func queryAuctionsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all auctions
|
// Get all auctions
|
||||||
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("/custom/%s/%s", types.ModuleName, types.QueryGetAuctions), nil)
|
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("/custom/%s/%s", types.ModuleName, types.QueryGetAuctions), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
rest.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Return auctions
|
|
||||||
|
// Decode and return results
|
||||||
cliCtx = cliCtx.WithHeight(height)
|
cliCtx = cliCtx.WithHeight(height)
|
||||||
|
|
||||||
var auctions types.Auctions
|
var auctions types.Auctions
|
||||||
@ -89,11 +91,10 @@ func queryAuctionsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var auctionsWithPhase []types.AuctionWithPhase
|
auctionsWithPhase := []types.AuctionWithPhase{} // using empty slice so json returns [] instead of null when there's no auctions
|
||||||
for _, a := range auctions {
|
for _, a := range auctions {
|
||||||
auctionsWithPhase = append(auctionsWithPhase, types.NewAuctionWithPhase(a))
|
auctionsWithPhase = append(auctionsWithPhase, types.NewAuctionWithPhase(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionsWithPhase))
|
rest.PostProcessResponse(w, cliCtx, cliCtx.Codec.MustMarshalJSON(auctionsWithPhase))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,7 +112,7 @@ func getParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Return the params
|
// Decode and return results
|
||||||
cliCtx = cliCtx.WithHeight(height)
|
cliCtx = cliCtx.WithHeight(height)
|
||||||
rest.PostProcessResponse(w, cliCtx, res)
|
rest.PostProcessResponse(w, cliCtx, res)
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
@ -16,65 +14,45 @@ import (
|
|||||||
"github.com/kava-labs/kava/x/auction/types"
|
"github.com/kava-labs/kava/x/auction/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type placeBidReq struct {
|
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||||
BaseReq rest.BaseReq `json:"base_req"`
|
r.HandleFunc(fmt.Sprintf("/{%s}/auctions/{%s}/bids", types.ModuleName, restAuctionID), bidHandlerFn(cliCtx)).Methods("POST")
|
||||||
AuctionID string `json:"auction_id"`
|
|
||||||
Bidder string `json:"bidder"`
|
|
||||||
Bid string `json:"bid"`
|
|
||||||
Lot string `json:"lot"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
type placeBidReq struct {
|
||||||
restAuctionID = "auction_id"
|
BaseReq rest.BaseReq `json:"base_req"`
|
||||||
restBidder = "bidder"
|
Amount sdk.Coin `json:"amount"`
|
||||||
restBid = "bid"
|
|
||||||
restLot = "lot"
|
|
||||||
)
|
|
||||||
|
|
||||||
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
|
||||||
r.HandleFunc(
|
|
||||||
fmt.Sprintf("/auction/bid/{%s}/{%s}/{%s}", restAuctionID, restBidder, restBid), bidHandlerFn(cliCtx)).Methods("PUT")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func bidHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
func bidHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
// Get auction ID from url
|
||||||
|
auctionID, ok := rest.ParseUint64OrReturnBadRequest(w, mux.Vars(r)[restAuctionID])
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get info from the http request body
|
||||||
var req placeBidReq
|
var req placeBidReq
|
||||||
vars := mux.Vars(r)
|
if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) {
|
||||||
strAuctionID := vars[restAuctionID]
|
return
|
||||||
bechBidder := vars[restBidder]
|
}
|
||||||
strBid := vars[restBid]
|
req.BaseReq = req.BaseReq.Sanitize()
|
||||||
|
if !req.BaseReq.ValidateBasic(w) {
|
||||||
auctionID, err := strconv.ParseUint(strAuctionID, 10, 64)
|
return
|
||||||
|
}
|
||||||
|
bidderAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bidder, err := sdk.AccAddressFromBech32(bechBidder)
|
// Create and return a StdTx
|
||||||
if err != nil {
|
msg := types.NewMsgPlaceBid(auctionID, bidderAddr, req.Amount)
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
bid, err := sdk.ParseCoin(strBid)
|
|
||||||
if err != nil {
|
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := types.NewMsgPlaceBid(auctionID, bidder, bid)
|
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From)
|
|
||||||
if !bytes.Equal(fromAddr, bidder) {
|
|
||||||
rest.WriteErrorResponse(w, http.StatusUnauthorized, "must bid from own address")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
|
utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ func TestDebtAuctionBasic(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("debt", 80)))
|
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("debt", 80)))
|
||||||
|
|
||||||
// Place a bid
|
// Place a bid
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, seller, c("token2", 10)))
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, seller, c("token2", 10)))
|
||||||
// Check seller's coins have decreased
|
// Check seller's coins have decreased
|
||||||
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
|
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
|
||||||
// Check buyer's coins have increased
|
// Check buyer's coins have increased
|
||||||
@ -127,7 +127,7 @@ func TestDebtAuctionDebtRemaining(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("debt", 80)))
|
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("debt", 80)))
|
||||||
|
|
||||||
// Place a bid
|
// Place a bid
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, seller, c("token2", 10)))
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, seller, c("token2", 10)))
|
||||||
// Check seller's coins have decreased
|
// Check seller's coins have decreased
|
||||||
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 90), c("token2", 100)))
|
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 90), c("token2", 100)))
|
||||||
// Check buyer's coins have increased
|
// Check buyer's coins have increased
|
||||||
@ -173,7 +173,7 @@ func TestCollateralAuctionBasic(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100), c("debt", 60)))
|
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100), c("debt", 60)))
|
||||||
|
|
||||||
// Place a forward bid
|
// Place a forward bid
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 10)))
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 10)))
|
||||||
// Check bidder's coins have decreased
|
// Check bidder's coins have decreased
|
||||||
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
|
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
|
||||||
// Check seller's coins have increased
|
// Check seller's coins have increased
|
||||||
@ -184,8 +184,8 @@ func TestCollateralAuctionBasic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Place a reverse bid
|
// Place a reverse bid
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 50))) // first bid up to max bid to switch phases
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 50))) // first bid up to max bid to switch phases
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token1", 15)))
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token1", 15)))
|
||||||
// Check bidder's coins have decreased
|
// Check bidder's coins have decreased
|
||||||
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 50)))
|
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 50)))
|
||||||
// Check seller's coins have increased
|
// Check seller's coins have increased
|
||||||
@ -233,7 +233,7 @@ func TestCollateralAuctionDebtRemaining(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100), c("debt", 60)))
|
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100), c("debt", 60)))
|
||||||
|
|
||||||
// Place a forward bid
|
// Place a forward bid
|
||||||
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 10)))
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 10)))
|
||||||
// Check bidder's coins have decreased
|
// Check bidder's coins have decreased
|
||||||
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
|
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
|
||||||
// Check seller's coins have increased
|
// Check seller's coins have increased
|
||||||
@ -322,7 +322,7 @@ func TestStartSurplusAuction(t *testing.T) {
|
|||||||
// check auction in store and is correct
|
// check auction in store and is correct
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
expectedAuction := types.Auction(types.SurplusAuction{BaseAuction: types.BaseAuction{
|
expectedAuction := types.Auction(types.SurplusAuction{BaseAuction: types.BaseAuction{
|
||||||
ID: 0,
|
ID: id,
|
||||||
Initiator: tc.args.seller,
|
Initiator: tc.args.seller,
|
||||||
Lot: tc.args.lot,
|
Lot: tc.args.lot,
|
||||||
Bidder: nil,
|
Bidder: nil,
|
||||||
|
@ -78,7 +78,7 @@ func (suite *QuerierTestSuite) TestQueryAuction() {
|
|||||||
// Set up request query
|
// Set up request query
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetAuction}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetAuction}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.QueryAuctionParams{AuctionID: 0}), // get the first auction
|
Data: types.ModuleCdc.MustMarshalJSON(types.QueryAuctionParams{AuctionID: types.DefaultNextAuctionID}), // get the first auction
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute query and check the []byte result
|
// Execute query and check the []byte result
|
||||||
|
@ -17,12 +17,15 @@ var DistantFuture = time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC)
|
|||||||
type Auction interface {
|
type Auction interface {
|
||||||
GetID() uint64
|
GetID() uint64
|
||||||
WithID(uint64) Auction
|
WithID(uint64) Auction
|
||||||
|
|
||||||
GetInitiator() string
|
GetInitiator() string
|
||||||
GetLot() sdk.Coin
|
GetLot() sdk.Coin
|
||||||
GetBidder() sdk.AccAddress
|
GetBidder() sdk.AccAddress
|
||||||
GetBid() sdk.Coin
|
GetBid() sdk.Coin
|
||||||
GetEndTime() time.Time
|
GetEndTime() time.Time
|
||||||
|
|
||||||
GetType() string
|
GetType() string
|
||||||
|
GetPhase() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auctions is a slice of auctions.
|
// Auctions is a slice of auctions.
|
||||||
@ -86,7 +89,7 @@ func (a BaseAuction) String() string {
|
|||||||
// SurplusAuction is a forward auction that burns what it receives from bids.
|
// SurplusAuction is a forward auction that burns what it receives from bids.
|
||||||
// It is normally used to sell off excess pegged asset acquired by the CDP system.
|
// It is normally used to sell off excess pegged asset acquired by the CDP system.
|
||||||
type SurplusAuction struct {
|
type SurplusAuction struct {
|
||||||
BaseAuction
|
BaseAuction `json:"base_auction" yaml:"base_auction"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithID returns an auction with the ID set.
|
// WithID returns an auction with the ID set.
|
||||||
@ -102,6 +105,9 @@ func (a SurplusAuction) GetModuleAccountCoins() sdk.Coins {
|
|||||||
return sdk.NewCoins(a.Lot)
|
return sdk.NewCoins(a.Lot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPhase returns the direction of a surplus auction, which never changes.
|
||||||
|
func (a SurplusAuction) GetPhase() string { return "forward" }
|
||||||
|
|
||||||
// NewSurplusAuction returns a new surplus auction.
|
// NewSurplusAuction returns a new surplus auction.
|
||||||
func NewSurplusAuction(seller string, lot sdk.Coin, bidDenom string, endTime time.Time) SurplusAuction {
|
func NewSurplusAuction(seller string, lot sdk.Coin, bidDenom string, endTime time.Time) SurplusAuction {
|
||||||
auction := SurplusAuction{BaseAuction{
|
auction := SurplusAuction{BaseAuction{
|
||||||
@ -120,7 +126,7 @@ func NewSurplusAuction(seller string, lot sdk.Coin, bidDenom string, endTime tim
|
|||||||
// DebtAuction is a reverse auction that mints what it pays out.
|
// DebtAuction is a reverse auction that mints what it pays out.
|
||||||
// It is normally used to acquire pegged asset to cover the CDP system's debts that were not covered by selling collateral.
|
// It is normally used to acquire pegged asset to cover the CDP system's debts that were not covered by selling collateral.
|
||||||
type DebtAuction struct {
|
type DebtAuction struct {
|
||||||
BaseAuction
|
BaseAuction `json:"base_auction" yaml:"base_auction"`
|
||||||
|
|
||||||
CorrespondingDebt sdk.Coin `json:"corresponding_debt" yaml:"corresponding_debt"`
|
CorrespondingDebt sdk.Coin `json:"corresponding_debt" yaml:"corresponding_debt"`
|
||||||
}
|
}
|
||||||
@ -139,6 +145,9 @@ func (a DebtAuction) GetModuleAccountCoins() sdk.Coins {
|
|||||||
return sdk.NewCoins(a.CorrespondingDebt)
|
return sdk.NewCoins(a.CorrespondingDebt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPhase returns the direction of a debt auction, which never changes.
|
||||||
|
func (a DebtAuction) GetPhase() string { return "reverse" }
|
||||||
|
|
||||||
// NewDebtAuction returns a new debt auction.
|
// NewDebtAuction returns a new debt auction.
|
||||||
func NewDebtAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, endTime time.Time, debt sdk.Coin) DebtAuction {
|
func NewDebtAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, endTime time.Time, debt sdk.Coin) DebtAuction {
|
||||||
// Note: Bidder is set to the initiator's module account address instead of module name. (when the first bid is placed, it is paid out to the initiator)
|
// Note: Bidder is set to the initiator's module account address instead of module name. (when the first bid is placed, it is paid out to the initiator)
|
||||||
@ -165,7 +174,7 @@ func NewDebtAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, e
|
|||||||
// Unsold Lot is sent to LotReturns, being divided among the addresses by weight.
|
// Unsold Lot is sent to LotReturns, being divided among the addresses by weight.
|
||||||
// Collateral auctions are normally used to sell off collateral seized from CDPs.
|
// Collateral auctions are normally used to sell off collateral seized from CDPs.
|
||||||
type CollateralAuction struct {
|
type CollateralAuction struct {
|
||||||
BaseAuction
|
BaseAuction `json:"base_auction" yaml:"base_auction"`
|
||||||
|
|
||||||
CorrespondingDebt sdk.Coin `json:"corresponding_debt" yaml:"corresponding_debt"`
|
CorrespondingDebt sdk.Coin `json:"corresponding_debt" yaml:"corresponding_debt"`
|
||||||
MaxBid sdk.Coin `json:"max_bid" yaml:"max_bid"`
|
MaxBid sdk.Coin `json:"max_bid" yaml:"max_bid"`
|
||||||
@ -186,12 +195,12 @@ func (a CollateralAuction) GetModuleAccountCoins() sdk.Coins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsReversePhase returns whether the auction has switched over to reverse phase or not.
|
// IsReversePhase returns whether the auction has switched over to reverse phase or not.
|
||||||
// Auction initially start in forward phase.
|
// CollateralAuctions initially start in forward phase.
|
||||||
func (a CollateralAuction) IsReversePhase() bool {
|
func (a CollateralAuction) IsReversePhase() bool {
|
||||||
return a.Bid.IsEqual(a.MaxBid)
|
return a.Bid.IsEqual(a.MaxBid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPhase returns the phase of a collateral auction
|
// GetPhase returns the direction of a collateral auction.
|
||||||
func (a CollateralAuction) GetPhase() string {
|
func (a CollateralAuction) GetPhase() string {
|
||||||
if a.IsReversePhase() {
|
if a.IsReversePhase() {
|
||||||
return "reverse"
|
return "reverse"
|
||||||
|
@ -7,6 +7,9 @@ import (
|
|||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultNextAuctionID is the starting poiint for auction IDs.
|
||||||
|
const DefaultNextAuctionID uint64 = 1
|
||||||
|
|
||||||
// GenesisAuction is an interface that extends the auction interface to add functionality needed for initializing auctions from genesis.
|
// GenesisAuction is an interface that extends the auction interface to add functionality needed for initializing auctions from genesis.
|
||||||
type GenesisAuction interface {
|
type GenesisAuction interface {
|
||||||
Auction
|
Auction
|
||||||
@ -35,7 +38,11 @@ func NewGenesisState(nextID uint64, ap Params, ga GenesisAuctions) GenesisState
|
|||||||
|
|
||||||
// DefaultGenesisState returns the default genesis state for auction module.
|
// DefaultGenesisState returns the default genesis state for auction module.
|
||||||
func DefaultGenesisState() GenesisState {
|
func DefaultGenesisState() GenesisState {
|
||||||
return NewGenesisState(0, DefaultParams(), GenesisAuctions{})
|
return NewGenesisState(
|
||||||
|
DefaultNextAuctionID,
|
||||||
|
DefaultParams(),
|
||||||
|
GenesisAuctions{},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal checks whether two GenesisState structs are equivalent.
|
// Equal checks whether two GenesisState structs are equivalent.
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import sdk "github.com/cosmos/cosmos-sdk/types"
|
import (
|
||||||
|
"fmt"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
// ensure Msg interface compliance at compile time
|
// ensure Msg interface compliance at compile time
|
||||||
var _ sdk.Msg = &MsgPlaceBid{}
|
var _ sdk.Msg = &MsgPlaceBid{}
|
||||||
@ -30,10 +33,10 @@ func (msg MsgPlaceBid) Type() string { return "place_bid" }
|
|||||||
// ValidateBasic does a simple validation check that doesn't require access to state.
|
// ValidateBasic does a simple validation check that doesn't require access to state.
|
||||||
func (msg MsgPlaceBid) ValidateBasic() sdk.Error {
|
func (msg MsgPlaceBid) ValidateBasic() sdk.Error {
|
||||||
if msg.Bidder.Empty() {
|
if msg.Bidder.Empty() {
|
||||||
return sdk.ErrInternal("invalid (empty) bidder address")
|
return sdk.ErrInvalidAddress("invalid (empty) bidder address")
|
||||||
}
|
}
|
||||||
if !msg.Amount.IsValid() {
|
if !msg.Amount.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Amount.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid bid amount: %s", msg.Amount))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func NewQueryAllAuctionParams(page int, limit int) QueryAllAuctionParams {
|
|||||||
|
|
||||||
// AuctionWithPhase augmented type for collateral auctions which includes auction phase for querying
|
// AuctionWithPhase augmented type for collateral auctions which includes auction phase for querying
|
||||||
type AuctionWithPhase struct {
|
type AuctionWithPhase struct {
|
||||||
Auction Auction
|
Auction Auction `json:"auction" yaml:"auction"`
|
||||||
|
|
||||||
Type string `json:"type" yaml:"type"`
|
Type string `json:"type" yaml:"type"`
|
||||||
Phase string `json:"phase" yaml:"phase"`
|
Phase string `json:"phase" yaml:"phase"`
|
||||||
@ -38,17 +38,9 @@ type AuctionWithPhase struct {
|
|||||||
|
|
||||||
// NewAuctionWithPhase returns new AuctionWithPhase
|
// NewAuctionWithPhase returns new AuctionWithPhase
|
||||||
func NewAuctionWithPhase(a Auction) AuctionWithPhase {
|
func NewAuctionWithPhase(a Auction) AuctionWithPhase {
|
||||||
switch auc := a.(type) {
|
return AuctionWithPhase{
|
||||||
case CollateralAuction:
|
Auction: a,
|
||||||
return AuctionWithPhase{
|
Type: a.GetType(),
|
||||||
Auction: auc,
|
Phase: a.GetPhase(),
|
||||||
Type: auc.GetType(),
|
|
||||||
Phase: auc.GetPhase(),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return AuctionWithPhase{
|
|
||||||
Auction: auc,
|
|
||||||
Type: auc.GetType(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,14 @@ import (
|
|||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
"github.com/kava-labs/kava/x/auction"
|
"github.com/kava-labs/kava/x/auction"
|
||||||
"github.com/kava-labs/kava/x/cdp/keeper"
|
"github.com/kava-labs/kava/x/cdp/keeper"
|
||||||
"github.com/kava-labs/kava/x/cdp/types"
|
"github.com/kava-labs/kava/x/cdp/types"
|
||||||
"github.com/stretchr/testify/suite"
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
tmtime "github.com/tendermint/tendermint/types/time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SeizeTestSuite struct {
|
type SeizeTestSuite struct {
|
||||||
@ -136,7 +137,7 @@ func (suite *SeizeTestSuite) TestSeizeCollateral() {
|
|||||||
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
||||||
suite.Equal(tpb.Sub(tpa), p)
|
suite.Equal(tpb.Sub(tpa), p)
|
||||||
auctionKeeper := suite.app.GetAuctionKeeper()
|
auctionKeeper := suite.app.GetAuctionKeeper()
|
||||||
_, found := auctionKeeper.GetAuction(suite.ctx, 0)
|
_, found := auctionKeeper.GetAuction(suite.ctx, auction.DefaultNextAuctionID)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
auctionMacc := sk.GetModuleAccount(suite.ctx, auction.ModuleName)
|
auctionMacc := sk.GetModuleAccount(suite.ctx, auction.ModuleName)
|
||||||
suite.Equal(cs(c("debt", p.Int64()), c("xrp", cl.Int64())), auctionMacc.GetCoins())
|
suite.Equal(cs(c("debt", p.Int64()), c("xrp", cl.Int64())), auctionMacc.GetCoins())
|
||||||
|
@ -46,16 +46,16 @@ func (msg MsgCreateCDP) ValidateBasic() sdk.Error {
|
|||||||
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsValid() {
|
if !msg.Collateral.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsAllPositive() {
|
if !msg.Collateral.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Principal.IsValid() {
|
if !msg.Principal.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Principal.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid principal amount: %s", msg.Principal))
|
||||||
}
|
}
|
||||||
if !msg.Principal.IsAllPositive() {
|
if !msg.Principal.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative principal amount: %s", msg.Principal))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -114,10 +114,10 @@ func (msg MsgDeposit) ValidateBasic() sdk.Error {
|
|||||||
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsValid() {
|
if !msg.Collateral.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsAllPositive() {
|
if !msg.Collateral.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -176,10 +176,10 @@ func (msg MsgWithdraw) ValidateBasic() sdk.Error {
|
|||||||
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
return sdk.ErrInvalidCoins(fmt.Sprintf("cdps do not support multiple collateral types: received %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsValid() {
|
if !msg.Collateral.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
if !msg.Collateral.IsAllPositive() {
|
if !msg.Collateral.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Collateral.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative collateral amount: %s", msg.Collateral))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -235,10 +235,10 @@ func (msg MsgDrawDebt) ValidateBasic() sdk.Error {
|
|||||||
return sdk.ErrInternal("invalid (empty) cdp denom")
|
return sdk.ErrInternal("invalid (empty) cdp denom")
|
||||||
}
|
}
|
||||||
if !msg.Principal.IsValid() {
|
if !msg.Principal.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Principal.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid principal amount: %s", msg.Principal))
|
||||||
}
|
}
|
||||||
if !msg.Principal.IsAllPositive() {
|
if !msg.Principal.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Principal.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative principal amount: %s", msg.Principal))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -294,10 +294,10 @@ func (msg MsgRepayDebt) ValidateBasic() sdk.Error {
|
|||||||
return sdk.ErrInternal("invalid (empty) cdp denom")
|
return sdk.ErrInternal("invalid (empty) cdp denom")
|
||||||
}
|
}
|
||||||
if !msg.Payment.IsValid() {
|
if !msg.Payment.IsValid() {
|
||||||
return sdk.ErrInvalidCoins(msg.Payment.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("invalid payment amount: %s", msg.Payment))
|
||||||
}
|
}
|
||||||
if !msg.Payment.IsAllPositive() {
|
if !msg.Payment.IsAllPositive() {
|
||||||
return sdk.ErrInvalidCoins(msg.Payment.String())
|
return sdk.ErrInvalidCoins(fmt.Sprintf("negative payment amount: %s", msg.Payment))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user