A comprehensive blockchain platform that combines YouTube engagement tracking with dual minting capabilities: ERC-20 token rewards for engagement growth AND NFT minting from video thumbnails. All data is tracked and persisted via Supabase (fully connected).
- 📊 Real-time Monitoring: Tracks views and subscribers for specified YouTube video/channel
- 🪙 ERC-20 Token Minting: Automatically mints tokens based on engagement growth (youtube-oracle.ts)
- 🎨 NFT Minting: Creates NFTs from video thumbnails via IPFS (nft-minter.ts)
- 📸 Thumbnail Storage: Downloads and stores video thumbnails in multiple qualities
- 📋 Playlist Tracking: Optional playlist image monitoring and download
- 💾 Supabase Integration: PostgreSQL database for all data persistence (
⚠️ requires your own setup) - ⛓️ Arbitrum One: Optimized for low-cost transactions
- 📈 Quota Management: Smart YouTube API quota tracking to avoid limits
- 🔄 Auto-recovery: PM2 process management with auto-restart
- 🔐 Secure: Environment-based configuration, no hardcoded secrets
The oracle (youtube-oracle.ts) monitors video metrics and mints ERC-20 tokens based on growth:
Tokens = floor(new_views / 20) × 5
Example: 100 new views = 25 tokens
Tokens = floor(new_subscribers / 10) × 100
Example: 30 new subscribers = 300 tokens Threshold: Minimum 10 new subscribers required
The NFT minter (nft-minter.ts) creates NFTs from video thumbnails:
- Fetch Thumbnail: Downloads highest quality thumbnail from YouTube
- Upload to IPFS: Uses thirdweb to upload image to IPFS
- Create Metadata: Generates ERC-721 metadata with video info
- Mint NFT: Mints on Arbitrum One with metadata URI
- Track in Database: Records mint in Supabase
# Mint NFT from a video thumbnail
npm run nft mint <VIDEO_ID> [RECIPIENT_ADDRESS]
# Mint NFTs for all tracked videos
npm run nft batch
# Check if video already minted
npm run nft check <VIDEO_ID>- Node.js 18+
- Supabase Account (free tier works) -
⚠️ YOU MUST CREATE YOUR OWN - YouTube Data API v3 Key
- Arbitrum One RPC Access
- ERC-20 Token Contract with
mint(address, uint256)function - Private Key with minting permissions
- Thirdweb Account (for IPFS uploads)
- Thirdweb Client ID and Secret Key
- ERC-721 NFT Contract with
mintTo(address, string)function on Arbitrum
cd /workspace
npm install- Go to your Supabase Dashboard and select your project
- Click Database → Connection string
- Reset password if needed and save it
- In Supabase dashboard, go to SQL Editor
- Click "+ New Query"
- Open
complete-schema.sqlfrom this repo - Copy ALL contents (entire file - 229 lines)
- Paste into SQL Editor and click "Run"
- Verify in Table Editor - you should see 10 tables:
videos,channel_stats,minting_events,thumbnails,oracle_stateplaylists,playlist_images,nft_mints,holders,airdrops
SUPABASE_URL=https://YOUR_PROJECT_ID.supabase.co
SUPABASE_ANON_KEY=eyJhbGci...YOUR_ACTUAL_KEY📖 See SUPABASE_SETUP_ACTUAL.md for detailed step-by-step instructions
setup-database.ts script doesn't work - use the SQL Editor method above.
- Go to Google Cloud Console
- Create a new project or select existing
- Enable YouTube Data API v3
- Create credentials → API Key
- Copy the API key
Copy .env.example to .env and fill in your values:
cp .env.example .env
nano .envRequired for ERC-20 Token Minting:
# Blockchain (ERC-20 tokens)
PRIVATE_KEY=0xYourPrivateKeyHere
CONTRACT_ADDRESS=0xYourTokenContractAddress
# YouTube
YOUTUBE_API_KEY=AIzaSy...
CHANNEL_ID=UC...
VIDEO_ID=LQAFm01IOT0
# Supabase - GET YOUR OWN from https://supabase.com
SUPABASE_URL=https://YOUR_PROJECT_ID.supabase.co
SUPABASE_ANON_KEY=eyJhbGci...YOUR_ACTUAL_KEY_HEREAdditional for NFT Minting:
# Thirdweb (for IPFS uploads)
THIRDWEB_CLIENT_ID=your_client_id
THIRDWEB_SECRET_KEY=your_secret_key
# NFT Contract (ERC-721)
NFT_CONTRACT_ADDRESS=0xYourNFTContractAddress
NFT_RECIPIENT_ADDRESS=0xDefaultRecipientAddressnpm run buildThis generates youtube-oracle.js from youtube-oracle.ts
Test ERC-20 Token Oracle:
npm startYou should see:
█████████████████████████████████████████████████████████████
█ █
█ 🎬 ARBITRUM ONE YOUTUBE ORACLE 🎬 █
█ █
█████████████████████████████████████████████████████████████
✅ Environment validated
🌐 Network: Arbitrum One
📹 Video ID: LQAFm01IOT0
💼 Wallet: 0x...
📝 Contract: 0x...
💾 Supabase: ✅ Connected
Test NFT Minting:
npm run nft mint LQAFm01IOT0You should see the complete workflow: thumbnail fetch → IPFS upload → NFT mint → Supabase record
# Create logs directory
mkdir -p logs
# Start with PM2
pm2 start pm2.config.js
# View logs
pm2 logs arbitrum-youtube-oracle
# Monitor
pm2 monit
# Save PM2 configuration
pm2 save
# Setup auto-start on reboot
pm2 startup/workspace/
├── youtube-oracle.ts # Main oracle logic (TypeScript)
├── youtube-oracle.js # Compiled JavaScript
├── abi.json # Token contract ABI
├── package.json # Dependencies
├── tsconfig.json # TypeScript config
├── pm2.config.js # PM2 process config
├── supabase-schema.sql # Database schema
├── .env # Your configuration (DO NOT COMMIT)
├── .env.example # Template configuration
├── README.md # This file
├── logs/ # PM2 logs
│ ├── output.log
│ └── error.log
└── thumbnails/ # Downloaded thumbnails
├── VIDEO_ID_maxres.jpg
├── VIDEO_ID_high.jpg
└── ...
| Variable | Default | Description |
|---|---|---|
RPC_URL |
https://arb1.arbitrum.io/rpc |
Arbitrum One RPC endpoint |
CONTRACT_ADDRESS |
- | Token contract address (required) |
PRIVATE_KEY |
- | Wallet private key (required) |
YOUTUBE_API_KEY |
- | YouTube Data API key (required) |
CHANNEL_ID |
- | YouTube channel ID (required) |
VIDEO_ID |
LQAFm01IOT0 |
Specific video to track |
SUPABASE_URL |
- | Supabase project URL (required) |
SUPABASE_ANON_KEY |
- | Supabase anon public key (required) |
CHECK_INTERVAL_MINUTES |
45 |
Minutes between checks |
DAILY_QUOTA |
10000 |
YouTube API daily quota |
QUOTA_BUFFER |
500 |
Safety buffer before quota limit |
SUBSCRIBER_MINT_THRESHOLD |
10 |
Min new subs to trigger mint |
SUBSCRIBER_REWARD_PER_10 |
100 |
Tokens per 10 subscribers |
VIEW_REWARD_DIVISOR |
20 |
View count divisor |
VIEW_REWARD_MULTIPLIER |
5 |
Token multiplier |
THUMBNAIL_STORAGE_PATH |
./thumbnails |
Where to save thumbnails |
DOWNLOAD_THUMBNAILS |
true |
Enable thumbnail downloads |
Edit .env to change minting rates:
# More generous: 1 token per 10 views
VIEW_REWARD_DIVISOR=10
VIEW_REWARD_MULTIPLIER=1
# More generous: 200 tokens per 10 subscribers
SUBSCRIBER_REWARD_PER_10=200SELECT
event_type,
delta,
tokens_minted,
tx_hash,
created_at
FROM minting_events
ORDER BY created_at DESC
LIMIT 10;SELECT
subscriber_count,
recorded_at
FROM channel_stats
ORDER BY recorded_at DESC
LIMIT 20;SELECT
event_type,
SUM(tokens_minted::numeric) as total_minted
FROM minting_events
GROUP BY event_type;# Status
pm2 status
# Logs (live)
pm2 logs arbitrum-youtube-oracle --lines 100
# Restart
pm2 restart arbitrum-youtube-oracle
# Stop
pm2 stop arbitrum-youtube-oracle
# Delete
pm2 delete arbitrum-youtube-oracle
# Info
pm2 info arbitrum-youtube-oracle- Go to Supabase Dashboard
- Table Editor → View your data
- Logs → Check for errors
- Check that all required variables in
.envare filled - Ensure
.envfile is in the project root
- Verify wallet has ETH for gas
- Check wallet has minting permissions on contract
- Verify contract address is correct
- Oracle will auto-sleep for 4 hours when quota is near limit
- Check current quota:
SELECT * FROM oracle_state WHERE key = 'quota_used' - Reduce
CHECK_INTERVAL_MINUTESif hitting limits
- Verify
SUPABASE_URLandSUPABASE_ANON_KEY - Check Supabase project is active
- Ensure database schema is created
- Check
DOWNLOAD_THUMBNAILS=truein.env - Verify
thumbnails/directory exists and is writable - Check disk space
- Never commit
.env- It's in.gitignore - Rotate keys if exposed
- Use dedicated wallet with limited funds
- Monitor transactions regularly
- Set spending limits on minting wallet
- Backup Supabase data regularly
Your token contract must implement:
function mint(address to, uint256 amount) external;The oracle wallet must have the MINTER_ROLE or equivalent permission.
To track a different video:
- Get video ID from URL:
https://youtube.com/watch?v=VIDEO_ID_HERE - Update
.env:VIDEO_ID=NEW_VIDEO_ID - Restart:
pm2 restart arbitrum-youtube-oracle
For multiple videos:
- Run multiple oracle instances with different
.envconfigs - Use different PM2 app names
- Consider shared Supabase database or separate per-video
- Supabase Docs: https://supabase.com/docs
- YouTube API Docs: https://developers.google.com/youtube/v3
- Ethers.js Docs: https://docs.ethers.org
- Arbitrum Docs: https://docs.arbitrum.io
MIT
Built for Arbitrum One 🔵 | Powered by Supabase 💚 | YouTube Data API v3 🎥