Fan → Frontend → Wallet (Freighter) → Soroban Contract → Stellar Network
↓
Backend → Database → Content Access
import { connectWallet, signTransaction } from '@/lib/wallet';
import { buildSubscriptionTx, submitTransaction } from '@/lib/stellar';
// Connect wallet
const address = await connectWallet();
// Subscribe to creator
const xdr = await buildSubscriptionTx(address, creatorAddress, planId, tokenAddress);
const signedXdr = await signTransaction(xdr);
const txHash = await submitTransaction(signedXdr);import { StellarService } from './common/stellar.service';
// Check if user has active subscription
const isActive = await stellarService.isSubscriber(fanAddress, creatorAddress);
// Gate content access
if (!isActive) {
throw new UnauthorizedException('Active subscription required');
}Listen to Soroban events for real-time updates:
// Subscribe to contract events
server.getEvents({
contractIds: [subscriptionContractId],
startLedger: lastProcessedLedger,
}).then(events => {
events.forEach(event => {
if (event.topic.includes('subscribed')) {
// Update database
// Send notification
}
});
});POST /api/subscriptions/checkout - Create checkout session
GET /api/subscriptions/checkout/:id - Get checkout details
POST /api/subscriptions/confirm - Confirm subscription
GET /api/subscriptions - List user subscriptions
GET /api/content/:id - Get content (gated)
POST /api/creators/plans - Create subscription plan
// Create plan
create_plan(creator, asset, amount, interval_days) -> plan_id
// Subscribe
subscribe(fan, plan_id, token)
// Check subscription
is_subscriber(fan, creator) -> bool
// Cancel
cancel(fan, creator)
// Extend
extend_subscription(fan, creator, extra_ledgers, token)- fan: Address
- plan_id: u32
- expiry: u64
- creator: Address
- asset: Address
- amount: i128
- interval_days: u32
- id: string
- fanAddress: string
- creatorAddress: string
- planId: number
- status: pending | completed | failed
- txHash?: string
All errors use standardized AppError format:
{
code: 'WALLET_NOT_FOUND' | 'TX_REJECTED' | 'INSUFFICIENT_BALANCE',
message: string,
description?: string,
severity: 'error' | 'warning' | 'info'
}cd contract
cargo testcd backend
npm run test
npm run test:e2ecd frontend
npm run testTrack key metrics:
- Subscription creations
- Failed transactions
- Active subscriptions
- Revenue by creator
- Platform fees collected
- All transactions require wallet signature
- Backend validates subscription status on-chain
- No private keys stored
- Rate limiting on API endpoints
- Input validation on all endpoints