JSPM

  • Created
  • Published
  • Downloads 330
  • Score
    100M100P100Q79114F
  • License MIT

Package Exports

  • @reflectmoney/stable.ts
  • @reflectmoney/stable.ts/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@reflectmoney/stable.ts) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

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

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

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

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

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

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

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

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

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

// 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:

// 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:

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