@abhyudday/x402-media-sdk
v1.0.0
Published
SDK for integrating x402 micropayment protocol into media streaming platforms on Solana
Downloads
22
Maintainers
Readme
x402 Media SDK
A TypeScript SDK for integrating x402 micropayment protocol into media streaming platforms on Solana. Enable pay-per-view/pay-per-listen experiences with automatic micropayments.
🚀 Features
- Automatic Micropayments: Pay-per-segment streaming with automatic payment processing
- Dynamic Pricing: Support for time-based price multipliers
- Revenue Splitting: Automatic 70/30 split between creators and platform
- Framework Agnostic: Works with any JavaScript framework (React, Vue, Svelte, etc.)
- Wallet Compatible: Works with all Solana wallet adapters
- TypeScript First: Full type safety and IntelliSense support
📦 Installation
npm install @x402/media-sdk @solana/web3.js @solana/wallet-adapter-baseOr with yarn:
yarn add @x402/media-sdk @solana/web3.js @solana/wallet-adapter-base🎯 Quick Start
Basic Usage
import { Connection } from '@solana/web3.js';
import { createX402Agent, createDefaultPricingConfig } from '@x402/media-sdk';
// 1. Set up connection and wallet
const connection = new Connection('https://api.devnet.solana.com');
const wallet = yourWalletAdapter; // Any Solana wallet adapter
// 2. Create x402 agent
const agent = createX402Agent({
connection,
wallet,
platformWallet: 'YOUR_PLATFORM_WALLET_ADDRESS', // Optional
});
// 3. Define your media content
const content = {
id: 'video-123',
title: 'My Awesome Video',
duration: 600, // 10 minutes
creatorWallet: 'CREATOR_WALLET_ADDRESS',
pricing: createDefaultPricingConfig(0.01, 'SOL'), // 0.01 SOL per minute
};
// 4. Start streaming with automatic payments
await agent.startAgent(content, {
onPaymentSuccess: (segment, amount, signature) => {
console.log(`✅ Paid ${amount} SOL for segment ${segment}`);
},
onPaymentFailed: (segment, error) => {
console.error(`❌ Payment failed for segment ${segment}:`, error);
},
onInsufficientFunds: () => {
alert('Insufficient funds! Please top up your wallet.');
},
onStatusChange: (status) => {
console.log('Agent status:', status);
},
});
// 5. Stop when done
agent.stopAgent();🎨 React Example
import React, { useEffect, useRef, useState } from 'react';
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import { createX402Agent, X402PaymentAgent } from '@x402/media-sdk';
function VideoPlayer({ videoUrl, content }) {
const { connection } = useConnection();
const wallet = useWallet();
const agentRef = useRef<X402PaymentAgent | null>(null);
const [totalPaid, setTotalPaid] = useState(0);
const [isPlaying, setIsPlaying] = useState(false);
useEffect(() => {
if (!wallet.publicKey) return;
// Create agent
const agent = createX402Agent({
connection,
wallet,
platformWallet: process.env.NEXT_PUBLIC_PLATFORM_WALLET,
});
agentRef.current = agent;
// Start agent when video plays
const startPayments = async () => {
await agent.startAgent(content, {
onPaymentSuccess: (segment, amount) => {
setTotalPaid(prev => prev + amount);
},
onInsufficientFunds: () => {
alert('Insufficient funds!');
setIsPlaying(false);
},
});
};
if (isPlaying) {
startPayments();
}
return () => {
agent.stopAgent();
};
}, [wallet.publicKey, isPlaying]);
return (
<div>
<video
src={videoUrl}
controls
onPlay={() => setIsPlaying(true)}
onPause={() => setIsPlaying(false)}
/>
<p>Total paid: {totalPaid} SOL</p>
</div>
);
}🎵 Audio Streaming Example
import { createX402Agent } from '@x402/media-sdk';
// Set up for audio streaming
const audioContent = {
id: 'podcast-456',
title: 'Tech Talk Episode 1',
duration: 3600, // 60 minutes
creatorWallet: 'CREATOR_WALLET',
pricing: {
basePrice: 0.001, // 0.001 SOL per minute
currency: 'SOL',
multipliers: [], // No dynamic pricing
},
};
const agent = createX402Agent({ connection, wallet });
// Start streaming
await agent.startAgent(audioContent, {
onPaymentSuccess: (segment, amount) => {
console.log(`Listening to minute ${segment + 1}`);
},
});
// Audio element controls
const audio = document.getElementById('audio-player');
audio.addEventListener('ended', () => {
agent.stopAgent();
});💰 Dynamic Pricing
Add premium pricing for specific parts of your content:
import { createDefaultPricingConfig, addPriceMultiplier } from '@x402/media-sdk';
// Start with base price
let pricing = createDefaultPricingConfig(0.01, 'SOL');
// Add 2x pricing for climax scene (45:00 - 50:00)
pricing = addPriceMultiplier(
pricing,
2700, // 45 minutes in seconds
3000, // 50 minutes in seconds
2.0, // 2x multiplier
'Epic climax scene'
);
// Add 3x pricing for exclusive bonus content (58:00 - 60:00)
pricing = addPriceMultiplier(
pricing,
3480, // 58 minutes
3600, // 60 minutes
3.0,
'Exclusive bonus content'
);
const content = {
id: 'movie-789',
title: 'Blockbuster Movie',
duration: 3600,
creatorWallet: 'CREATOR_WALLET',
pricing,
};🎛️ Advanced Configuration
Custom Segment Duration
const agent = createX402Agent(
{ connection, wallet },
{
segmentDuration: 30, // 30 second segments
paymentInterval: 30000, // Payment every 30 seconds
}
);Custom Revenue Split
const agent = createX402Agent(
{ connection, wallet },
{
revenueSplit: {
creator: 0.8, // 80% to creator
platform: 0.2, // 20% to platform
},
}
);Continue on Payment Failure
const agent = createX402Agent(
{ connection, wallet },
{
continueOnFailure: true, // Keep playing even if payment fails
}
);📊 Monitoring & Status
// Get current status
const status = agent.getStatus();
console.log('Active:', status.isActive);
console.log('Current segment:', status.currentSegment);
console.log('Segments paid:', status.segmentsPaid);
console.log('Total paid:', status.totalPaid);
// Check if specific segment is paid
if (agent.isSegmentPaid(5)) {
console.log('Segment 5 is paid');
}
// Reset for new content
agent.reset();🛠️ Pricing Utilities
import {
calculateSegmentPrice,
calculateTotalPrice,
getSegmentNumber,
durationToSegments,
formatPrice,
isSegmentPremium,
} from '@x402/media-sdk';
// Calculate price for a specific segment
const price = calculateSegmentPrice(5, pricingConfig);
// Calculate total price for range
const totalPrice = calculateTotalPrice(0, 10, pricingConfig);
// Get segment from timestamp
const segment = getSegmentNumber(125); // Returns 2 (for 60s segments)
// Convert duration to segments
const segments = durationToSegments(3600); // Returns 60 (for 60min video)
// Format price for display
const formatted = formatPrice(0.05, 'SOL'); // Returns "0.0500 SOL"
// Check if segment has premium pricing
const { isPremium, multiplier } = isSegmentPremium(5, pricingConfig);🔐 Security Best Practices
- Never expose private keys: Always use wallet adapters
- Validate wallet addresses: Ensure creator and platform wallets are valid
- Test on devnet first: Always test thoroughly before mainnet
- Handle errors gracefully: Implement proper error handling
- Monitor transactions: Log all payment attempts and confirmations
🌐 Framework Examples
Vue.js
<template>
<video ref="videoEl" @play="startPayments" @pause="stopPayments">
<source :src="videoUrl" />
</video>
<p>Total Paid: {{ totalPaid }} SOL</p>
</template>
<script setup>
import { ref, onUnmounted } from 'vue';
import { createX402Agent } from '@x402/media-sdk';
const agent = createX402Agent({ connection, wallet });
const totalPaid = ref(0);
const startPayments = async () => {
await agent.startAgent(content, {
onPaymentSuccess: (seg, amt) => {
totalPaid.value += amt;
},
});
};
const stopPayments = () => agent.stopAgent();
onUnmounted(() => agent.stopAgent());
</script>Svelte
<script>
import { createX402Agent } from '@x402/media-sdk';
let totalPaid = 0;
const agent = createX402Agent({ connection, wallet });
async function handlePlay() {
await agent.startAgent(content, {
onPaymentSuccess: (seg, amt) => {
totalPaid += amt;
},
});
}
function handlePause() {
agent.stopAgent();
}
</script>
<video on:play={handlePlay} on:pause={handlePause}>
<source src={videoUrl} />
</video>
<p>Total Paid: {totalPaid} SOL</p>📚 API Reference
X402PaymentAgent
Main class for handling payments.
Methods
startAgent(content, callbacks)- Start automatic payment processingstopAgent()- Stop payment processinggetStatus()- Get current agent statusisSegmentPaid(segment)- Check if segment is paidreset()- Reset agent statepayForSegment(segment, content, callbacks)- Manually pay for a segment
Types
See types.ts for full type definitions.
🤝 Contributing
Contributions welcome! Please see CONTRIBUTING.md.
📄 License
MIT License - see LICENSE file.
🔗 Links
💡 Support
- GitHub Issues: Report a bug
- Discord: Join our community
- Twitter: @yourusername
Built with ❤️ for the Solana x402 ecosystem
