Skip to main content

Quickstart

Use this flow to start the local API and web app. This is the safe path for a new checkout.

1. Prepare config

cp .env.example .env
cp config.example.toml config.toml
Secrets stay in .env. Non-secret policy stays in config.toml. The copied .env contains empty placeholders. They are harmless while protocol workers are disabled, but live mode requires real values. Default config uses:
  • API bind: 127.0.0.1:5050
  • Solana cluster label: mainnet-beta
  • assets: USDC, SOL, cbBTC
  • small demo caps
  • runtime.enable_protocol_workers = false
With protocol workers disabled, the backend serves health and runtime projection routes. Mutating RFQ and settlement routes return unavailable because the live orchestrator is not attached.

2. Start the backend

cargo run
The backend starts the Axum API and runtime projection. With the default runtime.enable_protocol_workers = false, it does not sign transactions or call Jupiter/Circle.

3. Start the web app

npm run dev
Open:
http://127.0.0.1:3000/app/
Runtime view:
http://127.0.0.1:3000/app/runtime

4. Start the API docs

npm run docs:dev
Open the local docs URL printed by Mintlify. The Backend Reference pages include an interactive Try it panel. It defaults to the deployed API at https://api.firmament.shaikazeem.com. Choose the local 127.0.0.1:5050 server in a local docs preview when testing against your own cargo run backend.

5. Inspect public runtime routes

curl http://127.0.0.1:5050/health
curl http://127.0.0.1:5050/v1/assets
curl http://127.0.0.1:5050/v1/pairs
curl http://127.0.0.1:5050/v1/runtime/state
curl http://127.0.0.1:5050/v1/runtime/events
curl http://127.0.0.1:5050/v1/runtime/ledger
curl 'http://127.0.0.1:5050/v1/runtime/trades?limit=10'
/v1/runtime/trades is the global recent-trades feed used by the Runtime tab. Trade rows and active wallet-settlement state are durable SQLite records, so terminal trades and resumable active settlements can survive a backend restart. Pass wallet=<address> to scope the feed to the connected taker wallet, which is what the swap page history drawer uses.

6. Request a friendly RFQ

The friendly request shape uses asset symbols and a decimal amount. Asset identifiers are case-insensitive. In default local mode this route returns 503 service_unavailable because the live orchestrator is not attached. That is expected. Use it to verify request shape and error handling before enabling live maker mode.
curl -X POST http://127.0.0.1:5050/v1/rfq \
  -H 'content-type: application/json' \
  -d '{
    "input_asset": "USDC",
    "output_asset": "SOL",
    "amount": "1.00",
    "taker_wallet": "11111111111111111111111111111111",
    "expiry_seconds": 30
  }'
Accepted responses include pair, input, output, and a next_action hint pointing at POST /v1/quotes/{quote_id}/wallet-settlement. Rejected responses include a user-facing message and a suggested_action. The legacy mint/raw-amount request shape (input_mint, output_mint, input_amount_raw) keeps working for existing API consumers. During browser-wallet settlement, the app can recover an active trade with POST /v1/trades/{trade_id}/resume. Before any on-chain lock signature, it can abandon the unused settlement with POST /v1/trades/{trade_id}/abandon by sending the browser-held secret_hash. Expired pre-lock settlements are marked failed instead of receiving fresh lock transactions. After a locked settlement expires, it can prepare and record a refund with POST /v1/trades/{trade_id}/taker-refund.

Live RFQ mode

To run live RFQ and settlement, follow Maker setup. At minimum, configure:
  • SOLANA_RPC_URL
  • exactly one maker keypair source
  • JUPITER_API_KEY when Jupiter is enabled
  • CIRCLE_GATEWAY_SOLANA_ADDRESS when Gateway is enabled
  • a verified Solana cbBTC mint in config.toml
  • runtime.enable_protocol_workers = true
Keep the demo caps small before funding the maker wallet.