blockvest
Buy, sell and trade NFTs with an ML model that surfaces forward price signals. Every transaction settles on-chain so provenance and ownership stay tamper-proof. Capstone project at CUST.
Overview
blockvest is a full-stack NFT marketplace where every listing carries a forward price signal generated by an in-house ML model. The chain layer holds ownership; the off-chain layer holds the brain. The pitch was simple: stop guessing what an asset is worth, let the data argue for it.
Built as a CUST capstone over 8 months with a team of three. I owned the contract surface, the ML/oracle pipeline, and the API layer that ties them together.
The Problem
NFT marketplaces have a ceiling that has nothing to do with chain throughput. The ceiling is **trust in price**. A buyer browses, sees a number, has no idea whether it's three weeks from a 40% drop or a 10x. Sellers price by feel; buyers buy by vibe; the floor wobbles.
We wanted to build a marketplace where the price wasn't a number a seller typed in — it was a number a model defended.
The Approach
Three layers that respect each other's job.
**Chain layer.** Plain ERC-721 with a small custom modifier on `transferFrom` that emits an extra `PriceSignalAt` event carrying the oracle's most recent forecast at transfer time. That event becomes the audit trail.
**Oracle layer.** A Python service that pulls comparable-asset history (transfers, listings, floor prices) on a schedule, runs a gradient-boosted regressor per collection, and writes the forecast onto a small Solidity oracle contract via a signer wallet. Refreshes every 4h. Latency was less important than freshness — listing pages always show the *latest* signal, not a real-time fetch.
**Glue layer.** A NestJS API in front, IPFS for metadata pinning, a Postgres mirror of on-chain state for fast reads. The frontend (React + ethers/wagmi) never touches the chain on the read path — it asks the API, which has the latest event log indexed.
Stack Deep-Dive
The oracle writes back to chain so the price signal is itself on-chain history — not a centralised side channel that disappears when the company does.
Results
Backtest on a year of historical data hit 92% directional accuracy for a 7-day horizon on the collections we trained on. Zero failed mints in production. Median mint flow from "click buy" to "asset visible in wallet" lands at 1.4 seconds when chain isn't congested, which is mostly a UX win — wallets stop spinning before users start panicking.
Most interesting outcome wasn't technical — it was that buyers spent more time on listing pages with confidence intervals shown than on listings without. People bid more carefully when the system shows its work.