A powerful payment-gated content proxy service built on Solana blockchain using the WS402 protocol. Monetize your digital content (images, videos, audio, PDFs) with per-second micropayments.
- Pay-Per-Second Access: Users pay only for the time they consume content
- Solana Blockchain: Fast, low-cost transactions on Solana
- Automatic Refunds: Unused funds are automatically refunded to users
- Content Protection: Hide original URLs behind masked endpoints
- Real-time Payments: WebSocket-based payment verification
- Creator Revenue: 95% revenue share for creators (5% service fee)
- Multiple Media Types: Support for images, videos, audio, and PDFs
- Analytics Dashboard: Track views, revenue, and engagement
- Embed Support: Easy integration with embed codes
Create payment-gated URLs and protect your content with per-second billing
Easily embed protected content into any website with our simple embed code
- Prerequisites
- Installation
- Configuration
- Running the Service
- API Documentation
- Usage Examples
- Architecture
- Environment Variables
- Troubleshooting
- Contributing
- License
- Node.js v16+ and npm
- Solana Wallet with some SOL (devnet or mainnet)
- Basic understanding of Solana and WebSockets
- Clone the repository:
git clone <your-repo-url>
cd ws402-proxy-service- Install dependencies:
npm install- Install required packages:
npm install express ws cors dotenv @solana/web3.js ws402Create a .env file in the root directory:
# Server Configuration
PORT=4021
NODE_ENV=development
# Solana Configuration
SOLANA_NETWORK=devnet
SOLANA_RPC_URL=https://api.devnet.solana.com
# Service Wallet (Merchant)
SERVICE_WALLET_PUBLIC_KEY=YourPublicKeyHere
SERVICE_WALLET_PRIVATE_KEY=YourPrivateKeyHere
# Pricing Configuration
MIN_PRICE_PER_SECOND=1000
SERVICE_FEE_PERCENTAGE=5
MAX_SESSION_DURATION=3600
# CORS
ALLOWED_ORIGINS=http://localhost:3000,https://yourdomain.comFor Devnet Testing:
# Generate new keypair
solana-keygen new --outfile ~/my-wallet.json
# Get public key
solana-keygen pubkey ~/my-wallet.json
# Get private key (as JSON array)
cat ~/my-wallet.json
# Fund with devnet SOL
solana airdrop 2 <YOUR_PUBLIC_KEY> --url devnetFor Production:
- Use your Phantom/Solflare wallet
- Export private key in base58 format
- Ensure wallet has sufficient SOL for transactions
The service accepts two private key formats:
JSON Array Format (recommended):
SERVICE_WALLET_PRIVATE_KEY=[1,2,3,4,5,...]Base58 Format (from Phantom/Solflare):
SERVICE_WALLET_PRIVATE_KEY=5J6fd...base58string...npm run devnpm startThe server will start on http://localhost:4021 (or your configured PORT).
Endpoint: POST /api/mask
Create a payment-gated resource.
Request Body:
{
"originalUrl": "https://example.com/image.jpg",
"pricePerSecond": 100000,
"estimatedDuration": 300,
"title": "My Premium Content",
"creatorWallet": "YourSolanaWalletAddress"
}Parameters:
originalUrl(required): Direct URL to media filepricePerSecond(required): Price in lamports (1 SOL = 1,000,000,000 lamports)estimatedDuration(optional): Estimated viewing time in seconds (default: 300)title(optional): Resource title (default: "Untitled Resource")creatorWallet(required): Creator's Solana wallet address
Response:
{
"success": true,
"maskedId": "abc123",
"accessUrl": "https://yourservice.com/watch/abc123",
"schemaUrl": "https://yourservice.com/api/resource/abc123/schema",
"embedCode": "<script src=\"...\"></script>",
"qrCode": "https://yourservice.com/api/qr/abc123",
"analytics": "https://yourservice.com/dashboard/abc123",
"resource": {
"id": "abc123",
"title": "My Premium Content",
"type": "image",
"pricePerSecond": 100000,
"priceSOL": "0.000100000 SOL",
"estimatedDuration": 300,
"totalEstimatedCost": 30000000,
"totalEstimatedCostSOL": "0.030000000 SOL"
}
}Endpoint: GET /api/resource/:maskedId/schema
Get payment schema for WS402 protocol.
Response:
{
"ws402Schema": {
"version": "1.0",
"serviceName": "WS402 Proxy Payment",
"pricePerSecond": 100000,
"currency": "lamports",
"estimatedDuration": 300,
"paymentProvider": "solana",
"websocketEndpoint": "wss://yourservice.com/ws402?resourceId=abc123&userId=",
"resourceInfo": {
"name": "My Premium Content",
"type": "image",
"estimatedTime": 300,
"priceSOL": "0.000100000 SOL",
"totalPriceSOL": "0.030000000 SOL"
}
}
}Endpoint: GET /proxy/:maskedId?token=xxx
Access the actual content (requires valid payment token).
Parameters:
maskedId: The masked resource IDtoken: Access token received after payment verification
Endpoint: GET /api/resources
List all masked resources.
Response:
{
"resources": [
{
"id": "abc123",
"title": "My Premium Content",
"type": "image",
"pricePerSecond": 100000,
"priceSOL": "0.000100000 SOL",
"estimatedDuration": 300,
"totalPrice": 30000000,
"totalPriceSOL": "0.030000000 SOL",
"views": 42,
"createdAt": 1699564800000
}
]
}Endpoint: GET /api/resource/:maskedId
Get public information about a specific resource.
Endpoint: GET /api/resource/:maskedId/analytics
Get detailed analytics for a resource.
Endpoint: GET /blockhash
Get latest Solana blockhash for client-side transactions.
Endpoint: GET /health
Check service health and status.
Response:
{
"status": "ok",
"activeSessions": 5,
"activeHTTPSessions": 3,
"maskedResources": 10,
"solanaProvider": {
"network": "devnet",
"rpcEndpoint": "https://api.devnet.solana.com",
"merchantWallet": "...",
"autoRefundEnabled": true
},
"timestamp": 1699564800000
}// Create masked resource
const response = await fetch('http://localhost:4021/api/mask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
originalUrl: 'https://example.com/premium-image.jpg',
pricePerSecond: 100000, // 0.0001 SOL per second
estimatedDuration: 60, // 1 minute
title: 'Premium Artwork',
creatorWallet: 'YourWalletAddress'
})
});
const data = await response.json();
console.log('Access URL:', data.accessUrl);
console.log('Total cost:', data.resource.totalEstimatedCostSOL);<!-- Add to your webpage -->
<script
src="https://yourservice.com/embed.js"
data-resource="abc123"
></script>Share the watch URL with users:
https://yourservice.com/watch/abc123
Users will:
- See a payment prompt
- Connect their Solana wallet
- Pay the estimated amount
- Get instant access to content
- Receive automatic refund for unused time
βββββββββββββββ
β Client β
β (Browser) β
ββββββββ¬βββββββ
β
β 1. Request Schema
ββββββββββββββββββββββββββββ
β β
β βββββββΌβββββββ
β β Server β
β β (Express) β
β βββββββ¬βββββββ
β β
β 2. Get WS402 Schema β
ββββββββββββββββββββββββββββ€
β β
β 3. Connect WebSocket β
ββββββββββββββββββββββββββββΊ
β β
β 4. Solana Payment β
ββββββββββββ β
β β β
βββββΌβββββ β ββββββΌββββββ
β Solana β β β WS402 β
β RPC β β β Protocol β
βββββ¬βββββ β ββββββ¬ββββββ
β β β
β 5. Verify Payment β
ββββββββββββΊββββββββββββββββΊ
β
6. Grant Access β
ββββββββββββββββββββββββββββ€
β β
β 7. Get HTTP Token β
ββββββββββββββββββββββββββββ€
β β
β 8. Access Content β
ββββββββββββββββββββββββββββΊ
β β
β 9. Stream Content β
ββββββββββββββββββββββββββββ€
β β
β 10. Session End β
ββββββββββββββββββββββββββββΊ
β β
β 11. Auto-Refund β
ββββββββββββββββββββββββββββ€
β β
- Content Protection: Original URLs are never exposed to clients
- Token-based Access: Temporary tokens for resource access
- Payment Verification: Blockchain-verified payments
- Session Tracking: Secure session management
- Automatic Cleanup: Expired sessions and payments are cleaned automatically
Price in Lamports (1 SOL = 1,000,000,000 lamports):
| Price per Second | SOL per Second | 1 Minute Cost | 5 Minutes Cost |
|---|---|---|---|
| 100,000 | 0.0001 SOL | 0.006 SOL | 0.03 SOL |
| 500,000 | 0.0005 SOL | 0.03 SOL | 0.15 SOL |
| 1,000,000 | 0.001 SOL | 0.06 SOL | 0.3 SOL |
| 10,000,000 | 0.01 SOL | 0.6 SOL | 3 SOL |
| Variable | Description | Default | Required |
|---|---|---|---|
PORT |
Server port | 4021 | No |
NODE_ENV |
Environment | development | No |
SOLANA_NETWORK |
devnet or mainnet-beta | devnet | Yes |
SOLANA_RPC_URL |
Solana RPC endpoint | https://api.devnet.solana.com | Yes |
SERVICE_WALLET_PUBLIC_KEY |
Merchant public key | Generated | No* |
SERVICE_WALLET_PRIVATE_KEY |
Merchant private key | None | No** |
MIN_PRICE_PER_SECOND |
Minimum price in lamports | 1000 | No |
SERVICE_FEE_PERCENTAGE |
Platform fee % | 5 | No |
MAX_SESSION_DURATION |
Max session time (seconds) | 3600 | No |
ALLOWED_ORIGINS |
CORS origins | * | No |
* If not provided, a temporary wallet is generated (not recommended for production)
** Required for automatic refunds and creator payments
Solution: Ensure your private key is in the correct format:
- JSON array:
[1,2,3,...](64 numbers) - Base58: Full string from wallet export
Solution:
- Check Solana network (devnet vs mainnet)
- Verify RPC endpoint is accessible
- Ensure wallet has sufficient SOL
- Check transaction explorer for details
Solution:
- Verify the masked ID is correct
- Check if resource was created successfully
- Review server logs for errors
Solution:
- Ensure
SERVICE_WALLET_PRIVATE_KEYis set - Verify private key format is correct
- Check wallet has SOL for transaction fees
- Get Devnet SOL:
solana airdrop 2 <YOUR_WALLET> --url devnet- Create Test Resource:
curl -X POST http://localhost:4021/api/mask \
-H "Content-Type: application/json" \
-d '{
"originalUrl": "https://picsum.photos/800/600",
"pricePerSecond": 100000,
"estimatedDuration": 60,
"title": "Test Image",
"creatorWallet": "YOUR_WALLET_ADDRESS"
}'- Access Resource:
Visit the returned
accessUrlin your browser.
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with WS402 Protocol
- Powered by Solana Blockchain
- Uses @solana/web3.js
- π Website: https://ws402.org
- π¦ NPM: https://npmjs.com/package/ws402
- π¬ X (Twitter): https://x.com/ws402org
- π Farcaster: https://farcaster.xyz/ws402
- π» GitHub: https://github.com/ws402/ws402
For issues and questions:
- Open an issue on GitHub
- Check WS402 documentation: https://ws402.org
- Follow updates on X: @ws402org
- Support for more payment providers
- Multi-currency support
- Advanced analytics dashboard
- NFT integration
- Mobile SDK
- Video streaming optimization
- Subscription models
- Rate limiting and DDoS protection
Made with β€οΈ using Solana and WS402
Last updated: November 2025

