Trader Guide
The end-to-end path for placing a parlay. Unlike CLOB orders, parlays are placed by sending a Solana transaction yourself — the Platform API mirrors the resulting state for reads, but it does not accept the bet.
1. Pick your legs
Section titled “1. Pick your legs”A leg is one market plus a YES/NO pick. Between 2 and 10 of them.
Before adding a market, check it’s eligible:
- Status
open, and not pastend_time - Old enough to have a full TWAP window of price history — at least one hour, and never less than the averaging window
- Outcome probability inside the configured band (hard bounds: 1%–99%)
- Deep enough and traded enough to price — the vault sets minimum liquidity and volume floors
- Traded recently enough that the TWAP isn’t stale
- Not the same market as another leg
- Not in the same event as another leg
Every threshold above is admin-tunable config, not a constant. Read them from the parlay config account rather than hardcoding — the deployed floor is not necessarily the hard bound.
The webapp greys out ineligible markets before you can add them. If you’re building your own client, mirror these client-side — every one is also enforced on-chain, but failing there costs a transaction.
The correlation rule
Section titled “The correlation rule”You cannot put two legs from the same event on one slip. “Team A wins” and
“Team A wins by 2+” are almost the same bet; multiplying their
probabilities as if independent would price the slip far below its true risk.
The program rejects it with SameEventCorrelation.
2. Read the multiplier
Section titled “2. Read the multiplier”combined = p₀ × p₁ × … × pₙmultiplier = 1 / combinedpayout = stake × multiplier| Legs | Each at | Combined | Multiplier |
|---|---|---|---|
| 2 | 50% | 0.25 | 4× |
| 3 | 50% | 0.125 | 8× |
| 3 | 50% / 40% / 25% | 0.05 | 20× |
| 4 | 30% | 0.0081 | 123× |
| 5 | 20% | 0.00032 | 3,125× |
The multiplier compounds fast. So does the chance of missing: five legs at 20% each land together 0.032% of the time.
3. Set your stake
Section titled “3. Set your stake”Within the configured bounds — typically $1 minimum. The resulting payout
must clear config.max_payout and fit the vault’s exposure headroom, so a
large stake on a long slip can be rejected even when the stake itself is
fine.
If you hit ExposureLimitExceeded, reduce the stake. The vault is protecting
its solvency, not rejecting you.
4. Set min_payout — and actually set it
Section titled “4. Set min_payout — and actually set it”create_parlay takes a min_payout slippage floor. If the computed payout
comes out below it, the transaction reverts with SlippageExceeded rather
than filling you at a worse multiplier.
5. Place it
Section titled “5. Place it”Send a create_parlay transaction to the high-market-parlay program.
Parlay PDA seeds = ["parlay", user_pubkey, user_seq_le_bytes]| Parameter | Meaning |
|---|---|
legs | Vec<LegInput> — one { selected_outcome } per leg |
stake | Micro-USDC |
min_payout | Your slippage floor |
user_seq | Your per-user sequence number |
The market references travel in remaining_accounts, length exactly
2 × legs.len():
| Range | Accounts |
|---|---|
[0..N] | Market accounts, in leg order |
[N..2N] | MarketEventLink PDAs, derived per leg’s market_id |
The user_seq race
Section titled “The user_seq race”The PDA is keyed on (user, user_seq), deliberately — two users can both
create their first parlay in the same slot without racing a global counter.
But you can race yourself: two browser tabs both computing
max(existing) + 1 will collide.
Handle it: on an “account already in use” error, increment user_seq and
retry. The webapp retries up to four times.
The stake transfers from your USDC ATA into the parlay vault in the same transaction.
6. Track it
Section titled “6. Track it”curl -s https://prod-api.gomarket.io/api/parlays/user/ \ -H "Authorization: Bearer $JWT"
curl -s https://prod-api.gomarket.io/api/parlays/user/?status=active \ -H "Authorization: Bearer $JWT"
curl -s https://prod-api.gomarket.io/api/parlays/{parlay_id}/ \ -H "Authorization: Bearer $JWT"The detail endpoint is scoped to the caller — you cannot read someone else’s slip, and a parlay that isn’t yours returns the same 404 as one that doesn’t exist.
| Status | Meaning | Claimable |
|---|---|---|
active | At least one leg still pending | — |
won | All legs terminal, none lost | yes — payout |
lost | A leg lost; nothing to collect | no |
voided | Every leg’s market cancelled | yes — stake refund |
refunded | Admin already paid the stake back | no |
claimed | Paid out | no |
voided and refunded are easy to confuse: voided still owes you a claim,
refunded has already been settled.
7. Settle the legs
Section titled “7. Settle the legs”Legs don’t settle themselves. Once a leg’s market is Resolved or Cancelled,
anyone can call settle_leg(leg_index) — you, an operator, an indexer.
| Error | Means |
|---|---|
MarketNotResolved (6013) | Too early — the market isn’t terminal yet |
LegNotPending (6033) | Already settled; harmless |
Settling is idempotent through that second check, so a retry loop is safe.
8. Claim — and don’t wait
Section titled “8. Claim — and don’t wait”claim_parlay is signed by you and accepts two statuses:
Won fee = floor(potential_payout × fee_bps_at_create / 10_000) net = potential_payout − fee
Voided net = stake fee = 0 // every leg's market cancelledThe vault pays net to your USDC ATA and, for a winner, fee to the
treasury in the same transaction. Status flips to Claimed.
fee_bps_at_create is snapshotted when you placed the slip — an admin fee
change in between cannot touch what you pay.
What can go wrong
Section titled “What can go wrong”| Error | Code | What to do |
|---|---|---|
ExposureLimitExceeded | 6011 | Reduce the stake — the vault is near its limit |
PayoutExceedsMax | 6010 | Reduce the stake or shorten the slip |
StakeTooLow / StakeTooHigh | 6008/6009 | Stake outside the configured bounds |
MarketNotOpen | 6012 | A leg’s market closed while you were building |
ProbabilityOutOfRange | 6014 | A leg sits outside the configured band |
SameEventCorrelation | 6005 | Two legs from one event |
DuplicateMarket | 6004 | Same market twice |
SlippageExceeded | 6042 | The TWAP price moved past your min_payout |
Paused | 6000 | Parlay creation is paused |
TooFewLegs / TooManyLegs | 6002/6003 | Outside 2–max_legs |
Full list: Error Codes.
Suggested slips
Section titled “Suggested slips”The Platform API serves curated templates:
curl -s https://prod-api.gomarket.io/api/markets/parlay-suggestions/In the webapp these are previews. Demo legs carry a synthetic negative market ID and no market address, and are blocked from submission — they exist to show the shape of a combo, not to be placed.
Things a parlay cannot do
Section titled “Things a parlay cannot do”- Be sold or exited. No secondary market, no partial close. Once placed, it runs to settlement.
- Be transferred. The
Parlayaccount is bound to your pubkey; only you can claim. - Be repriced.
probability_at_entryis written once. Later market moves don’t change your multiplier, in either direction.