Add service provider auctions #59
@ -4,6 +4,7 @@ const (
|
|||||||
EventTypeCreateAuction = "create-auction"
|
EventTypeCreateAuction = "create-auction"
|
||||||
EventTypeCommitBid = "commit-bid"
|
EventTypeCommitBid = "commit-bid"
|
||||||
EventTypeRevealBid = "reveal-bid"
|
EventTypeRevealBid = "reveal-bid"
|
||||||
|
EventTypeReleaseFunds = "release-funds"
|
||||||
|
|
||||||
AttributeKeyCommitsDuration = "commits-duration"
|
AttributeKeyCommitsDuration = "commits-duration"
|
||||||
AttributeKeyRevealsDuration = "reveals-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
|
// Send back any leftover locked amount to auction creator
|
||||||
// All of it in case of no winners
|
// All of it in case of no winners
|
||||||
totalLockedAmount := auction.MaxPrice.Amount.Mul(math.NewInt(int64(auction.NumProviders)))
|
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
|
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
|
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.
|
// ValidateBasic Implements Msg.
|
||||||
func (msg MsgCreateAuction) ValidateBasic() error {
|
func (msg MsgCreateAuction) ValidateBasic() error {
|
||||||
if msg.Signer == "" {
|
if msg.Signer == "" {
|
||||||
@ -101,15 +118,6 @@ func (msg MsgCommitBid) ValidateBasic() error {
|
|||||||
return nil
|
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.
|
// ValidateBasic Implements Msg.
|
||||||
func (msg MsgRevealBid) ValidateBasic() error {
|
func (msg MsgRevealBid) ValidateBasic() error {
|
||||||
if msg.Signer == "" {
|
if msg.Signer == "" {
|
||||||
@ -126,3 +134,16 @@ func (msg MsgRevealBid) ValidateBasic() error {
|
|||||||
|
|
||||||
return nil
|
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).
|
// Auction has completed (winner selected).
|
||||||
AuctionStatusCompleted = "completed"
|
AuctionStatusCompleted = "completed"
|
||||||
|
|
||||||
|
// Auction has completed (winner selected).
|
||||||
|
AuctionStatusFundsReleased = "funds_released"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bid status values.
|
// Bid status values.
|
||||||
|
Loading…
Reference in New Issue
Block a user