tally-sdk 0.1.0

Rust SDK for the Tally Solana subscriptions platform
Documentation

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
git clone https://github.com/Govcraft/tally-protocol
cd tally-protocol

# Build the entire workspace
cargo build --release

# Build specific components
cargo build -p tally_subs    # Solana program
cargo build -p tally-sdk     # Rust SDK
# CLI tool is now in a separate repository: https://github.com/Tally-Pay/tally-cli

# Build TypeScript packages
pnpm install
pnpm build

Running Tests

# Run all tests
cargo nextest run

# Test specific packages
cargo nextest run -p tally_subs
cargo nextest run -p tally-sdk
# CLI tests are now in tally-cli repository

Quick Start

1. Deploy the Program

# Build and deploy to localnet
anchor build
anchor deploy

# Or deploy to devnet
anchor deploy --provider.cluster devnet

Program IDs:

  • Localnet: Fwrs8tRRtw8HwmQZFS3XRRVcKBQhe1nuZ5heB4FgySXV
  • Devnet: 6jsdZp5TovWbPGuXcKvnNaBZr1EBYwVTWXW1RhGa2JM5

2. Initialize Configuration

Install the CLI tool first:

cargo install --git https://github.com/Tally-Pay/tally-cli

Then initialize the configuration:

# Initialize global program config (admin only)
tally-cli init-config \
  --platform-authority <ADMIN_PUBKEY> \
  --max-fee-bps 1000 \
  --min-period 86400

# Initialize merchant account
tally-cli init-merchant \
  --usdc-mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
  --platform-fee-bps 500

# Create a subscription plan
tally-cli create-plan \
  --plan-id "premium" \
  --name "Premium Plan" \
  --price 10000000 \
  --period 2592000 \
  --grace 86400

For more CLI commands, see the tally-cli repository.

3. Using the Rust SDK

use tally_sdk::{SimpleTallyClient, pda, ata};
use anchor_client::solana_sdk::signature::{Keypair, Signer};
use anchor_client::solana_sdk::pubkey::Pubkey;
use std::str::FromStr;

// Initialize client
let client = SimpleTallyClient::new("https://api.devnet.solana.com")?;

// Compute addresses
let merchant = Keypair::new();
let merchant_pda = pda::merchant_address(&merchant.pubkey())?;
let plan_pda = pda::plan_address_from_string(&merchant_pda, "premium")?;

// Get merchant's USDC ATA
let usdc_mint = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")?;
let treasury_ata = ata::get_associated_token_address_for_mint(
    &merchant.pubkey(),
    &usdc_mint
)?;

// Fetch subscription data
let subscription = client.get_subscription(&plan_pda, &user.pubkey()).await?;
println!("Next renewal: {}", subscription.next_renewal_ts);
println!("Renewals: {}", subscription.renewals);

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

  1. Start Subscription

    • User approves USDC delegate to program
    • Program transfers initial payment
    • Creates subscription account with renewal schedule
  2. Automated Renewal (via off-chain keeper)

    • Keeper calls renew_subscription when due
    • Program pulls funds via delegate approval
    • Updates next renewal timestamp
    • Emits renewal event
  3. 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:

cargo install --git https://github.com/Tally-Pay/tally-cli

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 tally_sdk::transaction_builder::TransactionBuilder;

// Start subscription transaction
let tx = TransactionBuilder::start_subscription(
    &subscriber_keypair,
    &plan_pda,
    &usdc_mint,
    approval_amount,
)?;

// Cancel subscription transaction
let tx = TransactionBuilder::cancel_subscription(
    &subscriber_keypair,
    &plan_pda,
)?;

Event Querying

use tally_sdk::event_query::EventQuery;

// Query subscription events with caching
let query = EventQuery::new(client, program_id);
let events = query.query_subscription_events(
    &subscription_pda,
    start_time,
    end_time
).await?;

Dashboard Data

use tally_sdk::dashboard::Dashboard;

// Aggregate subscription metrics
let dashboard = Dashboard::new(&client);
let metrics = dashboard.get_merchant_metrics(&merchant_pda).await?;

println!("Active subscriptions: {}", metrics.active_count);
println!("Total revenue: {}", metrics.total_revenue);
println!("MRR: {}", metrics.monthly_recurring_revenue);

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, nursery enabled
  • Test Coverage: Comprehensive unit and integration tests
  • Test Runner: Uses cargo nextest for 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

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new functionality
  4. Ensure cargo nextest run passes
  5. Ensure cargo clippy shows no warnings
  6. Submit a pull request

Deployment

Localnet

# Start local validator
solana-test-validator

# Deploy program
anchor build
anchor deploy

# Run CLI commands against localnet
tally-cli --url http://localhost:8899 <COMMAND>

Devnet

# Configure CLI for devnet
solana config set --url https://api.devnet.solana.com

# Deploy to devnet
anchor deploy --provider.cluster devnet

# Run CLI commands
tally-cli --cluster devnet <COMMAND>

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:


Status: Active Development Version: 0.1.0 Last Updated: 2025-10-01