> ## 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.

# Rise SDK

> Developer-facing SDK for Phoenix perpetuals, available in TypeScript and Rust

Rise is the developer-facing SDK surface for Phoenix perpetuals. It currently ships as:

* `rise/ts` — the TypeScript SDK, with HTTP route clients, a unified exchange-aware client, instruction builders, Flight helpers, and WebSocket adapters
* `rise/rust` — the Rust workspace, centered on the `phoenix-rise` crate, with typed HTTP/WS clients, transaction builders, math helpers, and low-level instruction builders

## Where to start

* Reach for `PhoenixHttpClient` / `client.api` when you need public HTTP data or invite activation.
* Reach for `createPhoenixClient(...)` when you want exchange metadata, PDA derivation, order-packet helpers, and `client.ixs`.
* Reach for `client.streams` or `createPhoenixWsClient(...)` when you want typed live adapters.
* Reach for `PhoenixTxBuilder` in Rust when you want to construct and sign your own Solana instructions.

## Runnable entry points

<Tabs>
  <Tab title="TypeScript">
    * [`ts/examples/01-http-client.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/01-http-client.ts)
    * [`ts/examples/02-ws-fills.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/02-ws-fills.ts)
    * [`ts/examples/03-build-limit-order-ix.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/03-build-limit-order-ix.ts)
    * [`ts/examples/04-trader-state-store.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/04-trader-state-store.ts)
    * [`ts/examples/05-cancel-all-conditional-orders.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/05-cancel-all-conditional-orders.ts)
    * [`ts/examples/phoenix-client-example.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/phoenix-client-example.ts)
    * [`ts/examples/phoenix-ws-example.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/phoenix-ws-example.ts)
    * [`ts/README.md`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/README.md)
    * [`ts/examples/README.md`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/README.md)
  </Tab>

  <Tab title="Rust">
    * [`rust/README.md`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/README.md)
    * [`rust/sdk/examples/register_trader.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/register_trader.rs)
    * [`rust/sdk/examples/http_client.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/http_client.rs)
    * [`rust/sdk/examples/send_limit_order.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/send_limit_order.rs)
    * [`rust/sdk/examples/send_market_order.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/send_market_order.rs)
  </Tab>
</Tabs>

## Onboarding: access code vs referral code

These invite routes are not interchangeable:

* Use `POST /v1/invite/activate` when you have an access code / allowlist code. Send that value as `code`.
* Use `POST /v1/invite/activate-with-referral` when you have a referral code. Send that value as `referral_code`.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { PhoenixHttpClient } from "@ellipsis-labs/rise";

  const client = new PhoenixHttpClient({
    apiUrl: "https://perp-api.phoenix.trade",
  });

  const authority = "AUTHORITY_PUBKEY";

  const activatedWithAccessCode = await client.invite().activateInvite({
    authority,
    code: "ACCESS_CODE",
  });

  const activatedWithReferral = await client.invite().activateInviteWithReferral({
    authority,
    referral_code: "REF_CODE",
  });
  ```

  ```rust Rust theme={null}
  use phoenix_rise::PhoenixHttpClient;
  use solana_pubkey::Pubkey;
  use std::str::FromStr;

  let client = PhoenixHttpClient::new_from_env()?;
  let authority = Pubkey::from_str("AUTHORITY_PUBKEY")?;

  let trader_from_access = client
      .invite()
      .activate_invite(&authority, "ACCESS_CODE")
      .await?;

  let trader_from_referral = client
      .invite()
      .activate_referral(&authority, "REF_CODE")
      .await?;
  ```
</CodeGroup>

<Tip>
  For a ready-to-run Rust version of this flow, see [`rust/sdk/examples/register_trader.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/register_trader.rs).
</Tip>

## Fetching exchange, market, and trader state

The HTTP surface is intentionally split by what kind of state you want:

* `exchange().getSnapshot()` — exchange-wide state plus every market's current config snapshot
* `exchange().getMarket(symbol)` — one market's fees, risk, funding cadence, and configuration
* `orderbook().getOrderbook(symbol)` — an HTTP L2 snapshot for one market
* `traders().getTraderStateSnapshot(...)` (TypeScript) or `traders().get_trader(...)` (Rust) — a trader-centric view of collateral, positions, orders, and triggers
* `markets().getMarketStatsHistory(...)` and `funding().getFundingRateHistory(...)` — time-series data for frontends, vault products, and analytics

<CodeGroup>
  ```ts TypeScript theme={null}
  import { PhoenixHttpClient } from "@ellipsis-labs/rise";

  const client = new PhoenixHttpClient({
    apiUrl: "https://perp-api.phoenix.trade",
  });

  const symbol = "SOL";
  const authority = "AUTHORITY_PUBKEY";

  const [snapshot, market, orderbook, trader] = await Promise.all([
    client.exchange().getSnapshot(),
    client.exchange().getMarket(symbol),
    client.orderbook().getOrderbook(symbol),
    client.traders().getTraderStateSnapshot(authority, { traderPdaIndex: 0 }),
  ]);
  ```

  ```rust Rust theme={null}
  use phoenix_rise::PhoenixHttpClient;
  use solana_pubkey::Pubkey;
  use std::str::FromStr;

  let client = PhoenixHttpClient::new_from_env()?;
  let authority = Pubkey::from_str("AUTHORITY_PUBKEY")?;

  let snapshot = client.exchange().get_snapshot().await?;
  let market = client.markets().get_market("SOL").await?;
  let trader_subaccounts = client.traders().get_trader(&authority).await?;
  ```
</CodeGroup>

For broader TypeScript walkthroughs, see [`ts/examples/01-http-client.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/01-http-client.ts) and [`ts/examples/phoenix-client-example.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/phoenix-client-example.ts).

## Order placement and cancellation

The SDK separates packet construction from instruction construction:

* Build packet sizes and prices with `client.orderPackets`
* Build or wrap the actual Solana instructions with `client.ixs`
* Use the lower-level builders when you need conditional-account setup or other specialized flows

<CodeGroup>
  ```ts TypeScript theme={null}
  import {
    Direction,
    Side,
    StopLossOrderKind,
    createPhoenixClient,
  } from "@ellipsis-labs/rise";

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

  const authority = "AUTHORITY_PUBKEY";
  const symbol = "SOL-PERP";

  const limitPacket = await client.orderPackets.buildLimitOrderPacket({
    symbol,
    side: Side.Bid,
    priceUsd: "150.50",
    baseUnits: "0.25",
  });

  const placeLimitIx = await client.ixs.placeLimitOrder({
    authority,
    symbol,
    orderPacket: limitPacket,
  });

  const marketPacket = await client.orderPackets.buildMarketOrderPacket({
    symbol,
    side: Side.Bid,
    baseUnits: "0.25",
  });

  const placeMarketIx = await client.ixs.placeMarketOrder({
    authority,
    symbol,
    orderPacket: marketPacket,
  });

  const stopLossIx = await client.ixs.buildPlaceStopLoss({
    authority,
    symbol,
    tradeSide: Side.Ask,
    executionDirection: Direction.LessThan,
    orderKind: StopLossOrderKind.IOC,
    triggerPrice: 1420n,
  });

  const cancelByIdIx = await client.ixs.buildCancelOrdersById({
    authority,
    symbol,
    orders: [{ price: 1500n, orderSequenceNumber: "123" }],
  });

  const cancelAllIx = await client.ixs.buildCancelAll({ authority, symbol });

  const cancelStopLossIx = await client.ixs.buildCancelStopLoss({
    authority,
    symbol,
    executionDirection: Direction.LessThan,
  });
  ```

  ```rust Rust theme={null}
  use phoenix_rise::{
      BracketLeg, BracketLegOrders, BracketLegTicket, CancelId, LimitOrderTicket,
      MarketOrderTicket, PhoenixTxBuilder, Side, TraderKey,
  };
  use solana_rpc_client::nonblocking::rpc_client::RpcClient;
  use std::sync::Arc;

  let trader = TraderKey::new(authority);
  let builder = PhoenixTxBuilder::new(&metadata);

  let limit_ixs = builder
      .place_limit_order(
          LimitOrderTicket::builder()
              .authority(trader.authority())
              .trader_account(trader.pda())
              .symbol("SOL-PERP")
              .side(Side::Bid)
              .price(150.50)
              .num_base_lots(25_000)
              .build()?,
      )
      .await?;

  let market_ixs = builder
      .place_market_order(
          MarketOrderTicket::builder()
              .authority(trader.authority())
              .trader_account(trader.pda())
              .symbol("SOL-PERP")
              .side(Side::Bid)
              .num_base_lots(25_000)
              .build()?,
      )
      .await?;

  let bracket_ixs = builder
      .place_position_bracket_order(
          trader.authority(),
          trader.pda(),
          "SOL-PERP",
          Side::Bid,
          BracketLegTicket::new(
              Arc::new(RpcClient::new("https://api.mainnet-beta.solana.com".into())),
              BracketLegOrders {
                  stop_loss: Some(BracketLeg::new(142.0)),
                  take_profit: None,
              },
          ),
      )
      .await?;

  let cancel_ixs = builder.build_cancel_orders(
      trader.authority(),
      trader.pda(),
      "SOL-PERP",
      vec![CancelId::new(1500, 123)],
  )?;
  ```
</CodeGroup>

<Note>
  `buildPlaceStopLoss(...)` takes tick-based trigger prices. When starting from USD prices, convert them from market metadata first, or reuse the conditional-order patterns in [`ts/examples/05-cancel-all-conditional-orders.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/05-cancel-all-conditional-orders.ts).
</Note>

Runnable examples:

* [`ts/examples/03-build-limit-order-ix.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/03-build-limit-order-ix.ts)
* [`ts/examples/05-cancel-all-conditional-orders.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/05-cancel-all-conditional-orders.ts)
* [`rust/sdk/examples/send_limit_order.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/send_limit_order.rs)
* [`rust/sdk/examples/send_market_order.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/send_market_order.rs)
* [`rust/sdk/examples/cancel_order.rs`](https://github.com/Ellipsis-Labs/rise-public/blob/master/rust/sdk/examples/cancel_order.rs)

## Flight builder activation and routed orders

<Warning>
  Flight support in Rise is currently beta and should not yet be treated as a stable production surface.
</Warning>

Flight is the builder-routing layer. Key pieces:

* The builder still needs a Phoenix trader account
* Builder registration is its own on-chain instruction (see [Flight](/phoenix/flight#registering))
* The builder's associated trader account is the fee collector for Flight-routed orders
* Once a client is configured with `flight: { builderAuthority, ... }`, supported order instructions are wrapped automatically

When you register Flight against a builder authority and its associated trader account, all builder fees from Flight-routed orders accrue to that builder trader account. Those fees are withdrawable from the Phoenix frontend.

<CodeGroup>
  ```ts TypeScript theme={null}
  import {
    MarginType,
    Side,
    createPhoenixClient,
    flight,
  } from "@ellipsis-labs/rise";

  const builderAuthority = "BUILDER_AUTHORITY";

  const client = createPhoenixClient({
    apiUrl: "https://perp-api.phoenix.trade",
    rpcUrl: "https://api.mainnet-beta.solana.com",
    ws: false,
    flight: {
      builderAuthority,
      builderPdaIndex: 0,
      builderSubaccountIndex: 0,
    },
  });

  const registerTraderIx = await client.ixs.buildRegisterTrader({
    authority: builderAuthority,
    marginType: MarginType.Cross,
  });

  const registerBuilderIx = await flight.buildRegisterBuilderIx({
    traderAuthority: builderAuthority,
    traderPdaIndex: 0,
    traderSubaccountIndex: 0,
    feeBps: 25n,
  });

  const routedMarketIx = await client.ixs.placeMarketOrder({
    authority: "TRADER_AUTHORITY",
    symbol: "SOL-PERP",
    orderPacket: await client.orderPackets.buildMarketOrderPacket({
      symbol: "SOL-PERP",
      side: Side.Bid,
      baseUnits: "0.25",
    }),
  });

  console.log(routedMarketIx.programAddress === flight.FLIGHT_PROGRAM_ADDRESS);
  ```

  ```rust Rust theme={null}
  use phoenix_rise::ix::flight::{RegisterBuilderParams, create_register_builder_ix};
  use phoenix_rise::{MarketOrderTicket, PhoenixFlightClient, PhoenixTxBuilder, Side};

  let register_builder_ix = create_register_builder_ix(
      RegisterBuilderParams::builder()
          .trader_authority(builder_authority)
          .trader_account(builder_trader_account)
          .fee_bps(25)
          .build()?,
  )?;

  let flight = PhoenixFlightClient::new(builder_authority, 0, 0);

  let routed_ixs = builder
      .place_market_order(
          MarketOrderTicket::builder()
              .authority(trader_authority)
              .trader_account(trader_account)
              .symbol("SOL-PERP")
              .side(Side::Bid)
              .num_base_lots(25_000)
              .build()?,
      )
      .await?
      .into_iter()
      .map(|ix| flight.try_wrap_order_instruction(ix, trader_authority))
      .collect::<Result<Vec<_>, _>>()?;
  ```
</CodeGroup>

For more Flight-specific TypeScript examples, see [`ts/src/flight/README.md`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/src/flight/README.md).

## Live market data

Use the typed WebSocket adapters when you want continuous updates instead of a single HTTP snapshot.

```ts TypeScript theme={null}
import { createPhoenixClient } from "@ellipsis-labs/rise";

const client = createPhoenixClient({
  apiUrl: "https://perp-api.phoenix.trade",
  ws: { connectMode: "eager" },
});

for await (const update of client.streams!.l2Book("SOL-PERP")) {
  console.log(update.bids[0], update.asks[0]);
}
```

Ready-to-run TypeScript stream examples:

* [`ts/examples/02-ws-fills.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/02-ws-fills.ts)
* [`ts/examples/phoenix-ws-example.ts`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/examples/phoenix-ws-example.ts)
