Implementing NFT Auctions in Mobile Applications
An NFT auction is a smart contract with a timer. The owner lists a token with a starting price and deadline. Buyers place bids; each new bid locks ETH in the contract and refunds the previous bidder. When time expires, the winner claims the NFT, the seller receives ETH.
In practice, auction UX on mobile is one of the most complex Web3 experiences: real-time bid updates, timers, competitive bids (someone outbids 3 seconds before end), refunds. Each scenario must be handled.
Auction Types
English Auction (Open): bids increase, highest bid at deadline wins. Most common.
Dutch Auction: price starts high and decreases over time. First buyer at current price gets the NFT. Simple to implement, requires no bidding — just one buy() call.
Reserve Price Auction: auction activates only if at least one bid exceeds the reserve price. Bids are accepted before this, but NFT doesn't sell.
Real-time Updates: Smart Contract Events
Current bid updates through the BidPlaced(auctionId, bidder, amount) event. Listen via WebSocket-RPC or polling through eth_getLogs.
// Android — subscribing to auction events via web3j
fun subscribeToAuctionBids(auctionId: BigInteger): Flow<BidPlacedEvent> = callbackFlow {
val subscription = auctionContract.bidPlacedEventFlowable(
DefaultBlockParameterName.LATEST,
DefaultBlockParameterName.LATEST
)
.filter { it.auctionId == auctionId }
.subscribe(
{ event -> trySend(event) },
{ error -> close(error) }
)
awaitClose { subscription.dispose() }
}
Update UI on each new event: current bid, leader address (shortened ENS or 0x…), bid count. Animate "outbid" — notification + visual signal on the card.
Bid Form
Input field for bid amount with minimum increment: smart contracts typically require new bids exceed current by at least N% (e.g., 5%). Display minimum allowed bid directly in the field.
// iOS — calculating minimum next bid with increment
func minNextBid(currentBid: BigUInt, incrementPercent: Int = 5) -> BigUInt {
let increment = currentBid * BigUInt(incrementPercent) / 100
let minimum = currentBid + max(increment, BigUInt(1_000_000_000_000_000)) // at least 0.001 ETH
return minimum
}
On successful bid — ETH locks in contract. Users must understand: funds are frozen until auction end or bid is outbid.
Timer and Anti-Sniping
A countdown timer is the main element of the auction screen. Update every second. In the last 5 minutes — change color visually (yellow → red). Push notification "Auction ends in 10 minutes" — 10 and 1 minute before end.
Many auction contracts implement anti-sniping: if a bid is placed in the last X minutes, the deadline extends by Y minutes. Show users "Time extended to HH:MM" when triggered.
Completion and Claiming NFT
After auction ends:
- Winner calls
claimNFT(auctionId)— NFT transfers to their wallet - Losers can withdraw locked bids via
withdrawBid(auctionId)
Both actions require transactions. "Claim NFT" and "Withdraw Bid" buttons should appear automatically after auction ends, with push notification to winner.
Timeline: 5 working days: bid form with minimum increment, real-time updates via events, timer with anti-sniping, NFT claiming and bid withdrawal flow. Dutch Auction — additional 1–2 days.







