AccountInfo
handles and needs to invoke Phoenix, Ember, Flight, or Hawkeye directly. The SDK
does not fetch accounts or derive every PDA at CPI time. Your program validates
and resolves accounts, then adapts them into typed CPI contexts such as
phoenix::PlaceMarketOrder, phoenix::PlaceStopLoss, or
hawkeye::ViewMargin.
Reference implementations:
- rise-public programs/example-program
- example-program/src/market.rs
- example-program/src/place_stop_loss.rs
- example-program/tests/common/mod.rs
Example Program Map
Use the example program as the source of truth for complete account lists. The docs below show the shape of each CPI, but the linked files show the full outer instruction, parameter struct, account metas, LiteSVM test setup, and log assertions.| Flow | Program code | Test coverage |
|---|---|---|
| Market order, limit order, cancel by id, matching-engine return data, and Hawkeye margin read | market.rs, place_market_order.rs, place_limit_order.rs, cancel_limit_order.rs | market_orders.rs |
| Ember wrap then Phoenix deposit | deposit_ember_then_phoenix.rs | deposit_withdraw.rs |
| Phoenix withdraw then Ember unwrap | withdraw_phoenix_then_ember.rs | deposit_withdraw.rs |
| Stop-loss placement and cancellation | place_stop_loss.rs, cancel_stop_loss.rs | stop_loss.rs |
| Register isolated subaccount, sync parent capabilities, transfer collateral, trade, close, and sweep | register_subaccount_sync_transfer_and_market_order.rs, close_subaccount_position_and_sweep.rs | subaccounts.rs |
| Shared fixture setup, dynamic accounts, account metas, compute budget, and log helpers | tests/common/mod.rs | programs/example-program/tests |
Dependencies
Most on-chain programs should depend on thephoenix-rise facade with only the
cpi feature enabled. That profile exposes account byte decoders, instruction
layouts, and Pinocchio CPI helpers without the HTTP, WebSocket, RPC, or
transaction-builder graph.
Cargo
phoenix-rise-ix
directly.
Cargo
Cargo
Imports
Using the facade crate:Rust
Rust
CPI Shape
The typed CPI contexts are account-context structs. They borrow accounts from your outer instruction and encode the expected Phoenix account order for you. They do not own accounts and they do not resolve missing accounts from chain state. Phoenix order CPIs usually need:- Phoenix program id and log authority.
- Global config and
PerpAssetMap. - Trader signer or delegated authority, plus the trader account.
- Market orderbook and spline collection.
- Dynamic
global_trader_indexaccounts. - Dynamic
active_trader_bufferaccounts. - Optional accounts for stop losses, conditionals, Hawkeye, Ember, or Flight.
global_trader_index and active_trader_buffer accounts at the tail. The tail
counts are carried in instruction data, so the loader can split the account
slice without allocation.
Rust
Market Context
A useful integration pattern is to create one outer context that knows how to load and validate your instruction accounts, then add small helper methods that project those accounts into the SDK’s typed CPI contexts.Rust
Invoke Phoenix
Once your outer context can build the typed CPI context, the invoke step is small: createCpiScratch, pass instruction-specific args, and let the SDK
write the account metas and instruction data.
Rust
CpiScratch owns fixed-size stack buffers for account infos, account metas, and
instruction data. For dynamic market accounts, size it to your integration’s
upper bound and check ctx.account_count() before invoking if the account count
is user-controlled. If you already have reusable storage, use CpiBuffers and
invoke_with_buffers(...) instead.
Stop Losses And Conditionals
Stop losses and conditional orders follow the same pattern, but the account context includes the funder, position authority, conditional or stop-loss account, and system program. Creating a stop-loss or conditional-order account can incur rent if the account does not already exist.Rust
Collateral CPIs
Collateral flows often compose Ember and Phoenix CPIs in one outer instruction. The example program wraps fake USDC into Phoenix collateral through Ember, then deposits that collateral into the Phoenix trader account.Rust
Subaccount CPIs
Subaccount flows are a good example of composing several typed contexts. The example registers the child trader account, syncs parent capabilities, transfers collateral to the child, then reusesMarketContext to place the child order.
Rust
Return Data
Phoenix order CPIs can return matching-engine data. Decode return data instead of parsing logs.Rust
Hawkeye Views
Hawkeye is the read-only program for authoritative margin, liquidation-price, BBO, and funding views. Invoke it when local SDK math is not enough and you need the result the on-chain programs would use. Hawkeye writes versioned return data; decode those bytes instead of parsing logs. Hawkeye program id:RiSeVw3ZjNfsaXPRb4mgaqYaEEt41pNNJoDvVh7pgQj.
Use it to validate the CPI program account on-chain and to assert that
simulation return data came from Hawkeye off-chain.
ix::cpi::hawkeye::ViewMargin; the
other views are exposed through off-chain instruction builders and can be
mirrored on-chain with the same account metas and discriminators if your program
needs them.
| View | Hawkeye ix | Return data | SDK entry points |
|---|---|---|---|
| Account margin | view_margin | ViewMarginReturn / HawkeyeMarginReturn | On-chain ix::cpi::hawkeye::ViewMargin; TypeScript client.rpc.hawkeye.viewMargin(...) or buildHawkeyeViewMarginIx(...); Rust PhoenixHawkeyeClient::view_margin(...) or create_hawkeye_view_margin_ix(...) |
| Asset margin | view_margin_for_asset | ViewAssetReturn / HawkeyeAssetReturn | TypeScript client.rpc.hawkeye.viewMarginForAsset(...) or buildHawkeyeViewMarginForAssetIx(...); Rust PhoenixHawkeyeClient::view_margin_for_asset(...) or create_hawkeye_view_margin_for_asset_ix(...) |
| Liquidation price | view_liquidation_price | ViewLiquidationPriceReturn / HawkeyeLiquidationPriceReturn | TypeScript client.rpc.hawkeye.viewLiquidationPrice(...) or buildHawkeyeViewLiquidationPriceIx(...); Rust PhoenixHawkeyeClient::view_liquidation_price(...) or create_hawkeye_view_liquidation_price_ix(...) |
| Best bid/offer | view_bbo | ViewBboReturn / HawkeyeBboReturn | TypeScript client.rpc.hawkeye.viewBbo(...) or buildHawkeyeViewBboIx(...); Rust PhoenixHawkeyeClient::view_bbo(...) or create_hawkeye_view_bbo_ix(...) |
| Funding | view_funding | ViewFundingReturn / HawkeyeFundingReturn | TypeScript client.rpc.hawkeye.viewFunding(...) or buildHawkeyeViewFundingIx(...); Rust PhoenixHawkeyeClient::view_funding(...) or create_hawkeye_view_funding_ix(...) |
On-chain CPI
On-chain programs read Hawkeye return data the same way they read Phoenix return data: invoke the program, callget_return_data() immediately, assert the
return-data program id is Hawkeye, then decode the expected struct. Return data
is overwritten by the next CPI that sets it, so decode or copy it before another
Phoenix or Hawkeye call.
The example program invokes hawkeye::ViewMargin after market orders and
decodes the return into ViewMarginReturn.
Rust
Rust
Off-chain simulation
For applications and services, prefer the SDK Hawkeye RPC helpers. They build a read-only simulation transaction, validate that return data came from the Hawkeye program id, and decode the bytes into the typed return shape.Supported CPI Contexts
The typed CPI surface includes:- Trader lifecycle:
RegisterTrader,SetTraderCapabilitiesDelegated,UpdateTraderState,SyncParentToChild. - Order flow:
PlaceMarketOrder,PlaceLimitOrder,PlaceMarketOrderDelegated,PlaceMultiLimitOrder,CancelAll,CancelUpTo,CancelOrdersById,CancelAllPlusConditional. - Collateral and subaccounts:
PhoenixDeposit,PhoenixWithdraw,TransferCollateral,TransferCollateralChildToParent. - Stop losses and conditionals:
CreateConditionalOrdersAccount,PlaceStopLoss,CancelStopLoss,PlacePositionConditionalOrder,PlaceAttachedConditionalOrder,PlaceLimitOrderWithConditionals,CancelConditionalOrder. - Ember collateral movement:
ember::EmberDeposit,ember::EmberWithdraw. - Hawkeye reads:
hawkeye::ViewMargin/hawkeye::HawkeyeViewMargin.