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