Skip to content

1rishuraj/strikebiller

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 

Repository files navigation

⚡ StrikeBiller: Decentralized Subscription Billing System

Live Web3 App: strikebiller.vercel.app

GitHub Repository: 1rishuraj/strikebiller

Devnet Program ID: DJPman6YhQpGAFp3PkLXjqcf6fXrdVrwmrjve7odk8j

Pattern: Subscription Billing System & Escrow Engine

Video Demo: HERE


🏛 Architecture Analysis: Web2 Backends vs. Solana State Machines

Visual Architecture & Account Model

graph TD
    subgraph Off-Chain Actors
        Merchant([Merchant Wallet])
        Subscriber([Subscriber Wallet])
        Cranker[[Cranker Bot / Node.js]]
    end

    subgraph StrikeBiller Anchor Program
        PlanPDA[SubscriptionPlan PDA<br/>Seeds: 'plan', Merchant, PlanID]
        SubPDA[Subscription PDA<br/>Seeds: 'subscription', Subscriber, PlanPDA]
    end

    subgraph Token Accounts Escrow
        SubATA[(Subscriber USDC ATA)]
        VaultATA[(Vault USDC ATA<br/>Owner: Subscription PDA)]
        MerchATA[(Merchant USDC ATA)]
    end

    %% Initialization & Subscription
    Merchant -->|1. initialize_plan| PlanPDA
    Subscriber -->|2. subscribe| SubPDA
    SubATA -.->|Locks upfront USDC| VaultATA

    %% Execution
    Cranker -->|3. process_billing| SubPDA
    SubPDA -->|Validates Clock::get & Rules| VaultATA
    VaultATA -.->|Transfers if due| MerchATA
    
    %% Cancellation
    Subscriber -->|4. cancel_subscription| SubPDA
    VaultATA -.->|Refunds unbilled USDC| SubATA
Loading

1. How Subscription Billing Works in Web2

In a traditional SaaS architecture (e.g., Node.js + PostgreSQL + Stripe):

  • State Storage: User status (is_active, next_billing_date) is stored in a centralized database row.
  • Execution (Active Cron Jobs): A backend server runs a continuous background cron job. When a billing date arrives, the server actively triggers an API call to a payment processor to charge a saved credit card.
  • Trust Model: The user surrenders their payment details to the merchant. The user must blindly trust that the merchant will not overcharge them, double-bill them, or shut down operations after taking a 30-day upfront payment.

2. How StrikeBiller Works on Solana

StrikeBiller reframes Solana as a distributed, lazy state-machine backend.

  • State Storage (PDAs): The traditional database is replaced by Program Derived Addresses (PDAs). SubscriptionPlan and Subscription states are publicly verifiable bytes on the ledger.
  • Trustless Escrow Vaults: Instead of trusting a merchant with a credit card, the subscriber locks their USDC into an isolated Vault ATA (owned by the Subscription PDA). The merchant can only claim funds after the time has elapsed.
  • Lazy Execution (The Cranker Bot): Solana smart contracts cannot "wake themselves up" like Web2 cron jobs. They are passive. To solve this, StrikeBiller uses an off-chain "Cranker" bot (Node.js). The bot queries the blockchain for subscriptions where next_billing_at is in the past, and submits a process_billing transaction.
  • The Contract is the Bouncer: The cranker bot has no administrative power. When it calls process_billing, the Rust program acts as the ultimate authority. It checks Clock::get()?.unix_timestamp and physically blocks the transaction if the bill is not legitimately due.
  • Strike System & Atomic Bundling: If a vault is empty, the contract issues "Strikes". At 3 strikes, the account is hard-paused. Users can execute an atomic "Top Up & Resume" bundle to instantly refill the vault, unpause, and reset their billing timeline relative to the paused duration.
  • Instant Cancellation & Guaranteed Refunds: Unlike Web2 where users must trust a company to honor a cancellation and stop future charges, StrikeBiller users maintain absolute sovereignty. Calling the cancel_subscription instruction instantly tears down the Subscription PDA, closes the Vault ATA, and refunds all unbilled USDC directly back to the user's wallet.

3. Tradeoffs & Constraints

  • Storage Costs (Rent): Storing subscription state in a Web2 database is practically free. On Solana, allocating bytes for the Subscription and Plan PDAs requires a small amount of SOL for rent exemption.
  • Clock Drift: Because the decentralized Solana network cluster calculates time slightly differently than a local server clock, the off-chain Cranker bot must account for slight network drift, otherwise the Rust contract will reject the transaction with a BillingCycleNotDue error.
  • Execution Centralization: Currently, the cranker bot is a centralized Node.js script. If the script crashes, automated billing stops. However, because the smart contract is permissionless, anyone (even the user or a decentralized oracle network like Clockwork/Switchboard) can manually sign the cranker transaction to push the state machine forward.

📂 Repository Structure

This monorepo contains the complete lifecycle of the billing engine:

strikebiller/
├── programs/biller/       # Anchor Rust smart contract (Backend State Machine)
│   ├── src/instructions/  # Core logic (init_plan, subscribe, toggle, cancel)
│   ├── src/state/         # PDA structures (Subscription, SubscriptionPlan)
│   └── tests/biller.ts    # E2E Escrow and state transition tests
├── frontend/              # Next.js Web3 client (Deployed on Vercel)
│   └── src/
│       ├── components/    # UI components (FundVaultModal, BillerHero)
│       └── services/      # Blockchain interaction logic & IDL parsing
└── cranker/               # Node.js daemon worker for lazy execution
    └── src/index.ts       # Off-chain bot querying and billing due subscriptions

How to Test Locally

  1. Rust Tests: Navigate to /programs -> run anchor test to verify all escrow constraints and state transitions.
  2. Frontend: Navigate to /frontend -> npm install -> npm run dev.
  3. Cranker Bot: Navigate to /cranker -> npm install -> npx ts-node src/index.ts.

(Note: The live frontend requires Devnet USDC. Mint: Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr)


🔗 Live Devnet Proof

Below is the complete, sequential transaction history proving the lifecycle of the system on Devnet.

Actors & Tokens

1. Initialization & Subscription Flow

  • Initialize "Pro Plan" (Merchant): 3unP88Y...
  • Subscribe & Lock Escrow Funds (Subscriber): 3QLEgNG...

2. Lazy Execution (The Cranker Bot)

3. State Toggling & Cancellation

4. Additional Flow Testing

About

⚡ A decentralized subscription billing engine on Solana. Replaces Web2 cron jobs with trustless PDAs, escrow vaults, and lazy execution.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages