npm package: @opusgamelabs/snapshotter
Description: Solana token snapshot and merkle proof generation utilities
Author: Open Game Protocol
Latest version: 0.0.6

# Solana Token Holders Fetcher with Committee Verification

Get all holders of a Solana token using the Helius API and Bun runtime, with optional **Multi-Party Computation (MPC)** committee verification for decentralized, trustless snapshots.

## Overview

This tool fetches all token holders for any SPL token on Solana using the Helius `getTokenAccounts` API method. It handles pagination automatically and can process tokens with millions of holders.

### 🆕 Committee Verification (MPC/TSS)

**NEW**: Snapshots can now be cryptographically signed by multiple committee members using **Multi-Party Computation (MPC)** and **Threshold Signature Schemes (TSS)**. This ensures:
- ✅ **Decentralization**: No single party controls the snapshot
- ✅ **Trustless Verification**: Cryptographic proofs instead of trust
- ✅ **Threshold Security**: Requires m-of-n signatures (e.g., 2-of-3)
- ✅ **Tamper-Proof**: SHA-256 hashing ensures data integrity

### Features

- ✅ Fetch all holders of any Solana token
- ✅ **Token2022 (Token Extensions) support** with automatic detection
- ✅ Automatic pagination handling
- ✅ Track holder balances (handles multiple token accounts per owner)
- ✅ **Jupiter API integration** for token metadata (price, decimals, market cap)
- ✅ **USD value calculations** for each holder
- ✅ **Filtering by minimum USD holdings** (configurable threshold)
- ✅ **Market cap filtering** (skip tokens below threshold)
- ✅ Sort holders by balance
- ✅ Export to JSON files
- ✅ Built with Bun for blazing fast performance
- ✅ TypeScript for type safety
- ✅ **Committee-based verification with MPC/TSS**
- ✅ **Cryptographic snapshot signatures**
- ✅ **Configurable threshold requirements**

## Prerequisites

- [Bun](https://bun.sh) installed on your system
- A free [Helius API key](https://www.helius.dev/)

## Installation

1. Clone this repository or download the files

2. Install Bun if you haven't already:
```bash
curl -fsSL https://bun.sh/install | bash
```

3. Install dependencies:
```bash
bun install
```

4. Copy `.env.example` to `.env` and add your Helius API key:
```bash
cp .env.example .env
```

5. Edit `.env` and add your API key and optional filters:
```
HELIUS_API_KEY=your_actual_api_key_here
TOKEN_MINT=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263

# Optional: Filter by minimum USD holdings (e.g., $10)
MIN_USD_HOLDINGS=10

# Optional: Skip tokens below market cap threshold (e.g., $100,000)
MIN_MCAP=100000
```

## Usage

### Option 1: Monitored Snapshot (Standard)

Run a snapshot with real-time transfer monitoring for accuracy:

```bash
# Basic usage
bun run start

# Custom token
HELIUS_API_KEY=your_key TOKEN_MINT=your_mint_address bun run start

# With USD holdings filter (only holders with $50+)
MIN_USD_HOLDINGS=50 bun run start

# With market cap filter (skip tokens below $1M market cap)
MIN_MCAP=1000000 bun run start

# Development mode with auto-reload
bun run dev
```

This will:
1. Start WebSocket monitoring to track transfers in real-time
2. Fetch all token holders via paginated API
3. Reconcile any balance changes that occurred during the fetch
4. Generate accurate snapshot at a specific slot

**Output**: `snapshot-monitored.json`

### Option 2: Committee-Verified Snapshot (Production Recommended)

For decentralized, tamper-proof snapshots with multi-party verification:

```bash
# Basic usage
bun run committee

# Custom token and network
HELIUS_API_KEY=your_key TOKEN_MINT=your_mint_address NETWORK=mainnet-beta bun run committee

# With filters
MIN_USD_HOLDINGS=100 MIN_MCAP=500000 bun run committee

# Development mode with auto-reload
bun run committee:dev
```

This will:
1. Start WebSocket monitoring (same as Option 1)
2. Fetch all token holders with reconciliation
3. Initialize a committee of validators
4. Create cryptographic signatures from multiple parties
5. Generate a verified snapshot with proof of authenticity

**Output**: `verified-snapshot.json`, `committee-info.json`, `token-holders.json`

### Using Environment Variables

Set your API key as an environment variable:
```bash
export HELIUS_API_KEY=your_api_key_here
bun run start  # For simple fetch
# or
bun run committee  # For committee-verified snapshot
```

## Popular Token Mint Addresses

- **USDC**: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`
- **BONK**: `DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263`
- **SOL (Wrapped)**: `So11111111111111111111111111111111111111112`
- **USDT**: `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB`

**Note**: The system automatically detects whether a token uses the standard Token program or Token2022 (Token Extensions) program.

## Output

### Monitored Snapshot Output

The script generates `snapshot-monitored.json`:

```json
{
  "metadata": {
    "tokenMint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
    "targetSlot": 245678901,
    "startSlot": 245678800,
    "slotDifference": 101,
    "totalHolders": 2543,
    "totalSupply": 1000000000000,
    "totalUsdValue": 42500.50,
    "stateChanges": 15,
    "timestamp": "2024-01-15T10:30:00.000Z",
    "tokenInfo": {
      "name": "Bonk",
      "symbol": "BONK",
      "decimals": 5,
      "usdPrice": 0.00000425,
      "mcap": 425000
    },
    "filters": {
      "minUsdHoldings": 10,
      "minMcap": 100000
    }
  },
  "holders": [
    {
      "owner": "111An9SVxuPpgjnuXW9Ub7hcVmZpYNrYZF4edsGwJEW",
      "totalBalance": 1000000000,
      "usdValue": 4250.00
    },
    ...
  ]
}
```

### Committee Mode Output

The committee-verified snapshot generates three JSON files:

1. **`verified-snapshot.json`**: Complete verified snapshot with signatures
```json
{
  "metadata": {
    "tokenMint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
    "timestamp": 1698765432000,
    "blockHeight": 245678901,
    "totalHolders": 2543,
    "totalSupply": 1000000000000,
    "snapshotHash": "a1b2c3d4...",
    "signatures": [
      {
        "memberId": "member-1",
        "signature": "abc123...",
        "publicKey": "9WzDXwBbmkg..."
      }
    ]
  },
  "holders": [...],
  "isVerified": true,
  "verificationThreshold": 2,
  "signatureCount": 2
}
```

2. **`committee-info.json`**: Committee member information
```json
{
  "members": [
    {
      "id": "member-1",
      "name": "Primary Validator",
      "publicKey": "9WzDXwBbmkg..."
    }
  ],
  "threshold": 2,
  "totalMembers": 3,
  "aggregatedPublicKey": "3HSYXeGc3Lj..."
}
```

3. **`token-holders.json`**: Simple list of holder addresses

## How It Works

### Monitored Snapshot Mode

1. **Fetch Metadata**: Retrieve token information from Jupiter API (decimals, price, market cap)
2. **Market Cap Filter**: Skip tokens below minimum market cap threshold (if configured)
3. **Start Monitoring**: WebSocket connection subscribes to all token account changes
   - Automatically detects Token vs Token2022 program
4. **Fetch Pages**: API pagination fetches token accounts in batches of 1000
5. **Track Changes**: During fetch, any transfers are recorded with slot numbers
6. **Reconcile**: Applies monitored state changes to accounts fetched earlier
7. **Calculate USD Values**: Convert raw balances to real amounts and USD values
8. **Apply Filters**: Remove holders below minimum USD holdings threshold (if configured)
9. **Target Slot**: Final snapshot represents state at the END of the fetch operation
10. **Export**: Save accurate snapshot with metadata

**Why Monitoring?** During pagination (which can take seconds or minutes for large tokens), balances can change. Monitoring ensures we capture those changes and reconcile to a specific slot for accuracy.

**Why Jupiter Integration?** Provides essential token metadata:
- **Decimals**: Convert raw amounts to human-readable values
- **USD Price**: Calculate holder values in dollars
- **Market Cap**: Filter out low-quality or scam tokens

### Committee Mode (MPC/TSS)

Built on top of the monitored snapshot, adds cryptographic verification:

1. **Fetch & Filter**: Same as monitored mode - includes metadata, USD calculations, and filtering
2. **Initialize Committee**: Generate keypairs for each committee member using TSS
3. **Create Snapshot Hash**: Generate SHA-256 hash of the snapshot data (holders + metadata)
4. **Multi-Party Signing**:
   - **Step 1**: Each member creates a signing commitment (public nonce)
   - **Step 2**: Members exchange nonces and create partial signatures
   - **Step 3**: Partial signatures are aggregated into a valid multi-sig
5. **Verification**: Anyone can verify the snapshot using the committee's aggregated public key
6. **Export**: Save verified snapshot with cryptographic proofs

### Why Committee Verification?

**Problem**: Traditional snapshots are centralized - one party controls the data
- Single point of failure
- Potential for manipulation
- Requires trust in operator

**Solution**: Multi-Party Computation (MPC) + Threshold Signatures (TSS)
- Requires multiple independent parties to sign
- No single party can manipulate the snapshot
- Cryptographically verifiable
- Threshold requirement (e.g., 2-of-3 signatures needed)

**Example**: For a 2-of-3 committee:
- 3 independent validators are selected
- Snapshot is only valid with 2+ signatures
- Even if 1 validator is compromised, snapshot remains secure

## API Rate Limits

Helius free tier includes:
- 10 requests per second
- 100,000 requests per day

For larger tokens, consider:
- Adding rate limiting delays
- Using a paid Helius plan
- Implementing retry logic

## Project Structure

```
src/
├── shared/
│   └── snapshotCore.ts          # Core snapshot logic (monitoring, fetching, reconciliation)
├── snapshotWithMonitoring.ts    # Standard monitored snapshot
├── committeeSnapshot.ts          # Committee-verified snapshot
├── committeeCoordinator.ts       # MPC/TSS coordination logic
└── committeeConfig.ts            # Committee configuration

Additional Documentation:
├── COMMITTEE_GUIDE.md           # Detailed committee setup guide
├── TODO.md                      # Development roadmap
└── SNAPSHOT_UNWINDING.md        # Unwinding protocol documentation
```

### Shared Architecture

Both snapshot modes use the same core components from `src/shared/snapshotCore.ts`:
- **AccountMonitor**: WebSocket-based real-time transfer monitoring
- **fetchAllAccounts()**: Paginated account fetching with slot tracking
- **reconcileToTargetSlot()**: Balance reconciliation logic

This ensures consistency and maintainability across different snapshot types.

## Use Cases

### Monitored Snapshot Mode
- **Quick Analytics**: Fast, accurate token holder analysis
- **Development Testing**: Test airdrops or features with precise snapshots
- **Personal Use**: Small-scale holder tracking with real-time accuracy
- **Integration**: Embed in applications needing current holder data

### Committee Mode (Recommended for Production)
- **Airdrops**: Provably fair token distribution with verifiable snapshots
- **Governance**: Trustless snapshot for DAO voting eligibility
- **Compliance**: Auditable holder records with cryptographic proof
- **Token Distribution**: Fair launch with multi-party verification
- **Transparency**: Public verification of snapshot integrity
- **Legal Requirements**: Tamper-proof records for regulatory compliance

**Real-World Example**: 
> A DAO wants to airdrop tokens to existing holders. Using committee verification:
> 1. 3 independent validators create a snapshot
> 2. Requires 2-of-3 signatures to be valid
> 3. Community can verify the snapshot hash
> 4. No single party can manipulate holder list
> 5. Cryptographic proof ensures fairness

## Committee Configuration

You can customize the committee setup by editing `committeeConfig.ts`:

```typescript
export const DEFAULT_COMMITTEE: CommitteeConfig = {
  threshold: 2,        // Require 2 signatures
  totalMembers: 3,     // Out of 3 total members
  members: [
    {
      id: 'member-1',
      name: 'Primary Validator',
      publicKey: '',   // Generated at runtime
      endpoint: 'https://validator1.example.com',
    },
    // Add more members...
  ],
  network: 'devnet',   // 'mainnet-beta' | 'devnet' | 'testnet'
};
```

### Security Best Practices

1. **Distribute Committee Members**: Use independent validators from different organizations
2. **Secure Key Storage**: Store member private keys in secure, isolated environments
3. **Regular Key Rotation**: Periodically regenerate committee keys
4. **Monitor Signatures**: Track which members sign each snapshot
5. **Backup Keys**: Securely backup committee member keys
6. **Use Hardware Wallets**: For production, consider hardware wallet integration

## Troubleshooting

### "Cannot find module 'bun'" error

This is a TypeScript error that can be safely ignored when running with Bun. The code will work correctly.

### API Key Error

Make sure your `.env` file exists and contains a valid API key:
```bash
cat .env
```

### No Results

- Verify the token mint address is correct
- Check that the token has been minted and has holders
- Ensure your API key is valid

### Committee Initialization Fails

- Check network connectivity to Solana RPC
- Verify you're using a supported network (mainnet-beta, devnet, testnet)
- Ensure sufficient SOL for transaction fees (devnet/testnet only)

### Insufficient Signatures

- Verify threshold is set correctly (must be ≤ total members)
- Check that enough committee members are participating
- Review committee configuration in `committeeConfig.ts`

## Contributing

Contributions are welcome! Feel free to:
- Report bugs
- Suggest features
- Submit pull requests

## License

MIT

## Technical Architecture

### Core Snapshot Engine

**Shared Components** (`src/shared/snapshotCore.ts`):
```
┌─────────────────────────────────────────────────────┐
│                   AccountMonitor                    │
│  WebSocket subscription to track real-time changes  │
└────────────┬────────────────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────────────────┐
│              fetchAllAccounts()                     │
│  Paginated API calls with slot tracking             │
└────────────┬────────────────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────────────────┐
│           reconcileToTargetSlot()                   │
│  Apply monitored changes to fetched accounts        │
└────────────┬────────────────────────────────────────┘
             │
             ▼
       Accurate Snapshot
```

### Monitoring Flow

```
Time: ────────────────────────────────────────►
      
      [Monitor Start]
           │
           ├──► Page 1 fetch (slot 100)
           ├──► Transfer detected! (slot 105)
           ├──► Page 2 fetch (slot 110)
           ├──► Page 3 fetch (slot 115)
           │
      [Monitor Stop] → Target Slot: 115
           │
           ▼
    Reconcile accounts:
    - Accounts from slot 100-110: apply changes up to slot 115
    - Accounts from slot 115: already current
           │
           ▼
    Final snapshot at slot 115 ✓
```

### MPC/TSS Implementation

This project uses the `solana-mpc-tss-lib` package which implements:
- **Ed25519 TSS**: Threshold signatures for Solana
- **ZenGo-X Compatible**: 100% API compatibility with ZenGo-X/solana-tss
- **WASM Optimized**: High-performance cryptography with automatic fallback

### Committee Verification Flow

```
┌──────────────────┐
│ Monitored Fetch  │
│ (Shared Code)    │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│   Initialize     │
│   Committee      │
│ (Generate Keys)  │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│  Create Hash     │
│  (SHA-256)       │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐      ┌──────────────┐
│  Step 1: Nonce   │◄────►│  Member 1    │
│  Exchange        │      │  Member 2    │
└────────┬─────────┘      │  Member 3    │
         │                └──────────────┘
         ▼
┌──────────────────┐
│  Step 2: Sign    │
│  (Partial Sigs)  │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│  Step 3: Verify  │
│  & Aggregate     │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Verified Output  │
│  (JSON files)    │
└──────────────────┘
```

## Advanced Features

### Token2022 Support

The system automatically detects and supports both:
- **Token Program**: `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`
- **Token2022 Program**: `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`

No configuration needed - detection is automatic by checking the mint's owner program.

### Filtering Options

#### Minimum USD Holdings
Filter out holders below a certain dollar value:

```bash
MIN_USD_HOLDINGS=50 bun run start
```

This is useful for:
- Focusing on significant holders
- Reducing airdrop costs
- Filtering dust accounts
- Compliance requirements

#### Minimum Market Cap
Skip tokens below a market cap threshold:

```bash
MIN_MCAP=100000 bun run start
```

This helps:
- Avoid scam tokens
- Focus on established projects
- Automate quality filtering
- Prevent wasted API calls

### Jupiter API Integration

Token metadata is automatically fetched from Jupiter API:
- **Decimals**: For converting raw to real amounts
- **USD Price**: Current market price
- **Market Cap**: Total value
- **Symbol & Name**: Token identification
- **Total Supply**: Circulating supply

**Example calculation**:
```
Raw balance: 1000000000
Decimals: 9
Real amount: 1000000000 / 10^9 = 1.0 tokens
USD price: $0.50
USD value: 1.0 × $0.50 = $0.50
```

## Resources

- [Helius Documentation](https://docs.helius.dev/)
- [Solana Token Program](https://spl.solana.com/token)
- [Token2022 (Token Extensions)](https://spl.solana.com/token-2022)
- [Jupiter API](https://station.jup.ag/docs/apis/swap-api)
- [Bun Documentation](https://bun.sh/docs)
- [Original Guide](https://www.helius.dev/blog/how-to-get-token-holders-on-solana)
- [solana-mpc-tss-lib](https://www.npmjs.com/package/solana-mpc-tss-lib)
- [Multi-Party Computation (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation)
- [Threshold Signatures](https://en.wikipedia.org/wiki/Threshold_cryptosystem)

## Acknowledgments

Based on the guide by Owen Venter at Helius.