npm package: @star-factory/sdk-staking
Description: Staking SDK for the Star protocol
Author: Star Team
Latest version: 0.2.0

### sdk-staking

Typed client for the on-chain staking program. It mirrors PDA seeds and instruction accounts, and adds read and convenience helpers.

- **Entry**: `sdk-staking/index.ts`
- **Types**: `sdk-staking/types.ts`
- **Peer deps**: `@coral-xyz/anchor`, `@solana/spl-token`

### Install

```bash
yarn add @coral-xyz/anchor @solana/spl-token
```

### Quick start

```ts
import { AnchorProvider, BN } from '@coral-xyz/anchor';
import { PublicKey } from '@solana/web3.js';
import { StakingSDK } from '.';

const provider = AnchorProvider.env();
const sdk = await StakingSDK.create(provider); // or pass custom programId

// Initialize pool (authority must sign)
await sdk.initialize(new PublicKey('...accepted_mint...'));

// Stake
await sdk.stake(new BN(1_000_000));

// Unstake (starts 30-day unlock)
await sdk.unstake(new BN(500_000));

// Claim when eligible
if (await sdk.canClaimUnstake()) {
  await sdk.claimUnstake();
}
```

### API

```ts
class StakingSDK {
  constructor(program: Program<StakeProgram>, provider: AnchorProvider);
  static create(provider: AnchorProvider, programId?: PublicKey): Promise<StakingSDK>;

  // PDAs
  getStakePoolPDA(): PDAWithBump;                    // [b"stake_pool"]
  getUserStakePDA(user: Address): PDAWithBump;       // [b"user_stake", user]
  getStakeVaultPDA(stakePool: Address): PDAWithBump; // [b"stake_vault", stake_pool]

  // Writes
  initialize(acceptedMint: Address, authority?: Address): Promise<TransactionSignature>;
  stake(amount: Amount, user?: Address): Promise<TransactionSignature>;
  unstake(amount: Amount, user?: Address): Promise<TransactionSignature>;
  claimUnstake(user?: Address): Promise<TransactionSignature>;

  // Reads
  getStakePool(): Promise<StakePoolAccount>;
  getUserStake(user?: Address): Promise<UserStakeAccount | null>;

  // Derived helpers
  getUserPoolShare(user?: Address): Promise<number>;         // percentage 0..100
  canClaimUnstake(user?: Address): Promise<boolean>;
  getTimeUntilClaim(user?: Address): Promise<number | null>; // seconds

  // Events
  onStakeEvent(cb: EventCallback<StakeEvent>): ListenerId;
  onUnstakeEvent(cb: EventCallback<UnstakeEvent>): ListenerId;
  onClaimUnstakeEvent(cb: EventCallback<ClaimUnstakeEvent>): ListenerId;
  removeEventListener(listenerId: ListenerId): Promise<void>;
}
```

### Types (subset)

```ts
type Address = web3.PublicKey;
type Amount = BN;

interface StakePoolAccount { acceptedMint: Address; totalStaked: BN }
interface UserStakeAccount { stakedAmount: BN; pendingUnstake: BN; unlockTimestamp: BN }
```

### Behavior notes

- Loads IDL from `../target/idl/stake_program.json`; use `StakingSDK.create(provider, programId)` to override address.
- Uses `.accountsPartial(...)` (Anchor v0.29+). If needed, switch to `.accounts(...)`.
- `getUserStake()` returns `null` if the PDA is not initialized.
- `getUserPoolShare()` computes `(stakedAmount / totalStaked) * 100` with two-decimal precision.

---

## Staker Snapshot Script

Creates a snapshot of all stakers for pro-rata reward distribution. Outputs CSV compatible with the airdrop script.

### Usage

```bash
# From sdk-staking directory
yarn snapshot --supply <AMOUNT> [options]

# Options:
#   --supply <amount>   Total reward tokens to distribute (whole tokens)
#   --decimals <n>      Reward token decimals (default: 6 for USDC)
#   --output <path>     Output CSV path (default: ./staker-snapshot.csv)
#   --rpc <url>         RPC endpoint (default: $RPC_URL or localhost)
```

### Examples

```bash
# Distribute 1M USDC (6 decimals) to stakers
yarn snapshot --supply 1000000 --decimals 6 --output ./usdc-rewards.csv

# Distribute 500K tokens with 9 decimals on mainnet
yarn snapshot --supply 500000 --decimals 9 --rpc https://api.mainnet-beta.solana.com
```

### Output

Creates three files:
- `staker-snapshot.csv` - `wallet,amount` format for airdrop script
- `staker-snapshot-detailed.csv` - Full allocation details (staked amounts, percentages)
- `staker-snapshot-summary.json` - Verification data and audit trail

### Features

- **100% integer arithmetic** - No floating point for token amounts
- **Verified math** - `sum(distributed) + remainder = total_supply`
- **Deterministic ordering** - Sorted by wallet address for reproducibility
- **Randomized output** - CSV is shuffled so whales aren't airdropped first

### Programmatic Usage

```ts
import { StakingSDK } from '@star-vault/sdk-staking';

const sdk = await StakingSDK.create(provider);

// Get all stakers
const { stakers, totalStaked, activeStakers } = await sdk.getAllStakers();

// Each staker has:
// - wallet: PublicKey
// - stakedAmount: BN
// - pendingUnstake: BN
// - unlockTimestamp: BN
```