Project overview
The challenge
- Traditional NFT platforms reveal metadata immediately after minting, creating opportunities for bots to snipe rare NFTs by analyzing metadata before legitimate users can claim them.
- Most NFT backends store complete token arrays and metadata indefinitely, leading to exponential storage growth and degraded performance as the collection scales.
- Existing platforms use global minting queues where all users compete for the same pool, creating unfair advantages for users with faster connections or automated scripts.
- Without cryptographic verification, NFT metadata can be tampered with or manipulated, compromising the integrity of the entire collection and user trust.
A short freelance build (March 2025, co-developed with a second engineer): a backend service that mints and reveals NFTs, with each reveal checked against a Merkle proof so metadata cannot be swapped after the fact.
The ERC721 contract (Solidity with OpenZeppelin ERC721, Ownable and MerkleProof) mints against a Merkle root and only reveals token URIs whose proof verifies. Batches are tracked as start/end token-ID ranges rather than arrays of IDs.
The Express API gives each user an independent minting cycle triggered on login, and a cleanup service periodically removes expired batches and unrevealed token URIs. The repository ships Mocha, Chai and Supertest suites for the API, the user minting cycle and Merkle verification.
Technical architecture
Express API layer: REST endpoints for NFT and user operations, with Morgan logging and error-handling middleware
User service: activity tracking, automatic registration, a minting cycle per user and inactivity-based cleanup
NFT service: minting and reveal against the contract through Ethers.js, batch expiry and token-ID ranges
Merkle layer: proof generation with merkletreejs and keccak256, verified on-chain by OpenZeppelin's MerkleProof
Smart contract: ERC721 with Ownable access control, Merkle root storage, reveal threshold and owner batch transfers
Key challenges & solutions
Merkle Tree Proof Generation & Verification
Used merkletreejs with keccak256 hashing to generate proofs on the backend, verified on-chain with OpenZeppelin's MerkleProof.sol, and aligned the backend proof format with the contract.
User-Centric Minting Cycles
Designed per-user minting timers with configurable intervals, implemented heartbeat system for activity tracking, created automatic mint triggering on user login, and added user-specific cleanup to prevent data accumulation.
Storage Optimization with Token ID Ranges
Replaced token arrays with startTokenId/endTokenId ranges, implemented automatic cleanup of expired batches, and added periodic pruning of URIs for unrevealed tokens.
Automated Cleanup & Maintenance
Built automatic batch expiration based on configurable thresholds, created user-specific cleanup endpoints, implemented global cleanup scheduler, and added comprehensive cleanup reporting and monitoring.
Impact & results
Mint and reveal gated by Merkle proofs verified on-chain with OpenZeppelin's MerkleProof
Batch state stored as token-ID ranges instead of per-token arrays
Independent minting cycle per user, with automatic cleanup of expired batches
Test suites covering the API, the user minting cycle and Merkle verification
Key features
- Merkle-proof verification on mint and reveal (merkletreejs, keccak256, MerkleProof.sol)
- Per-user minting cycles triggered on login
- Token-ID ranges instead of token arrays
- Automatic cleanup of expired batches and token URIs
- REST API with Express and Morgan logging
- API, minting-cycle and Merkle test suites (Mocha, Chai, Supertest)
