- Solana Web3 Billing Protocol
- System Architecture
- Prerequisites
- Installation Guide
- Configuration Guide
- Wallet Setup (Local Development)
- Visual Walkthrough & Usage
- Testing
- Troubleshooting
- Contributing
- Connect with Me
- License
Welcome to the Solana Web3 Billing Protocol, a cutting-edge decentralized application (dApp) designed to revolutionize how recurring payments are handled on the blockchain.
In the traditional Web2 world, services like Stripe Billing handle subscriptions by storing user credit card data and charging them periodically. This centralized model relies on trust and intermediaries. The Solana Web3 Billing Protocol moves this entire logic on-chain, leveraging the speed and low cost of the Solana blockchain to create a trustless, automated, and transparent billing infrastructure.
Why is this important?
- Decentralization: No central authority controls the billing logic. It is immutable and governed by smart contracts.
- Security: Users pay with their non-custodial wallets. No sensitive data (like credit card numbers) is ever stored.
- Transparency: Every subscription creation, payment, and cancellation is recorded on the blockchain and verifiable by anyone.
- Automation: Smart contracts automatically handle the logic for valid subscription periods, ensuring access is granted only when payment is confirmed.
This project serves as a comprehensive reference implementation for developers looking to build SaaS (Software as a Service) platforms, membership sites, or any application requiring recurring revenue models on Solana.
- Merchant Plan Creation:
- Merchants can deploy their own "Plan" accounts on-chain.
- Flexible configuration: Set the plan name, description, price (in USDC), and duration (e.g., 30 days).
- Full control: Merchants are the authorities of their plans.
- PDA-Based Subscription Management:
- Uses Program Derived Addresses (PDAs) to deterministically generate account addresses.
- Ensures that a specific user + specific plan always maps to the same unique subscription account.
- Prevents collisions and ensures secure data access.
- Time-Based Billing Logic:
- Smart contracts utilize the on-chain
Clocksysvar to track time. - Subscriptions have a
start_timeandend_time. - The system automatically calculates if a subscription is active or expired based on the current block time.
- Smart contracts utilize the on-chain
- USDC Payment Integration:
- Built to work with SPL Tokens, specifically USDC (or any standard SPL token).
- Handles secure token transfers from the customer's wallet to the merchant's wallet.
Understanding the underlying architecture is crucial for developers. This protocol uses the Anchor Framework, which simplifies Solana development by enforcing security checks and standardizing account structures.
The system is built around four main account types, linked together via PDAs:
-
Merchant Account (Authority)
- Role: Represents the owner/admin of the service.
- Data: Stores the merchant's wallet address.
- Signer: Required to initialize plans.
-
Plan Account
- Role: Defines a subscription tier (e.g., "Basic", "Pro").
- Derivation (PDA): Derived from the string
"plan", the Merchant's public key, and a unique identifier (e.g., "plan-1"). - Data:
owner: The merchant's public key.price: Cost in USDC (atomic units).duration: Length of the subscription in seconds.
-
Subscription Account
- Role: The record of a user's purchase.
- Derivation (PDA): Derived from the string
"subscription", the Plan's public key, and the Customer's public key. - Data:
customer: The user's public key.plan: The plan being subscribed to.start_time: Unix timestamp of purchase.end_time: Unix timestamp of expiration.is_active: Boolean status.
-
Invoice Account
- Role: A receipt for a specific payment.
- Derivation (PDA): Derived from
"invoice", the Subscription public key, and the current timestamp. - Data: Immutable record of the amount paid and time.
Before you begin, you must have a development environment set up. If you are new to Solana development, follow these steps carefully.
- Linux (Ubuntu/Debian): Recommended.
- macOS: Supported.
- Windows: Must use WSL2 (Windows Subsystem for Linux). Native Windows is not fully supported for Anchor development.
Rust is the programming language used for Solana smart contracts.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Select option 1 (default)
source $HOME/.cargo/env
rustc --version
# Output should be 1.70.0 or higherThe Command Line Interface for interacting with the Solana blockchain.
sh -c "$(curl -sSfL https://release.solana.com/v1.18.4/install)"
# Add to path if prompted
solana --versionRequired for the frontend (Next.js) and testing scripts.
# Using NVM (Node Version Manager) is recommended
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
nvm install 18
nvm use 18
node --version
# Install Yarn
npm install -g yarnThe framework for building Solana programs.
cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
avm install latest
avm use latest
anchor --versionNow that your environment is ready, let's set up the project.
Use the official repository URL to get the source code.
git clone https://github.com/raushan728/solana-web3-billing.git
cd solana-web3-billingTake a moment to understand the folder structure:
programs/: Contains the Rust smart contract code (lib.rs).app/: Contains the Next.js frontend application.tests/: Contains TypeScript integration tests.Anchor.toml: Main configuration file for the workspace.
Install the Rust crates required for the smart contract.
# From the root directory
anchor buildNote: This first build might take a few minutes as it compiles all dependencies.
Move to the app folder to install the web application packages.
cd app
npm install
# or
yarn installImportant
CRITICAL STEP: If you skip this, your frontend will not be able to talk to your smart contract.
When you build an Anchor program, it generates a unique Program ID (Public Key). You must update your code to use this specific ID.
After running anchor build, a keypair is generated in target/deploy/.
# From the root directory
solana address -k target/deploy/solana_billing-keypair.jsonCopy the output address (e.g., Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS).
Open programs/solana_billing/src/lib.rs.
use anchor_lang::prelude::*;
// REPLACE THIS STRING with your copied address
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod solana_billing {
// ...
}Open the Anchor.toml file in the root directory.
[programs.localnet]
solana_billing = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"Since you changed the source code (lib.rs), you must build again to bake in the new ID.
anchor buildOpen app/utils/constants.ts.
import { PublicKey } from "@solana/web3.js";
// REPLACE THIS with your copied address
export const PROGRAM_ID = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS";To test this application, you need a Solana wallet with some "fake" money (SOL) on the Localnet.
-
Start the Local Validator: Open a new terminal window and keep this running.
solana-test-validator
-
Configure Solana CLI to Localhost:
solana config set --url localhost -
Create a File System Wallet (if you don't have one):
solana-keygen new -o ~/.config/solana/id.json -
Airdrop SOL: Give yourself some tokens to pay for transactions.
solana airdrop 10
-
Deploy the Program:
anchor deploy
This section guides you through the application flow. Ensure your frontend is running:
cd app
npm run devOpen http://localhost:3000 in your browser.
Goal: Initialize the store and create a subscription plan.
Pre-requisites:
- You must have a Solana Wallet extension installed in your browser (e.g., Phantom or Solflare).
- Switch your wallet network to Localhost (Settings -> Developer Settings -> Change Network).
- Airdrop some SOL to your browser wallet address (
solana airdrop 5 <YOUR_WALLET_ADDRESS>).
Action:
- Connect your wallet using the "Select Wallet" button.
- Navigate to the "Merchant Dashboard".
- Fill in the Plan details (Name, Price in USDC, Duration).
- Click "Create Plan".
Above: The interface where merchants define the terms of the subscription.
Goal: A user views the available plans.
Context: Once a plan is created on-chain, it is public. Any user who visits the dApp can fetch the plan account and see the details.
Action:
- (Optional) Switch to a different wallet account in Phantom to simulate a "Customer".
- Ensure the Customer wallet has SOL (for gas) and USDC (for payment).
- Dev Tip: You can mint fake USDC to your wallet using spl-token CLI tools if testing on Devnet, or use the mock-usdc feature if enabled in the contract.
Above: The customer sees the plan details fetched directly from the blockchain.
Goal: Execute the transaction to subscribe.
What happens under the hood?:
- The frontend constructs a transaction with two main instructions:
Transfer: Moves USDC from Customer to Merchant.Subscribe: Calls the smart contract to create theSubscriptionPDA.
- The user is prompted to sign the transaction.
Action:
- Click the "Subscribe" button.
- Approve the transaction in your wallet popup.
- Wait for confirmation (usually < 1 second on Solana).
Above: The wallet approval screen showing the transfer of funds and program interaction.
Automated tests are crucial for smart contracts. We use the Anchor testing framework (Mocha/Chai).
To run the full test suite:
anchor testWhat is being tested?
- Initialization: Can the merchant create a plan?
- Subscription: Can a user subscribe successfully?
- Payment: Are tokens actually transferred?
- Restrictions: Does the system fail if a user tries to subscribe without paying?
- Expiry: Does the system correctly identify an expired subscription?
Common issues you might encounter:
1. "Account not found" or "Program not deployed"
- Cause: You restarted
solana-test-validatorbut didn't redeploy the program. - Fix: Run
anchor deployagain.
2. "Signature verification failed"
- Cause: The Program ID in
lib.rsdoes not match the keypair intarget/deploy. - Fix: Check the Configuration Guide and ensure IDs match everywhere.
3. "Wallet not connected"
- Cause: Browser extension not detecting the local network.
- Fix: Ensure Phantom/Solflare is set to "Localhost" or "Devnet" depending on where you are running.
4. Node.js Version Errors
- Cause: Using an old version of Node.
- Fix: Run
nvm use 18before runningnpm install.
We welcome contributions! Please follow these steps:
- Fork the repository.
- Create a feature branch (
git checkout -b feature/amazing-feature). - Commit your changes.
- Push to the branch.
- Open a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
