Tally Protocol
A Solana-native subscription platform implementing delegate-based recurring payments using SPL Token delegate approvals. Tally enables merchants to create subscription plans and collect automated USDC payments without requiring user signatures on each renewal.
Overview
Tally Protocol provides a complete subscription infrastructure on Solana with:
- On-Chain Program: Anchor-based Solana program for subscription management
- Rust SDK: Comprehensive SDK for building subscription integrations
- TypeScript Packages: IDL and type definitions for web integrations
Note: The CLI tool has been moved to a separate repository: tally-cli
Key Features
- Delegate-Based Payments: Users approve once, renewals happen automatically
- USDC Native: Built on SPL Token standard with USDC support
- Flexible Plans: Configure pricing, periods, and grace periods
- Platform Fees: Configurable merchant fees with admin controls
- Event System: Comprehensive event logging for subscriptions
- Dashboard API: Real-time subscription metrics and analytics
Project Structure
tally-protocol/
├── program/ # Solana program (Anchor)
│ └── src/
│ ├── lib.rs # Program entry point
│ ├── state.rs # Account structures
│ ├── init_config.rs # Global config initialization
│ ├── init_merchant.rs # Merchant registration
│ ├── create_plan.rs # Subscription plan creation
│ ├── start_subscription.rs # New subscription with delegate
│ ├── renew_subscription.rs # Automated renewal via delegate
│ ├── cancel_subscription.rs # Subscription cancellation
│ ├── admin_withdraw_fees.rs # Platform fee withdrawal
│ ├── events.rs # Event definitions
│ └── errors.rs # Error types
├── sdk/ # Rust SDK
│ └── src/
│ ├── lib.rs # SDK entry point
│ ├── simple_client.rs # High-level client API
│ ├── transaction_builder.rs # Transaction construction
│ ├── pda.rs # PDA computation utilities
│ ├── ata.rs # Associated token account helpers
│ ├── events.rs # Event parsing
│ ├── event_query.rs # Event querying with caching
│ ├── dashboard.rs # Dashboard data aggregation
│ ├── validation.rs # Input validation
│ └── error.rs # SDK error types
├── packages/ # TypeScript packages
│ ├── idl/ # Program IDL
│ ├── sdk/ # TypeScript SDK (WIP)
│ └── types/ # Type definitions (WIP)
└── examples/ # Usage examples (WIP)
Installation
Prerequisites
- Rust 1.75+ with Cargo
- Solana CLI 1.18+
- Anchor CLI 0.31.1
- Node.js 18+ with pnpm (for TypeScript packages)
Building from Source
# Clone the repository
# Build the entire workspace
# Build specific components
# CLI tool is now in a separate repository: https://github.com/Tally-Pay/tally-cli
# Build TypeScript packages
Running Tests
# Run all tests
# Test specific packages
# CLI tests are now in tally-cli repository
Quick Start
1. Deploy the Program
# Build and deploy to localnet
# Or deploy to devnet
Program IDs:
- Localnet:
Fwrs8tRRtw8HwmQZFS3XRRVcKBQhe1nuZ5heB4FgySXV - Devnet:
6jsdZp5TovWbPGuXcKvnNaBZr1EBYwVTWXW1RhGa2JM5
2. Initialize Configuration
Install the CLI tool first:
Then initialize the configuration:
# Initialize global program config (admin only)
# Initialize merchant account
# Create a subscription plan
For more CLI commands, see the tally-cli repository.
3. Using the Rust SDK
use ;
use ;
use Pubkey;
use FromStr;
// Initialize client
let client = new?;
// Compute addresses
let merchant = new;
let merchant_pda = merchant_address?;
let plan_pda = plan_address_from_string?;
// Get merchant's USDC ATA
let usdc_mint = from_str?;
let treasury_ata = get_associated_token_address_for_mint?;
// Fetch subscription data
let subscription = client.get_subscription.await?;
println!;
println!;
Architecture
Program Accounts
Config Account (PDA: ["config"])
- Global program configuration
- Platform authority and fee settings
- Min/max validation parameters
Merchant Account (PDA: ["merchant", authority])
- Merchant registration and settings
- USDC mint and treasury configuration
- Platform fee percentage
Plan Account (PDA: ["plan", merchant, plan_id])
- Subscription plan definition
- Pricing, period, and grace period
- Active/inactive status
Subscription Account (PDA: ["subscription", plan, subscriber])
- Individual user subscription state
- Next renewal timestamp
- Renewal count and last amount charged
Payment Flow
-
Start Subscription
- User approves USDC delegate to program
- Program transfers initial payment
- Creates subscription account with renewal schedule
-
Automated Renewal (via off-chain keeper)
- Keeper calls
renew_subscriptionwhen due - Program pulls funds via delegate approval
- Updates next renewal timestamp
- Emits renewal event
- Keeper calls
-
Cancel Subscription
- User or merchant cancels subscription
- Program revokes delegate approval
- Marks subscription as inactive
Fee Distribution
For each payment:
- Merchant Fee:
amount * (1 - platform_fee_bps / 10000)→ Merchant treasury - Platform Fee:
amount * (platform_fee_bps / 10000)→ Platform fee vault
CLI Tool
The CLI tool has been moved to a separate repository for easier distribution and maintenance.
Repository: https://github.com/Tally-Pay/tally-cli
Installation:
For complete CLI documentation and usage examples, please refer to the tally-cli repository.
SDK Features
Transaction Building
The SDK provides high-level transaction builders:
use TransactionBuilder;
// Start subscription transaction
let tx = start_subscription?;
// Cancel subscription transaction
let tx = cancel_subscription?;
Event Querying
use EventQuery;
// Query subscription events with caching
let query = new;
let events = query.query_subscription_events.await?;
Dashboard Data
use Dashboard;
// Aggregate subscription metrics
let dashboard = new;
let metrics = dashboard.get_merchant_metrics.await?;
println!;
println!;
println!;
Events
The program emits comprehensive events for off-chain indexing:
- SubscriptionStarted: New subscription created
- SubscriptionRenewed: Successful renewal payment
- SubscriptionCancelled: Subscription cancelled
- PlanCreated: New plan created
- PlanDeactivated: Plan deactivated
- MerchantInitialized: Merchant registered
- FeesWithdrawn: Platform fees withdrawn
Development
Code Quality
The project enforces strict code quality standards:
- Zero Unsafe Code:
#![forbid(unsafe_code)]across all crates - Clippy Lints:
all,pedantic,nurseryenabled - Test Coverage: Comprehensive unit and integration tests
- Test Runner: Uses
cargo nextestfor parallel test execution
Safety Standards
Following Solana SDK patterns:
- Arithmetic overflow checks in release builds
- No unsafe code blocks allowed
- Strict clippy lints for security-critical operations
- Comprehensive input validation
Contributing
- Fork the repository
- Create a feature branch
- Write tests for new functionality
- Ensure
cargo nextest runpasses - Ensure
cargo clippyshows no warnings - Submit a pull request
Deployment
Localnet
# Start local validator
# Deploy program
# Run CLI commands against localnet
Devnet
# Configure CLI for devnet
# Deploy to devnet
# Run CLI commands
Mainnet
⚠️ Not recommended for production yet - under active development
Security
Audit Status
This project has not been formally audited. Use at your own risk.
Known Limitations
- Relies on off-chain keeper for renewal timing
- Delegate approval must be maintained by users
- No automatic grace period recovery mechanism
- Platform fee changes don't affect existing subscriptions
Reporting Issues
Please report security issues privately to the maintainers.
License
MIT License - see LICENSE file for details
Resources
Support
For questions and support:
- GitHub Issues: tally-protocol/issues
- Documentation: Coming soon
Status: Active Development Version: 0.1.0 Last Updated: 2025-10-01