reflect-sdk 0.1.0

Rust SDK for minting and redeeming USDC+ on Reflect
Documentation

reflect-sdk

Rust SDK for minting and redeeming USDC+ on the Reflect delta-neutral protocol (Solana).

Supports both off-chain instruction building (for client-side transaction construction) and on-chain CPI (for composing with USDC+ from another Solana program).

Installation

Add to your Cargo.toml:

[dependencies]
reflect-sdk = "0.1.0"

Feature flags

Feature Description
fetch Enables RPC account fetch helpers via solana-client
serde Derives serde::Serialize / serde::Deserialize on all types
anchor Implements Anchor account traits (AccountSerialize, AccountDeserialize, Owner)
anchor-idl-build Enables Anchor IDL build support

Program ID

rFLctqnUuxLmYsW5r9zNujfJx9hGpnP1csXr9PYwVgX

Available as reflect_sdk::REFLECT_MAIN_ID.

Minting USDC+

Deposit USDC into the Drift-backed strategy and receive USDC+ receipt tokens.

Arguments

Field Type Description
usdc_amount u64 Amount of USDC to deposit (native units, 6 decimals)
min_usdc_amount u64 Minimum receipt tokens to receive (slippage protection)

Accounts

# Account Writable Signer Description
0 user yes yes The depositing user
1 main yes Reflect protocol main state PDA
2 usdc_controller yes Strategy controller PDA
3 admin_permissions Optional user permissions PDA (required when permissioned)
4 user_receipt_ata yes User's ATA for the USDC+ mint
5 user_usdc_ata yes User's ATA for USDC
6 controller_usdc_ata yes Controller's ATA for USDC
7 receipt_mint yes The USDC+ mint
8 drift Drift program ID
9 state yes Drift state account
10 user_stats yes Drift user stats for the controller
11 referrer_user_stats yes Drift referrer user stats
12 referrer_user yes Drift referrer user
13 user_account yes Drift user account for the controller
14 spot_market_vault yes Drift spot market vault (market index 0)
15 drift_vault yes Drift vault signer
16 token_program SPL Token program (defaults to TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA)
17 system_program System program
18 clock Clock sysvar

Off-chain (builder)

use reflect_sdk::instructions::MintDriftS1Builder;

let ix = MintDriftS1Builder::new()
    .user(user_pubkey)
    .main(main_pda)
    .usdc_controller(controller_pda)
    .admin_permissions(Some(permissions_pda))
    .user_receipt_ata(user_receipt_ata)
    .user_usdc_ata(user_usdc_ata)
    .controller_usdc_ata(controller_usdc_ata)
    .receipt_mint(usdc_plus_mint)
    .drift(drift_program_id)
    .state(drift_state)
    .user_stats(drift_user_stats)
    .referrer_user_stats(referrer_user_stats)
    .referrer_user(referrer_user)
    .user_account(drift_user_account)
    .spot_market_vault(spot_market_vault)
    .drift_vault(drift_vault)
    .usdc_amount(1_000_000) // 1 USDC
    .min_usdc_amount(990_000) // 1% slippage
    .instruction();

On-chain (CPI)

use reflect_sdk::instructions::{MintDriftS1CpiBuilder, MintDriftS1InstructionArgs};

MintDriftS1CpiBuilder::new(&reflect_program_info)
    .user(&user_info)
    .main(&main_info)
    .usdc_controller(&controller_info)
    .admin_permissions(Some(&permissions_info))
    .user_receipt_ata(&user_receipt_ata_info)
    .user_usdc_ata(&user_usdc_ata_info)
    .controller_usdc_ata(&controller_usdc_ata_info)
    .receipt_mint(&receipt_mint_info)
    .drift(&drift_info)
    .state(&state_info)
    .user_stats(&user_stats_info)
    .referrer_user_stats(&referrer_user_stats_info)
    .referrer_user(&referrer_user_info)
    .user_account(&user_account_info)
    .spot_market_vault(&spot_market_vault_info)
    .drift_vault(&drift_vault_info)
    .token_program(&token_program_info)
    .system_program(&system_program_info)
    .clock(&clock_info)
    .usdc_amount(1_000_000)
    .min_usdc_amount(990_000)
    .invoke_signed(&[&[b"seed", &[bump]]])?;

Redeeming USDC+

Burn USDC+ receipt tokens and withdraw the underlying USDC back to the user.

Arguments

Field Type Description
rusd_burn_amount u64 Amount of USDC+ to burn (native units)
min_lst_redeem u64 Minimum USDC to receive back (slippage protection)
can_chill bool If true, allows the tx to succeed even when Drift withdrawal is delayed

Accounts

Same layout as minting (see table above).

Off-chain (builder)

use reflect_sdk::instructions::RedeemDriftS1Builder;

let ix = RedeemDriftS1Builder::new()
    .user(user_pubkey)
    .main(main_pda)
    .usdc_controller(controller_pda)
    .admin_permissions(Some(permissions_pda))
    .user_receipt_ata(user_receipt_ata)
    .user_usdc_ata(user_usdc_ata)
    .controller_usdc_ata(controller_usdc_ata)
    .receipt_mint(usdc_plus_mint)
    .drift(drift_program_id)
    .state(drift_state)
    .user_stats(drift_user_stats)
    .referrer_user_stats(referrer_user_stats)
    .referrer_user(referrer_user)
    .user_account(drift_user_account)
    .spot_market_vault(spot_market_vault)
    .drift_vault(drift_vault)
    .rusd_burn_amount(1_000_000)
    .min_lst_redeem(990_000)
    .can_chill(false)
    .instruction();

On-chain (CPI)

use reflect_sdk::instructions::RedeemDriftS1CpiBuilder;

RedeemDriftS1CpiBuilder::new(&reflect_program_info)
    .user(&user_info)
    .main(&main_info)
    .usdc_controller(&controller_info)
    .admin_permissions(Some(&permissions_info))
    .user_receipt_ata(&user_receipt_ata_info)
    .user_usdc_ata(&user_usdc_ata_info)
    .controller_usdc_ata(&controller_usdc_ata_info)
    .receipt_mint(&receipt_mint_info)
    .drift(&drift_info)
    .state(&state_info)
    .user_stats(&user_stats_info)
    .referrer_user_stats(&referrer_user_stats_info)
    .referrer_user(&referrer_user_info)
    .user_account(&user_account_info)
    .spot_market_vault(&spot_market_vault_info)
    .drift_vault(&drift_vault_info)
    .token_program(&token_program_info)
    .system_program(&system_program_info)
    .clock(&clock_info)
    .rusd_burn_amount(1_000_000)
    .min_lst_redeem(990_000)
    .can_chill(false)
    .invoke_signed(&[&[b"seed", &[bump]]])?;

Errors

Program errors are available in errors::ReflectMainError:

use reflect_sdk::errors::ReflectMainError;

match error {
    ReflectMainError::CapExceeded => { /* mint cap reached */ }
    ReflectMainError::OutputAmountTooLow => { /* slippage check failed */ }
    ReflectMainError::SplMintFrozen => { /* deposits suspended for this SPL */ }
    ReflectMainError::ActionFrozen => { /* action is suspended */ }
    // ...
}