- Refresh prices (fork only). The fork has no live price pushers. The app calls
POST /api/prices/refresh, which rewrites the oracle accounts with live prices before a borrow, withdraw ormargin_execute. - Build named accounts from PDAs.
- Build
remaining_accountswithbuildHealthRemainingAccounts: allowed-token groups, venue groups, debt groups, then the oracle segment (and the validator segment for Phoenix). - Compute budget and lookup tables.
margin_executeinto Phoenix or a basis vault needs a v0 transaction with an address lookup table and a high compute-unit limit. - Simulate, then send. If simulation fails, do not broadcast.
MarginIndexModel in lib/solana/margin.ts replays each instruction’s effect on the margin’s active lists, so each one gets the right groups.
Example: perps open
Multi-step flows
The program has no atomic “close everything” instruction. The app’s flash repay (lib/solana/flash-repay.ts) is a sequence of ordinary transactions: close Phoenix positions, redeem Kamino cTokens, swap holdings into each debt token, repay_all each loan, then optionally withdraw everything. Each step re-reads the chain, so a run that stopped half-way resumes cleanly.
Common errors
- Blockhash not found: the wallet is not pointed at the fork RPC.
- Stale price: refresh prices and retry.
- Stale pool on the fork: Jupiter’s route used a cloned pool that drifted. The app re-clones it from mainnet and retries.

