Author: Md. Sowad Al-Mughni
An open-source NFT ticketing protocol designed to combat scalping while providing artists and event organizers with resale control and royalty mechanisms. Built with ERC-721 smart contracts, React Native mobile wallet integration, and POAP functionality for attendance verification.
The NFTicket Anti-Scalping Protocol addresses the post-pandemic challenge of event ticket scalping while enabling artists and organizers to maintain control over secondary sales and earn royalties. The protocol combines blockchain technology with user-friendly mobile applications to create a comprehensive ticketing ecosystem that benefits everyoneβexcept scalpers.
- π« ERC-721 NFT Tickets: Secure, transfer-restricted digital assets with on-chain metadata.
- π‘οΈ Anti-Scalping Engine:
- Price Caps: Smart contracts enforce a strict maximum resale price.
- Royalty Enforcement: Automated royalty distribution to organizers on every secondary sale.
- π± Mobile & Offline Integration:
- QR Verification: Offline-first cryptographic signatures for venue entry.
- Wallet Integration: Compatible with MetaMask and WalletConnect.
- π POAP Distribution: "Scan-to-airdrop" mechanisms to reward attendees with soulbound Proof of Attendance tokens.
- π Decentralized Indexing: Powered by The Graph for high-performance data querying.
- π White-label Ready: Modular architecture allowing easy deployment for any event organizer.
graph TD
User[π± Mobile App User] -->|Signs Message| QR[QR Code]
QR -->|Scanned by| Validator[Validator Device]
Validator -->|Verifies Sig| API[Validator API]
User -->|Mints/Transfers| Chain[Blockchain (Ethereum/Polygon)]
API -.->|Reads State| Chain
Subgraph[The Graph Node] -->|Indexes Events| Chain
Dashboard[π» Web Dashboard] -->|Queries Data| Subgraph
Dashboard -->|Deploys Contracts| Chain
Organizer[Event Organizer] -->|Manages Events| Dashboard
| Component | Technology | Description |
|---|---|---|
| Smart Contracts | Solidity 0.8.24, Hardhat, OpenZeppelin | Core logic, ERC-721 extensions, AccessControl |
| Web3 Integration | Viem, Wagmi, Ethers.js | Blockchain interaction and wallet management |
| Frontend | React + Vite, Tailwind CSS, shadcn/ui | Responsive dashboard for organizers and users |
| Mobile | React Native | Cross-platform wallet and ticket viewer |
| Indexing | The Graph Protocol | Decentralized querying of on-chain data |
| Backend API | Express.js | Off-chain signature verification and proof generation |
| Payments | Stripe | Fiat-to-crypto ticket purchases |
| Seat Selection | seats.io | Interactive venue seat maps |
| Caching | Redis | Persistent nonce storage for QR verification |
| Deployment | Docker, Docker Compose | Production containerization |
| Testing | Hardhat, Mocha, Chai | Comprehensive unit and integration testing |
NFTicket Protocol supports deployment across multiple EVM-compatible chains:
| Network | Chain ID | Status | Use Case |
|---|---|---|---|
| Polygon | 137 | β Primary | Low gas fees, fast confirmations |
| Polygon Amoy | 80002 | β Testnet | Development and testing |
| Ethereum | 1 | β Supported | High-value events |
| Sepolia | 11155111 | β Testnet | Development and testing |
| Base | 8453 | β Supported | Coinbase ecosystem |
| Arbitrum | 42161 | β Supported | Low fees with Ethereum security |
cd backend
# Deploy to Polygon (recommended for production)
npm run deploy:polygon
# Deploy to Sepolia testnet
npm run deploy:sepolia
# Deploy to Base
npm run deploy:base
# Deploy to Arbitrum
npm run deploy:arbitrumFull setup guide: See SETUP.md for complete instructions including testnet deployment.
# Clone and setup backend
git clone https://github.com/sowadalmughni/nfticket-protocol.git
cd nfticket-protocol/backend
npm install && cp .env.example .env
npm run api:dev # Starts API on http://localhost:3001
# In a new terminal - run dashboard
cd frontend/nfticket-dashboard
pnpm install && cp .env.example .env
pnpm dev # Opens http://localhost:5173The app runs in demo mode with mock data. To use real contracts:
- Get free testnet MATIC from faucet.polygon.technology
- Add your wallet private key to
backend/.env:DEPLOYER_PRIVATE_KEY=0x...
- Deploy:
cd backend npm run deploy:polygon-amoy - Copy the output contract addresses to your
.envfiles
- Node.js v18+ and npm or pnpm
- Git
- MetaMask or compatible Web3 wallet
-
Clone the repository
git clone https://github.com/sowadalmughni/nfticket-protocol.git cd nfticket-protocol -
Install Root Dependencies
npm install
-
Backend & API Setup
cd backend npm install # Compile contracts to generate artifacts npx hardhat compile # (Optional) Run local validator API # node api/server.js cd ..
-
Dashboard Setup
cd frontend/nfticket-dashboard pnpm install cd ../..
-
Mobile App Setup
cd frontend/mobile-app/NFTicketApp npm install cd ../../..
-
Run Tests
cd backend npx hardhat test
-
Deploy Contracts
# Deploy to local Hardhat Network npx hardhat node npx hardhat run scripts/deploy.js --network localhost # Deploy to Sepolia Testnet npx hardhat run scripts/deploy.js --network sepolia
Web Dashboard
cd frontend/nfticket-dashboard
pnpm run dev
# Access at http://localhost:5173Mobile App
cd frontend/mobile-app/NFTicketApp
# iOS
npx react-native run-ios
# Android
npx react-native run-androidnfticket-protocol/
βββ backend/ # Smart contracts and backend services
β βββ contracts/ # Solidity contracts (NFTicket.sol, POAPDistributor.sol)
β βββ api/ # Express.js Validator API for QR proofs
β βββ test/ # Hardhat unit tests
βββ frontend/
β βββ mobile-app/ # React Native mobile application
β βββ nfticket-dashboard/ # React web dashboard for organizers
βββ subgraph/ # The Graph subgraph definition
β βββ schema.graphql # GraphQL schema
β βββ subgraph.yaml # Subgraph manifest
βββ docs/ # Technical documentation
βββ CONTRIBUTING.md # Contribution guidelines
βββ README.md # Project documentationCreate a .env file in backend/ based on .env.example:
# Required - Wallet private key for signing
SIGNER_PRIVATE_KEY=your_wallet_private_key
# Required - JWT secret for API authentication
JWT_SECRET=your_secure_jwt_secret_at_least_32_chars
# RPC URLs (defaults provided, but recommended to use your own)
RPC_URL_POLYGON=https://polygon-rpc.com
RPC_URL_MAINNET=https://rpc.ankr.com/eth
RPC_URL_SEPOLIA=https://rpc.ankr.com/eth_sepolia
# Stripe Integration (required for fiat payments)
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
# Redis (optional - falls back to in-memory in development)
REDIS_URL=redis://localhost:6379
# Contract verification
ETHERSCAN_API_KEY=your_etherscan_key
POLYGONSCAN_API_KEY=your_polygonscan_keyCreate a .env file in frontend/nfticket-dashboard/:
# Contract addresses (from deployment)
VITE_CONTRACT_ADDRESS=0xYourNFTicketContractAddress
VITE_POAP_CONTRACT_ADDRESS=0xYourPOAPContractAddress
VITE_LOYALTY_CONTRACT_ADDRESS=0xYourLoyaltyContractAddress
# Subgraph URLs (from The Graph deployment)
VITE_SUBGRAPH_POLYGON=https://api.thegraph.com/subgraphs/name/your-org/nfticket-polygon
VITE_SUBGRAPH_SEPOLIA=https://api.thegraph.com/subgraphs/name/your-org/nfticket-sepolia
# seats.io (for seat selection)
VITE_SEATSIO_PUBLIC_KEY=your_seatsio_public_workspace_key
# WalletConnect (optional)
VITE_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_idAdjust default values in scripts/deploy.js to customize:
Royalty Cap(Default: 500 basis points = 5%)Max Price(Default: 1 ETH)
NFTicket supports fiat-to-crypto ticket purchases via Stripe:
- Create a Stripe account
- Get your API keys from the Stripe Dashboard
- Set up webhooks pointing to
/api/payments/webhook
| Endpoint | Method | Description |
|---|---|---|
/api/payments/create-checkout-session |
POST | Create Stripe checkout session |
/api/payments/webhook |
POST | Handle Stripe webhook events |
/api/payments/session/:sessionId |
GET | Get session status |
- User selects tickets β Frontend calls
create-checkout-session - User redirected to Stripe Checkout
- On success, webhook triggers β Backend mints NFT to user's wallet
Interactive venue seat selection powered by seats.io:
- Create a seats.io account and workspace
- Design your venue chart in the seats.io designer
- Add your public key to environment variables
import { SeatingChart, useSeatSelection } from '@/components/SeatingChart'
function EventPage({ eventId }) {
const { selectedSeats, totalPrice, clearSelection } = useSeatSelection()
return (
<SeatingChart
eventId={eventId}
onSelectionChange={(seats) => console.log(seats)}
/>
)
}Production deployment with Docker Compose:
# Build and start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down| Service | Port | Description |
|---|---|---|
api |
3000 | Backend API server |
dashboard |
80 | Frontend dashboard (nginx) |
redis |
6379 | Nonce storage cache |
- Copy
.env.examplefiles and configure for production - Set
NODE_ENV=production - Use a reverse proxy (nginx/Traefik) for SSL termination
- Configure Redis persistence for nonce storage
We welcome contributions! Please see CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.
- Fork the repo
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes
- Push to the branch
- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- OpenZeppelin for rock-solid contract libraries.
- The Graph for making indexing easy.
- POAP for the inspiration on attendance protocols.
For support, feature requests, or enterprise inquiries:
- Primary Contact: Md. Sowad Al-Mughni (sowad@kitalonlabs.com)
- Company: Kitalon Labs
- GitHub Issues: Open an Issue
Maintained by Kitalon Labs β Md. Sowad Al-Mughni
Made with β€οΈ for the decentralized future.