diff --git a/x/auction/keeper/keeper.go b/x/auction/keeper/keeper.go index 8bb95a21..635cbb89 100644 --- a/x/auction/keeper/keeper.go +++ b/x/auction/keeper/keeper.go @@ -37,6 +37,23 @@ func newAuctionIndexes(sb *collections.SchemaBuilder) AuctionsIndexes { } } +type BidsIndexes struct { + Bidder *indexes.ReversePair[string, string, auctiontypes.Bid] +} + +func (b BidsIndexes) IndexesList() []collections.Index[collections.Pair[string, string], auctiontypes.Bid] { + return []collections.Index[collections.Pair[string, string], auctiontypes.Bid]{b.Bidder} +} + +func newBidsIndexes(sb *collections.SchemaBuilder) BidsIndexes { + return BidsIndexes{ + Bidder: indexes.NewReversePair[auctiontypes.Bid]( + sb, auctiontypes.BidderAuctionIdIndexPrefix, "auction_id_by_bidder", + collections.PairKeyCodec(collections.StringKey, collections.StringKey), + ), + } +} + // TODO: Add required methods type Keeper struct { @@ -53,7 +70,8 @@ type Keeper struct { // state management Schema collections.Schema Params collections.Item[auctiontypes.Params] - Auctions *collections.IndexedMap[string, auctiontypes.Auction, AuctionsIndexes] + Auctions *collections.IndexedMap[string, auctiontypes.Auction, AuctionsIndexes] // map: auctionId -> Auction, index: owner -> Auctions + Bids *collections.IndexedMap[collections.Pair[string, string], auctiontypes.Bid, BidsIndexes] // map: (auctionId, bidder) -> Bid, index: bidder -> auctionId } // NewKeeper creates a new Keeper instance @@ -68,8 +86,9 @@ func NewKeeper( cdc: cdc, accountKeeper: accountKeeper, bankKeeper: bankKeeper, - Params: collections.NewItem(sb, auctiontypes.ParamsKeyPrefix, "params", codec.CollValue[auctiontypes.Params](cdc)), - Auctions: collections.NewIndexedMap(sb, auctiontypes.AuctionsKeyPrefix, "auctions", collections.StringKey, codec.CollValue[auctiontypes.Auction](cdc), newAuctionIndexes(sb)), + Params: collections.NewItem(sb, auctiontypes.ParamsPrefix, "params", codec.CollValue[auctiontypes.Params](cdc)), + Auctions: collections.NewIndexedMap(sb, auctiontypes.AuctionsPrefix, "auctions", collections.StringKey, codec.CollValue[auctiontypes.Auction](cdc), newAuctionIndexes(sb)), + Bids: collections.NewIndexedMap(sb, auctiontypes.BidsPrefix, "bids", collections.PairKeyCodec(collections.StringKey, collections.StringKey), codec.CollValue[auctiontypes.Bid](cdc), newBidsIndexes(sb)), // usageKeepers: usageKeepers, } @@ -98,6 +117,51 @@ func (k Keeper) SaveAuction(ctx sdk.Context, auction *auctiontypes.Auction) erro // return nil } +func (k Keeper) HasAuction(ctx sdk.Context, id string) (bool, error) { + has, err := k.Auctions.Has(ctx, id) + if err != nil { + return false, err + } + + return has, nil +} + +func (k Keeper) SaveBid(ctx sdk.Context, bid *auctiontypes.Bid) error { + key := collections.Join(bid.AuctionId, bid.BidderAddress) + return k.Bids.Set(ctx, key, *bid) + + // // Notify interested parties. + // for _, keeper := range k.usageKeepers { + // keeper.OnAuctionBid(ctx, bid.AuctionId, bid.BidderAddress) + // } + // return nil +} + +func (k Keeper) DeleteBid(ctx sdk.Context, bid auctiontypes.Bid) error { + key := collections.Join(bid.AuctionId, bid.BidderAddress) + return k.Bids.Remove(ctx, key) +} + +func (k Keeper) HasBid(ctx sdk.Context, id string, bidder string) (bool, error) { + key := collections.Join(id, bidder) + has, err := k.Bids.Has(ctx, key) + if err != nil { + return false, err + } + + return has, nil +} + +func (k Keeper) GetBid(ctx sdk.Context, id string, bidder string) (auctiontypes.Bid, error) { + key := collections.Join(id, bidder) + bid, err := k.Bids.Get(ctx, key) + if err != nil { + return auctiontypes.Bid{}, err + } + + return bid, nil +} + // ListAuctions - get all auctions. func (k Keeper) ListAuctions(ctx sdk.Context) ([]auctiontypes.Auction, error) { var auctions []auctiontypes.Auction @@ -185,13 +249,78 @@ func (k Keeper) CreateAuction(ctx sdk.Context, msg auctiontypes.MsgCreateAuction } // Save auction in store. - k.SaveAuction(ctx, &auction) + if err = k.SaveAuction(ctx, &auction); err != nil { + return nil, err + } return &auction, nil } func (k Keeper) CommitBid(ctx sdk.Context, msg auctiontypes.MsgCommitBid) (*auctiontypes.Bid, error) { - panic("unimplemented") + 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.Status != auctiontypes.AuctionStatusCommitPhase { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in commit phase.") + } + + signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, err + } + + // Take auction fees from account. + totalFee := auction.CommitFee.Add(auction.RevealFee) + sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, auctiontypes.ModuleName, sdk.NewCoins(totalFee)) + if sdkErr != nil { + return nil, sdkErr + } + + // Check if an old bid already exists, if so, return old bids auction fee (update bid scenario). + bidder := signerAddress.String() + bidExists, err := k.HasBid(ctx, msg.AuctionId, bidder) + if err != nil { + return nil, err + } + + if bidExists { + oldBid, err := k.GetBid(ctx, msg.AuctionId, bidder) + if err != nil { + return nil, err + } + + oldTotalFee := oldBid.CommitFee.Add(oldBid.RevealFee) + sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, signerAddress, sdk.NewCoins(oldTotalFee)) + if sdkErr != nil { + return nil, sdkErr + } + } + + // Save new bid. + bid := auctiontypes.Bid{ + AuctionId: msg.AuctionId, + BidderAddress: bidder, + Status: auctiontypes.BidStatusCommitted, + CommitHash: msg.CommitHash, + CommitTime: ctx.BlockTime(), + CommitFee: auction.CommitFee, + RevealFee: auction.RevealFee, + } + + if err = k.SaveBid(ctx, &bid); err != nil { + return nil, err + } + + return &bid, nil } func (k Keeper) RevealBid(ctx sdk.Context, msg auctiontypes.MsgRevealBid) (*auctiontypes.Auction, error) { diff --git a/x/auction/keys.go b/x/auction/keys.go index f1c0c0a3..fe626433 100644 --- a/x/auction/keys.go +++ b/x/auction/keys.go @@ -12,8 +12,11 @@ const ( // Store prefixes var ( // ParamsKey is the prefix for params key - ParamsKeyPrefix = collections.NewPrefix(0) + ParamsPrefix = collections.NewPrefix(0) - AuctionsKeyPrefix = collections.NewPrefix(1) + AuctionsPrefix = collections.NewPrefix(1) AuctionOwnerIndexPrefix = collections.NewPrefix(2) + + BidsPrefix = collections.NewPrefix(3) + BidderAuctionIdIndexPrefix = collections.NewPrefix(4) ) diff --git a/x/bond/keeper/keeper.go b/x/bond/keeper/keeper.go index e1dd9eb9..2d2ff846 100644 --- a/x/bond/keeper/keeper.go +++ b/x/bond/keeper/keeper.go @@ -70,8 +70,8 @@ func NewKeeper( cdc: cdc, accountKeeper: accountKeeper, bankKeeper: bankKeeper, - Params: collections.NewItem(sb, bondtypes.ParamsKeyPrefix, "params", codec.CollValue[bondtypes.Params](cdc)), - Bonds: collections.NewIndexedMap(sb, bondtypes.BondsKeyPrefix, "bonds", collections.StringKey, codec.CollValue[bondtypes.Bond](cdc), newBondIndexes(sb)), + Params: collections.NewItem(sb, bondtypes.ParamsPrefix, "params", codec.CollValue[bondtypes.Params](cdc)), + Bonds: collections.NewIndexedMap(sb, bondtypes.BondsPrefix, "bonds", collections.StringKey, codec.CollValue[bondtypes.Bond](cdc), newBondIndexes(sb)), // usageKeepers: usageKeepers, } diff --git a/x/bond/keys.go b/x/bond/keys.go index deb56ef1..ddb5e32e 100644 --- a/x/bond/keys.go +++ b/x/bond/keys.go @@ -8,9 +8,8 @@ const ( // Store prefixes var ( - // ParamsKey is the prefix for params key - ParamsKeyPrefix = collections.NewPrefix(0) + ParamsPrefix = collections.NewPrefix(0) - BondsKeyPrefix = collections.NewPrefix(1) + BondsPrefix = collections.NewPrefix(1) BondOwnerIndexPrefix = collections.NewPrefix(2) )