Quick Start Guide
This guide helps developers understand the NFT infrastructure and start contributing quickly.
System Overview
The NFT infrastructure consists of three main components:
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Smart │ │ Blockchain │ │ Frontend │
│ Contracts │ ──▶ │ Indexer │ ──▶ │ (Studio) │
│ (Hardhat) │ │ (Ponder) │ │ (wagmi/viem) │
└────────────────┘ └────────────────┘ └────────────────┘- Smart Contracts - ERC721A NFT contracts with factory pattern
- Blockchain Indexer - Ponder service that indexes events and provides API
- Frontend - React components using wagmi hooks for Web3 interactions
Repository Status
| Component | Location | Status |
|---|---|---|
| Smart Contracts | External repo (emprops-hardhat) | Ready for integration |
| Indexer | External repo (emprops-ponder) | Ready for integration |
| Frontend Integration | apps/emprops-studio | Production (Tezos) |
Target
These will be integrated into the monorepo as part of the Arbitrum launch.
Contract Architecture
Core Contracts
| Contract | Purpose | Type |
|---|---|---|
| NFTContractFactory | Creates new collections | Upgradeable (UUPS) |
| Emerge_721 | Individual NFT collection | Minimal Proxy (ERC1167) |
Deployment Flow
1. Platform calls NFTContractFactory.createNFTContract()
│
├─▶ Factory deploys Emerge_721 (minimal proxy)
│ └─▶ Uses CREATE2 for deterministic address
│
└─▶ Clone is initialized
└─▶ Sets name, symbol, maxSupply, owner, baseURIWhy This Design?
- Minimal proxies - Deploy collections for ~$0.50 on Arbitrum
- CREATE2 - Same address on all EVM chains
- UUPS upgrades - Factory can evolve; collections are immutable
- Centralized minting - Users receive NFTs without gas costs
Indexer Architecture
Ponder watches blockchain events and provides:
REST API
bash
# List all collections
GET /api/apps
# Get collection details
GET /api/apps/:address
# List minting events
GET /api/app-token-mints/:addressWebSocket Events
typescript
// Real-time event streaming
socket.on('emprops:app:created', (data) => {
// New collection deployed
});
socket.on('emprops:appToken:minted', (data) => {
// NFT minted
});Database Schema
| Table | Purpose |
|---|---|
apps | NFT collections (Emerge_721 instances) |
app_tokens | Individual NFTs |
app_token_mints | Minting events |
app_token_transfers | Transfer history |
app_token_upgrades | Token upgrade history |
Frontend Patterns
Reading Collection Data
typescript
// Use indexer for lists (faster, cached)
const collections = await fetch('/api/apps');
// Use on-chain for critical data (authoritative)
const { data: mintPrice } = useReadContract({
address: collectionAddress,
abi: Emerge_721Abi,
functionName: 'mintPrice'
});Writing Transactions
typescript
const { writeContractAsync } = useWriteContract();
const mint = async (quantity: number) => {
const hash = await writeContractAsync({
address: collectionAddress,
abi: Emerge_721Abi,
functionName: 'mint',
args: [BigInt(quantity)],
value: mintPrice * BigInt(quantity)
});
// Wait for confirmation
await waitForTransactionReceipt({ hash });
};Real-time Updates
typescript
// Combine React Query with WebSocket for real-time UI
useEffect(() => {
const socket = io(INDEXER_URL);
socket.on('emprops:appToken:minted', () => {
queryClient.invalidateQueries(['collection', address]);
});
return () => socket.disconnect();
}, []);Development Workflow
Local Development Setup
Not Yet Integrated
These components are not yet in the monorepo. This workflow will be updated after integration.
Start Hardhat Node (contracts)
bashcd emprops-hardhat pnpm chainDeploy Contracts
bashpnpm deploy:contracts --network localhost pnpm db:store-deploymentsStart Ponder (indexer)
bashcd emprops-ponder pnpm devStart Studio (frontend)
bashcd apps/emprops-studio pnpm dev
Testing on Testnet
Current testnet deployments:
| Network | Status | Contract Verification |
|---|---|---|
| Base Sepolia | Deployed | Basescan |
| Arbitrum Sepolia | In progress | - |
Key Files to Understand
Smart Contracts
| File | Description |
|---|---|
contracts/NFTContractFactoryContract.sol | Factory that creates collections |
contracts/Emerge_721Contract.sol | ERC721A collection with upgrade support |
deploy/00_app_factory.ts | Factory deployment script |
Indexer
| File | Description |
|---|---|
ponder.schema.ts | Database schema definition |
ponder.config.ts | Contract configuration |
src/handlers/ | Event processing logic |
src/api/index.ts | REST API endpoints |
Frontend
| File | Description |
|---|---|
| (TBD after integration) | wagmi configuration |
| (TBD after integration) | Collection hooks |
| (TBD after integration) | Minting components |
Common Tasks
Deploy a New Collection
- Connect wallet
- Call
NFTContractFactory.createNFTContract()with:appType:keccak256("SIMPLE_APP_V1")appId: Unique identifiername: Collection namesymbol: Token symbolinitData: Encoded mint parameters
Mint an NFT
- Check collection status:
paused,totalEditions,mintPrice - Call
Emerge_721.mint(quantity)with appropriate value - Wait for transaction confirmation
- Token ID returned in event logs
Read Collection State
typescript
// From indexer (for lists, historical data)
const response = await fetch(`${INDEXER_URL}/api/apps/${address}`);
const collection = await response.json();
// From chain (for current state)
const mintPrice = await publicClient.readContract({
address,
abi: Emerge_721Abi,
functionName: 'mintPrice'
});Next Steps
- Technical Architecture - Deep dive into system design
- Smart Contracts Documentation - Contract details
- Indexer Documentation - API reference
- Arbitrum Overview - Current development focus
