GET /v1/config with "kind": "solana". Chain ids
are 101 (mainnet-beta), 102 (testnet), 103 (devnet), and 104 and above for local validators. Keys and
signatures are base58; transactions are standard base64; amounts are base-unit decimal strings.
Who signs what
A settlement transaction has three signers: the maker (the resolver node), the taker, and the fee payer (the relay’s keeper). The taker needs no SOL.- The node signs as maker when it answers the RFQ.
- The relay checks the transaction byte for byte against the terms it asked for, simulates it, and quotes it.
- The taker’s client rebuilds the same transaction from
/v1/configand the quote, checks it, and signs as taker. - The keeper signs last as fee payer and submits.
gasFee.rent is true). The
canonical transaction pays only the taker, so recipient must equal taker.
Fee mints and pairs
fee.tokens in the chain’s config lists the mints fees may be charged in, in priority order. A pair’s fee
mint is the first of fee.tokens that is its sell mint or its buy mint: cNGN/USDC is charged in USDC and
cNGN/USDT in USDT. pairs lists the corridors the relay quotes on the chain, as mint pairs. A pair outside
that list is refused 400 unsupported_pair.
Requesting a quote
Same as EVM, with base58 values and a base58 taker proof:"kind": "solana" and a solana block instead of permit, auth, offers and typedData:
fee be floor(leg × bps / 10000), where the leg is sellAmount when the fee mint is the
sell mint and received otherwise. Let gas be gasFee.amount.
Checks before the wallet signs
1
Build the terms
Take the fee mint as the first of
config.fee.tokens that is sellToken or buyToken. Check that
solana.feeMint, fee.token and gasFee.token are that mint. Then:2
Verify the transaction
verifySettlement(terms, base64Decode(solana.transaction), [solana.maker]) must pass. The reference
implementation is panofx-api/src/domain/solana/settlement.ts, copied byte for byte into the web app.3
Check the amounts
What the wallet will show must match
takerPays, proceeds, fee and gasFee computed from those terms.4
After signing
Check that the message bytes are unchanged, the taker’s signature verifies, and the maker’s signature is
still present.
Submitting
POST /v1/executions with { "quoteId": "<uuid>", "transaction": "<base64>" }: the quote’s transaction
with the taker’s signature added. The fee payer’s slot may be empty. The relay requires the message bytes
to equal the quoted message, verifies both signatures, and builds the transaction it sends from its own
stored copy plus the taker’s signature and the keeper’s.
Other routes
GET /v1/executions/:id:txHashis the base58 transaction signature;gasUsedis compute units consumed.GET /v1/quotes/:id:txHashvalues are base58 andsettlement.blockis the slot.finalis true once the transaction is finalized.GET /v1/limits?chainId=103&…: the same shape as EVM, withallowanceequal tobalance.GET /v1/corridors: a Solana chain lists only itspairs, each with its own fee mint.GET /v1/health: the chain’s entry hasslot,keeperLamportsandkeeperLow.- Limit-order routes answer
400 limit_orders_unsupported.

