Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.phoenix.trade/llms.txt

Use this file to discover all available pages before exploring further.

Phoenix perps are margined in USDC. The SDK deposit and withdrawal helpers build Solana instructions; your app still signs and sends the transaction with the trader authority wallet. Deposit and withdrawal amounts are expressed in native USDC units when using the TypeScript SDK: 1 USDC = 1_000_000n. The Rust PhoenixTxBuilder convenience methods accept decimal USDC amounts as f64.
Deposit and withdrawal flows target a Phoenix trader account. Register the trader account first if it does not already exist. Withdrawals are subject to Phoenix account health checks and the protocol withdraw queue; see Collateral for more detail.

TypeScript

Use createPhoenixClient(...) and the client.ixs helpers when you want the SDK to resolve exchange accounts, Ember accounts, trader PDAs, and token accounts for you. buildDepositIxs(...) returns three instructions:
  1. Create the Phoenix token ATA if needed.
  2. Convert wallet USDC to Phoenix canonical tokens through Ember.
  3. Deposit the Phoenix tokens into the Phoenix trader account.
buildWithdrawIxs(...) returns five instructions:
  1. Create the Phoenix token ATA if needed.
  2. Approve Ember to spend Phoenix canonical tokens.
  3. Create the USDC ATA if needed.
  4. Withdraw Phoenix tokens from the Phoenix trader account.
  5. Convert Phoenix tokens back to wallet USDC through Ember.
TypeScript
import { createPhoenixClient } from "@ellipsis-labs/rise";

const client = createPhoenixClient({
  apiUrl: "https://perp-api.phoenix.trade",
  rpcUrl: "https://api.mainnet-beta.solana.com",
  exchangeMetadata: { stream: false },
});

const authority = "AUTHORITY_PUBKEY";
const traderPdaIndex = 0;
const traderSubaccountIndex = 0;
const usdc = (wholeUsdc: bigint) => wholeUsdc * 1_000_000n;

const deposit = await client.ixs.buildDepositIxs({
  authority,
  traderPdaIndex,
  traderSubaccountIndex,
  amount: usdc(100n),
});

const withdraw = await client.ixs.buildWithdrawIxs({
  authority,
  traderPdaIndex,
  traderSubaccountIndex,
  amount: usdc(25n),
});

console.log(deposit.instructions);
console.log(withdraw.instructions);

// Send each instruction array in a transaction signed by `authority`.
// Wallet and transaction submission code depends on your Solana client stack.
You can also build the protocol instructions individually with buildEmberDeposit, buildDepositFunds, buildWithdrawFunds, and buildEmberWithdraw, but most integrations should prefer the full flow helpers above.

Rust

Use PhoenixHttpClient to fetch exchange metadata, then pass that metadata into PhoenixTxBuilder. The builder returns instruction arrays that should be sent in a single transaction signed by the trader authority.
Rust
use phoenix_rise::{PhoenixHttpClient, PhoenixMetadata, PhoenixTxBuilder, TraderKey};
use solana_commitment_config::CommitmentConfig;
use solana_keypair::read_keypair_file;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
use solana_signer::Signer;
use solana_transaction::Transaction;

const RPC_ENDPOINT: &str = "https://api.mainnet-beta.solana.com";

let keypair = read_keypair_file("PATH_TO_KEYPAIR.json")?;
let trader_key = TraderKey::new(keypair.pubkey());

let http = PhoenixHttpClient::new_from_env()?;
let exchange = http.get_exchange().await?.into();
let metadata = PhoenixMetadata::new(exchange);
let builder = PhoenixTxBuilder::new(&metadata);

let rpc = RpcClient::new_with_commitment(
    RPC_ENDPOINT.to_string(),
    CommitmentConfig::confirmed(),
);

let deposit_ixs = builder.build_deposit_funds(
    trader_key.authority(),
    trader_key.pda(),
    100.0,
)?;
let deposit_blockhash = rpc.get_latest_blockhash().await?;
let deposit_tx = Transaction::new_signed_with_payer(
    &deposit_ixs,
    Some(&trader_key.authority()),
    &[&keypair],
    deposit_blockhash,
);
let deposit_signature = rpc.send_and_confirm_transaction(&deposit_tx).await?;

let withdraw_ixs = builder.build_withdraw_funds(
    trader_key.authority(),
    trader_key.pda(),
    25.0,
)?;
let withdraw_blockhash = rpc.get_latest_blockhash().await?;
let withdraw_tx = Transaction::new_signed_with_payer(
    &withdraw_ixs,
    Some(&trader_key.authority()),
    &[&keypair],
    withdraw_blockhash,
);
let withdraw_signature = rpc.send_and_confirm_transaction(&withdraw_tx).await?;

println!("deposit: {deposit_signature}");
println!("withdraw: {withdraw_signature}");
For a complete runnable Rust example, see rust/sdk/examples/deposit_funds.rs.

Monitoring

After a transaction confirms, fetch trader state or collateral history to verify the account:
const trader = await client.api
  .traders()
  .getTraderStateSnapshot(authority, { traderPdaIndex });

const subaccount = trader.snapshot.subaccounts.find(
  (subaccount) => subaccount.subaccountIndex === traderSubaccountIndex
);
console.log("collateral:", subaccount?.collateral ?? "0");

const history = await client.api
  .collateral()
  .getTraderCollateralHistory(authority, {
    pdaIndex: traderPdaIndex,
    limit: 10,
  });