Commands and recovery
Use these commands from the SDK example directory.
Each quote command publishes once. Use one quote writer per trader and perp.
cargo run --locked -- accountnpm run start -- accountReplace account with a command from the tables below.
Commands
markets needs only PUBLIC_ENDPOINT. Every other command needs TRADER_ID,
PERP_ID and RPC_URL, plus PUBLIC_ENDPOINT for the program check except
disable-rpc.
Keys are Solana JSON keypair files:
- Owner commands use
OWNER_KEYPAIR. - Bot commands use
QUOTER_KEYPAIR. - Maker API commands also need
MAKER_ENDPOINT.
The tables list any extra inputs.
Read state
| Command | Effect | Extra inputs | Uses |
|---|---|---|---|
markets | List perps, marks and collateral markets | None | Public API |
account | Read collateral, health and perp positions | None | Public API; no key required |
state | Read levels, sequences, slot, strategy and enabled flag | None | Bot, Maker API |
fills | Read the last 50 maker fills on the selected perp | Historical store required | Bot, Maker API |
state --raw includes strategy bytes.
Publish and disable quotes
| Command | Effect | Extra inputs | Uses |
|---|---|---|---|
quote MODE BID ASK LOTS TTL | Reset the strategy and publish both sides | Quote arguments | Bot, Maker API |
disable | Keep quote bytes; set enabled=false | None | Bot, Maker API |
disable-rpc | Disable quotes without the gateway | None | Bot, RPC |
Both disable commands require the bot's on-chain Trade permission.
Follow Stop quote writes before the final disable.
Manage the account
| Command | Effect | Extra inputs | Uses |
|---|---|---|---|
setup | Create a missing trader; grant Trade + Quote | QUOTER_KEYPAIR | Owner, RPC |
deposit | Deposit collateral | COLLATERAL_MINT, COLLATERAL_ATOMS | Owner, RPC |
open | Open a slot after the MAY_QUOTE grant | None | Owner, RPC |
release | Release the slot for reuse | None | Owner, RPC |
revoke | Permanently revoke the selected bot key on this trader | QUOTER_KEYPAIR | Owner, RPC |
settle-funding | Book accrued funding | None | Owner as fee payer, RPC |
settle-pnl | Settle available realised PnL | COLLATERAL_MINT | Owner as fee payer, RPC |
withdraw | Withdraw free collateral | COLLATERAL_MINT, WITHDRAW_ATOMS | Owner, RPC |
Deposit and withdrawal use existing owner associated token accounts.
withdraw does not create one.
Operator permission
| Command | Effect | Extra inputs | Uses |
|---|---|---|---|
grant | Grant MAY_QUOTE to an existing trader | Operator's ADMIN_KEYPAIR | Operator, RPC |
The maker asks the Flint operator for this grant.
Quote arguments
- MODE:
order-list,densityorrelative-density. - BID and ASK: prices in ticks, with ASK greater than BID.
- LOTS: quantity in contract lots.
- TTL: lifetime in slots.
All four numbers must be positive UInt32 integers. Every mode expires automatically. Density modes install a one-tick band at each fair.
Settlement mint
For settle-pnl, use the perp's PnL currency in COLLATERAL_MINT, even if you
deposited another asset. Restore your collateral mint before deposit or withdrawal.
Settlement changes the trader account's balances; withdrawal moves funds to
the owner's wallet.
Check a complete trade
Both examples require err == null at confirmed or finalized RPC
commitment. After a timeout, follow
Unknown transaction outcome before submitting a replacement.
- Submit a small, collateral-backed quote and wait for confirmation.
- Read
statebefore expiry. Check the enabled flag, strategy and both sides. - Have an independently funded taker cross one side. Save its signature.
- Run
fillsandaccount. Check the maker's direction, price, quantity, rebate and position against the taker's confirmed transaction. - Stop maker quotes and cancel resting orders before closing both positions. Follow Shutdown to settle and test a small withdrawal.
Use the order instructions in your integration for taker and reduce-only orders. Local maker testing provides an isolated network, synthetic keys and an independent taker example.
Stop quote writes
Use this procedure before shutdown, planned key rotation, sequence reset or reopening a slot:
- Stop every writer for the affected account and perps, including submission queues and retries that can send signed transactions.
- Submit a disable if quotes are still fillable. A pending update can re-enable the slot, so repeat the disable after the remaining steps.
- Resolve every outstanding signed transaction. Wait for its confirmed or finalized result. If its outcome is unknown, follow Unknown transaction outcome. Continue until no earlier transaction can execute later.
- Read the current slot and account state. Then perform the final disable, cancellation, reset or reopen required by your procedure.
Stopping a process leaves its stored quotes and resting orders active until they expire or you remove them. Revoking a key removes its authority; stored quotes and orders remain active under their existing rules.
Planned key rotation
For a compromised key, revoke its on-chain authority first.
- Follow Stop quote writes for the old key. Disable each
slot, cancel resting orders and confirm the results. Use
disable-rpcwith the old bot key if the gateway is unavailable. - Set
QUOTER_KEYPAIRto a new key with fee SOL and runsetupwith the owner. Flint supplies fee SOL. This reuses the owned trader account. - Read
stateand confirm a short-lived quote with the new key. - Set
QUOTER_KEYPAIRto the old key and runrevokewith the owner. - Restore the new key path, verify the old key cannot write, then start the writer.
Revocation is permanent for that key on that trader. An API session cannot restore the on-chain grant.
Shutdown
- Follow Stop quote writes. Disable each slot and cancel resting orders. Confirm the transactions and read state to check the results.
- Read
accountand close exposure with reduce-only orders if leaving the market. Removing quotes does not close positions. - Settle funding and PnL. Verify flat positions and enough free collateral for the intended withdrawal. A flat position can still owe fees or funding; a refused no-op settlement does not prove exposure is closed.
- Release unused slots and revoke any bot grant with the owner.
- Set
WITHDRAW_ATOMSto integer token atoms and runwithdraw, or use the dashboard. Check account collateral and the owner's token balance. WSOL withdrawals return wrapped tokens to the owner's token account.
Releasing a slot returns no rent, settles no cash and leaves exposure open.
Fix an error
| Observation | Next step |
|---|---|
| Package install 401/403 | Ask the operator for registry/package access. |
| No email sign-in code | Check the address and spam folder. Ask your Flint contact to check email registration and code delivery. |
| No Perps after email login | Ask the operator to check perp_maker_id. |
| Account ID taken | Check ownership; ask for another ID if someone else owns it. |
| Delegate exists | Inspect the grant. Expired or revoked grants need a new key; setup cannot renew them. |
| No MAY_QUOTE | Ask the operator to grant the existing trader account. |
| No slot / maker limit | Open after permission, or wait for a released slot if all 32 are occupied. |
| Sequence did not advance | Stop competing writers, read state and allocate a counter above the accepted value. |
| Sequence exhausted | Stop all writers and use the guarded reset. |
| Transaction outcome unknown | Follow the procedure below. |
| Rust chain streams not ready | Stop the bot; ask the operator to restore blockhash, slot and fee feeds. |
| Stale mark/oracle or absent health | Stop quoting; ask the operator to restore prices and keeper updates. |
| Nothing to settle | Check outstanding funding/PnL; a no-op may be refused. |
| PnL exceeds pool liquidity | Accept a partial payout or wait for pool funding. Unsettled gains are not wallet cash. |
Unknown transaction outcome
Both examples print prepared <signature> blockhash=<hash> before submission;
TypeScript also prints lastValidBlockHeight. Save those values, the command,
trader/perp IDs and intended change. A submission error can occur after acceptance.
- Stop retries that build new transactions. Keep the original signed bytes if available.
- Query
getSignatureStatuseson your configured RPC withsearchTransactionHistory: true. UsegetTransactionat confirmed or finalized commitment for instructions and logs. - If confirmed or finalized with
err: null, do not repeat the action. Reconcilestateandaccount, plusfillsfor a trade. - If execution failed, inspect logs and state; correct the cause before rebuilding.
- If no status is available, check lifetime: compare TypeScript's
lastValidBlockHeightwithgetBlockHeight; for Rust, check the saved blockhash withisBlockhashValidat confirmed commitment. While valid, keep observing. Transport retries must send the same signed bytes. - After expiry, search history again and reconcile account and slot state. Expiry stops future execution but does not rule out earlier execution. If history is unavailable or state inconsistent, keep the writer stopped and ask the operator to reconcile before rebuilding.
Quote expiry is separate: an empty or expired quote does not prove its transaction failed.