Skip to content

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.

bullpen upgrade

Then check auth before trading:

bullpen status --output json
bullpen doctor auth --output json

Run bullpen login only when status or auth diagnostics say login is required. Then enable Solana:

State change: Enable the experimental Solana command group.

bullpen experimental enable solana

Fund your Bullpen-managed Solana wallet through the web app deposit flow:

bullpen solana deposit

After the deposit settles, refresh balances:

bullpen solana balance --refresh --output json
Example refreshed balance output
{
  "address": "7qRk...u1G8e",
  "sol_balance": "0.42",
  "total_usd": "125.55",
  "tokens": [
    {
      "mint": "EPjF...Dt1v",
      "symbol": "USDC",
      "amount_ui": "125.55",
      "value_usd": "125.55"
    }
  ]
}

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:

bullpen solana token risk <MINT> --output json

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:

bullpen solana buy <MINT> 5 --preview --output json

Review the input amount, output amount, route, price impact, slippage, fees, and any shield warnings.

Example buy preview output
{
  "action": "buy",
  "input_mint": "EPjF...Dt1v",
  "input_symbol": "USDC",
  "input_amount": "5",
  "output_mint": "<MINT>",
  "output_symbol": "TOKEN",
  "output_amount": "1234.56",
  "price_impact_pct": "0.18",
  "slippage_bps": 50,
  "would_submit": false,
  "warning": null
}

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:

bullpen solana buy <MINT> 5 --preview --output json

Live: Run the buy preview first. Submit only when the route, mint, amount, slippage, and warnings match your intent.

bullpen solana buy <MINT> 5 --yes --output json

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:

bullpen solana history --type trades --limit 10 --output json

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.

bullpen solana sell <MINT> <TOKEN_AMOUNT> --yes --retry-after-rate-limit --output json

--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 to buy or sell only at a target price. Preview first; the preview builds the request without signing or submitting. Jupiter Trigger requires at least about $5 per limit order. The examples below use the minimum valid size; smaller orders return SOLANA_TRIGGER_ORDER_TOO_SMALL before signing or provider submission.

bullpen solana limit-buy <MINT> 5 --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, order key, and route.

bullpen solana limit-buy <MINT> 5 --price <USD> --yes --output json
bullpen solana cancel-order <ORDER_KEY> --yes --output json

orders is read-only. Use the order key returned by orders or by the live create response; do not invent one from the token mint. Live limit-order JSON results expose kind, success, status, order_key, signature, and the compatibility aliases order and tx_signature. After a live cancel, run bullpen solana balance --refresh --output json before relying on returned funds.

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.