Onchain Solana First Trade¶
Use this tutorial to make a small Onchain Solana trade from the CLI. It starts with read-only Solana checks, uses preview before live submission, and ends with post-trade reconciliation.
Onchain (Solana) trading is experimental. Keep first trades small and use explicit SPL mint addresses for token trades.
Prerequisites¶
Update the CLI when you intend to replace the installed binary:
State change: Upgrade the installed Bullpen CLI.
Then check auth before trading:
Run bullpen login only when status or auth diagnostics say login is required.
Then enable Solana:
State change: Enable the experimental Solana command group.
Fund your Bullpen-managed Solana wallet through the web app deposit flow:
After the deposit settles, refresh balances:
Example refreshed balance output
Find a Token¶
Search by symbol or name, then inspect the exact mint:
bullpen solana search WIF --output json
bullpen solana token <MINT> --output json
bullpen solana price <MINT> --output json
Use the mint address from search output. Do not use a ticker alone for buy,
sell, swap, SPL withdraw, limit-order, or DCA commands. Native SOL withdrawal
is different: omit --token instead of passing a mint. General reads such as
balance, portfolio, and unfiltered history do not require a mint.
Check Token Risk¶
Review token risk before previewing a buy:
Continue only when the risk warnings, holder concentration, developer context, and token metadata match your tolerance. Treat missing risk fields as incomplete evidence, not as a clean bill of health.
Solana token trades and SPL withdrawals require base58 SPL token mint
addresses. Use bullpen solana search <SYMBOL> for discovery, then pass the
returned mint to buy, sell, swap, limit-buy, limit-sell,
dca create, or withdraw --token; symbols such as BONK are not accepted
as trade inputs. Native SOL withdrawal omits --token.
Preview the Buy¶
Preview returns a Jupiter Ultra quote without signing or submitting a transaction:
Review the input amount, output amount, route, price impact, slippage, fees, and any shield warnings.
Example buy preview output
Default slippage is 50 bps. Use --slippage-bps only when you have reviewed
the route and price impact.
Submit the Buy¶
Run the live command only after the preview matches your intent:
Live: Run the buy preview first. Submit only when the route, mint, amount, slippage, and warnings match your intent.
The live path signs with the Bullpen-managed Turnkey Solana signer and submits
through Bullpen's Solana transaction path. If the command reports an auth or
signing-session error, run bullpen status --output json and
bullpen doctor auth --output json; run bullpen login only when diagnostics
or the failed command says login is required. Then rerun the same preview
before submitting again.
Example live buy output shape
{
"kind": "solana_swap_result",
"success": true,
"status": "confirmed",
"signature": "5Zk...abc",
"tx_signature": "5Zk...abc",
"readback_status": "confirmed",
"receipt_status": "confirmed",
"input_mint": "EPjF...Dt1v",
"input_symbol": "USDC",
"input_amount": "5",
"output_mint": "<MINT>",
"output_symbol": "TOKEN",
"output_amount": "1234.56",
"input": {
"mint": "EPjF...Dt1v",
"symbol": "USDC",
"amount": "5"
},
"output": {
"mint": "<MINT>",
"symbol": "TOKEN",
"amount": "1234.56"
},
"slot": 341234567
}
Reconcile After Submission¶
Refresh balances and inspect recent activity:
bullpen solana balance --refresh --output json
bullpen solana history --limit 10 --output json
bullpen solana orders --output json
balance --refresh is the preferred post-trade check because it requests a
portfolio refresh and overlays fresh on-chain SOL and SPL-token balances when a
Solana RPC source is available. JSON output includes freshness.status,
freshness.source, freshness.on_chain_proven, freshness.checked_at_ms, and
freshness.warning.
Treat freshness.status: "fresh" with on_chain_proven: true as the strongest
post-fill proof. If the CLI returns pending_indexer_refresh, the command kept
the portfolio cache and attached a warning because it could not prove the latest
on-chain state through RPC. Wait briefly and run the refresh again before
submitting another live buy or declaring cleanup failed.
When a live swap report returns success: true, the transaction landed even if
readback_status is readback_pending or readback_failed. If you need to
sell the received token immediately, run:
Match the live report signature against entries[].signature, then use the
matching received.amount for the cleanup sell. Do not size cleanup from a
stale balance snapshot.
Sell or Swap Back¶
Preview the exit first. If you plan to use rate-limit retry for the live sell, include it in the preview too so the documented intent matches:
bullpen solana sell <MINT> <TOKEN_AMOUNT> --preview --retry-after-rate-limit --output json
bullpen solana swap <MINT> EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v <TOKEN_AMOUNT> --preview --output json
Submit only after reviewing the route:
Live: Submit only after the matching sell preview shows the intended route, mint, amount, slippage, and rate-limit retry behavior.
--retry-after-rate-limit waits for Jupiter's returned cooldown and retries
once when the first live submit was rate-limited before a transaction signature
existed. It does not replay a transaction after a signature or receipt exists.
If the sell succeeds but leaves only sub-cent residual token dust, the live JSON
report includes post_swap_dust; leave that dust alone unless the balance grows
enough for a normal sell route.
Native SOL as the input side of a live sell or swap may require a Jupiter
auxiliary signature that Bullpen cannot provide. If the CLI returns
SOLANA_SWAP_UNSUPPORTED_ROUTE, use an SPL-token input route or retry with a
USDC-to-token flow.
Preview Limit Orders¶
Use a limit order when you want Jupiter Trigger v2 to buy or sell once a
target price is crossed. Preview first; the preview builds the order plan
without signing or submitting. These orders execute as a swap when the
trigger price is crossed, not as an exact resting fill — Trigger v2's
create request has no output-amount field, only inputAmount and
triggerPriceUsd, so the amount you receive depends on the swap Jupiter
runs at that moment. --slippage-bps controls that swap's slippage
tolerance and defaults to the CLI's configured Solana swap slippage; preview
JSON marks output_amount_is_estimate: true and execution: "trigger_swap"
for exactly this reason. Jupiter Trigger v2 requires a deposit of at least
$10 per limit order (raised from Trigger v1's $5). The examples below use
the minimum valid size; smaller orders return SOLANA_TRIGGER_ORDER_TOO_SMALL
before signing or provider submission. --expiry defaults to 30d;
--expiry never is rejected because Trigger v2 has no never-expiring order.
bullpen solana limit-buy <MINT> 10 --price <USD> --preview --output json
bullpen solana orders --status active --output json
bullpen solana cancel-order <ORDER_KEY> --preview --output json
Submit or cancel only after you review the preview:
Live: Submit or cancel only after the matching preview shows the intended mint, price, amount, and trigger condition.
bullpen solana limit-buy <MINT> 10 --price <USD> --yes --output json
bullpen solana cancel-order <ORDER_KEY> --yes --output json
orders is read-only, but Jupiter Trigger v2 requires a signed authentication
challenge to read order history, so orders needs a real signer even though
it never submits a transaction. Use the order id returned by orders or by
the live create response; do not invent one from the token mint. Live
limit-order create JSON results expose kind, success, status,
order_key, order_id, deposit_confirmed, and signature; cancel results
keep the order, tx_signature, and landed fields. cancel-all-orders has
no upstream batch route: it cancels one order at a time and stops before
processing the rest of the batch if an order's outcome cannot be
automatically reconciled. After a live cancel, run
bullpen solana balance --refresh --output json before relying on returned
funds — unless landed is true and status reads landed_unconfirmed
(Jupiter confirmed the withdrawal but returned an unreadable body), in which
case reconcile with bullpen solana orders --output json instead.
Preview DCA¶
Use DCA when you want Jupiter Recurring to split a USDC-to-token buy over time.
--per-cycle is in input-token units. For USDC input, --per-cycle 50 means
50 USDC per cycle. --cycles must be between 2 and 1000; invalid cycle counts
return SOLANA_DCA_INVALID_CYCLES before Jupiter is called.
bullpen solana dca create EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v <MINT> --per-cycle 50 --cycles 4 --interval 1d --preview --output json
bullpen solana dca list --status active --output json
bullpen solana dca cancel <ORDER_KEY> --preview --output json
Jupiter Recurring enforces provider-side minimums. If the CLI reports
SOLANA_DCA_MINIMUM_PER_CYCLE, increase --per-cycle or use a normal preview
buy instead.
After a live DCA create, inspect index_status in JSON output. If the schedule
is still indexing, the CLI returns index_status: "index_timeout" on create or
SOLANA_DCA_INDEX_PENDING on cancel with retry_after_secs and next_command.
Wait before retrying and run bullpen solana dca list --all --output json
before creating another schedule. Live DCA JSON results expose kind,
success, status, order_key, signature, and tx_signature. After a live
cancel, run bullpen solana balance --refresh --output json before relying on
returned funds.
Troubleshooting¶
| Symptom | What to run |
|---|---|
| Solana command is hidden | bullpen experimental enable solana |
| Balance looks stale | bullpen solana balance --refresh --output json |
| Jupiter rate limited the route | Read next_command_after, wait for retry_after_secs, rerun preview, then retry the same live command only if the preview is still acceptable. Use --retry-after-rate-limit for unattended cleanup after a confirmed buy or swap. |
| Signing session expired | Run bullpen status --output json and bullpen doctor auth --output json; run bullpen login only when diagnostics or the failed command requires login |
| Token ticker is ambiguous | bullpen solana search <QUERY> --output json and use the mint |
| Live route is unsupported | Use an SPL-token route or a USDC-to-token buy |
See Onchain (Solana) for the full command surface and current limitations.
Use generated references for exact flags:
buy,
sell,
swap,
history,
limit-buy,
orders,
cancel-order,
dca create,
dca list,
dca cancel,
token risk,
token hide, and
token unhide.