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]https://github.com/Tally-Pay/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

```bash
# 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

```bash
# 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

```bash
# 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:
```bash
cargo install --git https://github.com/Tally-Pay/tally-cli
```

Then initialize the configuration:
```bash
# 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](https://github.com/Tally-Pay/tally-cli).

### 3. Using the Rust SDK

```rust
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](https://github.com/Tally-Pay/tally-cli)

**Installation**:
```bash
cargo install --git https://github.com/Tally-Pay/tally-cli
```

For complete CLI documentation and usage examples, please refer to the [tally-cli repository](https://github.com/Tally-Pay/tally-cli).

## SDK Features

### Transaction Building

The SDK provides high-level transaction builders:

```rust
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

```rust
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

```rust
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

```bash
# 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

```bash
# 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

- [Anchor Framework]https://www.anchor-lang.com/
- [Solana Documentation]https://docs.solana.com/
- [SPL Token Program]https://spl.solana.com/token

## Support

For questions and support:
- GitHub Issues: [tally-protocol/issues]https://github.com/Govcraft/tally-protocol/issues
- Documentation: Coming soon

---

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