Stream402 - A complete platform for monetizing digital content using Solana payments via the HTTP 402 Payment Required protocol.
Stream402 enables content creators to monetize their digital assets (images, videos, audio, etc.) through micropayments on Solana. Built with Next.js, it features autonomous agent networks, reputation systems, IPFS storage, and a comprehensive SDK for easy integration.
- Image Upload & Monetization - Upload images with custom pricing and tags
- HTTP 402 Payment Challenge - Standardized payment protocol implementation
- Solana Wallet Integration - Connect Phantom, Solflare, or any Solana wallet
- SPL Token Payments - Pay with USDC on Solana DevNet/Mainnet
- On-Chain Verification - Payments verified directly on Solana blockchain
- Time-Limited Access - JWT tokens provide secure, temporary access
- IPFS Storage - Decentralized storage via Pinata for production-ready deployments
- Low-Resolution Previews - Free previews with full-resolution after payment
- Stream402 SDK - TypeScript SDK for easy integration into any application
- Autonomous Agent Network - AI agents that automatically discover, negotiate, and pay for content
- Reputation System - NFT-based reputation scores that track user activity
- Provider Dashboard - Track earnings, downloads, and asset performance
- Search & Tags - Find content by title or tags
- Supabase Database - Production-ready PostgreSQL database with automatic fallback
- Node.js 18+
- npm, yarn, or pnpm
- A Solana wallet (Phantom or Solflare)
- USDC on Solana DevNet (for testing)
- Supabase account (optional, for production)
- Pinata account (for IPFS storage)
- Clone and install:
git clone <repository-url>
cd img402
npm install- Set up environment variables:
Create a .env.local file:
# Solana Configuration
SOLANA_NETWORK=devnet
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_RECIPIENT=your_solana_wallet_address_here
SOLANA_USDC_MINT=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
# JWT Secret (change in production!)
JWT_SECRET=your-secret-key-change-in-production
# Next.js Public Variables
NEXT_PUBLIC_SOLANA_RPC_URL=https://api.devnet.solana.com
NEXT_PUBLIC_SOLANA_NETWORK=devnet
NEXT_PUBLIC_USDC_MINT=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
# IPFS (Pinata) Configuration
PINATA_JWT=your_pinata_jwt_token_here
# Supabase Configuration (Optional - falls back to local storage)
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
# Service Wallet for NFT Minting (Optional)
SERVICE_WALLET_PRIVATE_KEY=your_service_wallet_private_key_base58
# Metaplex API Key (Optional)
METAPLEX_API_KEY=your_metaplex_api_key- Set up Supabase (Optional):
Run the SQL schema in supabase-schema.sql in your Supabase SQL Editor. This sets up tables for assets, payments, reputation, and agent wallets.
- Run the development server:
npm run dev- Provider navigates to
/upload - Connects Solana wallet
- Uploads image with:
- Title
- Price (in USDC)
- Tags (comma-separated)
- Recipient wallet (optional, defaults to connected wallet)
- Image is:
- Uploaded to IPFS (Pinata)
- Thumbnail generated (low-resolution preview)
- Metadata saved to database
- Asset ID is generated and returned
- Client requests image:
GET /api/asset/:assetId - Server responds with 402:
{ "error": "Payment Required", "paymentChallenge": { "version": "1.0", "network": "solana:devnet", "currency": "USDC", "decimals": 6, "amount": 10000, "mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", "recipient": "...", "expiresAt": 1234567890, "assetId": "...", "paymentRequestToken": "..." } } - Client constructs payment:
- Creates SPL token transfer transaction
- Transfers USDC to recipient address
- Signs and sends transaction
- Client submits receipt:
POST /api/receipt- Sends transaction signature
- Server verifies payment on-chain
- Server returns JWT access token
- Reputation NFT may be minted (if criteria met)
- Client accesses image:
- Retries
GET /api/asset/:assetIdwithAuthorization: Bearer <token> - Server returns IPFS URL or download URL
- Client can download full image
- Retries
The server verifies payments by:
- Fetching transaction from Solana blockchain
- Checking transaction status (confirmed, no errors)
- Verifying token transfer amount
- Confirming recipient address matches
- Validating transfer amount meets requirement
- Checking challenge expiration (if provided)
Stream402 features an autonomous agent system that can automatically discover, evaluate, and purchase content without manual intervention.
-
Agent Creation:
- Users create dedicated agent wallets
- Each agent has its own Solana keypair
- Private keys are encrypted with a password
- Agents can be funded with USDC
-
Natural Language Queries:
- Users input queries like "I want a Solana logo" or "Bitcoin image"
- Agent parses the query and searches available assets
- Uses keyword matching and tag-based search
-
Autonomous Decision Making:
- Agent evaluates:
- Query relevance to asset
- Asset price vs. agent balance
- Agent reputation score
- Payment history
- Makes autonomous decision to pay or skip
- Agent evaluates:
-
Automatic Payment:
- If approved, agent automatically:
- Constructs payment transaction
- Signs with agent's private key (server-side, no popups!)
- Submits payment
- Downloads asset
- All happens without user interaction
- If approved, agent automatically:
User Query β Parse Query β Find Asset β Evaluate Decision β Auto-Pay β Download
-
Create Agent:
- Go to
/agent/manage - Click "Create Agent"
- Enter password (used to encrypt agent wallet)
- Agent wallet is created and stored
- Go to
-
Fund Agent:
- Transfer USDC to agent wallet
- Agent balance is tracked automatically
-
Use Agent:
- Go to
/agent - Select your agent
- Enter agent password
- Enter query (e.g., "I want a Solana logo")
- Agent automatically finds, pays, and downloads
- Go to
- No Popups - Server-side signing means no wallet popups
- Password Protection - Agent wallets encrypted with user password
- Remember Password - Optional password persistence for convenience
- Balance Tracking - Real-time balance and spending statistics
- Autonomous Mode - Toggle for automatic payment decisions
Stream402 includes a comprehensive reputation system that tracks user activity and mints NFTs for milestones.
Reputation Score Calculation:
- Each payment: +10 points
- Each download: +5 points
- Earnings: +1 point per 0.001 USDC earned
Reputation Levels:
- Newcomer (0-9 points)
- Beginner (10-49 points)
- Intermediate (50-99 points)
- Advanced (100-249 points)
- Expert (250-499 points)
- Master (500-999 points)
- Legendary (1000+ points)
Reputation NFTs are automatically minted when:
- First Payment - Always mints on first payment
- Score Increase - Every payment increases score (triggers mint)
- Level Change - When reputation level increases
NFT Features:
- Programmable NFTs (pNFTs) on Solana
- SVG images generated dynamically
- Metadata includes:
- Reputation score
- Level
- Total payments
- Total downloads
- Total earnings
- Stored on Arweave via Irys
- Viewable on Solana Explorer
- Navbar Badge - Shows current reputation level
- Provider Dashboard - Detailed reputation stats
- NFT Gallery - View all minted reputation NFTs
The Stream402 SDK makes it easy to integrate payment functionality into any application.
npm install stream402-sdkimport { discover } from "stream402-sdk";
const result = await discover("https://example.com/api/asset/123");
if (result.type === "free") {
console.log("Free asset:", result.url);
} else {
console.log("Payment required:", result.challenge.amount);
}import { payAndFetch } from "stream402-sdk";
import { useWallet } from "@solana/wallet-adapter-react";
function MyComponent() {
const wallet = useWallet();
const handlePay = async () => {
const result = await payAndFetch(
"https://example.com/api/asset/123",
wallet
);
// Access the resource
window.open(result.downloadUrl, "_blank");
};
return <button onClick={handlePay}>Pay & Download</button>;
}import { uploadAsset } from "stream402-sdk";
const result = await uploadAsset(file, {
title: "My Image",
price: 0.01,
tags: ["nature", "landscape"],
}, wallet);
console.log("Asset ID:", result.assetId);See SDK README for complete API documentation.
Stream402 uses Supabase (PostgreSQL) for production-ready data storage:
- Assets - Image metadata, pricing, IPFS URLs
- Payments - Transaction records and verification
- Reputation - User reputation scores and levels
- Reputation NFTs - Minted NFT records
- Agent Wallets - Encrypted agent keypairs
If Supabase is not configured, the app automatically falls back to local JSON file storage for development.
All images are uploaded to IPFS via Pinata:
- Original images stored on IPFS
- Thumbnails generated and stored on IPFS
- IPFS URLs used for serving images
- Local storage only used as fallback
Content creators can track their performance at /provider:
- Total Earnings - Sum of all payments received
- Total Downloads - Number of times assets were purchased
- Asset Statistics - Per-asset performance metrics
- Reputation Display - Current reputation level and score
- NFT Gallery - View all minted reputation NFTs
- Search by Title - Find assets by name
- Search by Tags - Filter by tags
- Tag System - Add tags when uploading for better discoverability
- Real-time Results - Instant search results
img402/
βββ app/
β βββ api/
β β βββ upload/ # POST - Upload images
β β βββ asset/[id]/ # GET - Asset access (returns 402 if not paid)
β β βββ receipt/ # POST - Verify payment and get access token
β β βββ full/[id]/ # GET - Download full image (requires auth)
β β βββ thumb/[id]/ # GET - Get thumbnail
β β βββ images/
β β β βββ list/ # GET - List all images
β β β βββ search/ # GET - Search images
β β βββ provider/
β β β βββ assets/ # GET - Provider's assets
β β β βββ earnings/ # GET - Provider's earnings
β β β βββ stats/ # GET - Provider's statistics
β β βββ reputation/
β β β βββ [wallet]/ # GET - Get reputation for wallet
β β β βββ mint-nft/ # POST - Manually mint reputation NFT
β β βββ agent/
β β βββ request/ # POST - Agent query handler
β β βββ create/ # POST - Create agent wallet
β β βββ list/ # GET - List user's agents
β β βββ fund/ # POST - Verify agent funding
β β βββ pay/ # POST - Server-side agent payment
β βββ images/ # Image gallery with payment flow
β βββ upload/ # Image upload page
β βββ provider/ # Provider dashboard
β βββ agent/ # Agent network interface
β βββ agent/manage/ # Agent wallet management
β βββ page.tsx # Home page
βββ components/
β βββ navbar.tsx # Global navigation
β βββ reputation-badge.tsx # Reputation display component
β βββ solana/
β βββ solana-provider.tsx # Solana wallet provider
βββ lib/
β βββ solana-config.ts # Solana configuration
β βββ jwt.ts # JWT utilities
β βββ payment-verification.ts # Payment verification logic
β βββ payment-challenge.ts # 402 challenge formatting
β βββ storage.ts # Asset and payment storage
β βββ storage-db.ts # Supabase database layer
β βββ ipfs.ts # IPFS (Pinata) integration
β βββ thumbnail.ts # Thumbnail generation
β βββ reputation.ts # Reputation calculation
β βββ reputation-storage.ts # Reputation data management
β βββ nft-mint.ts # NFT minting (Metaplex)
β βββ agent.ts # Agent search and matching
β βββ agent-autonomous.ts # Autonomous decision logic
β βββ agent-wallet.ts # Agent wallet encryption
β βββ agent-wallet-storage.ts # Agent wallet persistence
β βββ supabase.ts # Supabase client
βββ sdk/ # Stream402 SDK package
β βββ src/
β β βββ discover.ts # Asset discovery
β β βββ payAndFetch.ts # Payment flow
β β βββ uploadAsset.ts # Asset upload
β β βββ types/ # TypeScript types
β βββ examples/ # SDK usage examples
β βββ test/ # SDK tests
βββ supabase-schema.sql # Database schema
Upload an image.
Request:
file: Image file (multipart/form-data)title: Image titleprice: Price in USDC (e.g., "0.01")tags: Comma-separated tagsrecipient: Recipient wallet address (optional)
Response:
{
"assetId": "uuid",
"url": "/api/asset/uuid",
"title": "Image Title",
"price": 0.01,
"ipfsCid": "...",
"ipfsUrl": "https://..."
}Get asset access (returns 402 if not paid).
Response (402):
{
"error": "Payment Required",
"paymentChallenge": { ... },
"paymentRequestToken": "..."
}Response (200 with auth):
{
"url": "/api/full/:id"
}Verify payment and get access token.
Request:
{
"signature": "transaction_signature",
"paymentRequestToken": "...",
"imageId": "asset_id"
}Response:
{
"accessToken": "jwt_token"
}Handle agent query and return payment challenge.
Request:
{
"query": "I want a Solana logo",
"walletAddress": "agent_wallet_address"
}Response:
{
"success": true,
"assetId": "...",
"requiresPayment": true,
"paymentChallenge": { ... }
}Create a new agent wallet.
Request:
{
"userId": "user_wallet_address",
"password": "agent_password"
}Server-side agent payment (no popups).
Request:
{
"agentId": "agent_id",
"password": "agent_password",
"assetId": "...",
"paymentChallenge": { ... },
"paymentRequestToken": "..."
}Get reputation data for a wallet.
Response:
{
"wallet": "...",
"score": 150,
"level": "Advanced",
"totalPayments": 10,
"totalDownloads": 10,
"totalEarnings": 100000,
"nfts": [...]
}-
Upload an image:
- Go to
/upload - Connect wallet
- Upload image with price 0.01 USDC
- Go to
-
Access the image:
- Go to
/images - Click on an image
- Connect wallet if not connected
- Click "Pay"
- Approve transaction in wallet
- Image will open in new tab
- Go to
-
Test Agent:
- Go to
/agent/manage - Create an agent
- Fund the agent
- Go to
/agent - Enter query and watch automatic payment
- Go to
-
Check Reputation:
- Make a payment
- Check navbar for reputation badge
- Go to
/providerto see detailed stats
cd sdk
npm test
npm run test:integration-
Set Environment Variables:
- Add all
.env.localvariables to Vercel - Ensure
PINATA_JWTis set for IPFS - Set
SUPABASE_*variables for database
- Add all
-
Deploy:
vercel
-
Database Migration:
- Run
supabase-schema.sqlin Supabase SQL Editor - Ensure
filenamecolumn is nullable
- Run
- Change
SOLANA_NETWORKtomainnet-beta - Update
SOLANA_RPC_URLto mainnet RPC - Update
SOLANA_USDC_MINTto mainnet USDC mint - Use secure
JWT_SECRET - Configure Supabase for production
- Set up Pinata for IPFS
- Configure service wallet for NFT minting
- Add proper error handling and logging
- Implement rate limiting
- Set up monitoring
- Ensure transaction is confirmed on Solana
- Check that correct amount was transferred
- Verify recipient address matches
- Check transaction signature is correct
- Ensure Phantom or Solflare is installed
- Check browser console for errors
- Try disconnecting and reconnecting wallet
- Verify
PINATA_JWTis set correctly - Check Pinata account has available storage
- Review server logs for detailed errors
- Ensure Supabase is configured correctly
- Run
supabase-schema.sqlmigration - Check that
filenamecolumn is nullable - Verify RLS policies are set correctly
- Verify agent has sufficient balance
- Check agent password is correct
- Ensure agent wallet is funded
- Review server logs for decryption errors
next- Next.js framework@solana/web3.js- Solana blockchain interaction@solana/wallet-adapter-*- Wallet integration@solana/spl-token- SPL token operationsjsonwebtoken- JWT token generation
@supabase/supabase-js- Supabase clientpinata- IPFS storage via Pinatasharp- Image processing and thumbnails
@metaplex-foundation/umi- Metaplex UMI framework@metaplex-foundation/mpl-token-metadata- Token metadata program@metaplex-foundation/umi-uploader-irys- Arweave uploads
fs-extra- File system operationsuuid- UUID generationbs58- Base58 encoding/decoding
MIT License
Contributions welcome! Please open an issue or submit a PR.
For issues and questions, please open an issue on GitHub.