diff --git a/src/database/index.js b/src/database/index.js index 2bbe183..3930254 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -200,8 +200,8 @@ export const getOfferBids = flopoDB.prepare(` `); export const insertBid = flopoDB.prepare(` - INSERT INTO bids (id, bidder_id, market_offer_id, offer_amount) - VALUES (@id, @bidder_id, @market_offer_id, @offer_amount) + INSERT INTO bids (bidder_id, market_offer_id, offer_amount) + VALUES (@bidder_id, @market_offer_id, @offer_amount) `); export const insertManyUsers = flopoDB.transaction(async (users) => { diff --git a/src/server/routes/market.js b/src/server/routes/market.js index 2bd2090..006c185 100644 --- a/src/server/routes/market.js +++ b/src/server/routes/market.js @@ -5,7 +5,16 @@ import express from "express"; // --- Utility and API Imports --- // --- Discord.js Builder Imports --- import { ButtonStyle } from "discord.js"; -import { getMarketOfferById, getMarketOffers, getOfferBids, getSkin, getUser } from "../../database/index.js"; +import { + getMarketOfferById, + getMarketOffers, + getOfferBids, + getSkin, + getUser, + insertBid, + insertLog, + updateUserCoins, +} from "../../database/index.js"; // Create a new router instance const router = express.Router(); @@ -50,7 +59,6 @@ export function marketRoutes(client, io) { router.get("/offers/:id/bids", async (req, res) => { try { - // Placeholder for fetching bids logic const bids = getOfferBids.get(req.params.id); res.status(200).send({ bids }); } catch (e) { @@ -69,11 +77,59 @@ export function marketRoutes(client, io) { }); router.post("/offers/:id/place-bid", async (req, res) => { + const { buyer_id, bid_amount, timestamp } = req.body; try { - // Placeholder for placing a bid logic - // Extract data from req.body and process accordingly + console.log(getMarketOfferById.get(req.params.id)); + console.log(buyer_id, bid_amount, timestamp); + + const offer = getMarketOfferById.get(req.params.id); + if (!offer) return res.status(404).send({ error: "Offer not found" }); + if (offer.closing_at < timestamp) return res.status(403).send({ error: "Bidding period has ended" }); + + if (buyer_id === offer.seller_id) return res.status(403).send({ error: "You can't bid on your own offer" }); + + const offerBids = getOfferBids.all(offer.id); + const lastBid = offerBids[0]; + + if (lastBid) { + if (lastBid?.bidder_id === buyer_id) + return res.status(403).send({ error: "You are already the highest bidder" }); + if (bid_amount < lastBid?.offer_amount + 10) { + return res.status(403).send({ message: "Bid amount is below minimum" }); + } + } else { + if (bid_amount < offer.starting_price + 10) { + return res.status(403).send({ message: "Bid amount is below minimum" }); + } + } + + const bidder = getUser.get(buyer_id); + if (!bidder) return res.status(404).send({ error: "Bidder not found" }); + if (bidder.coins < bid_amount) + return res.status(403).send({ error: "You do not have enough coins to place this bid" }); + + // TODO: + // buyer must refunded on outbid + + insertBid.run({ + bidder_id: buyer_id, + market_offer_id: offer.id, + offer_amount: bid_amount, + }); + const newCoinsAmount = bidder.coins - bid_amount; + updateUserCoins.run({ buyer_id, coins: newCoinsAmount }); + insertLog.run({ + id: `${buyer_id}-bid-${offer.id}-${Date.now()}`, + user_id: buyer_id, + action: "BID_PLACED", + target_user_id: null, + coins_amount: bid_amount, + user_new_amount: newCoinsAmount, + }); + res.status(200).send({ message: "Bid placed successfully" }); } catch (e) { + console.log(e); res.status(500).send({ error: e }); } });