19 KiB
Bounty System Implementation Plan
🎯 Goal
Create a bounty system to incentivize Thai/Asian skaters to document spots, funded by your ZapFunder campaign, with spam prevention mechanisms.
🛡️ SPAM PREVENTION STRATEGY
Multi-Layered Approach (Recommended)
Layer 1: NIP-05 Verification (Soft Requirement)
What: DNS-based identity verification How it works:
- Users with NIP-05 (like
username@skate-spots.com) are trusted - Non-verified users can still participate BUT:
- Their bounty claims require manual review
- Verified users get instant payouts
- Verified users can earn 2x bounties
Implementation:
// Check if user has NIP-05
const hasNIP05 = user.metadata?.nip05 && isValidNIP05(user.metadata.nip05);
// Verified users = auto-approve
// Non-verified = pending review
const bountyStatus = hasNIP05 ? 'approved' : 'pending_review';
Pros:
- ✅ Not too restrictive (anyone can still try)
- ✅ Incentivizes getting NIP-05 (builds trust)
- ✅ Manual review catches spam before payout
- ✅ Thai skaters can get free NIP-05 from nostr.directory
Cons:
- ⚠️ Requires manual review for non-verified
- ⚠️ Slight friction for new users
Layer 2: NIP-32 Labeling System (Quality Control)
What: Community labeling and moderation
How it works:
- Bounty system publishes kind 1985 labels on submitted spots
- Labels:
verified-spot,spam,low-quality,excellent - Community can also label (distributed moderation)
- Only spots with
verified-spotlabel get paid
Example label event:
{
"kind": 1985,
"tags": [
["L", "skatespots.bounty"],
["l", "verified-spot", "skatespots.bounty"],
["a", "30818:<user-pubkey>:<spot-identifier>"]
],
"content": "Verified: Real skate spot in Bangkok with photos"
}
Pros:
- ✅ Distributed moderation (community helps)
- ✅ Transparent verification process
- ✅ Can query spots by label
- ✅ Reusable for other quality control
Layer 3: Geographic Validation (Smart Checking)
What: Verify spots are in target regions
How it works:
- Bounty specifies region: "Bangkok", "Thailand", "Asia"
- Spot must have geohash in that region
- Reverse geocode to verify city/country
- Auto-reject if outside target area
Implementation:
// Bounty: "Add 5 spots in Bangkok"
const bountyRegion = { lat: 13.7563, lng: 100.5018, radiusKm: 50 };
// Check if spot is within region
const spotCoords = decodeGeohash(spot.geohash);
const distance = calculateDistance(bountyRegion, spotCoords);
if (distance > bountyRegion.radiusKm) {
// Not in Bangkok - reject claim
return false;
}
Pros:
- ✅ Automated verification
- ✅ Prevents gaming (can't claim Bangkok bounty with NYC spot)
- ✅ Works for city/country/region bounties
Layer 4: NIP-13 Proof of Work (Optional - Heavy Hammer)
What: Require computational work for bounty claims
How it works:
- Spots claiming bounties must have 16-20 difficulty PoW
- Makes bulk spam economically infeasible
- Normal users barely notice (30 seconds to mine)
Pros:
- ✅ Extremely effective against bots/spam
- ✅ No human review needed
- ✅ Standard Nostr feature
Cons:
- ⚠️ Battery drain on mobile
- ⚠️ Friction for legitimate users
- ⚠️ Only use if spam becomes serious problem
Recommendation: Keep as backup option, don't implement initially
Layer 5: Social Graph Filtering (Pyramid Integration)
What: Only Pyramid relay members can claim bounties
How it works:
- Bounty claims only valid from
goskatespots.nostr1.commembers - Invite-only relay (using Pyramid)
- Members vouch for quality
- Spam = member gets kicked
Pros:
- ✅ Self-regulating community
- ✅ High trust environment
- ✅ Uses your Pyramid relay
Cons:
- ⚠️ Excludes new users initially
- ⚠️ Requires Pyramid setup
- ⚠️ Less open/permissionless
Recommendation: Good for "premium bounties" tier
🏗️ RECOMMENDED ANTI-SPAM STACK
For Launch (Simple & Effective):
- ✅ NIP-05 Verification - Instant approve if verified, manual review if not
- ✅ Geographic Validation - Auto-check region boundaries
- ✅ Manual Review Queue - You or moderators approve claims
For Scale (When Community Grows):
- ✅ NIP-32 Labeling - Community helps moderate
- ✅ Reputation System - Track user history (spam = ban)
- ✅ Pyramid Relay - Premium bounties for members only
Nuclear Option (If Spam Gets Bad):
- ✅ NIP-13 PoW - Make spam expensive
📋 BOUNTY SYSTEM ARCHITECTURE
A. Custom Event Kind for Bounties
Create new kind: 30824 (Bounty Listing)
{
"kind": 30824,
"tags": [
["d", "bangkok-5-spots-jan2025"],
["title", "Add 5 spots in Bangkok"],
["description", "Document 5 skateable spots in Bangkok with photos"],
["reward", "10000"], // sats
["region", "Bangkok"],
["region", "Thailand"], // can have multiple
["g", "w4rqq"], // geohash for Bangkok center
["requirements", "min_photos:3"],
["requirements", "spot_types:street,park,diy"],
["status", "active"], // active, claimed, completed, expired
["expires", "1738368000"], // unix timestamp
["funded_by", "zapfunder"],
["fund_event", "<zapfunder event id>"]
],
"content": "We're funding documentation of Bangkok's skate scene! Add 5 quality spots with photos and description to earn 10,000 sats. Spots must be in Bangkok metro area."
}
B. Custom Event Kind for Bounty Claims
Create new kind: 30825 (Bounty Claim)
{
"kind": 30825,
"tags": [
["d", "claim-bangkok-5-spots-user123"],
["a", "30824:<bounty-creator-pubkey>:bangkok-5-spots-jan2025"],
["bounty", "bangkok-5-spots-jan2025"],
["status", "pending"], // pending, approved, rejected, paid
// References to submitted spots (proof of work)
["a", "30818:<user-pubkey>:<spot1-id>"],
["a", "30818:<user-pubkey>:<spot2-id>"],
["a", "30818:<user-pubkey>:<spot3-id>"],
["a", "30818:<user-pubkey>:<spot4-id>"],
["a", "30818:<user-pubkey>:<spot5-id>"],
// Verification data
["nip05", "<user-nip05-if-verified>"],
["L", "skatespots.verification"],
["l", "pending-review", "skatespots.verification"],
// Payment info
["lud16", "<user-lightning-address>"],
["payment_request", "<bolt11-or-lnurl>"]
],
"content": "I've added 5 spots in Bangkok as requested!"
}
C. Verification Events (NIP-32 Labels)
Moderator approves claim:
{
"kind": 1985,
"tags": [
["L", "skatespots.bounty"],
["l", "verified", "skatespots.bounty"],
["l", "approved", "skatespots.bounty"],
["a", "30825:<user-pubkey>:<claim-id>"],
["p", "<user-pubkey>"] // notify user
],
"content": "Claim verified! All 5 spots are legit Bangkok locations with good photos."
}
Community flags spam:
{
"kind": 1985,
"tags": [
["L", "skatespots.bounty"],
["l", "spam", "skatespots.bounty"],
["a", "30818:<spammer-pubkey>:<fake-spot-id>"],
["p", "<spammer-pubkey>"]
],
"content": "This is not a real skate spot - it's a restaurant"
}
🔧 TECHNICAL IMPLEMENTATION PLAN
Phase 1: Core Infrastructure (Week 1-2)
1.1 Create Bounty Management System
- Define custom kinds (30824, 30825) in
NIP.md - Create
src/lib/bounty-types.tswith TypeScript types - Create
src/hooks/useBounties.ts(query active bounties) - Create
src/hooks/useBountyClaims.ts(query user's claims) - Create
src/hooks/useCreateBounty.ts(admin only) - Create
src/hooks/useClaimBounty.ts(submit claim)
1.2 Geographic Validation Utilities
- Create
src/lib/geo-validation.ts- Function:
isSpotInRegion(geohash, regionBounds) - Function:
getRegionBounds(cityName)(Bangkok, Chiang Mai, etc.) - Function:
validateBountyClaim(bounty, spots)
- Function:
1.3 NIP-05 Verification Helper
- Create
src/lib/nip05-verification.ts- Function:
isUserVerified(user) - Function:
getVerificationStatus(user) - Cache verification results (24hr expiry)
- Function:
Phase 2: UI Components (Week 2-3)
2.1 Bounty Cards
src/components/BountyCard.tsx- Display bounty details (title, reward, region, expires)
- Progress indicator (e.g., "Add 5 spots: 2/5 complete")
- "Claim Bounty" button
- Requirements checklist
2.2 Bounty Claim Flow
src/components/BountyClaimDialog.tsx- Select spots to submit (from user's spots)
- Show auto-validation results (region check, photo check)
- Submit claim button
- Lightning address field (for payment)
2.3 Admin Bounty Creation
src/components/CreateBountyDialog.tsx(admin only)- Bounty details form
- Region selector (city/country)
- Requirements (min photos, spot types)
- Reward amount
- Expiration date
- Fund source (ZapFunder link)
2.4 Claim Review Dashboard
src/pages/BountyReviewPage.tsx(admin/moderator only)- List pending claims
- View submitted spots on map
- Approve/reject buttons
- Bulk actions
- Payment tracking
Phase 3: Rewards Page Integration (Week 3-4)
3.1 Update RewardsPage
- Add "Active Bounties" section at top
- Show user's claimed bounties
- Display total earnings from bounties
- Leaderboard: "Top Bounty Hunters"
3.2 Notifications
- New bounty posted → Notify all users
- Claim approved → Notify user + send zap
- Claim rejected → Notify user with reason
Phase 4: Payment System (Week 4)
4.1 Auto-Zap Integration
- When claim approved → Auto-zap user from your wallet
- Use NWC (Nostr Wallet Connect) for automated payments
- Track payments in database or Nostr events
- Handle failed payments (retry logic)
4.2 ZapFunder Integration
- Link bounty to ZapFunder event ID
- Display funding progress
- "This bounty is funded by community via ZapFunder"
- Track total spent vs. total funded
🎨 UI/UX FLOW
User Journey: Claiming a Bounty
- Discover - User sees "Active Bounties" on Rewards page
- View Details - Click bounty card to see requirements
- Check Eligibility - See if they qualify (NIP-05, region, etc.)
- Add Spots - Go to map and add required spots
- Submit Claim - Select their spots, submit claim
- Wait for Review - Track status (pending → approved/rejected)
- Get Paid - Receive zap automatically when approved
Admin Journey: Creating a Bounty
- Admin Panel - Settings → Bounties (or /admin/bounties)
- Create Bounty - Fill form (title, reward, region, requirements)
- Fund Bounty - Link ZapFunder campaign
- Publish - Bounty goes live immediately
- Monitor Claims - Review submissions as they come
- Approve/Reject - One-click approval sends zap
- Close Bounty - Mark complete when quota reached
🔐 ACCESS CONTROL & ROLES
Public (Everyone)
- ✅ View active bounties
- ✅ Submit claims (with verification)
- ✅ See leaderboards
Verified Users (NIP-05)
- ✅ Instant claim approval (for simple bounties)
- ✅ 2x reward multiplier
- ✅ Priority review
Moderators (Designated pubkeys)
- ✅ Review claims
- ✅ Approve/reject submissions
- ✅ Add labels to spots (NIP-32)
- ✅ Flag spam
Admin (You)
- ✅ Create bounties
- ✅ Edit bounties
- ✅ Assign moderators
- ✅ View analytics
- ✅ Manage funds
💾 DATA STORAGE
Option A: Pure Nostr (Fully Decentralized)
Pros: No backend, censorship-resistant, transparent Cons: Harder to query, no guaranteed delivery
Option B: Hybrid (Nostr + Your Relay)
Pros: Fast queries, reliable, still on Nostr Cons: Depends on your relay staying online Recommendation: ⭐ Use this
Architecture:
- Bounties published to Nostr (kind 30824)
- Claims published to Nostr (kind 30825)
- Your relay indexes them for fast lookup
- Verification labels (kind 1985) published to Nostr
🎮 GAMIFICATION FEATURES
1. Bounty Hunter Badges (NIP-58)
- 🥉 "Rookie Hunter" - Claimed 1st bounty
- 🥈 "Bounty Collector" - Claimed 5 bounties
- 🥇 "Master Hunter" - Claimed 20 bounties
- 💎 "Bangkok Legend" - Claimed all Bangkok bounties
2. Leaderboards
- Top bounty earners (all-time)
- Top this month
- Top per region (Bangkok, Chiang Mai, etc.)
- Fastest claim (first to complete new bounty)
3. Streaks
- "7-Day Streak" - Claimed bounty every week for 7 weeks
- Streak bonuses (+10% per week)
4. Combo Multipliers
- Claim 3 bounties in one day = 1.5x reward
- Complete bounty within 24hr of posting = 2x reward
📊 EXAMPLE BOUNTIES (Thailand Focus)
Starter Bounties (Easy Entry)
🇹🇭 Bangkok Basics
- Add 3 spots in Bangkok
- Reward: 5,000 sats
- Requirements: 2+ photos each, description
- NIP-05: Not required (manual review)
Regional Expansion
🌏 Chiang Mai Explorer
- First 5 spots in Chiang Mai
- Reward: 15,000 sats
- Requirements: 3+ photos, detailed features
- NIP-05: Required for instant payout
Quality Focus
📸 Bangkok Photo Mission
- Add high-quality photos to 10 existing Bangkok spots
- Reward: 8,000 sats
- Requirements: 1080p+ photos, multiple angles
- NIP-05: Recommended
Pioneer Bounties
🚀 First in Laos
- Be the first to add ANY spot in Laos
- Reward: 50,000 sats BONUS
- Requirements: Verified location, proof photo
- NIP-05: Required
Community Building
🏪 Shop Network
- Add 5 verified skate shops in Thailand
- Reward: 20,000 sats
- Requirements: Shop owner verification, contact info
- NIP-05: Required + shop NIP-05
🚨 SPAM SCENARIOS & SOLUTIONS
Scenario 1: Bulk Fake Spots
Attack: User adds 100 fake "spots" (restaurants, random locations) Prevention:
- ✅ Geographic validation (must be in target region)
- ✅ Manual review for non-NIP-05 users
- ✅ Community can label as spam (NIP-32)
- ✅ Reputation system (1 rejection = ban from future bounties)
Scenario 2: Low-Quality Content
Attack: User adds 5 spots with no photos, generic descriptions Prevention:
- ✅ Auto-validation checks (min 2 photos required)
- ✅ Quality multiplier (low quality = reduced payout)
- ✅ Manual review rejects poor submissions
Scenario 3: Duplicate Submissions
Attack: Multiple users claim same spot for bounty Prevention:
- ✅ Check if spot already exists (by geohash proximity)
- ✅ First valid submission wins
- ✅ Later duplicates auto-rejected
Scenario 4: Sybil Attack
Attack: One person creates multiple accounts to claim same bounty multiple times Prevention:
- ✅ NIP-05 required (hard to get multiple verifications)
- ✅ Lightning address reuse detection
- ✅ IP/device fingerprinting (optional, privacy trade-off)
- ✅ Manual review for suspicious patterns
💰 PAYMENT FLOW
Automated Payment (NIP-47 NWC)
1. Claim approved (kind 1985 label)
2. System reads user's lud16/lnurl from profile
3. System generates invoice request
4. System sends zap via your NWC connection
5. Zap receipt (kind 9735) published to Nostr
6. Update bounty claim status to "paid"
7. Notify user
Manual Payment (Backup)
1. Claim approved
2. User added to "pending payment" queue
3. Admin manually zaps user
4. Mark as paid in system
Recommendation: Start with manual, add automation later
📈 ANALYTICS TO TRACK
- Total bounties created
- Total claims submitted
- Approval rate (% approved vs rejected)
- Average time to approval
- Total sats paid out
- Regional breakdown (Bangkok: 45%, Chiang Mai: 20%, etc.)
- Top earners
- Spam detection rate
🛠️ TECH STACK
Frontend (SkateSpots App)
- React components for bounty UI
- Custom hooks for querying bounties/claims
- NIP-32 labeling integration
- NIP-05 verification checking
Backend/Logic
- Bounty validation functions (pure TypeScript)
- Geographic boundary checking (ngeohash)
- Auto-approval logic for verified users
- Payment queue management
Nostr Events
- Kind 30824: Bounty listings
- Kind 30825: Bounty claims
- Kind 1985: Verification labels (NIP-32)
- Kind 8: Badge awards (NIP-58) for achievements
Payment
- NIP-47: Nostr Wallet Connect (for auto-zaps)
- Manual zap via your wallet (backup)
- Track via kind 9735 zap receipts
📅 IMPLEMENTATION TIMELINE
Week 1: Foundation
- Define custom kinds in NIP.md
- Create bounty data types
- Build query hooks
- Geographic validation utilities
Week 2: UI
- BountyCard component
- BountyClaimDialog
- Update RewardsPage
- Admin creation form
Week 3: Verification
- NIP-05 checking
- Manual review dashboard
- Approval/rejection flow
- NIP-32 labeling
Week 4: Payment
- Manual payment tracking
- Zap integration
- Notification system
- Analytics dashboard
Week 5: Launch
- Create first 5 bounties (Bangkok, Chiang Mai, Phuket, etc.)
- Promote on social media
- Monitor for spam
- Iterate based on feedback
🎯 SUCCESS METRICS
Month 1 Goals
- 50+ bounty claims submitted
- 30+ approved claims
- 10+ verified skaters with NIP-05
- <5% spam rate
Month 3 Goals
- 200+ spots added via bounties
- 100+ active bounty hunters
- Organic bounty requests from community
- Self-sustaining with community funding
⚖️ ANTI-SPAM RECOMMENDATION
Start Simple, Add Layers as Needed:
-
Launch with:
- ✅ NIP-05 incentives (2x for verified)
- ✅ Geographic validation (auto-check)
- ✅ Manual review queue
-
Add if spam appears:
- ✅ NIP-32 community labeling
- ✅ Reputation/ban system
-
Nuclear option:
- ✅ NIP-13 Proof of Work
- ✅ Pyramid relay requirement
This progressive approach:
- Keeps friction low initially
- Can scale up protection as needed
- Doesn't scare away legitimate users
- Community helps moderate at scale
🚀 LAUNCH STRATEGY (Thailand)
Week 0: Pre-Launch
- Create 10 diverse bounties (Bangkok, Chiang Mai, Phuket, etc.)
- Recruit 3 Thai moderators (trusted skaters)
- Test with small group (10 beta testers)
Week 1: Soft Launch
- Announce on Thai skate Facebook groups
- Offer "Early Bird Bonus" (first 50 claims = +50%)
- Monitor closely for spam
- Quick approvals (same-day)
Week 2-4: Scale Up
- Add regional bounties (Vietnam, Philippines, Malaysia)
- Introduce quality multipliers
- Announce weekly winners on social
- Cross-promote with Thai skate shops
💡 FINAL RECOMMENDATION
Most Important Decision: Verification Method
Option A: NIP-05 Optional (Friendly)
- Anyone can claim
- Non-verified = manual review
- Verified = instant approval
- Best for: Growing user base quickly
Option B: NIP-05 Required (Quality)
- Only verified users can claim
- All claims auto-approved (with geo check)
- Best for: High-quality, spam-free
Option C: Pyramid Members Only (Exclusive)
- Only relay members can claim
- Invite-based (you control who joins)
- Best for: Tight-knit community
My vote: Start with Option A (friendly), move to Option B if spam becomes a problem. Keep Option C for "premium bounties" (50k+ sats).
Does this plan make sense for your use case? Any questions about implementation specifics? 🛹⚡