npm package: @solpulse/sdk
Description: TypeScript SDK for interacting with the SolPulse Solana program
Latest version: 0.2.0

# @solpulse/sdk

TypeScript SDK for interacting with the SolPulse Solana program — a decentralised raffle and PULSE token staking platform built with Anchor.

## Installation

```bash
npm install @solpulse/sdk @coral-xyz/anchor @solana/web3.js @solana/spl-token
```

> **Note:** `@solana/wallet-adapter-react` is an optional peer dependency required only when using `createSolPulseClient` with an Anchor wallet from the wallet adapter.

## Quick Start

```typescript
import { Connection } from "@solana/web3.js";
import { createSolPulseClient, getConnection, SOLPULSE_PROGRAM_ID, PULSE_MINT } from "@solpulse/sdk";

// Use the default devnet connection
const connection = getConnection();

// Or bring your own
const connection2 = new Connection("https://api.devnet.solana.com", "confirmed");

// Create a client (requires an AnchorWallet from @solana/wallet-adapter-react)
const client = createSolPulseClient(wallet, connection, {
  programId: SOLPULSE_PROGRAM_ID,
  pulseMint: PULSE_MINT,
});

// Fetch the current raffle pool
const pool = await client.getPoolState();
console.log("Draw ID:", pool?.drawId.toNumber());
console.log("Total SOL:", pool?.totalSol.toNumber() / 1e9);

// Buy tickets
const txSignature = await client.buyTickets(5);
console.log("Purchased 5 tickets:", txSignature);

// Stake PULSE tokens (30-day lock period = index 1)
const stakeTx = await client.stake(100, 1);
console.log("Staked 100 PULSE:", stakeTx);

// Claim staking rewards
const claimTx = await client.claimRewards();
console.log("Claimed rewards:", claimTx);
```

## API Reference

### Constants

| Export | Type | Description |
|--------|------|-------------|
| `SOLPULSE_PROGRAM_ID` | `PublicKey` | The deployed SolPulse program address |
| `PULSE_MINT` | `PublicKey` | The PULSE SPL token mint address |
| `TICKET_PRICE_SOL` | `number` | Price per raffle ticket in SOL (0.01) |
| `PULSE_DECIMALS` | `number` | Decimal places for the PULSE token (6) |
| `PULSE_DECIMALS_FACTOR` | `number` | `10 ** PULSE_DECIMALS` — use to convert raw amounts |
| `CLUSTER` | `"devnet" \| "mainnet-beta"` | Active Solana cluster |
| `IS_PLACEHOLDER` | `boolean` | `true` when program ID / mint are still the default placeholders |

### Connection

```typescript
import { getConnection } from "@solpulse/sdk";

const connection = getConnection(); // Returns a confirmed-commitment Connection to CLUSTER
```

### PDA Helpers

All helpers accept an optional `programId` (and `pulseMint` where relevant) to support custom deployments.

```typescript
import {
  getPoolPda,
  getPoolVaultPda,
  getTicketEntryPda,
  getDrawResultPda,
  getStakeAccountPda,
  getVaultAuthorityPda,
  getStakeVaultAddress,
  getRewardsVaultAddress,
  getUserPulseAta,
} from "@solpulse/sdk";
import { BN } from "@coral-xyz/anchor";

const [poolPda, poolBump] = getPoolPda();
const [ticketPda] = getTicketEntryPda(new BN(1), walletPublicKey);
const [stakePda] = getStakeAccountPda(walletPublicKey);
const stakeVault = getStakeVaultAddress();          // PublicKey
const userAta = getUserPulseAta(walletPublicKey);   // PublicKey
```

### `createSolPulseClient(wallet, connection, opts?)`

Creates a `SolPulseClient` instance tied to the given wallet and connection.

```typescript
import { createSolPulseClient } from "@solpulse/sdk";

const client = createSolPulseClient(anchorWallet, connection, {
  programId: myCustomProgramId,   // optional, defaults to SOLPULSE_PROGRAM_ID
  pulseMint: myCustomMint,        // optional, defaults to PULSE_MINT
});
```

### `SolPulseClient` Methods

#### Fetch Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `getPoolState()` | `Promise<RafflePoolAccount \| null>` | Fetch the current raffle pool state |
| `fetchPool()` | `Promise<RafflePoolAccount \| null>` | Alias for `getPoolState()` |
| `getDrawHistory()` | `Promise<Array<{ publicKey, account: DrawResultAccount }>>` | Fetch all past draw results |
| `fetchAllDrawResults()` | `Promise<Array<{ publicKey, account: DrawResultAccount }>>` | Alias for `getDrawHistory()` |
| `getUserStakeInfo(user)` | `Promise<StakeAccountData \| null>` | Fetch a user's staking account |
| `fetchStakeAccount(user)` | `Promise<StakeAccountData \| null>` | Alias for `getUserStakeInfo()` |
| `fetchPulseBalance(user)` | `Promise<number>` | PULSE token balance (human-readable) |
| `fetchSolBalance(user)` | `Promise<number>` | SOL balance in SOL |
| `fetchStakeVaultBalance()` | `Promise<number>` | Total PULSE locked in the stake vault (TVL) |
| `fetchUserTickets(user)` | `Promise<Array<{ publicKey, account: TicketEntryAccount }>>` | Raffle tickets owned by the user |
| `fetchUserWins(user)` | `Promise<Array<{ publicKey, account: DrawResultAccount }>>` | Draws won by the user |

#### Transaction Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `buyTickets(quantity)` | `Promise<string>` | Buy `quantity` raffle tickets, returns tx signature |
| `stake(amount, lockPeriod)` | `Promise<string>` | Stake `amount` PULSE with the given `lockPeriod` index (0–3) |
| `unstake()` | `Promise<string>` | Unstake all tokens after lock expires |
| `claimRewards()` | `Promise<string>` | Claim accumulated staking rewards |

### IDL Types

```typescript
import type {
  RafflePoolAccount,
  TicketEntryAccount,
  DrawResultAccount,
  StakeAccountData,
} from "@solpulse/sdk";
```

### Utility Functions

```typescript
import { lamportsToSol, shortenAddress } from "@solpulse/sdk";

lamportsToSol(1_000_000_000); // → 1
shortenAddress("9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"); // → "9WzD...AWWM"
```

## Building

```bash
pnpm build    # outputs CJS + ESM + .d.ts to dist/
pnpm dev      # watch mode
```

## Lock Period Reference

| Index | Lock Duration | APY (basis points) |
|-------|---------------|-------------------|
| 0 | 7 days | 2450 bps (24.5%) |
| 1 | 30 days | 3670 bps (36.7%) |
| 2 | 90 days | 4900 bps (49.0%) |
| 3 | 180 days | 7350 bps (73.5%) |