Add service provider auctions #59
@ -4,6 +4,7 @@ const (
|
||||
EventTypeCreateAuction = "create-auction"
|
||||
EventTypeCommitBid = "commit-bid"
|
||||
EventTypeRevealBid = "reveal-bid"
|
||||
EventTypeReleaseFunds = "release-funds"
|
||||
|
||||
AttributeKeyCommitsDuration = "commits-duration"
|
||||
AttributeKeyRevealsDuration = "reveals-duration"
|
||||
|
@ -886,24 +886,6 @@ func (k Keeper) pickProviderAuctionWinners(ctx sdk.Context, auction *auctiontype
|
||||
}
|
||||
}
|
||||
|
||||
// Process winner accounts (if nobody bids, there won't be a winner).
|
||||
if len(winnerBids) > 0 {
|
||||
for _, bid := range winnerBids {
|
||||
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
|
||||
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, winnerAddress, sdk.NewCoins(auction.WinningPrice))
|
||||
if sdkErr != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error sending funds to winner: %v", sdkErr))
|
||||
panic(sdkErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send back any leftover locked amount to auction creator
|
||||
// All of it in case of no winners
|
||||
totalLockedAmount := auction.MaxPrice.Amount.Mul(math.NewInt(int64(auction.NumProviders)))
|
||||
@ -936,3 +918,61 @@ func (k Keeper) pickProviderAuctionWinners(ctx sdk.Context, auction *auctiontype
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) ReleaseFunds(ctx sdk.Context, msg auctiontypes.MsgReleaseFunds) (*auctiontypes.Auction, error) {
|
||||
if has, err := k.HasAuction(ctx, msg.AuctionId); !has {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.")
|
||||
}
|
||||
|
||||
auction, err := k.GetAuctionById(ctx, msg.AuctionId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if auction.Kind != auctiontypes.AuctionKindProvider {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction kind must be provider.")
|
||||
}
|
||||
|
||||
if auction.Status != auctiontypes.AuctionStatusCompleted {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not completed.")
|
||||
}
|
||||
|
||||
if auction.Status == auctiontypes.AuctionStatusFundsReleased {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Funds have already been released.")
|
||||
}
|
||||
|
||||
// Only the auction owner can release funds.
|
||||
if msg.Signer != auction.OwnerAddress {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Auction owner mismatch.")
|
||||
}
|
||||
|
||||
// Process winner accounts (if nobody bids, there won't be a winner).
|
||||
if len(auction.WinnerAddresses) > 0 {
|
||||
for _, winnerAddress := range auction.WinnerAddresses {
|
||||
winnerAccAddress, err := sdk.AccAddressFromBech32(winnerAddress)
|
||||
if err != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Invalid winner address. %v", err))
|
||||
panic("Invalid winner address.")
|
||||
}
|
||||
|
||||
// Send winning price to bidders
|
||||
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(
|
||||
ctx,
|
||||
auctiontypes.ModuleName,
|
||||
winnerAccAddress,
|
||||
sdk.NewCoins(auction.WinningPrice),
|
||||
)
|
||||
if sdkErr != nil {
|
||||
k.Logger(ctx).Error(fmt.Sprintf("Auction error sending funds to winner: %v", sdkErr))
|
||||
panic(sdkErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auction.FundsReleased = true
|
||||
|
||||
return &auction, err
|
||||
}
|
||||
|
@ -149,3 +149,40 @@ func (ms msgServer) UpdateParams(c context.Context, msg *auctiontypes.MsgUpdateP
|
||||
|
||||
return &auctiontypes.MsgUpdateParamsResponse{}, nil
|
||||
}
|
||||
|
||||
// ReleaseFunds is the command to pay the winning amounts to provider auction winners
|
||||
// nolint: all
|
||||
func (ms msgServer) ReleaseFunds(c context.Context, msg *auctiontypes.MsgReleaseFunds) (*auctiontypes.MsgReleaseFundsResponse, error) {
|
||||
if err := msg.ValidateBasic(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
ctx = *utils.CtxWithCustomKVGasConfig(&ctx)
|
||||
|
||||
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := ms.k.ReleaseFunds(ctx, *msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
auctiontypes.EventTypeReleaseFunds,
|
||||
sdk.NewAttribute(auctiontypes.AttributeKeyAuctionId, msg.AuctionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, auctiontypes.AttributeValueCategory),
|
||||
sdk.NewAttribute(auctiontypes.AttributeKeySigner, signerAddress.String()),
|
||||
),
|
||||
})
|
||||
|
||||
utils.LogTxGasConsumed(ctx, ms.k.Logger(ctx), "ReleaseFunds")
|
||||
|
||||
return &auctiontypes.MsgReleaseFundsResponse{Auction: resp}, nil
|
||||
}
|
||||
|
@ -49,6 +49,23 @@ func NewMsgCommitBid(auctionId string, commitHash string, signer sdk.AccAddress)
|
||||
}
|
||||
}
|
||||
|
||||
// NewMsgRevealBid is the constructor function for MsgRevealBid.
|
||||
func NewMsgRevealBid(auctionId string, reveal string, signer sdk.AccAddress) MsgRevealBid {
|
||||
return MsgRevealBid{
|
||||
AuctionId: auctionId,
|
||||
Reveal: reveal,
|
||||
Signer: signer.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewMsgReleaseFunds is the constructor function for MsgReleaseFunds.
|
||||
func NewMsgReleaseFunds(auctionId string, signer sdk.AccAddress) MsgReleaseFunds {
|
||||
return MsgReleaseFunds{
|
||||
AuctionId: auctionId,
|
||||
Signer: signer.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateBasic Implements Msg.
|
||||
func (msg MsgCreateAuction) ValidateBasic() error {
|
||||
if msg.Signer == "" {
|
||||
@ -101,15 +118,6 @@ func (msg MsgCommitBid) ValidateBasic() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewMsgRevealBid is the constructor function for MsgRevealBid.
|
||||
func NewMsgRevealBid(auctionId string, reveal string, signer sdk.AccAddress) MsgRevealBid {
|
||||
return MsgRevealBid{
|
||||
AuctionId: auctionId,
|
||||
Reveal: reveal,
|
||||
Signer: signer.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateBasic Implements Msg.
|
||||
func (msg MsgRevealBid) ValidateBasic() error {
|
||||
if msg.Signer == "" {
|
||||
@ -126,3 +134,16 @@ func (msg MsgRevealBid) ValidateBasic() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBasic Implements Msg.
|
||||
func (msg MsgReleaseFunds) ValidateBasic() error {
|
||||
if msg.Signer == "" {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address")
|
||||
}
|
||||
|
||||
if msg.AuctionId == "" {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction id")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ const (
|
||||
|
||||
// Auction has completed (winner selected).
|
||||
AuctionStatusCompleted = "completed"
|
||||
|
||||
// Auction has completed (winner selected).
|
||||
AuctionStatusFundsReleased = "funds_released"
|
||||
)
|
||||
|
||||
// Bid status values.
|
||||
|
Loading…
Reference in New Issue
Block a user