Add commands to create and list auctions

This commit is contained in:
Prathamesh Musale 2024-02-12 10:03:39 +05:30
parent 328c06d919
commit 6e72f58616
9 changed files with 408 additions and 20 deletions

19
x/auction/events.go Normal file
View File

@ -0,0 +1,19 @@
package auction
const (
EventTypeCreateAuction = "create-auction"
EventTypeCommitBid = "commit-bid"
EventTypeRevealBid = "reveal-bid"
AttributeKeyCommitsDuration = "commits-duration"
AttributeKeyRevealsDuration = "reveals-duration"
AttributeKeyCommitFee = "commit-fee"
AttributeKeyRevealFee = "reveal-fee"
AttributeKeyMinimumBid = "minimum-bid"
AttributeKeySigner = "signer"
AttributeKeyAuctionID = "auction-id"
AttributeKeyCommitHash = "commit-hash"
AttributeKeyReveal = "reveal"
AttributeValueCategory = ModuleName
)

View File

@ -2,15 +2,41 @@ package keeper
import ( import (
"cosmossdk.io/collections" "cosmossdk.io/collections"
"cosmossdk.io/collections/indexes"
storetypes "cosmossdk.io/core/store" storetypes "cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
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"
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper" bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction" auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction"
) )
type AuctionsIndexes struct {
Owner *indexes.Multi[string, string, auctiontypes.Auction]
}
func (a AuctionsIndexes) IndexesList() []collections.Index[string, auctiontypes.Auction] {
return []collections.Index[string, auctiontypes.Auction]{a.Owner}
}
func newAuctionIndexes(sb *collections.SchemaBuilder) AuctionsIndexes {
return AuctionsIndexes{
Owner: indexes.NewMulti(
sb, auctiontypes.AuctionOwnerIndexPrefix, "auctions_by_owner",
collections.StringKey, collections.StringKey,
func(_ string, v auctiontypes.Auction) (string, error) {
return v.OwnerAddress, nil
},
),
}
}
// TODO: Add required methods
type Keeper struct { type Keeper struct {
// Codecs // Codecs
cdc codec.BinaryCodec cdc codec.BinaryCodec
@ -23,10 +49,9 @@ type Keeper struct {
// usageKeepers []types.AuctionUsageKeeper // usageKeepers []types.AuctionUsageKeeper
// state management // state management
Schema collections.Schema Schema collections.Schema
Params collections.Item[auctiontypes.Params] Params collections.Item[auctiontypes.Params]
// TODO Auctions *collections.IndexedMap[string, auctiontypes.Auction, AuctionsIndexes]
// Auctions ...
} }
// NewKeeper creates a new Keeper instance // NewKeeper creates a new Keeper instance
@ -42,7 +67,8 @@ func NewKeeper(
accountKeeper: accountKeeper, accountKeeper: accountKeeper,
bankKeeper: bankKeeper, bankKeeper: bankKeeper,
Params: collections.NewItem(sb, auctiontypes.ParamsKeyPrefix, "params", codec.CollValue[auctiontypes.Params](cdc)), Params: collections.NewItem(sb, auctiontypes.ParamsKeyPrefix, "params", codec.CollValue[auctiontypes.Params](cdc)),
// Auctions: ... Auctions: collections.NewIndexedMap(sb, auctiontypes.AuctionsKeyPrefix, "auctions", collections.StringKey, codec.CollValue[auctiontypes.Auction](cdc), newAuctionIndexes(sb)),
// usageKeepers: usageKeepers,
} }
schema, err := sb.Build() schema, err := sb.Build()
@ -58,3 +84,92 @@ func NewKeeper(
// func (k *Keeper) SetUsageKeepers(usageKeepers []types.AuctionUsageKeeper) { // func (k *Keeper) SetUsageKeepers(usageKeepers []types.AuctionUsageKeeper) {
// k.usageKeepers = usageKeepers // k.usageKeepers = usageKeepers
// } // }
// SaveAuction - saves a auction to the store.
func (k Keeper) SaveAuction(ctx sdk.Context, auction *auctiontypes.Auction) error {
return k.Auctions.Set(ctx, auction.Id, *auction)
// // Notify interested parties.
// for _, keeper := range k.usageKeepers {
// keeper.OnAuction(ctx, auction.Id)
// }
// return nil
}
// ListAuctions - get all auctions.
func (k Keeper) ListAuctions(ctx sdk.Context) ([]auctiontypes.Auction, error) {
var auctions []auctiontypes.Auction
iter, err := k.Auctions.Iterate(ctx, nil)
if err != nil {
return nil, err
}
for ; iter.Valid(); iter.Next() {
auction, err := iter.Value()
if err != nil {
return nil, err
}
auctions = append(auctions, auction)
}
return auctions, nil
}
// CreateAuction creates a new auction.
func (k Keeper) CreateAuction(ctx sdk.Context, msg auctiontypes.MsgCreateAuction) (*auctiontypes.Auction, error) {
// TODO: Setup checks
// Might be called from another module directly, always validate.
// err := msg.ValidateBasic()
// if err != nil {
// return nil, err
// }
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
// Generate auction Id.
account := k.accountKeeper.GetAccount(ctx, signerAddress)
if account == nil {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "Account not found.")
}
auctionId := auctiontypes.AuctionId{
Address: signerAddress,
AccNum: account.GetAccountNumber(),
Sequence: account.GetSequence(),
}.Generate()
// Compute timestamps.
now := ctx.BlockTime()
commitsEndTime := now.Add(msg.CommitsDuration)
revealsEndTime := now.Add(msg.CommitsDuration + msg.RevealsDuration)
auction := auctiontypes.Auction{
Id: auctionId,
Status: auctiontypes.AuctionStatusCommitPhase,
OwnerAddress: signerAddress.String(),
CreateTime: now,
CommitsEndTime: commitsEndTime,
RevealsEndTime: revealsEndTime,
CommitFee: msg.CommitFee,
RevealFee: msg.RevealFee,
MinimumBid: msg.MinimumBid,
}
// Save auction in store.
k.SaveAuction(ctx, &auction)
return &auction, nil
}
func (k Keeper) CommitBid(ctx sdk.Context, msg auctiontypes.MsgCommitBid) (*auctiontypes.Bid, error) {
panic("unimplemented")
}
func (k Keeper) RevealBid(ctx sdk.Context, msg auctiontypes.MsgRevealBid) (*auctiontypes.Auction, error) {
panic("unimplemented")
}

View File

@ -1,14 +1,112 @@
package keeper package keeper
// TODO: Add required read methods import (
"context"
// var _ auctiontypes.MsgServer = msgServer{} auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var _ auctiontypes.MsgServer = msgServer{}
type msgServer struct { type msgServer struct {
k Keeper k Keeper
} }
// NewMsgServerImpl returns an implementation of the module MsgServer interface. // NewMsgServerImpl returns an implementation of the module MsgServer interface.
// func NewMsgServerImpl(keeper Keeper) auctiontypes.MsgServer { func NewMsgServerImpl(keeper Keeper) auctiontypes.MsgServer {
// return &msgServer{k: keeper} return &msgServer{k: keeper}
// } }
func (ms msgServer) CreateAuction(c context.Context, msg *auctiontypes.MsgCreateAuction) (*auctiontypes.MsgCreateAuctionResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := ms.k.CreateAuction(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
auctiontypes.EventTypeCreateAuction,
sdk.NewAttribute(auctiontypes.AttributeKeyCommitsDuration, msg.CommitsDuration.String()),
sdk.NewAttribute(auctiontypes.AttributeKeyCommitFee, msg.CommitFee.String()),
sdk.NewAttribute(auctiontypes.AttributeKeyRevealFee, msg.RevealFee.String()),
sdk.NewAttribute(auctiontypes.AttributeKeyMinimumBid, msg.MinimumBid.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, auctiontypes.AttributeValueCategory),
sdk.NewAttribute(auctiontypes.AttributeKeySigner, signerAddress.String()),
),
})
return &auctiontypes.MsgCreateAuctionResponse{Auction: resp}, nil
}
// CommitBid is the command for committing a bid
// nolint: all
func (ms msgServer) CommitBid(c context.Context, msg *auctiontypes.MsgCommitBid) (*auctiontypes.MsgCommitBidResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := ms.k.CommitBid(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
auctiontypes.EventTypeCommitBid,
sdk.NewAttribute(auctiontypes.AttributeKeyAuctionID, msg.AuctionId),
sdk.NewAttribute(auctiontypes.AttributeKeyCommitHash, msg.CommitHash),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, auctiontypes.AttributeValueCategory),
sdk.NewAttribute(auctiontypes.AttributeKeySigner, signerAddress.String()),
),
})
return &auctiontypes.MsgCommitBidResponse{Bid: resp}, nil
}
// RevealBid is the command for revealing a bid
// nolint: all
func (ms msgServer) RevealBid(c context.Context, msg *auctiontypes.MsgRevealBid) (*auctiontypes.MsgRevealBidResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := ms.k.RevealBid(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
auctiontypes.EventTypeRevealBid,
sdk.NewAttribute(auctiontypes.AttributeKeyAuctionID, msg.AuctionId),
sdk.NewAttribute(auctiontypes.AttributeKeyReveal, msg.Reveal),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, auctiontypes.AttributeValueCategory),
sdk.NewAttribute(auctiontypes.AttributeKeySigner, signerAddress.String()),
),
})
return &auctiontypes.MsgRevealBidResponse{Auction: resp}, nil
}

View File

@ -1,14 +1,68 @@
package keeper package keeper
import (
"context"
auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// TODO: Add required read methods // TODO: Add required read methods
// var _ auctiontypes.QueryServer = queryServer{} var _ auctiontypes.QueryServer = queryServer{}
type queryServer struct { type queryServer struct {
k Keeper k Keeper
} }
// NewQueryServerImpl returns an implementation of the module QueryServer. // NewQueryServerImpl returns an implementation of the module QueryServer.
// func NewQueryServerImpl(k Keeper) auctiontypes.QueryServer { func NewQueryServerImpl(k Keeper) auctiontypes.QueryServer {
// return queryServer{k} return queryServer{k}
// } }
// Params implements the params query command
func (qs queryServer) Params(c context.Context, req *auctiontypes.QueryParamsRequest) (*auctiontypes.QueryParamsResponse, error) {
panic("unimplemented")
}
// Auctions queries all auctions
func (qs queryServer) Auctions(c context.Context, req *auctiontypes.QueryAuctionsRequest) (*auctiontypes.QueryAuctionsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
resp, err := qs.k.ListAuctions(ctx)
if err != nil {
return nil, err
}
return &auctiontypes.QueryAuctionsResponse{Auctions: &auctiontypes.Auctions{Auctions: resp}}, nil
}
// GetAuction queries an auction
func (qs queryServer) GetAuction(c context.Context, req *auctiontypes.QueryAuctionRequest) (*auctiontypes.QueryAuctionResponse, error) {
panic("unimplemented")
}
// GetBid queries and auction bid
func (qs queryServer) GetBid(c context.Context, req *auctiontypes.QueryBidRequest) (*auctiontypes.QueryBidResponse, error) {
panic("unimplemented")
}
// GetBids queries all auction bids
func (qs queryServer) GetBids(c context.Context, req *auctiontypes.QueryBidsRequest) (*auctiontypes.QueryBidsResponse, error) {
panic("unimplemented")
}
// AuctionsByBidder queries auctions by bidder
func (qs queryServer) AuctionsByBidder(c context.Context, req *auctiontypes.QueryAuctionsByBidderRequest) (*auctiontypes.QueryAuctionsByBidderResponse, error) {
panic("unimplemented")
}
// AuctionsByOwner queries auctions by owner
func (qs queryServer) AuctionsByOwner(c context.Context, req *auctiontypes.QueryAuctionsByOwnerRequest) (*auctiontypes.QueryAuctionsByOwnerResponse, error) {
panic("unimplemented")
}
// GetAuctionModuleBalance queries the auction module account balance
func (qs queryServer) GetAuctionModuleBalance(c context.Context, req *auctiontypes.QueryGetAuctionModuleBalanceRequest) (*auctiontypes.QueryGetAuctionModuleBalanceResponse, error) {
panic("unimplemented")
}

View File

@ -13,4 +13,7 @@ const (
var ( var (
// ParamsKey is the prefix for params key // ParamsKey is the prefix for params key
ParamsKeyPrefix = collections.NewPrefix(0) ParamsKeyPrefix = collections.NewPrefix(0)
AuctionsKeyPrefix = collections.NewPrefix(1)
AuctionOwnerIndexPrefix = collections.NewPrefix(2)
) )

View File

@ -3,6 +3,8 @@ package module
import ( import (
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
"cosmossdk.io/client/v2/autocli" "cosmossdk.io/client/v2/autocli"
auctionv1 "git.vdb.to/cerc-io/laconic2d/api/cerc/auction/v1"
) )
var _ autocli.HasAutoCLIConfig = AppModule{} var _ autocli.HasAutoCLIConfig = AppModule{}
@ -10,7 +12,39 @@ var _ autocli.HasAutoCLIConfig = AppModule{}
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. // AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
return &autocliv1.ModuleOptions{ return &autocliv1.ModuleOptions{
Query: nil, Query: &autocliv1.ServiceCommandDescriptor{
Tx: nil, Service: auctionv1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Params",
Use: "params",
Short: "Get the current bond parameters",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{},
},
{
RpcMethod: "Auctions",
Use: "list",
Short: "List auctions",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{},
},
},
},
Tx: &autocliv1.ServiceCommandDescriptor{
Service: auctionv1.Msg_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "CreateAuction",
Use: "create [commits-duration] [reveals-duration] [commit-fee] [reveal-fee] [minimum-bid]",
Short: "Create an auction",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "commits_duration"},
{ProtoField: "reveals_duration"},
{ProtoField: "commit_fee"},
{ProtoField: "reveal_fee"},
{ProtoField: "minimum_bid"},
},
},
},
},
} }
} }

View File

@ -116,8 +116,8 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
func (am AppModule) RegisterServices(cfg module.Configurator) { func (am AppModule) RegisterServices(cfg module.Configurator) {
// Register servers // Register servers
// auction.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) auction.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
// auction.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) auction.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper))
} }
// appmodule.HasEndBlocker // appmodule.HasEndBlocker

65
x/auction/types.go Normal file
View File

@ -0,0 +1,65 @@
package auction
import (
"crypto/sha256"
"encoding/hex"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Auction status values.
const (
// Auction is in commit phase.
AuctionStatusCommitPhase = "commit"
// Auction is in reveal phase.
AuctionStatusRevealPhase = "reveal"
// Auction has ended (no reveals allowed).
AuctionStatusExpired = "expired"
// Auction has completed (winner selected).
AuctionStatusCompleted = "completed"
)
// Bid status values.
const (
BidStatusCommitted = "commit"
BidStatusRevealed = "reveal"
)
// AuctionId simplifies generation of auction IDs.
type AuctionId struct {
Address sdk.Address
AccNum uint64
Sequence uint64
}
// Generate creates the auction ID.
func (auctionId AuctionId) Generate() string {
hasher := sha256.New()
str := fmt.Sprintf("%s:%d:%d", auctionId.Address.String(), auctionId.AccNum, auctionId.Sequence)
hasher.Write([]byte(str))
return hex.EncodeToString(hasher.Sum(nil))
}
func (auction Auction) GetCreateTime() string {
return string(sdk.FormatTimeBytes(auction.CreateTime))
}
func (auction Auction) GetCommitsEndTime() string {
return string(sdk.FormatTimeBytes(auction.CommitsEndTime))
}
func (auction Auction) GetRevealsEndTime() string {
return string(sdk.FormatTimeBytes(auction.RevealsEndTime))
}
func (bid Bid) GetCommitTime() string {
return string(sdk.FormatTimeBytes(bid.CommitTime))
}
func (bid Bid) GetRevealTime() string {
return string(sdk.FormatTimeBytes(bid.RevealTime))
}

View File

@ -8,12 +8,12 @@ import (
"git.vdb.to/cerc-io/laconic2d/x/bond" "git.vdb.to/cerc-io/laconic2d/x/bond"
) )
var _ bond.MsgServer = msgServer{}
type msgServer struct { type msgServer struct {
k Keeper k Keeper
} }
var _ bond.MsgServer = msgServer{}
// NewMsgServerImpl returns an implementation of the module MsgServer interface. // NewMsgServerImpl returns an implementation of the module MsgServer interface.
func NewMsgServerImpl(keeper Keeper) bond.MsgServer { func NewMsgServerImpl(keeper Keeper) bond.MsgServer {
return &msgServer{k: keeper} return &msgServer{k: keeper}