npm package: @reflectmoney/stable.ts
Description: A TypeScript SDK for interacting with the Reflect protocol on Solana. The SDK provides high-level abstractions for minting, redeeming, and managing stablecoins.
Author: stablecoinjesus @ Palindrome Engineering
Latest version: 4.0.2

# Reflect Money SDK

A TypeScript SDK for interacting with the Reflect protocol on Solana. The SDK provides high-level abstractions for minting, redeeming, and managing stablecoins.

## Installation

```bash
npm install @reflectmoney/stable.ts
# or
yarn add @reflectmoney/stable.ts
```

## Overview

The Reflect SDK enables developers to interact with the protocol's stablecoins:

- **USDC+ (Index 0)**: Yield-bearing stablecoin backed by USDC deployed in money markets

## Architecture

### Core Classes

#### `Stablecoin` (Abstract Base Class)

The foundation for all stablecoin implementations. Provides common interface for:

- Minting stablecoins
- Redemption operations
- Administrative functions (cap updates, freezing)
- Drift protocol integration

**Key Properties:**
- `controllerKey` - PDA for the stablecoin controller account
- `stablecoinMint` - Address of the stablecoin token mint
- `collaterals` - Array of supported collateral assets
- `lookupTable` - Address lookup table for transaction optimization

#### `UsdcPlusStablecoin`

USDC+ implementation - a yield-bearing stablecoin backed by USDC in money markets.

- **Strategy ID**: 0
- **Collateral**: USDC
- **Status**: Live on mainnet

#### `ReflectKeeper`

Static utility class for protocol-level administrative operations:

- `initializeMain()` - Initialize the main protocol account
- Protocol configuration and management

#### `PdaClient`

Utility class for deriving Program Derived Addresses:

- `deriveMain()` - Main protocol configuration account
- `deriveController(index)` - Stablecoin controller accounts
- `derivePermissions(admin)` - Admin permission accounts

## Usage

### Setup

```typescript
import { createSolanaRpc } from "@solana/kit";
import { UsdcPlusStablecoin } from "@reflectmoney/stable.ts";

// Create RPC connection
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");

// Initialize the stablecoin client
const usdcPlus = new UsdcPlusStablecoin(rpc);

// Load on-chain state (fetches controller data, mint, exchange rate)
await usdcPlus.load();
```

### Minting Stablecoins

```typescript
import { 
    createSolanaRpc,
    pipe,
    createTransactionMessage,
    setTransactionMessageFeePayer,
    setTransactionMessageLifetimeUsingBlockhash,
    appendTransactionMessageInstructions,
    signTransactionMessageWithSigners,
    sendAndConfirmTransactionFactory,
} from "@solana/kit";
import { UsdcPlusStablecoin } from "@reflectmoney/stable.ts";

// Your wallet signer (from wallet adapter or keypair)
const user = /* your signer */;

// Initialize and load stablecoin state
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const usdcPlus = new UsdcPlusStablecoin(rpc);
await usdcPlus.load();

// Create mint instruction
// Deposit 1,000 USDC, expect minimum 999 USDC+ (0.1% slippage)
const instructions = await usdcPlus.mint(
    user,
    BigInt(1000_000_000),  // 1,000 USDC (6 decimals)
    BigInt(999_000_000),   // Minimum USDC+ to receive
);

// Build and send transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

const transactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    tx => setTransactionMessageFeePayer(user.address, tx),
    tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
    tx => appendTransactionMessageInstructions(instructions, tx),
);

const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc });
const signature = await sendAndConfirm(signedTransaction, { commitment: "confirmed" });

console.log("Mint transaction:", signature);
```

### Redeeming Stablecoins

```typescript
import { 
    createSolanaRpc,
    pipe,
    createTransactionMessage,
    setTransactionMessageFeePayer,
    setTransactionMessageLifetimeUsingBlockhash,
    appendTransactionMessageInstructions,
    signTransactionMessageWithSigners,
    sendAndConfirmTransactionFactory,
} from "@solana/kit";
import { UsdcPlusStablecoin } from "@reflectmoney/stable.ts";

const user = /* your signer */;

const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const usdcPlus = new UsdcPlusStablecoin(rpc);
await usdcPlus.load();

// Create redeem instruction
// Burn 999 USDC+, expect minimum 1,000 USDC (USDC+ accrues yield)
const instructions = await usdcPlus.redeem(
    user,
    BigInt(999_000_000),   // USDC+ to burn
    BigInt(1000_000_000),  // Minimum USDC to receive
);

// Build and send transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

const transactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    tx => setTransactionMessageFeePayer(user.address, tx),
    tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
    tx => appendTransactionMessageInstructions(instructions, tx),
);

const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc });
const signature = await sendAndConfirm(signedTransaction, { commitment: "confirmed" });

console.log("Redeem transaction:", signature);
```

### Getting Exchange Rate

```typescript
import { createSolanaRpc } from "@solana/kit";
import { UsdcPlusStablecoin } from "@reflectmoney/stable.ts";

const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const usdcPlus = new UsdcPlusStablecoin(rpc);
await usdcPlus.load();

// Get current exchange rate (USDC per USDC+)
const exchangeRate = await usdcPlus.getExchangeRate();
console.log(`1 USDC+ = ${exchangeRate} USDC`);
```

### PDA Derivation

```typescript
import { PdaClient } from "@reflectmoney/stable.ts";

// Derive main protocol account
const mainPda = await PdaClient.deriveMain();

// Derive controller for strategy index 0 (USDC+)
const controllerPda = await PdaClient.deriveController(0);

// Derive permissions account for an admin
const permissionsPda = await PdaClient.derivePermissions(adminAddress);
```

### Administrative Operations

```typescript
import { UsdcPlusStablecoin, ReflectKeeper } from "@reflectmoney/stable.ts";

const admin = /* admin signer */;

// Initialize main protocol (one-time setup)
const initMainIx = await ReflectKeeper.initializeMain(admin);

// Update supply cap
const usdcPlus = new UsdcPlusStablecoin(rpc);
await usdcPlus.load();
const updateCapIx = await usdcPlus.updateCap(
    admin,
    BigInt(1_000_000_000_000_000) // New cap
);

// Freeze/unfreeze minting
const freezeIx = await usdcPlus.freeze(admin, true, 0);  // Freeze action 0
const unfreezeIx = await usdcPlus.freeze(admin, false, 0); // Unfreeze
```

## API Reference

### UsdcPlusStablecoin

#### Constructor

```typescript
constructor(rpc: Rpc<SolanaRpcApi>, mint?: Address)
```

- `rpc` - Solana RPC client
- `mint` - Optional stablecoin mint address (auto-loaded if not provided)

#### Methods

| Method | Description | Returns |
|--------|-------------|---------|
| `load()` | Load on-chain state (controller, mint, exchange rate) | `Promise<void>` |
| `initializeKeys()` | Initialize PDA keys without fetching on-chain data | `Promise<void>` |
| `mint(user, amount, minReceived)` | Create mint instruction | `Promise<Instruction[]>` |
| `redeem(user, amount, minReceived)` | Create redeem instruction | `Promise<Instruction[]>` |
| `getExchangeRate()` | Get current USDC/USDC+ exchange rate | `Promise<number>` |
| `updateCap(admin, newCap)` | Update supply cap (admin) | `Promise<Instruction>` |
| `freeze(admin, freeze, action)` | Freeze/unfreeze actions (admin) | `Promise<Instruction>` |

### PdaClient

#### Static Methods

| Method | Description | Returns |
|--------|-------------|---------|
| `deriveMain(devnet?)` | Derive main protocol PDA | `Promise<Address>` |
| `deriveController(index, devnet?)` | Derive controller PDA for strategy | `Promise<Address>` |
| `derivePermissions(admin, devnet?)` | Derive admin permissions PDA | `Promise<Address>` |

### ReflectKeeper

#### Static Methods

| Method | Description | Returns |
|--------|-------------|---------|
| `initializeMain(admin)` | Initialize main protocol account | `Promise<Instruction>` |

## Types

```typescript
// Collateral asset configuration
interface Collateral {
    mint: Address;
    oracle: string;
    decimals: number;
}

// Stablecoin metadata
interface StablecoinMetadata {
    name: string;
    ticker: string;
    uri: string;
}
```

## Integration Notes

### Drift Protocol

The SDK integrates with Drift Protocol for perpetual futures positions. Admin operations for Drift account management:

```typescript
// Initialize Drift stats account for the controller
const driftStatsIx = await usdcPlus.initializeStablecoinDriftStatsAccount(admin);

// Initialize Drift sub-account
const driftAccountIx = await usdcPlus.initializeStablecoinDriftAccount(admin);
```

### Address Lookup Tables

For transaction optimization, use the stablecoin's lookup table:

```typescript
const lookupTableAddress = usdcPlus.lookupTable;
// Fetch and use in versioned transactions for reduced transaction size
```

## Network Support

- **Mainnet**: Default configuration
- **Devnet**: Pass `devnet: true` to constructor or use devnet RPC

## License

MIT License

## Support

- Documentation: [docs.reflect.money](https://docs.reflect.money)
- GitHub: [github.com/palindrome-eng/reflect-delta-neutral](https://github.com/palindrome-eng/reflect-delta-neutral)