Auctions
Last updated
Time-boxed bidding with a clear winner and a buy-out finalization step. Built on top of the basic listing flow.
┌─────────┐ ┌────────┐ ┌─────────┐
create │ waiting │──────▶│ active │──────▶│ ended │ ──▶ winner buys out
└─────────┘ └────────┘ └─────────┘
▲ │
│ │
(no bids, (winner inactive
can remove) 48h auto-cleanup)waiting — now < auction_starts_at. Visible in the market but Submit bid is disabled.
active — bids accepted; current price = highest bid.
ended — now > auction_ends_at. No more bids. Only the highest bidder sees Buy out.
A bid is accepted if all of these hold:
Listing exists and is of type auction.
Auction has not ended (auction_ends_at > NOW()).
amount >= price (the seller's reserve).
amount > currentMax (must outbid the leader).
Bidder has at least amount in their bank.
Rule #5 was added in v1.0.0. Earlier versions let players bid arbitrarily and refuse to pay later — now you must have the funds at bid-time.
No fee to bid — submitting an offer is free.
Listing fees still apply to the seller, same as buy-now. See Exchange.
Commission is taken from the final sale price the same way as buy-now.
The seller has nothing to do. The winner sees a Buy out button next to the listing:
Winner clicks Buy out.
Server validates: are they the highest bidder? does the auction actually end?
Money moves: winner → seller (minus commission) → zone owner (if any).
Vehicle is transferred to the winner's garage; listing is deleted.
If the winner never claims, a periodic sweep deletes the listing after a grace period. The vehicle stays with the original seller.
You can cancel an auction:
If status == 'waiting' (no bids yet)
You cannot cancel:
Once active (any bid placed locks the auction)
Once ended (winner gets first dibs)
The frontend listens to koja_carmarket:client:auctionUpdated:
started — fires the minute auction_starts_at is crossed
bid_placed — fires on every accepted bid (broadcast to all clients)
ended — fires when the auction is over (either by time or by buy-out)
The market view auto-refreshes on these events so bidders see live data without polling.
Last updated
{ listingId: number, event: 'started' | 'ended' | 'bid_placed' }