Skip to content

$swarms Token Subscription Payment System

Overview

This documentation covers the implementation of subscription-based payments using $swarms tokens on the Solana blockchain.

System Architecture

flowchart TB
    subgraph Frontend
        UI[User Interface]
        PM[Payment Manager]
    end

    subgraph Backend
        SM[Subscription Manager]
        DB[(Database)]
        Queue[Job Queue]
    end

    subgraph Blockchain
        SC[Smart Contract]
        Token[$swarms Token]
    end

    UI -->|Subscribe| PM
    PM -->|Create Subscription| SM
    SM -->|Store| DB
    SM -->|Schedule| Queue
    Queue -->|Execute Payment| SC
    SC -->|Transfer| Token

Core Components

1. Subscription Smart Contract

import { Program, web3 } from '@project-serum/anchor';
import { PublicKey, SystemProgram } from '@solana/web3.js';

interface SubscriptionAccount {
    subscriber: PublicKey;
    merchant: PublicKey;
    amount: number;
    interval: number;
    nextPaymentDate: number;
    active: boolean;
}

class SubscriptionContract {
    program: Program;

    constructor(program: Program) {
        this.program = program;
    }

    async createSubscription(
        subscriber: PublicKey,
        merchant: PublicKey,
        amount: number,
        interval: number
    ): Promise<string> {
        const subscription = web3.Keypair.generate();
        const currentTimestamp = Math.floor(Date.now() / 1000);

        await this.program.rpc.createSubscription(
            new BN(amount),
            new BN(interval),
            new BN(currentTimestamp + interval),
            {
                accounts: {
                    subscription: subscription.publicKey,
                    subscriber,
                    merchant,
                    systemProgram: SystemProgram.programId,
                },
                signers: [subscription],
            }
        );

        return subscription.publicKey.toString();
    }

    async processPayment(subscriptionAddress: string): Promise<string> {
        const subscription = await this.program.account.subscription.fetch(
            new PublicKey(subscriptionAddress)
        );

        // Transfer tokens
        const signature = await this.transferTokens(
            subscription.subscriber,
            subscription.merchant,
            subscription.amount
        );

        // Update next payment date
        await this.updateNextPaymentDate(
            subscriptionAddress,
            subscription.nextPaymentDate + subscription.interval
        );

        return signature;
    }
}

2. Subscription Manager Service

class SubscriptionManager {
    private contract: SubscriptionContract;
    private db: Database;
    private queue: Queue;

    constructor(
        contract: SubscriptionContract,
        db: Database,
        queue: Queue
    ) {
        this.contract = contract;
        this.db = db;
        this.queue = queue;
    }

    async createSubscription(
        subscriberAddress: string,
        merchantAddress: string,
        amount: number,
        interval: number,
        planDetails: SubscriptionPlan
    ): Promise<SubscriptionResponse> {
        // Create blockchain subscription
        const subscriptionAddress = await this.contract.createSubscription(
            new PublicKey(subscriberAddress),
            new PublicKey(merchantAddress),
            amount,
            interval
        );

        // Store subscription details
        const subscription = await this.db.subscriptions.create({
            address: subscriptionAddress,
            subscriber: subscriberAddress,
            merchant: merchantAddress,
            amount,
            interval,
            planDetails,
            status: 'active',
            createdAt: new Date()
        });

        // Schedule first payment
        await this.scheduleNextPayment(subscription);

        return {
            subscriptionId: subscription.id,
            address: subscriptionAddress,
            status: 'active'
        };
    }

    async cancelSubscription(
        subscriptionId: string,
        reason?: string
    ): Promise<void> {
        // Update blockchain state
        await this.contract.deactivateSubscription(subscriptionId);

        // Update database
        await this.db.subscriptions.update({
            where: { id: subscriptionId },
            data: {
                status: 'cancelled',
                cancelledAt: new Date(),
                cancelReason: reason
            }
        });

        // Remove scheduled payments
        await this.queue.removeScheduledJobs(subscriptionId);
    }
}

3. Payment Processing System

class PaymentProcessor {
    private connection: Connection;
    private subscriptionManager: SubscriptionManager;

    async processSubscriptionPayment(
        subscriptionId: string
    ): Promise<PaymentResult> {
        const subscription = await this.subscriptionManager.get(subscriptionId);

        try {
            // Create and send transaction
            const signature = await this.createAndExecutePayment(subscription);

            // Update payment history
            await this.recordPayment({
                subscriptionId,
                amount: subscription.amount,
                signature,
                status: 'success'
            });

            // Schedule next payment
            await this.subscriptionManager.scheduleNextPayment(subscription);

            return { success: true, signature };

        } catch (error) {
            await this.handlePaymentFailure(subscription, error);
            return { success: false, error };
        }
    }

    private async createAndExecutePayment(
        subscription: Subscription
    ): Promise<string> {
        const transaction = await this.buildPaymentTransaction(subscription);
        return await this.sendAndConfirmTransaction(transaction);
    }
}

Subscription Plans and Pricing

classDiagram
    class SubscriptionPlan {
        +string id
        +string name
        +number amount
        +number interval
        +Feature[] features
        +boolean isActive
        +create(PlanData) Plan
        +update(string, PlanData) Plan
        +delete(string) void
    }

    class Feature {
        +string id
        +string name
        +string description
        +boolean isEnabled
    }

    class PricingTier {
        +string id
        +string name
        +number amount
        +Discount[] discounts
    }

    class Discount {
        +string id
        +number percentage
        +number duration
    }

    SubscriptionPlan "1" -- "*" Feature
    SubscriptionPlan "1" -- "1" PricingTier
    PricingTier "1" -- "*" Discount

Implementation Example

interface SubscriptionPlan {
    id: string;
    name: string;
    amount: number;
    interval: number;
    features: Feature[];
    isActive: boolean;
}

class PlanManager {
    async createPlan(planData: CreatePlanDTO): Promise<SubscriptionPlan> {
        // Validate plan data
        this.validatePlanData(planData);

        // Create plan in database
        const plan = await this.db.plans.create({
            data: {
                ...planData,
                isActive: true,
                createdAt: new Date()
            }
        });

        // Create on-chain representation
        await this.contract.registerPlan(plan.id, plan.amount, plan.interval);

        return plan;
    }

    async updatePlan(
        planId: string,
        updates: UpdatePlanDTO
    ): Promise<SubscriptionPlan> {
        // Validate updates
        this.validatePlanUpdates(updates);

        // Update in database
        const updatedPlan = await this.db.plans.update({
            where: { id: planId },
            data: updates
        });

        // Update on-chain if necessary
        if (updates.amount || updates.interval) {
            await this.contract.updatePlan(
                planId,
                updates.amount,
                updates.interval
            );
        }

        return updatedPlan;
    }
}

Payment Flow

sequenceDiagram
    participant User
    participant UI
    participant Backend
    participant Blockchain
    participant Wallet

    User->>UI: Select Subscription Plan
    UI->>Backend: Create Subscription Request
    Backend->>Blockchain: Deploy Subscription Contract
    Blockchain-->>Backend: Contract Address
    Backend->>UI: Subscription Details
    UI->>Wallet: Request Approval
    Wallet->>User: Confirm Transaction
    User->>Wallet: Approve
    Wallet->>Blockchain: Submit Transaction
    Blockchain-->>Backend: Confirmation
    Backend->>UI: Success Response
    UI->>User: Show Confirmation

Error Handling and Recovery

class SubscriptionErrorHandler {
    async handlePaymentFailure(
        subscription: Subscription,
        error: Error
    ): Promise<void> {
        // Log error
        await this.logError({
            subscriptionId: subscription.id,
            error,
            timestamp: new Date()
        });

        // Determine retry strategy
        const retryStrategy = this.determineRetryStrategy(
            subscription,
            error
        );

        if (retryStrategy.shouldRetry) {
            await this.scheduleRetry(
                subscription,
                retryStrategy.retryAfter
            );
        } else {
            await this.handleSubscriptionFailure(subscription);
        }

        // Notify relevant parties
        await this.sendNotifications(subscription, error);
    }

    private async handleSubscriptionFailure(
        subscription: Subscription
    ): Promise<void> {
        // Update subscription status
        await this.subscriptionManager.updateStatus(
            subscription.id,
            'failed'
        );

        // Notify merchant
        await this.notifyMerchant(subscription);

        // Create recovery task
        await this.createRecoveryTask(subscription);
    }
}

Analytics and Reporting

class SubscriptionAnalytics {
    async generateMetrics(
        timeframe: TimeFrame
    ): Promise<SubscriptionMetrics> {
        const metrics = {
            activeSubscriptions: await this.countActiveSubscriptions(),
            recurringRevenue: await this.calculateMRR(),
            churnRate: await this.calculateChurnRate(timeframe),
            lifetimeValue: await this.calculateLTV(),
            conversionRate: await this.calculateConversionRate()
        };

        return metrics;
    }

    async generateReport(
        options: ReportOptions
    ): Promise<SubscriptionReport> {
        const report = {
            metrics: await this.generateMetrics(options.timeframe),
            subscriptionsByPlan: await this.aggregateByPlan(),
            revenueProjection: await this.projectRevenue(options.months),
            churnAnalysis: await this.analyzeChurn()
        };

        return report;
    }
}

Security Measures

class SubscriptionSecurity {
    validateSubscription(subscription: Subscription): boolean {
        return this.validateSignature(subscription.signature) &&
               this.validatePermissions(subscription.subscriber) &&
               this.validateLimits(subscription.amount);
    }

    async monitorTransactions(): Promise<void> {
        // Monitor for suspicious activity
        const transactions = await this.getRecentTransactions();

        for (const tx of transactions) {
            if (this.isAnomalous(tx)) {
                await this.flagTransaction(tx);
                await this.notifyAdmin(tx);
            }
        }
    }
}

Testing Framework

describe('Subscription System', () => {
    let subscriptionManager: SubscriptionManager;
    let paymentProcessor: PaymentProcessor;

    beforeEach(async () => {
        // Setup test environment
        subscriptionManager = new SubscriptionManager(
            mockContract,
            mockDb,
            mockQueue
        );

        paymentProcessor = new PaymentProcessor(
            mockConnection,
            subscriptionManager
        );
    });

    describe('Subscription Creation', () => {
        it('should create a new subscription', async () => {
            const subscription = await subscriptionManager.createSubscription(
                testData.subscriber,
                testData.merchant,
                testData.amount,
                testData.interval,
                testData.plan
            );

            expect(subscription).to.have.property('id');
            expect(subscription.status).to.equal('active');
        });
    });

    describe('Payment Processing', () => {
        it('should process recurring payments', async () => {
            const result = await paymentProcessor.processSubscriptionPayment(
                testData.subscriptionId
            );

            expect(result.success).to.be.true;
            expect(result).to.have.property('signature');
        });
    });
});

Migration and Upgrades

class SubscriptionMigrationManager {
    async migrateSubscriptions(
        fromVersion: string,
        toVersion: string
    ): Promise<MigrationResult> {
        const subscriptions = await this.getSubscriptionsForMigration(
            fromVersion
        );

        const results = await Promise.allSettled(
            subscriptions.map(sub => this.migrateSubscription(sub, toVersion))
        );

        return this.generateMigrationReport(results);
    }

    private async migrateSubscription(
        subscription: Subscription,
        newVersion: string
    ): Promise<void> {
        // Create new subscription with updated structure
        const newSubscription = await this.createNewVersionSubscription(
            subscription,
            newVersion
        );

        // Migrate payment history
        await this.migratePaymentHistory(
            subscription.id,
            newSubscription.id
        );

        // Update references
        await this.updateSubscriptionReferences(
            subscription.id,
            newSubscription.id
        );

        // Archive old subscription
        await this.archiveSubscription(subscription.id);
    }
}

Compliance and Audit

class SubscriptionAuditor {
    async auditSubscription(
        subscriptionId: string
    ): Promise<AuditReport> {
        const subscription = await this.getSubscription(subscriptionId);
        const payments = await this.getPaymentHistory(subscriptionId);

        return {
            subscription: this.validateSubscriptionData(subscription),
            payments: this.validatePayments(payments),
            compliance: await this.checkCompliance(subscription),
            recommendations: this.generateRecommendations(subscription)
        };
    }

    async generateComplianceReport(): Promise<ComplianceReport> {
        return {
            totalSubscriptions: await this.countSubscriptions(),
            activeSubscriptions: await this.countActiveSubscriptions(),
            riskAssessment: await this.assessRisk(),
            complianceStatus: await this.checkComplianceStatus(),
            regulatoryRequirements: await this.checkRegulatory()
        };
    }
}

Performance Optimization

class SubscriptionOptimizer {
    async optimizePerformance(): Promise<OptimizationResult> {
        const metrics = await this.gatherPerformanceMetrics();
        const bottlenecks = this.identifyBottlenecks(metrics);

        // Optimize database queries
        await this.optimizeDatabaseQueries();

        // Optimize blockchain interactions
        await this.optimizeBlockchainCalls();

        // Cache frequently accessed data
        await this.setupCaching();

        return {
            beforeMetrics: metrics,
            afterMetrics: await this.gatherPerformanceMetrics(),
            improvements: this.calculateImprovements(),
            recommendations: this.generateOptimizationRecommendations()
        };
    }

    private async optimizeDatabaseQueries(): Promise<void> {
        await this.createIndexes();
        await this.optimizeJoins();
        await this.implementQueryCaching();
    }

    private async optimizeBlockchainCalls(): Promise<void> {
        await this.implementBatchProcessing();
        await this.setupWebSocketConnections();
        await this.cacheBlockchainState();
    }
}

Webhook Integration

class SubscriptionWebhooks {
    private endpoints: Map<string, WebhookEndpoint>;

    async registerWebhook(
        event: WebhookEvent,
        endpoint: string,
        secret: string
    ): Promise<string> {
        const webhookId = generateUniqueId();

        await this.db.webhooks.create({
            id: webhookId,
            event,
            endpoint,
            secret,
            status: 'active'
        });

        return webhookId;
    }

    async triggerWebhook(
        event: WebhookEvent,
        data: any
    ): Promise<void> {
        const webhooks = await this.getWebhooksForEvent(event);

        for (const webhook of webhooks) {
            try {
                const payload = this.createWebhookPayload(event, data);
                const signature = this.signPayload(payload, webhook.secret);

                await this.sendWebhookRequest(
                    webhook.endpoint,
                    payload,
                    signature
                );

            } catch (error) {
                await this.handleWebhookError(webhook, error);
            }
        }
    }
}

Notification System

flowchart TB
    subgraph NotificationSystem
        E[Event Handler]
        T[Template Engine]
        Q[Queue Manager]
        D[Delivery Service]
    end

    subgraph Channels
        Email[Email Service]
        SMS[SMS Service]
        Push[Push Notifications]
        Web[Web Hooks]
    end

    E -->|Event| T
    T -->|Formatted| Q
    Q -->|Queued| D
    D -->|Send| Email
    D -->|Send| SMS
    D -->|Send| Push
    D -->|Send| Web
class SubscriptionNotifier {
    async notify(
        event: SubscriptionEvent,
        subscription: Subscription
    ): Promise<void> {
        const template = await this.getNotificationTemplate(event);
        const recipients = await this.getRecipients(subscription);

        const notifications = recipients.map(recipient =>
            this.createNotification(template, recipient, subscription)
        );

        await this.queueNotifications(notifications);
    }

    private async createNotification(
        template: Template,
        recipient: Recipient,
        subscription: Subscription
    ): Promise<Notification> {
        return {
            recipient,
            content: this.renderTemplate(template, {
                subscription,
                recipient
            }),
            channel: recipient.preferredChannel,
            priority: this.determinePriority(template.event)
        };
    }
}

Usage Analytics Dashboard

interface SubscriptionAnalytics {
    totalRevenue: number;
    activeSubscriptions: number;
    churnRate: number;
    averageLifetime: number;
    topPlans: PlanAnalytics[];
}

class AnalyticsDashboard {
    async generateDashboardData(
        timeframe: TimeFrame
    ): Promise<DashboardData> {
        return {
            overview: await this.generateOverview(timeframe),
            trends: await this.analyzeTrends(timeframe),
            forecasts: await this.generateForecasts(),
            recommendations: await this.generateRecommendations()
        };
    }

    private async generateOverview(
        timeframe: TimeFrame
    ): Promise<Overview> {
        return {
            totalRevenue: await this.calculateRevenue(timeframe),
            activeSubscriptions: await this.countActiveSubscriptions(),
            growthRate: await this.calculateGrowthRate(timeframe),
            churnMetrics: await this.analyzeChurn(timeframe)
        };
    }
}

Rate Limiting and Throttling

class RateLimiter {
    private readonly redis: Redis;
    private readonly limits: Map<string, RateLimit>;

    async checkLimit(
        key: string,
        operation: string
    ): Promise<boolean> {
        const limit = this.limits.get(operation);
        if (!limit) return true;

        const current = await this.redis.incr(key);
        if (current === 1) {
            await this.redis.expire(key, limit.windowSeconds);
        }

        return current <= limit.maxRequests;
    }

    async handleRateLimit(
        subscription: Subscription,
        operation: string
    ): Promise<void> {
        const key = `${subscription.id}:${operation}`;

        if (!await this.checkLimit(key, operation)) {
            throw new RateLimitError(
                `Rate limit exceeded for ${operation}`
            );
        }
    }
}

Disaster Recovery

class DisasterRecovery {
    async backupData(): Promise<BackupResult> {
        const backup = {
            subscriptions: await this.backupSubscriptions(),
            payments: await this.backupPayments(),
            metadata: await this.backupMetadata()
        };

        await this.storeBackup(backup);
        return backup;
    }

    async restore(
        backupId: string,
        options: RestoreOptions
    ): Promise<RestoreResult> {
        const backup = await this.loadBackup(backupId);

        // Validate backup integrity
        this.validateBackup(backup);

        // Perform restoration
        const result = await this.performRestore(backup, options);

        // Verify restoration
        await this.verifyRestoration(result);

        return result;
    }
}

Subscription Lifecycle Events

stateDiagram-v2
    [*] --> Created
    Created --> Active: Payment Successful
    Active --> Suspended: Payment Failed
    Active --> Cancelled: User Cancellation
    Active --> Expired: Term Ended
    Suspended --> Active: Payment Resumed
    Suspended --> Cancelled: Grace Period Ended
    Cancelled --> [*]
    Expired --> [*]

Future Enhancements

  1. Smart Contract Upgrades

    class ContractUpgrader {
        async upgradeContract(
            newVersion: string
        ): Promise<UpgradeResult> {
            // Validate new version
            await this.validateNewVersion(newVersion);
    
            // Deploy new contract
            const newContract = await this.deployNewVersion(newVersion);
    
            // Migrate state
            await this.migrateState(newContract);
    
            // Switch over
            await this.switchToNewContract(newContract);
    
            return {
                newContractAddress: newContract.address,
                migrationStatus: 'success'
            };
        }
    }
    

  2. Multi-Token Support

    interface TokenConfig {
        address: string;
        decimals: number;
        symbol: string;
    }
    
    class MultiTokenSubscription {
        private supportedTokens: Map<string, TokenConfig>;
    
        async addToken(
            config: TokenConfig
        ): Promise<void> {
            await this.validateToken(config);
            this.supportedTokens.set(config.symbol, config);
        }
    
        async createMultiTokenSubscription(
            subscriber: string,
            token: string,
            amount: number
        ): Promise<string> {
            const config = this.supportedTokens.get(token);
            if (!config) throw new Error('Unsupported token');
    
            return await this.createSubscription(
                subscriber,
                config,
                amount
            );
        }
    }
    

API Documentation

REST Endpoints

interface SubscriptionAPI {
    // Subscription Management
    'POST /subscriptions': {
        body: CreateSubscriptionDTO;
        response: SubscriptionResponse;
    };

    'GET /subscriptions/:id': {
        params: { id: string };
        response: SubscriptionDetails;
    };

    'PATCH /subscriptions/:id': {
        params: { id: string };
        body: UpdateSubscriptionDTO;
        response: SubscriptionResponse;
    };

    'DELETE /subscriptions/:id': {
        params: { id: string };
        response: void;
    };

    // Payment Management
    'GET /subscriptions/:id/payments': {
        params: { id: string };
        query: PaymentQueryParams;
        response: PaymentHistory;
    };

    // Analytics
    'GET /subscriptions/analytics': {
        query: AnalyticsParams;
        response: AnalyticsResponse;
    };
}

Complete Implementation Checklist

  1. Core Infrastructure
  2. Smart Contract Development
  3. Database Schema Design
  4. API Layer Implementation
  5. Payment Processing System

  6. Security Measures

  7. Authentication System
  8. Authorization Rules
  9. Rate Limiting
  10. Input Validation

  11. Integration Features

  12. Webhook System
  13. Notification Service
  14. Analytics Dashboard
  15. Reporting System

  16. Maintenance Tools

  17. Monitoring System
  18. Backup Solution
  19. Migration Tools
  20. Testing Framework

Deployment Guide

flowchart TB
    subgraph Preparation
        Config[Configuration]
        Deps[Dependencies]
        Env[Environment Setup]
    end

    subgraph Deployment
        Contract[Deploy Contract]
        Backend[Deploy Backend]
        Frontend[Deploy Frontend]
    end

    subgraph Verification
        Test[Testing]
        Monitor[Monitoring]
        Backup[Backup]
    end

    Preparation --> Deployment
    Deployment --> Verification

Support and Resources

Support Channels

  • Technical Support: support@swarms.world
  • Developer Discord: discord.gg/swarms
  • Documentation Site: docs.swarms.world

Version History

  • v1.0.0: Initial Release
  • v1.1.0: Added Multi-Token Support
  • v1.2.0: Enhanced Analytics
  • v1.3.0: Improved Error Handling