Add service provider auctions #59
@ -795,3 +795,139 @@ func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *auctiontypes.Auction
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pick winner for service_provider auction
|
||||
func (k Keeper) pickServiceProviderAuctionWinner(ctx sdk.Context, auction *auctiontypes.Auction) error {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Picking auction %s winners.", auction.Id))
|
||||
|
||||
bids, err := k.GetBids(ctx, auction.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var revealedBids []*auctiontypes.Bid
|
||||
for _, bid := range bids {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Processing bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||
|
||||
// Only consider revealed bids.
|
||||
if bid.Status != auctiontypes.BidStatusRevealed {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Ignoring unrevealed bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
|
||||
continue
|
||||
}
|
||||
|
||||
revealedBids = append(revealedBids, bid)
|
||||
}
|
||||
|
||||
// Sort the valid bids
|
||||
slices.SortFunc(revealedBids, func(a, b *auctiontypes.Bid) int {
|
||||
if a.BidAmount.Amount.LT(b.BidAmount.Amount) {
|
||||
return -1
|
||||
} else if a.BidAmount.Amount.GT(b.BidAmount.Amount) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
numWinners := int(auction.NumProviders)
|
||||
if len(revealedBids) < numWinners {
|
||||
numWinners = (len(revealedBids))
|
||||
}
|
||||
winnerBids := revealedBids[:numWinners]
|
||||
|
||||
auction.Status = auctiontypes.AuctionStatusCompleted
|
||||
|
||||
if len(winnerBids) > 0 {
|
||||
winnerAddresses := make([]string, len(winnerBids))
|
||||
winningBids := make([]types.Coin, len(winnerBids))
|
||||
for i, bid := range winnerBids {
|
||||
winnerAddresses[i] = bid.BidderAddress
|
||||
winningBids[i] = bid.BidAmount
|
||||
}
|
||||
auction.WinnerAddresses = winnerAddresses
|
||||
auction.WinningBids = winningBids
|
||||
auction.WinningPrice = winnerBids[0].BidAmount
|
||||
|
||||
if len(winnerBids) > 0 {
|
||||
// The last best bid is the winning price
|
||||
auction.WinningPrice = winnerBids[len(winnerBids)-1].BidAmount
|
||||
}
|
||||
for _, bid := range winnerBids {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s winner address: %s, bid amount: %s.", auction.Id, bid.BidderAddress, bid.BidAmount.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))
|
||||
}
|
||||
|
||||
if err := k.SaveAuction(ctx, auction); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, bid := range bids {
|
||||
bidderAddress, err := sdk.AccAddressFromBech32(bid.BidderAddress)
|
||||
if err != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Invalid bidderAddress address. %v", err))
|
||||
panic("Invalid bidder address.")
|
||||
}
|
||||
|
||||
if bid.Status == auctiontypes.BidStatusRevealed {
|
||||
// Send reveal fee back to bidders that've revealed the bid.
|
||||
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, bidderAddress, sdk.NewCoins(bid.RevealFee))
|
||||
if sdkErr != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error returning reveal fee: %v", sdkErr))
|
||||
panic(sdkErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process winner account (if nobody bids, there won't be a winner).
|
||||
if len(winnerBids) > 0 {
|
||||
winnerAddresses := make([]string, len(winnerBids))
|
||||
for i, bid := range winnerBids {
|
||||
winnerAddresses[i] = bid.BidderAddress
|
||||
winnerAddress, err := sdk.AccAddressFromBech32(bid.BidderAddress)
|
||||
if err != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Invalid winner address. %v", err))
|
||||
panic("Invalid winner address.")
|
||||
}
|
||||
|
||||
// Send winning price to bidders
|
||||
sdkErrWinner := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, winnerAddress, sdk.NewCoins(auction.WinningPrice))
|
||||
if sdkErrWinner != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error sending funds to winner: %v", sdkErrWinner))
|
||||
panic(sdkErrWinner)
|
||||
}
|
||||
|
||||
// Send back extra amount to auction creator
|
||||
totalMaxBidAmount := auction.MaxPrice.Amount.MulRaw(int64(auction.NumProviders))
|
||||
totalAmountPaid := auction.WinningPrice.Amount.Mul(math.NewInt(int64(auction.NumProviders)))
|
||||
|
||||
extraAmountCoin := sdk.NewCoin(auction.MaxPrice.Denom, totalMaxBidAmount.Sub(totalAmountPaid))
|
||||
|
||||
sdkErrCreator := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, sdk.AccAddress(auction.OwnerAddress), sdk.NewCoins(extraAmountCoin))
|
||||
if sdkErrCreator != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error returning bid amount: %v", sdkErrCreator))
|
||||
panic(sdkErrCreator)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(
|
||||
ctx,
|
||||
auctiontypes.ModuleName,
|
||||
sdk.AccAddress(auction.OwnerAddress),
|
||||
sdk.NewCoins(auction.MaxPrice))
|
||||
if sdkErr != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error returning bid amount: %v", sdkErr))
|
||||
panic(sdkErr)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify other modules (hook).
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s notifying %d modules.", auction.Id, len(k.usageKeepers)))
|
||||
for _, keeper := range k.usageKeepers {
|
||||
k.Logger(ctx).Info(fmt.Sprintf("Auction %s notifying module %s.", auction.Id, keeper.ModuleName()))
|
||||
keeper.OnAuctionWinnerSelected(ctx, auction.Id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user