add basic auction tests

This commit is contained in:
rhuairahrighairigh 2019-12-28 18:46:53 +00:00
parent ac27571d15
commit 0d72f47bc2
7 changed files with 587 additions and 525 deletions

View File

@ -61,7 +61,7 @@ var (
supply.AppModuleBasic{}, supply.AppModuleBasic{},
auction.AppModuleBasic{}, auction.AppModuleBasic{},
cdp.AppModuleBasic{}, cdp.AppModuleBasic{},
liquidator.AppModuleBasic{}, //liquidator.AppModuleBasic{},
pricefeed.AppModuleBasic{}, pricefeed.AppModuleBasic{},
) )
@ -74,6 +74,8 @@ var (
staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.NotBondedPoolName: {supply.Burner, supply.Staking},
gov.ModuleName: {supply.Burner}, gov.ModuleName: {supply.Burner},
validatorvesting.ModuleName: {supply.Burner}, validatorvesting.ModuleName: {supply.Burner},
auction.ModuleName: nil,
liquidator.ModuleName: {supply.Minter, supply.Burner},
} }
) )
@ -238,7 +240,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
app.auctionKeeper = auction.NewKeeper( app.auctionKeeper = auction.NewKeeper(
app.cdc, app.cdc,
keys[auction.StoreKey], keys[auction.StoreKey],
app.supplyKeeper, // CDP keeper standing in for bank app.supplyKeeper,
auctionSubspace) auctionSubspace)
// app.liquidatorKeeper = liquidator.NewKeeper( // app.liquidatorKeeper = liquidator.NewKeeper(
// app.cdc, // app.cdc,
@ -269,7 +271,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
validatorvesting.NewAppModule(app.vvKeeper, app.accountKeeper), validatorvesting.NewAppModule(app.vvKeeper, app.accountKeeper),
auction.NewAppModule(app.auctionKeeper), auction.NewAppModule(app.auctionKeeper),
cdp.NewAppModule(app.cdpKeeper, app.pricefeedKeeper), cdp.NewAppModule(app.cdpKeeper, app.pricefeedKeeper),
liquidator.NewAppModule(app.liquidatorKeeper), //liquidator.NewAppModule(app.liquidatorKeeper),
pricefeed.NewAppModule(app.pricefeedKeeper), pricefeed.NewAppModule(app.pricefeedKeeper),
) )
@ -289,7 +291,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
auth.ModuleName, validatorvesting.ModuleName, distr.ModuleName, auth.ModuleName, validatorvesting.ModuleName, distr.ModuleName,
staking.ModuleName, bank.ModuleName, slashing.ModuleName, staking.ModuleName, bank.ModuleName, slashing.ModuleName,
gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName,
pricefeed.ModuleName, cdp.ModuleName, auction.ModuleName, liquidator.ModuleName, // TODO is this order ok? pricefeed.ModuleName, cdp.ModuleName, auction.ModuleName, //liquidator.ModuleName, // TODO is this order ok?
) )
app.mm.RegisterInvariants(&app.crisisKeeper) app.mm.RegisterInvariants(&app.crisisKeeper)

View File

@ -20,7 +20,7 @@ func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin
return 0, err return 0, err
} }
// store the auction // store the auction
auctionID, err := k.storeNewAuction(ctx, auction) // TODO does this need to be a pointer to satisfy the interface? auctionID, err := k.storeNewAuction(ctx, auction)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -38,7 +38,7 @@ func (k Keeper) StartReverseAuction(ctx sdk.Context, buyer string, bid sdk.Coin,
return 0, sdk.ErrInternal("module does not have minting permissions") return 0, sdk.ErrInternal("module does not have minting permissions")
} }
// store the auction // store the auction
auctionID, err := k.storeNewAuction(ctx, &auction) auctionID, err := k.storeNewAuction(ctx, auction)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -51,12 +51,12 @@ func (k Keeper) StartForwardReverseAuction(ctx sdk.Context, seller string, lot s
auction := types.NewForwardReverseAuction(seller, lot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration), maxBid, otherPerson) auction := types.NewForwardReverseAuction(seller, lot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration), maxBid, otherPerson)
// take coins from module account // take coins from module account
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.Coins{lot}) err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.NewCoins(lot))
if err != nil { if err != nil {
return 0, err return 0, err
} }
// store the auction // store the auction
auctionID, err := k.storeNewAuction(ctx, &auction) auctionID, err := k.storeNewAuction(ctx, auction)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -64,6 +64,7 @@ func (k Keeper) StartForwardReverseAuction(ctx sdk.Context, seller string, lot s
} }
// PlaceBid places a bid on any auction. // PlaceBid places a bid on any auction.
// TODO passing bid and lot is weird when only one needed
func (k Keeper) PlaceBid(ctx sdk.Context, auctionID types.ID, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) sdk.Error { func (k Keeper) PlaceBid(ctx sdk.Context, auctionID types.ID, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) sdk.Error {
// get auction from store // get auction from store
@ -72,11 +73,18 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID types.ID, bidder sdk.AccAddr
return sdk.ErrInternal("auction doesn't exist") return sdk.ErrInternal("auction doesn't exist")
} }
// check end time // validate
if ctx.BlockTime().After(auction.GetEndTime()) { if ctx.BlockTime().After(auction.GetEndTime()) {
return sdk.ErrInternal("auction has closed") return sdk.ErrInternal("auction has closed")
} }
if auction.GetBid().Denom != bid.Denom {
return sdk.ErrInternal("bid has incorrect denom")
}
if auction.GetLot().Denom != lot.Denom {
return sdk.ErrInternal("lot has incorrect denom")
}
// place bid
var err sdk.Error var err sdk.Error
var a types.Auction var a types.Auction
switch auc := auction.(type) { switch auc := auction.(type) {
@ -124,7 +132,7 @@ func (k Keeper) PlaceBidForward(ctx sdk.Context, a types.ForwardAuction, bidder
if err != nil { if err != nil {
return a, err return a, err
} }
err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidder, sdk.NewCoins(bidAmtToReturn)) err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, a.Bidder, sdk.NewCoins(bidAmtToReturn))
if err != nil { if err != nil {
return a, err return a, err
} }
@ -185,7 +193,7 @@ func (k Keeper) PlaceBidForwardReverse(ctx sdk.Context, a types.ForwardReverseAu
if err != nil { if err != nil {
return a, err return a, err
} }
err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidder, sdk.NewCoins(bidAmtToReturn)) err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, a.Bidder, sdk.NewCoins(bidAmtToReturn))
if err != nil { if err != nil {
return a, err return a, err
} }
@ -205,7 +213,7 @@ func (k Keeper) PlaceBidForwardReverse(ctx sdk.Context, a types.ForwardReverseAu
// increment timeout // increment timeout
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration), a.MaxEndTime) a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration), a.MaxEndTime)
return types.ForwardReverseAuction{}, nil return a, nil
} }
func (k Keeper) PlaceBidReverse(ctx sdk.Context, a types.ReverseAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.ReverseAuction, sdk.Error) { func (k Keeper) PlaceBidReverse(ctx sdk.Context, a types.ReverseAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.ReverseAuction, sdk.Error) {
// Validate New Bid // Validate New Bid
@ -228,7 +236,7 @@ func (k Keeper) PlaceBidReverse(ctx sdk.Context, a types.ReverseAuction, bidder
if err != nil { if err != nil {
return a, err return a, err
} }
err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidder, sdk.NewCoins(bidAmtToReturn)) err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, a.Bidder, sdk.NewCoins(bidAmtToReturn))
if err != nil { if err != nil {
return a, err return a, err
} }
@ -297,7 +305,11 @@ func (k Keeper) PayoutAuctionLot(ctx sdk.Context, a types.Auction) sdk.Error {
return nil return nil
} }
// FIXME stand in func for compiler // earliestTime returns the earliest of two times.
func earliestTime(t1, t2 time.Time) time.Time { func earliestTime(t1, t2 time.Time) time.Time {
return t1 if t1.Before(t2) {
return t1
} else {
return t2 // also returned if times are equal
}
} }

View File

@ -0,0 +1,145 @@
package keeper_test
import (
"testing"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/supply"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/auction/types"
"github.com/kava-labs/kava/x/liquidator"
)
func TestForwardAuctionBasic(t *testing.T) {
// Setup
_, addrs := app.GeneratePrivKeyAddressPairs(1)
buyer := addrs[0]
sellerModName := liquidator.ModuleName
sellerAddr := supply.NewModuleAddress(sellerModName)
tApp := app.NewTestApp()
sellerAcc := supply.NewEmptyModuleAccount(sellerModName, supply.Burner) // forward auctions burn proceeds
require.NoError(t, sellerAcc.SetCoins(cs(c("token1", 100), c("token2", 100))))
tApp.InitializeFromGenesisStates(
NewAuthGenStateFromAccs(authexported.GenesisAccounts{
auth.NewBaseAccount(buyer, cs(c("token1", 100), c("token2", 100)), nil, 0, 0),
sellerAcc,
}),
)
ctx := tApp.NewContext(false, abci.Header{})
keeper := tApp.GetAuctionKeeper()
// Create an auction (lot: 20 token1, initialBid: 0 token2)
auctionID, err := keeper.StartForwardAuction(ctx, sellerModName, c("token1", 20), "token2") // lot, bid denom
require.NoError(t, err)
// Check seller's coins have decreased
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
// PlaceBid (bid: 10 token, lot: same as starting)
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 10), c("token1", 20))) // bid, lot
// Check buyer's coins have decreased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
// Check seller's coins have not increased (because proceeds are burned)
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
// Close auction at just at auction expiry time
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// Check buyer's coins increased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
}
func TestReverseAuctionBasic(t *testing.T) {
// Setup
_, addrs := app.GeneratePrivKeyAddressPairs(1)
seller := addrs[0]
buyerModName := liquidator.ModuleName
buyerAddr := supply.NewModuleAddress(buyerModName)
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates(
NewAuthGenStateFromAccs(authexported.GenesisAccounts{
auth.NewBaseAccount(seller, cs(c("token1", 100), c("token2", 100)), nil, 0, 0),
supply.NewEmptyModuleAccount(buyerModName, supply.Minter), // reverse auctions mint payout
}),
)
ctx := tApp.NewContext(false, abci.Header{})
keeper := tApp.GetAuctionKeeper()
// Start auction
auctionID, err := keeper.StartReverseAuction(ctx, buyerModName, c("token1", 20), c("token2", 99999)) // buyer, bid, initialLot
require.NoError(t, err)
// Check buyer's coins have not decreased, as lot is minted at the end
tApp.CheckBalance(t, ctx, buyerAddr, nil) // zero coins
// Place a bid
require.NoError(t, keeper.PlaceBid(ctx, 0, seller, c("token1", 20), c("token2", 10))) // bid, lot
// Check seller's coins have decreased
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
// Check buyer's coins have increased
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("token1", 20)))
// Close auction at just after auction expiry
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// Check seller's coins increased
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 110)))
}
func TestForwardReverseAuctionBasic(t *testing.T) {
// Setup
_, addrs := app.GeneratePrivKeyAddressPairs(2)
buyer := addrs[0]
recipient := addrs[1]
sellerModName := liquidator.ModuleName
sellerAddr := supply.NewModuleAddress(sellerModName)
tApp := app.NewTestApp()
sellerAcc := supply.NewEmptyModuleAccount(sellerModName)
require.NoError(t, sellerAcc.SetCoins(cs(c("token1", 100), c("token2", 100))))
tApp.InitializeFromGenesisStates(
NewAuthGenStateFromAccs(authexported.GenesisAccounts{
auth.NewBaseAccount(buyer, cs(c("token1", 100), c("token2", 100)), nil, 0, 0),
auth.NewBaseAccount(recipient, cs(c("token1", 100), c("token2", 100)), nil, 0, 0),
sellerAcc,
}),
)
ctx := tApp.NewContext(false, abci.Header{})
keeper := tApp.GetAuctionKeeper()
// Start auction
auctionID, err := keeper.StartForwardReverseAuction(ctx, sellerModName, c("token1", 20), c("token2", 50), recipient) // seller, lot, maxBid, otherPerson
require.NoError(t, err)
// Check seller's coins have decreased
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
// Place a forward bid
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 10), c("token1", 20))) // bid, lot
// Check bidder's coins have decreased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
// Check seller's coins have increased
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 110)))
// Check recipient has not received coins
tApp.CheckBalance(t, ctx, recipient, cs(c("token1", 100), c("token2", 100)))
// Place a reverse bid
require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 50), c("token1", 15))) // bid, lot
// Check bidder's coins have decreased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 50)))
// Check seller's coins have increased
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 150)))
// Check "recipient" has received coins
tApp.CheckBalance(t, ctx, recipient, cs(c("token1", 105), c("token2", 100)))
// Close auction at just after auction expiry
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// Check buyer's coins increased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 115), c("token2", 50)))
}

View File

@ -0,0 +1,17 @@
package keeper_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/kava-labs/kava/app"
)
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
func NewAuthGenStateFromAccs(accounts authexported.GenesisAccounts) app.GenesisState {
authGenesis := auth.NewGenesisState(auth.DefaultParams(), accounts)
return app.GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
}

View File

@ -13,128 +13,22 @@ import (
"github.com/kava-labs/kava/x/auction/types" "github.com/kava-labs/kava/x/auction/types"
) )
// func TestKeeper_ForwardAuction(t *testing.T) {
// // Setup
// _, addrs := app.GeneratePrivKeyAddressPairs(2)
// seller := addrs[0]
// buyer := addrs[1]
// tApp := app.NewTestApp()
// tApp.InitializeFromGenesisStates(
// app.NewAuthGenState(addrs, []sdk.Coins{cs(c("token1", 100), c("token2", 100)), cs(c("token1", 100), c("token2", 100))}),
// )
// ctx := tApp.NewContext(false, abci.Header{})
// keeper := tApp.GetAuctionKeeper()
// // Create an auction (lot: 20 t1, initialBid: 0 t2)
// auctionID, err := keeper.StartForwardAuction(ctx, seller, c("token1", 20), c("token2", 0)) // lot, initialBid
// require.NoError(t, err)
// // Check seller's coins have decreased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
// // PlaceBid (bid: 10 t2, lot: same as starting)
// require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 10), c("token1", 20))) // bid, lot
// // Check buyer's coins have decreased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 90)))
// // Check seller's coins have increased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 110)))
// // Close auction at just after auction expiry
// ctx = ctx.WithBlockHeight(int64(types.DefaultMaxBidDuration))
// require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// // Check buyer's coins increased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
// }
// func TestKeeper_ReverseAuction(t *testing.T) {
// // Setup
// _, addrs := app.GeneratePrivKeyAddressPairs(2)
// seller := addrs[0]
// buyer := addrs[1]
// tApp := app.NewTestApp()
// tApp.InitializeFromGenesisStates(
// app.NewAuthGenState(addrs, []sdk.Coins{cs(c("token1", 100), c("token2", 100)), cs(c("token1", 100), c("token2", 100))}),
// )
// ctx := tApp.NewContext(false, abci.Header{})
// keeper := tApp.GetAuctionKeeper()
// // Start auction
// auctionID, err := keeper.StartReverseAuction(ctx, buyer, c("token1", 20), c("token2", 99)) // buyer, bid, initialLot
// require.NoError(t, err)
// // Check buyer's coins have decreased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 1)))
// // Place a bid
// require.NoError(t, keeper.PlaceBid(ctx, 0, seller, c("token1", 20), c("token2", 10))) // bid, lot
// // Check seller's coins have decreased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
// // Check buyer's coins have increased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
// // Close auction at just after auction expiry
// ctx = ctx.WithBlockHeight(int64(types.DefaultMaxBidDuration))
// require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// // Check seller's coins increased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 110)))
// }
// func TestKeeper_ForwardReverseAuction(t *testing.T) {
// // Setup
// _, addrs := app.GeneratePrivKeyAddressPairs(3)
// seller := addrs[0]
// buyer := addrs[1]
// recipient := addrs[2]
// tApp := app.NewTestApp()
// tApp.InitializeFromGenesisStates(
// app.NewAuthGenState(addrs, []sdk.Coins{cs(c("token1", 100), c("token2", 100)), cs(c("token1", 100), c("token2", 100)), cs(c("token1", 100), c("token2", 100))}),
// )
// ctx := tApp.NewContext(false, abci.Header{})
// keeper := tApp.GetAuctionKeeper()
// // Start auction
// auctionID, err := keeper.StartForwardReverseAuction(ctx, seller, c("token1", 20), c("token2", 50), recipient) // seller, lot, maxBid, otherPerson
// require.NoError(t, err)
// // Check seller's coins have decreased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 100)))
// // Place a bid
// require.NoError(t, keeper.PlaceBid(ctx, 0, buyer, c("token2", 50), c("token1", 15))) // bid, lot
// // Check bidder's coins have decreased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 100), c("token2", 50)))
// // Check seller's coins have increased
// tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 150)))
// // Check "recipient" has received coins
// tApp.CheckBalance(t, ctx, recipient, cs(c("token1", 105), c("token2", 100)))
// // Close auction at just after auction expiry
// ctx = ctx.WithBlockHeight(int64(types.DefaultMaxBidDuration))
// require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// // Check buyer's coins increased
// tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 115), c("token2", 50)))
// }
func SetGetDeleteAuction(t *testing.T) { func SetGetDeleteAuction(t *testing.T) {
// setup keeper, create auction // setup keeper, create auction
tApp := app.NewTestApp() tApp := app.NewTestApp()
keeper := tApp.GetAuctionKeeper() keeper := tApp.GetAuctionKeeper()
ctx := tApp.NewContext(true, abci.Header{}) ctx := tApp.NewContext(true, abci.Header{})
someTime := time.Date(43, time.January, 1, 0, 0, 0, 0, time.UTC) // need to specify UTC as tz info is lost on unmarshal someTime := time.Date(43, time.January, 1, 0, 0, 0, 0, time.UTC) // need to specify UTC as tz info is lost on unmarshal
auction := types.NewForwardAuction("some_module", c("usdx", 100), "kava", someTime)
id := types.ID(5) id := types.ID(5)
auction.SetID(id) auction := types.NewForwardAuction("some_module", c("usdx", 100), "kava", someTime).WithID(id)
// write and read from store // write and read from store
keeper.SetAuction(ctx, &auction) keeper.SetAuction(ctx, auction)
readAuction, found := keeper.GetAuction(ctx, id) readAuction, found := keeper.GetAuction(ctx, id)
// check before and after match // check before and after match
require.True(t, found) require.True(t, found)
require.Equal(t, &auction, readAuction) require.Equal(t, auction, readAuction)
// check auction is in queue // check auction is in queue
// iter := keeper.GetQueueIterator(ctx, 100000) // iter := keeper.GetQueueIterator(ctx, 100000)
// require.Equal(t, 1, len(convertIteratorToSlice(keeper, iter))) // require.Equal(t, 1, len(convertIteratorToSlice(keeper, iter)))
@ -245,6 +139,3 @@ func convertIteratorToSlice(keeper keeper.Keeper, iterator sdk.Iterator) []types
} }
return queue return queue
} }
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }

View File

@ -37,6 +37,7 @@ type Auction interface {
GetID() ID GetID() ID
WithID(ID) Auction WithID(ID) Auction
GetBidder() sdk.AccAddress GetBidder() sdk.AccAddress
GetBid() sdk.Coin
GetLot() sdk.Coin GetLot() sdk.Coin
GetEndTime() time.Time GetEndTime() time.Time
} }
@ -44,7 +45,7 @@ type Auction interface {
// BaseAuction type shared by all Auctions // BaseAuction type shared by all Auctions
type BaseAuction struct { type BaseAuction struct {
ID ID ID ID
Initiator string // Module who starts the auction. Giving away Lot (aka seller in a forward auction). Restricted to being a module account name rather than any account. Initiator string // Module that starts the auction. Giving away Lot (aka seller in a forward auction). Restricted to being a module account name rather than any account.
Lot sdk.Coin // Amount of coins up being given by initiator (FA - amount for sale by seller, RA - cost of good by buyer (bid)) Lot sdk.Coin // Amount of coins up being given by initiator (FA - amount for sale by seller, RA - cost of good by buyer (bid))
Bidder sdk.AccAddress // Person who bids in the auction. Receiver of Lot. (aka buyer in forward auction, seller in RA) Bidder sdk.AccAddress // Person who bids in the auction. Receiver of Lot. (aka buyer in forward auction, seller in RA)
Bid sdk.Coin // Amount of coins being given by the bidder (FA - bid, RA - amount being sold) Bid sdk.Coin // Amount of coins being given by the bidder (FA - bid, RA - amount being sold)
@ -58,6 +59,9 @@ func (a BaseAuction) GetID() ID { return a.ID }
// GetBid getter for auction bid // GetBid getter for auction bid
func (a BaseAuction) GetBidder() sdk.AccAddress { return a.Bidder } func (a BaseAuction) GetBidder() sdk.AccAddress { return a.Bidder }
// GetBid getter for auction lot
func (a BaseAuction) GetBid() sdk.Coin { return a.Bid }
// GetLot getter for auction lot // GetLot getter for auction lot
func (a BaseAuction) GetLot() sdk.Coin { return a.Lot } func (a BaseAuction) GetLot() sdk.Coin { return a.Lot }
@ -83,7 +87,7 @@ type ForwardAuction struct {
BaseAuction BaseAuction
} }
// WithID returns an auction wtih the ID set // WithID returns an auction with the ID set
func (a ForwardAuction) WithID(id ID) Auction { a.ID = id; return a } func (a ForwardAuction) WithID(id ID) Auction { a.ID = id; return a }
// NewForwardAuction creates a new forward auction // NewForwardAuction creates a new forward auction
@ -97,7 +101,6 @@ func NewForwardAuction(seller string, lot sdk.Coin, bidDenom string, endTime tim
EndTime: endTime, EndTime: endTime,
MaxEndTime: endTime, MaxEndTime: endTime,
}} }}
// output := BankOutput{seller, lot}
return auction return auction
} }
@ -106,7 +109,7 @@ type ReverseAuction struct {
BaseAuction BaseAuction
} }
// WithID returns an auction wtih the ID set // WithID returns an auction with the ID set
func (a ReverseAuction) WithID(id ID) Auction { a.ID = id; return a } func (a ReverseAuction) WithID(id ID) Auction { a.ID = id; return a }
// NewReverseAuction creates a new reverse auction // NewReverseAuction creates a new reverse auction
@ -134,7 +137,7 @@ type ForwardReverseAuction struct {
OtherPerson sdk.AccAddress // TODO rename, this is normally the original CDP owner, will have to be updated to account for deposits OtherPerson sdk.AccAddress // TODO rename, this is normally the original CDP owner, will have to be updated to account for deposits
} }
// WithID returns an auction wtih the ID set // WithID returns an auction with the ID set
func (a ForwardReverseAuction) WithID(id ID) Auction { a.ID = id; return a } func (a ForwardReverseAuction) WithID(id ID) Auction { a.ID = id; return a }
func (a ForwardReverseAuction) String() string { func (a ForwardReverseAuction) String() string {
@ -167,6 +170,5 @@ func NewForwardReverseAuction(seller string, lot sdk.Coin, EndTime time.Time, ma
MaxBid: maxBid, MaxBid: maxBid,
OtherPerson: otherPerson, OtherPerson: otherPerson,
} }
//output := BankOutput{seller, lot}
return auction return auction
} }

View File

@ -1,403 +1,396 @@
package types package types
import ( // // TODO can this be less verbose? Should PlaceBid() be split into smaller functions?
"testing" // // It would be possible to combine all auction tests into one test runner.
// func TestForwardAuction_PlaceBid(t *testing.T) {
// seller := sdk.AccAddress([]byte("a_seller"))
// buyer1 := sdk.AccAddress([]byte("buyer1"))
// buyer2 := sdk.AccAddress([]byte("buyer2"))
// end := EndTime(10000)
// now := EndTime(10)
sdk "github.com/cosmos/cosmos-sdk/types" // type args struct {
"github.com/stretchr/testify/require" // currentBlockHeight EndTime
) // bidder sdk.AccAddress
// lot sdk.Coin
// bid sdk.Coin
// }
// tests := []struct {
// name string
// auction ForwardAuction
// args args
// expectedOutputs []BankOutput
// expectedInputs []BankInput
// expectedEndTime EndTime
// expectedBidder sdk.AccAddress
// expectedBid sdk.Coin
// expectpass bool
// }{
// {
// "normal",
// ForwardAuction{BaseAuction{
// Initiator: seller,
// Lot: c("usdx", 100),
// Bidder: buyer1,
// Bid: c("kava", 6),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, buyer2, c("usdx", 100), c("kava", 10)},
// []BankOutput{{buyer2, c("kava", 10)}},
// []BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
// now + DefaultMaxBidDuration,
// buyer2,
// c("kava", 10),
// true,
// },
// {
// "lowBid",
// ForwardAuction{BaseAuction{
// Initiator: seller,
// Lot: c("usdx", 100),
// Bidder: buyer1,
// Bid: c("kava", 6),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, buyer2, c("usdx", 100), c("kava", 5)},
// []BankOutput{},
// []BankInput{},
// end,
// buyer1,
// c("kava", 6),
// false,
// },
// {
// "equalBid",
// ForwardAuction{BaseAuction{
// Initiator: seller,
// Lot: c("usdx", 100),
// Bidder: buyer1,
// Bid: c("kava", 6),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, buyer2, c("usdx", 100), c("kava", 6)},
// []BankOutput{},
// []BankInput{},
// end,
// buyer1,
// c("kava", 6),
// false,
// },
// {
// "timeout",
// ForwardAuction{BaseAuction{
// Initiator: seller,
// Lot: c("usdx", 100),
// Bidder: buyer1,
// Bid: c("kava", 6),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{end + 1, buyer2, c("usdx", 100), c("kava", 10)},
// []BankOutput{},
// []BankInput{},
// end,
// buyer1,
// c("kava", 6),
// false,
// },
// {
// "hitMaxEndTime",
// ForwardAuction{BaseAuction{
// Initiator: seller,
// Lot: c("usdx", 100),
// Bidder: buyer1,
// Bid: c("kava", 6),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{end - 1, buyer2, c("usdx", 100), c("kava", 10)},
// []BankOutput{{buyer2, c("kava", 10)}},
// []BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
// end, // end time should be capped at MaxEndTime
// buyer2,
// c("kava", 10),
// true,
// },
// }
// for _, tc := range tests {
// t.Run(tc.name, func(t *testing.T) {
// // update auction and return in/outputs
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
// TODO can this be less verbose? Should PlaceBid() be split into smaller functions? // // check for err
// It would be possible to combine all auction tests into one test runner. // if tc.expectpass {
func TestForwardAuction_PlaceBid(t *testing.T) { // require.Nil(t, err)
seller := sdk.AccAddress([]byte("a_seller")) // } else {
buyer1 := sdk.AccAddress([]byte("buyer1")) // require.NotNil(t, err)
buyer2 := sdk.AccAddress([]byte("buyer2")) // }
end := EndTime(10000) // // check for correct in/outputs
now := EndTime(10) // require.Equal(t, tc.expectedOutputs, outputs)
// require.Equal(t, tc.expectedInputs, inputs)
// // check for correct EndTime, bidder, bid
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
// require.Equal(t, tc.expectedBid, tc.auction.Bid)
// })
// }
// }
type args struct { // func TestReverseAuction_PlaceBid(t *testing.T) {
currentBlockHeight EndTime // buyer := sdk.AccAddress([]byte("a_buyer"))
bidder sdk.AccAddress // seller1 := sdk.AccAddress([]byte("seller1"))
lot sdk.Coin // seller2 := sdk.AccAddress([]byte("seller2"))
bid sdk.Coin // end := EndTime(10000)
} // now := EndTime(10)
tests := []struct {
name string
auction ForwardAuction
args args
expectedOutputs []BankOutput
expectedInputs []BankInput
expectedEndTime EndTime
expectedBidder sdk.AccAddress
expectedBid sdk.Coin
expectpass bool
}{
{
"normal",
ForwardAuction{BaseAuction{
Initiator: seller,
Lot: c("usdx", 100),
Bidder: buyer1,
Bid: c("kava", 6),
EndTime: end,
MaxEndTime: end,
}},
args{now, buyer2, c("usdx", 100), c("kava", 10)},
[]BankOutput{{buyer2, c("kava", 10)}},
[]BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
now + DefaultMaxBidDuration,
buyer2,
c("kava", 10),
true,
},
{
"lowBid",
ForwardAuction{BaseAuction{
Initiator: seller,
Lot: c("usdx", 100),
Bidder: buyer1,
Bid: c("kava", 6),
EndTime: end,
MaxEndTime: end,
}},
args{now, buyer2, c("usdx", 100), c("kava", 5)},
[]BankOutput{},
[]BankInput{},
end,
buyer1,
c("kava", 6),
false,
},
{
"equalBid",
ForwardAuction{BaseAuction{
Initiator: seller,
Lot: c("usdx", 100),
Bidder: buyer1,
Bid: c("kava", 6),
EndTime: end,
MaxEndTime: end,
}},
args{now, buyer2, c("usdx", 100), c("kava", 6)},
[]BankOutput{},
[]BankInput{},
end,
buyer1,
c("kava", 6),
false,
},
{
"timeout",
ForwardAuction{BaseAuction{
Initiator: seller,
Lot: c("usdx", 100),
Bidder: buyer1,
Bid: c("kava", 6),
EndTime: end,
MaxEndTime: end,
}},
args{end + 1, buyer2, c("usdx", 100), c("kava", 10)},
[]BankOutput{},
[]BankInput{},
end,
buyer1,
c("kava", 6),
false,
},
{
"hitMaxEndTime",
ForwardAuction{BaseAuction{
Initiator: seller,
Lot: c("usdx", 100),
Bidder: buyer1,
Bid: c("kava", 6),
EndTime: end,
MaxEndTime: end,
}},
args{end - 1, buyer2, c("usdx", 100), c("kava", 10)},
[]BankOutput{{buyer2, c("kava", 10)}},
[]BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
end, // end time should be capped at MaxEndTime
buyer2,
c("kava", 10),
true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// update auction and return in/outputs
outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
// check for err // type args struct {
if tc.expectpass { // currentBlockHeight EndTime
require.Nil(t, err) // bidder sdk.AccAddress
} else { // lot sdk.Coin
require.NotNil(t, err) // bid sdk.Coin
} // }
// check for correct in/outputs // tests := []struct {
require.Equal(t, tc.expectedOutputs, outputs) // name string
require.Equal(t, tc.expectedInputs, inputs) // auction ReverseAuction
// check for correct EndTime, bidder, bid // args args
require.Equal(t, tc.expectedEndTime, tc.auction.EndTime) // expectedOutputs []BankOutput
require.Equal(t, tc.expectedBidder, tc.auction.Bidder) // expectedInputs []BankInput
require.Equal(t, tc.expectedBid, tc.auction.Bid) // expectedEndTime EndTime
}) // expectedBidder sdk.AccAddress
} // expectedLot sdk.Coin
} // expectpass bool
// }{
// {
// "normal",
// ReverseAuction{BaseAuction{
// Initiator: buyer,
// Lot: c("kava", 10),
// Bidder: seller1,
// Bid: c("usdx", 100),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, seller2, c("kava", 9), c("usdx", 100)},
// []BankOutput{{seller2, c("usdx", 100)}},
// []BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
// now + DefaultMaxBidDuration,
// seller2,
// c("kava", 9),
// true,
// },
// {
// "highBid",
// ReverseAuction{BaseAuction{
// Initiator: buyer,
// Lot: c("kava", 10),
// Bidder: seller1,
// Bid: c("usdx", 100),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, seller2, c("kava", 11), c("usdx", 100)},
// []BankOutput{},
// []BankInput{},
// end,
// seller1,
// c("kava", 10),
// false,
// },
// {
// "equalBid",
// ReverseAuction{BaseAuction{
// Initiator: buyer,
// Lot: c("kava", 10),
// Bidder: seller1,
// Bid: c("usdx", 100),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{now, seller2, c("kava", 10), c("usdx", 100)},
// []BankOutput{},
// []BankInput{},
// end,
// seller1,
// c("kava", 10),
// false,
// },
// {
// "timeout",
// ReverseAuction{BaseAuction{
// Initiator: buyer,
// Lot: c("kava", 10),
// Bidder: seller1,
// Bid: c("usdx", 100),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{end + 1, seller2, c("kava", 9), c("usdx", 100)},
// []BankOutput{},
// []BankInput{},
// end,
// seller1,
// c("kava", 10),
// false,
// },
// {
// "hitMaxEndTime",
// ReverseAuction{BaseAuction{
// Initiator: buyer,
// Lot: c("kava", 10),
// Bidder: seller1,
// Bid: c("usdx", 100),
// EndTime: end,
// MaxEndTime: end,
// }},
// args{end - 1, seller2, c("kava", 9), c("usdx", 100)},
// []BankOutput{{seller2, c("usdx", 100)}},
// []BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
// end, // end time should be capped at MaxEndTime
// seller2,
// c("kava", 9),
// true,
// },
// }
// for _, tc := range tests {
// t.Run(tc.name, func(t *testing.T) {
// // update auction and return in/outputs
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
func TestReverseAuction_PlaceBid(t *testing.T) { // // check for err
buyer := sdk.AccAddress([]byte("a_buyer")) // if tc.expectpass {
seller1 := sdk.AccAddress([]byte("seller1")) // require.Nil(t, err)
seller2 := sdk.AccAddress([]byte("seller2")) // } else {
end := EndTime(10000) // require.NotNil(t, err)
now := EndTime(10) // }
// // check for correct in/outputs
// require.Equal(t, tc.expectedOutputs, outputs)
// require.Equal(t, tc.expectedInputs, inputs)
// // check for correct EndTime, bidder, bid
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
// require.Equal(t, tc.expectedLot, tc.auction.Lot)
// })
// }
// }
type args struct { // func TestForwardReverseAuction_PlaceBid(t *testing.T) {
currentBlockHeight EndTime // cdpOwner := sdk.AccAddress([]byte("a_cdp_owner"))
bidder sdk.AccAddress // seller := sdk.AccAddress([]byte("a_seller"))
lot sdk.Coin // buyer1 := sdk.AccAddress([]byte("buyer1"))
bid sdk.Coin // buyer2 := sdk.AccAddress([]byte("buyer2"))
} // end := EndTime(10000)
tests := []struct { // now := EndTime(10)
name string
auction ReverseAuction
args args
expectedOutputs []BankOutput
expectedInputs []BankInput
expectedEndTime EndTime
expectedBidder sdk.AccAddress
expectedLot sdk.Coin
expectpass bool
}{
{
"normal",
ReverseAuction{BaseAuction{
Initiator: buyer,
Lot: c("kava", 10),
Bidder: seller1,
Bid: c("usdx", 100),
EndTime: end,
MaxEndTime: end,
}},
args{now, seller2, c("kava", 9), c("usdx", 100)},
[]BankOutput{{seller2, c("usdx", 100)}},
[]BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
now + DefaultMaxBidDuration,
seller2,
c("kava", 9),
true,
},
{
"highBid",
ReverseAuction{BaseAuction{
Initiator: buyer,
Lot: c("kava", 10),
Bidder: seller1,
Bid: c("usdx", 100),
EndTime: end,
MaxEndTime: end,
}},
args{now, seller2, c("kava", 11), c("usdx", 100)},
[]BankOutput{},
[]BankInput{},
end,
seller1,
c("kava", 10),
false,
},
{
"equalBid",
ReverseAuction{BaseAuction{
Initiator: buyer,
Lot: c("kava", 10),
Bidder: seller1,
Bid: c("usdx", 100),
EndTime: end,
MaxEndTime: end,
}},
args{now, seller2, c("kava", 10), c("usdx", 100)},
[]BankOutput{},
[]BankInput{},
end,
seller1,
c("kava", 10),
false,
},
{
"timeout",
ReverseAuction{BaseAuction{
Initiator: buyer,
Lot: c("kava", 10),
Bidder: seller1,
Bid: c("usdx", 100),
EndTime: end,
MaxEndTime: end,
}},
args{end + 1, seller2, c("kava", 9), c("usdx", 100)},
[]BankOutput{},
[]BankInput{},
end,
seller1,
c("kava", 10),
false,
},
{
"hitMaxEndTime",
ReverseAuction{BaseAuction{
Initiator: buyer,
Lot: c("kava", 10),
Bidder: seller1,
Bid: c("usdx", 100),
EndTime: end,
MaxEndTime: end,
}},
args{end - 1, seller2, c("kava", 9), c("usdx", 100)},
[]BankOutput{{seller2, c("usdx", 100)}},
[]BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
end, // end time should be capped at MaxEndTime
seller2,
c("kava", 9),
true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// update auction and return in/outputs
outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
// check for err // type args struct {
if tc.expectpass { // currentBlockHeight EndTime
require.Nil(t, err) // bidder sdk.AccAddress
} else { // lot sdk.Coin
require.NotNil(t, err) // bid sdk.Coin
} // }
// check for correct in/outputs // tests := []struct {
require.Equal(t, tc.expectedOutputs, outputs) // name string
require.Equal(t, tc.expectedInputs, inputs) // auction ForwardReverseAuction
// check for correct EndTime, bidder, bid // args args
require.Equal(t, tc.expectedEndTime, tc.auction.EndTime) // expectedOutputs []BankOutput
require.Equal(t, tc.expectedBidder, tc.auction.Bidder) // expectedInputs []BankInput
require.Equal(t, tc.expectedLot, tc.auction.Lot) // expectedEndTime EndTime
}) // expectedBidder sdk.AccAddress
} // expectedLot sdk.Coin
} // expectedBid sdk.Coin
// expectpass bool
// }{
// {
// "normalForwardBid",
// ForwardReverseAuction{BaseAuction: BaseAuction{
// Initiator: seller,
// Lot: c("xrp", 100),
// Bidder: buyer1,
// Bid: c("usdx", 5),
// EndTime: end,
// MaxEndTime: end},
// MaxBid: c("usdx", 10),
// OtherPerson: cdpOwner,
// },
// args{now, buyer2, c("xrp", 100), c("usdx", 6)},
// []BankOutput{{buyer2, c("usdx", 6)}},
// []BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 1)}},
// now + DefaultMaxBidDuration,
// buyer2,
// c("xrp", 100),
// c("usdx", 6),
// true,
// },
// {
// "normalSwitchOverBid",
// ForwardReverseAuction{BaseAuction: BaseAuction{
// Initiator: seller,
// Lot: c("xrp", 100),
// Bidder: buyer1,
// Bid: c("usdx", 5),
// EndTime: end,
// MaxEndTime: end},
// MaxBid: c("usdx", 10),
// OtherPerson: cdpOwner,
// },
// args{now, buyer2, c("xrp", 99), c("usdx", 10)},
// []BankOutput{{buyer2, c("usdx", 10)}},
// []BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 5)}, {cdpOwner, c("xrp", 1)}},
// now + DefaultMaxBidDuration,
// buyer2,
// c("xrp", 99),
// c("usdx", 10),
// true,
// },
// {
// "normalReverseBid",
// ForwardReverseAuction{BaseAuction: BaseAuction{
// Initiator: seller,
// Lot: c("xrp", 99),
// Bidder: buyer1,
// Bid: c("usdx", 10),
// EndTime: end,
// MaxEndTime: end},
// MaxBid: c("usdx", 10),
// OtherPerson: cdpOwner,
// },
// args{now, buyer2, c("xrp", 90), c("usdx", 10)},
// []BankOutput{{buyer2, c("usdx", 10)}},
// []BankInput{{buyer1, c("usdx", 10)}, {cdpOwner, c("xrp", 9)}},
// now + DefaultMaxBidDuration,
// buyer2,
// c("xrp", 90),
// c("usdx", 10),
// true,
// },
// // TODO more test cases
// }
// for _, tc := range tests {
// t.Run(tc.name, func(t *testing.T) {
// // update auction and return in/outputs
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
func TestForwardReverseAuction_PlaceBid(t *testing.T) { // // check for err
cdpOwner := sdk.AccAddress([]byte("a_cdp_owner")) // if tc.expectpass {
seller := sdk.AccAddress([]byte("a_seller")) // require.Nil(t, err)
buyer1 := sdk.AccAddress([]byte("buyer1")) // } else {
buyer2 := sdk.AccAddress([]byte("buyer2")) // require.NotNil(t, err)
end := EndTime(10000) // }
now := EndTime(10) // // check for correct in/outputs
// require.Equal(t, tc.expectedOutputs, outputs)
// require.Equal(t, tc.expectedInputs, inputs)
// // check for correct EndTime, bidder, bid
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
// require.Equal(t, tc.expectedLot, tc.auction.Lot)
// require.Equal(t, tc.expectedBid, tc.auction.Bid)
// })
// }
// }
type args struct { // // defined to avoid cluttering test cases with long function name
currentBlockHeight EndTime // func c(denom string, amount int64) sdk.Coin {
bidder sdk.AccAddress // return sdk.NewInt64Coin(denom, amount)
lot sdk.Coin // }
bid sdk.Coin
}
tests := []struct {
name string
auction ForwardReverseAuction
args args
expectedOutputs []BankOutput
expectedInputs []BankInput
expectedEndTime EndTime
expectedBidder sdk.AccAddress
expectedLot sdk.Coin
expectedBid sdk.Coin
expectpass bool
}{
{
"normalForwardBid",
ForwardReverseAuction{BaseAuction: BaseAuction{
Initiator: seller,
Lot: c("xrp", 100),
Bidder: buyer1,
Bid: c("usdx", 5),
EndTime: end,
MaxEndTime: end},
MaxBid: c("usdx", 10),
OtherPerson: cdpOwner,
},
args{now, buyer2, c("xrp", 100), c("usdx", 6)},
[]BankOutput{{buyer2, c("usdx", 6)}},
[]BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 1)}},
now + DefaultMaxBidDuration,
buyer2,
c("xrp", 100),
c("usdx", 6),
true,
},
{
"normalSwitchOverBid",
ForwardReverseAuction{BaseAuction: BaseAuction{
Initiator: seller,
Lot: c("xrp", 100),
Bidder: buyer1,
Bid: c("usdx", 5),
EndTime: end,
MaxEndTime: end},
MaxBid: c("usdx", 10),
OtherPerson: cdpOwner,
},
args{now, buyer2, c("xrp", 99), c("usdx", 10)},
[]BankOutput{{buyer2, c("usdx", 10)}},
[]BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 5)}, {cdpOwner, c("xrp", 1)}},
now + DefaultMaxBidDuration,
buyer2,
c("xrp", 99),
c("usdx", 10),
true,
},
{
"normalReverseBid",
ForwardReverseAuction{BaseAuction: BaseAuction{
Initiator: seller,
Lot: c("xrp", 99),
Bidder: buyer1,
Bid: c("usdx", 10),
EndTime: end,
MaxEndTime: end},
MaxBid: c("usdx", 10),
OtherPerson: cdpOwner,
},
args{now, buyer2, c("xrp", 90), c("usdx", 10)},
[]BankOutput{{buyer2, c("usdx", 10)}},
[]BankInput{{buyer1, c("usdx", 10)}, {cdpOwner, c("xrp", 9)}},
now + DefaultMaxBidDuration,
buyer2,
c("xrp", 90),
c("usdx", 10),
true,
},
// TODO more test cases
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// update auction and return in/outputs
outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
// check for err
if tc.expectpass {
require.Nil(t, err)
} else {
require.NotNil(t, err)
}
// check for correct in/outputs
require.Equal(t, tc.expectedOutputs, outputs)
require.Equal(t, tc.expectedInputs, inputs)
// check for correct EndTime, bidder, bid
require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
require.Equal(t, tc.expectedLot, tc.auction.Lot)
require.Equal(t, tc.expectedBid, tc.auction.Bid)
})
}
}
// defined to avoid cluttering test cases with long function name
func c(denom string, amount int64) sdk.Coin {
return sdk.NewInt64Coin(denom, amount)
}