Add service provider auctions #59
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
@ -12,8 +13,10 @@ import (
|
||||
storetypes "cosmossdk.io/core/store"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
@ -339,6 +342,16 @@ func (k Keeper) CreateAuction(ctx sdk.Context, msg auctiontypes.MsgCreateAuction
|
||||
commitsEndTime := now.Add(msg.CommitsDuration)
|
||||
revealsEndTime := now.Add(msg.CommitsDuration + msg.RevealsDuration)
|
||||
|
||||
if msg.Kind == auctiontypes.AuctionKindServiceProvider {
|
||||
totalMaxBidAmount := sdk.NewCoin(msg.MaxPrice.Denom, msg.MaxPrice.Amount.MulRaw(int64(msg.NumProviders)))
|
||||
|
||||
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, auctiontypes.ModuleName, sdk.NewCoins(totalMaxBidAmount))
|
||||
if sdkErr != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error transferring maximum_bid amount: %v", sdkErr))
|
||||
panic(sdkErr)
|
||||
}
|
||||
}
|
||||
|
||||
auction := auctiontypes.Auction{
|
||||
Id: auctionId,
|
||||
Status: auctiontypes.AuctionStatusCommitPhase,
|
||||
@ -349,6 +362,9 @@ func (k Keeper) CreateAuction(ctx sdk.Context, msg auctiontypes.MsgCreateAuction
|
||||
CommitFee: msg.CommitFee,
|
||||
RevealFee: msg.RevealFee,
|
||||
MinimumBid: msg.MinimumBid,
|
||||
MaxPrice: msg.MaxPrice,
|
||||
Kind: msg.Kind,
|
||||
NumProviders: msg.NumProviders,
|
||||
}
|
||||
|
||||
// Save auction in store.
|
||||
@ -606,9 +622,15 @@ func (k Keeper) processAuctionPhases(ctx sdk.Context) error {
|
||||
|
||||
// If auction has expired, pick a winner from revealed bids.
|
||||
if auction.Status == auctiontypes.AuctionStatusExpired {
|
||||
if auction.Kind == auctiontypes.AuctionKindVickrey {
|
||||
if err = k.pickAuctionWinner(ctx, auction); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err = k.pickServiceProviderAuctionWinner(ctx, auction); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,6 +657,7 @@ func (k Keeper) deleteCompletedAuctions(ctx sdk.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pick winner for vickrey auction
|
||||
func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *auctiontypes.Auction) error {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Picking auction %s winner.", auction.Id))
|
||||
|
||||
@ -686,16 +709,15 @@ func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *auctiontypes.Auction
|
||||
auction.Status = auctiontypes.AuctionStatusCompleted
|
||||
|
||||
if highestBid != nil {
|
||||
auction.WinnerAddress = highestBid.BidderAddress
|
||||
auction.WinningBid = highestBid.BidAmount
|
||||
|
||||
winnerAddresses := make([]string, 1)
|
||||
auction.WinnerAddresses = winnerAddresses
|
||||
// Winner pays 2nd price, if a 2nd price exists.
|
||||
auction.WinningPrice = highestBid.BidAmount
|
||||
if secondHighestBid != nil {
|
||||
auction.WinningPrice = secondHighestBid.BidAmount
|
||||
}
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner %s.", auction.Id, auction.WinnerAddress))
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner bid %s.", auction.Id, auction.WinningBid.String()))
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner %s.", auction.Id, auction.WinnerAddresses[0]))
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner bid %s.", auction.Id, auction.WinningBids[0].String()))
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner price %s.", auction.Id, auction.WinningPrice.String()))
|
||||
} else {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s has no valid revealed bids (no winner).", auction.Id))
|
||||
@ -730,8 +752,8 @@ func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *auctiontypes.Auction
|
||||
}
|
||||
|
||||
// Process winner account (if nobody bids, there won't be a winner).
|
||||
if auction.WinnerAddress != "" {
|
||||
winnerAddress, err := sdk.AccAddressFromBech32(auction.WinnerAddress)
|
||||
if len(auction.WinnerAddresses) == 0 {
|
||||
winnerAddress, err := sdk.AccAddressFromBech32(auction.WinnerAddresses[0])
|
||||
if err != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Invalid winner address. %v", err))
|
||||
panic("Invalid winner address.")
|
||||
|
@ -29,6 +29,12 @@ const (
|
||||
BidStatusRevealed = "reveal"
|
||||
)
|
||||
|
||||
// Auction kinds
|
||||
const (
|
||||
AuctionKindVickrey = "vickrey"
|
||||
AuctionKindServiceProvider = "service_provider"
|
||||
)
|
||||
|
||||
// AuctionId simplifies generation of auction ids.
|
||||
type AuctionId struct {
|
||||
Address sdk.Address
|
||||
|
Loading…
Reference in New Issue
Block a user