Solana walkthrough
One complete Solana run — deposit, rest, cancel, trade against the AMM, resolve, claim, withdraw — as commands, with the arithmetic to check against.
Complete run
Market 880101 on devnet, funded and closed out through the Solana /tx/* calls. Check
your own run against the arithmetic: when a step is silently doing nothing, the totals
stop adding up long before anything throws.
| Step | Call | Wallet | Exchange balance | Shares |
|---|---|---|---|---|
| start | — | $500.00 | — | — |
| deposit | POST /tx/deposit | $400.00 | $100.00 | — |
| rest an order | POST /orders | $400.00 | $100.00 | — |
| cancel it | DELETE /orders/{id} | $400.00 | $100.00 | — |
| buy 10 YES at 50¢ | POST /market-order | $400.00 | $94.95 | 10 YES |
| market resolves YES | (an operator does this) | $400.00 | $94.95 | 10 YES |
| claim | POST /tx/claim | $400.00 | $104.95 | 0 |
| withdraw | POST /tx/withdraw | $504.95 | $0.00 | 0 |
Net $4.95 = a $10 payout on 10 winning shares, less the $5 they cost at 50¢, less $0.05 of fee. The fee is 1% of the trade.
The same run, as commands
Paste them in order against a market of your own. The build steps never touch your
private key; the signing pipe is the wallet side. Every write needs an API key with
write — -H "X-API-Key: $KEY" below; see Authentication.
Setup
export ENGINE=https://app-staging.daejin.xyz/clob/v1
export BRIDGE=https://app-staging.daejin.xyz/clob-engine
export KEY=tp_test_… # your API key (write scope), from the keys page
export USER_PUB=<your base58 pubkey> # the wallet that signs and holds the collateral
export M=880201 # the numeric on-chain market id, from GET /marketsAmounts below are raw units: USDC has 6 decimals, so 50000000 is $50. Prices are ticks:
1000 = $1.00.
1 — Look at the market
curl -s "$BRIDGE/quote?market=$M"
# {"market":880201,"yes":500,"no":500}
curl -s $ENGINE/markets/$M
curl -s $ENGINE/markets/$M/book
curl -s $ENGINE/markets/$M/tickerA market published through the app is already live on chain by the time it appears in
GET /markets; /quote answering with prices is the confirmation. Everything below needs
nothing but your own wallet and key.
2 — Deposit (signs)
# build — see what comes back before piping it anywhere
curl -s -X POST $BRIDGE/tx/deposit -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"marketId\":$M,\"user\":\"$USER_PUB\",\"amount\":\"50000000\"}"
# {"ok":true,"transaction":"<base64>","blockhash":"…","createsTokenAccount":false}
# build → sign → submit, in one pipe
curl -s -X POST $BRIDGE/tx/deposit -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"marketId\":$M,\"user\":\"$USER_PUB\",\"amount\":\"50000000\"}" \
| jq -r .transaction | node sign.mjs \
| curl -s -X POST $BRIDGE/tx/submit -H "X-API-Key: $KEY" -H 'content-type: application/json' --data-binary @-
# {"ok":true,"signature":"…","confirmed":true}sign.mjs is the whole of your side of this. It ships as scripts/sign.mjs in
tokenplay-clob-bridge and is printed in full on
Build Transaction. Run it as
USER_KEY=<base58 secret key> node sign.mjs. A real integration signs with the user's
wallet — Phantom, a Ledger, a custodial signer — and the code is the same three lines,
Transaction.from, sign, serialize.
3 — Rest an order, then cancel it (signs)
npm run mm:solana -- place --action buy --outcome YES --price 400 --size 5000000
# HTTP 201 {"accepted":true,"order":{"id":"o2","status":"open",…}}
curl -s $ENGINE/markets/$M/book
curl -s -H "X-API-Key: $KEY" "$ENGINE/users/$USER_PUB/orders?market=$M"
export OID=$(curl -s $ENGINE/markets/$M/orders | jq -r '.orders[0].id')
curl -s -H "X-API-Key: $KEY" $ENGINE/orders/$OID
# {"order":{"id":"o2","status":"open","remaining":"5000000"}} ← no salt, no signature
npm run mm:solana -- cancel --id $OID
curl -s -H "X-API-Key: $KEY" "$ENGINE/users/$USER_PUB/orders/closed?market=$M"Swap place for message to print the signed string and the signature without sending
anything — the fastest way to see why a signature is being rejected.
4 — Prove the signature is really checked
curl -s -X POST $ENGINE/orders -H "X-API-Key: $KEY" -H 'content-type: application/json' -d "{
\"user\":\"$USER_PUB\",\"market\":\"$M\",\"action\":\"buy\",\"outcome\":\"YES\",
\"price\":500,\"size\":\"1000000\",\"type\":\"GTC\",\"salt\":42,\"expiry\":0,
\"signature\":\"<any other valid base58 signature>\"}"
# 422 {"accepted":false,"reason":"invalid signature"}5 — Trade against the AMM (signs)
curl -s -X POST $BRIDGE/market-order -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d '{"market":880201,"user":"<pubkey>","action":"buy","outcome":"yes",
"price":700,"size":5000000,"salt":123,"expiry":0,"signature":"<base58>"}'
# {"ok":true,"sig":"…","execPrice":500}
curl -s "$BRIDGE/quote?market=$M"
# {"yes":667,"no":333} ← the AMM sold YES, so YES got dearerYour signed price is a limit, not a request: 700 here means "fill me at 70¢ or better",
and it filled at 50¢. A 422 means the pool could not do it within your limit.
6 — Liquidity, resolution, payout (signs)
curl -s -X POST $BRIDGE/tx/add-liquidity -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"marketId\":$M,\"user\":\"$USER_PUB\",\"amount\":\"25000000\"}" \
| jq -r .transaction | node sign.mjs \
| curl -s -X POST $BRIDGE/tx/submit -H "X-API-Key: $KEY" -H 'content-type: application/json' --data-binary @-
# … the market resolves YES. Resolution is an operator action, not an API you call;
# GET $ENGINE/markets/$M stops listing the book once it has closed.
for k in claim claim-lp-fees remove-liquidity; do
curl -s -X POST $BRIDGE/tx/$k -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"marketId\":$M,\"user\":\"$USER_PUB\"}" \
| jq -r .transaction | node sign.mjs \
| curl -s -X POST $BRIDGE/tx/submit -H "X-API-Key: $KEY" -H 'content-type: application/json' --data-binary @-
doneThe three claims only succeed after resolution; before it they fail on chain rather than doing nothing, so a run that reaches step 7 has really been paid out.
7 — Withdraw (signs)
# the balance after a claim is never a round number — read it, do not guess
curl -s -X POST $BRIDGE/tx/withdraw -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"marketId\":$M,\"user\":\"$USER_PUB\",\"amount\":\"76975000\"}" \
| jq -r .transaction | node sign.mjs \
| curl -s -X POST $BRIDGE/tx/submit -H "X-API-Key: $KEY" -H 'content-type: application/json' --data-binary @-Leaving a placeholder in amount makes the build return an error, jq print null, and
the signer choke on nothing. If a pipe dies oddly, run the /tx/ call alone and read its
error.
Check the arithmetic, not just the status codes
Deposit $50, buy 5000000 at an exec price of 500, and the position should read $47.475:
the trade cost $2.50 of notional and $0.025 of fee. After YES resolves, claim adds $5.00
— the shares are worth par — for $52.475. Removing $25 of liquidity returns $24.50, not
$25: the pool sold shares for $2.50 that settled at $5.00, and your 25 of its 125 shares
carry 20% of that $2.50 loss. A run where every call returns 200 and the totals do not
close is a run that has quietly failed.