LiberFi Prediction Market
Browse prediction market events, manage positions, and place orders on Kalshi and Polymarket using the LiberFi CLI.
Pre-flight Checks
See bootstrap.md for CLI installation and connectivity verification.
This skill's auth requirements:
| Command | Requires Auth |
|---|
lfi predict events | No |
lfi predict event <slug> | No |
lfi predict balance | No |
lfi predict positions | No |
lfi predict trades | No |
lfi predict orders | No (Polymarket needs POLY_* headers) |
lfi predict order <id> | No (Polymarket needs POLY_* headers) |
lfi predict polymarket-tick-size | No |
lfi predict polymarket-fee-rate | No |
lfi predict polymarket-setup-status | No (uses TEE wallet if logged in) |
lfi predict polymarket-deposit-addresses | No |
lfi predict polymarket-setup | Yes (LiberFi JWT) |
lfi predict polymarket-place | Yes (LiberFi JWT — server signs via TEE) |
lfi predict kalshi-place | Yes (LiberFi JWT — server signs via TEE) |
lfi predict cancel | Yes (LiberFi JWT — auto L2 auth for polymarket) |
lfi predict kalshi-quote (DEPRECATED) | No |
lfi predict kalshi-submit (DEPRECATED) | No |
lfi predict polymarket-order (DEPRECATED) | No (requires POLY_* headers) |
Recommended flow (TEE auto): polymarket-setup → polymarket-place /
kalshi-place / cancel. The server holds the user's TEE wallet via Privy
and signs every transaction internally — no POLY_* HMAC, no Solana signing,
no EIP-712 work for the caller.
Legacy flow: Polymarket order operations via polymarket-order require
CLOB HMAC authentication via five --poly-* flags. These are NOT LiberFi
JWT credentials — they are the user's own Polymarket CLOB API credentials.
TEE Auto Order Flow (CRITICAL)
For the canonical end-to-end order placement flow — including pre-flight
status checks, deposit handling, market vs limit order branching, and post-
order verification — see reference/order-flow.md.
The CLI/skill expects this exact ordering for Polymarket:
lfi status — confirm authenticated; if not, run lfi login key
lfi predict polymarket-setup-status --json — check Safe deployment +
token approvals
- If
safe_deployed=false or any approval missing: lfi predict polymarket-setup --json (one-shot; gasless via Builder Relayer)
- Check Safe USDC balance — pass the TEE EOA, NOT the Safe:
lfi predict balance --source polymarket --user <tee-eoa> --json
(server derives Safe from EOA internally). If balance < 2, fetch
BRIDGE deposit addresses using the Safe address from step 2/3:
lfi predict polymarket-deposit-addresses --safe-address <safe> --json
→ returns { evm, svm, btc, tron }. Pick the field matching the user's
chain (default evm for ETH/Polygon/Base/Arb/Op/BNB). Tell user to send
≥ $2 USDC to that bridge address (NEVER to the Safe address — the Safe
is Polymarket's internal custody contract, not a user-facing deposit
target). The Polymarket Bridge service auto-credits the Safe.
- Ask the user: market or limit? For limit, also ask price + size + GTC
vs GTD (with expiration if GTD). For market, ask USDC spend (BUY) or
share count (SELL)
- Show the final order summary, wait for explicit confirmation
lfi predict polymarket-place --token-id <id> --side <s> --order-type <t> [--price <p>] [--size <sz>] [--expiration <epoch>] --json
lfi predict orders --source polymarket --json — verify open orders
lfi predict cancel <id> --source polymarket --json — cancel if user
asks
For Kalshi the flow is shorter: lfi predict kalshi-place --input-mint <inMint> --output-mint <outMint> --amount <amt> --json — quote, sign
(SignSOL), and submit are all done server-side.
Skill Routing
| If user asks about... | Route to |
|---|
| Token search, price, details, security | liberfi-token |
| Token K-line, candlestick chart | liberfi-token |
| Trending tokens, market rankings | liberfi-market |
| Newly listed tokens | liberfi-market |
| Wallet holdings, balance (non-prediction), PnL | liberfi-portfolio |
| Wallet activity, transaction history | liberfi-portfolio |
| Token swap, trade execution | liberfi-swap |
| Login, logout, session management | liberfi-auth |
CLI Command Index
Query Commands (read-only)
| Command | Description | Auth |
|---|
lfi predict events | List prediction events with filtering | No |
lfi predict event <slug> --source <s> | Get event details by slug | No |
lfi predict balance --source <s> --user <addr> | Get USDC balance | No |
lfi predict positions --user <addr> | Get portfolio positions | No |
lfi predict trades --wallet <addr> | List trade history | No |
lfi predict orders | List orders | No (POLY_* for Polymarket) |
lfi predict order <id> --source <s> | Get order details | No (POLY_* for Polymarket) |
TEE Auto Flow Commands (recommended)
| Command | Description | Auth |
|---|
lfi predict polymarket-tick-size --token-id <id> | Min tick size for a token | No |
lfi predict polymarket-fee-rate --token-id <id> | Base fee rate (bps) | No |
lfi predict polymarket-setup-status [--wallet-address <addr>] | Safe deployment + approval status | No (uses TEE wallet if logged in) |
lfi predict polymarket-setup | Deploy Safe + approve all tokens (gasless) | JWT |
lfi predict polymarket-deposit-addresses --safe-address <addr> | Multi-chain deposit addresses for Safe | No |
lfi predict polymarket-place --token-id <id> --side BUY|SELL --order-type GTC|GTD|FOK|FAK|MARKET [--price <p>] [--size <sz>] [--expiration <epoch>] [...] | Prepare → TEE sign → execute Polymarket order | JWT |
lfi predict kalshi-place --input-mint <m> --output-mint <m> --amount <a> [--slippage-bps <bps>] | Quote → SignSOL → submit Kalshi order | JWT |
lfi predict cancel <id> --source polymarket|kalshi | Cancel order (auto L2 auth for poly) | JWT |
Legacy / Deprecated Commands
| Command | Description | Auth |
|---|
lfi predict kalshi-quote --input-mint <m> --output-mint <m> --amount <a> --user-public-key <k> | DEPRECATED — use kalshi-place. Request Kalshi quote | No |
lfi predict kalshi-submit --signed-transaction <tx> --order-context '<json>' | DEPRECATED — use kalshi-place. Submit pre-signed Kalshi tx | No |
lfi predict polymarket-order --body '<json>' --poly-api-key <k> --poly-address <a> --poly-signature <s> --poly-passphrase <p> --poly-timestamp <t> | DEPRECATED — use polymarket-place. Create Polymarket order with caller-managed POLY_* headers | POLY_* headers |
Parameter Reference
Events list (lfi predict events):
--limit <n> — Max results per page
--cursor <cursor> — Pagination cursor
--status <status> — Event status filter (e.g. active, resolved)
--source <source> — Provider source: kalshi or polymarket
--tag-slug <slug> — Filter by tag
--search <query> — Free-text search
--sort-by <field> — Sort field
--sort-asc <bool> — Sort ascending: true or false
--with-markets <bool> — Include embedded markets: true or false
Event detail (lfi predict event <slug>):
<slug> — Required. Event slug identifier
--source <source> — Required. Provider source: kalshi or polymarket
Balance (lfi predict balance):
--source <source> — Required. Provider source: kalshi or polymarket
--user <address> — Required. For polymarket: pass the user's TEE EOA (e.g. evmAddress from lfi whoami); the server auto-derives the Safe via CREATE2. NEVER pass a Safe address here. For kalshi: pass the Solana public key (solAddress).
Positions (lfi predict positions):
--user <address> — Required. Same rule as balance: TEE EOA for polymarket (server derives Safe), Solana public key for kalshi.
--source <source> — Optional provider source filter
Trades (lfi predict trades):
--wallet <address> — Required. Same rule as balance: TEE EOA for polymarket (server derives Safe), Solana public key for kalshi.
--source <source> — Optional provider source filter
--limit <n> — Max results per page
--cursor <cursor> — Pagination cursor
--type <types> — Comma-separated trade types
--side <side> — Trade side filter
Orders (lfi predict orders):
--source <source> — Provider source
--wallet-address <address> — Wallet address (required for kalshi)
--market-id <id> — Market ID filter
--asset-id <id> — Asset ID filter
--next-cursor <cursor> — Pagination cursor
--poly-api-key, --poly-address, --poly-signature, --poly-passphrase, --poly-timestamp — Polymarket CLOB auth (required when source is polymarket)
Order detail (lfi predict order <id>):
<id> — Required. Order ID
--source <source> — Required. Provider source
- Same
--poly-* flags as orders list
Polymarket tick size (lfi predict polymarket-tick-size):
--token-id <id> — Required. Polymarket CLOB token ID
Polymarket fee rate (lfi predict polymarket-fee-rate):
--token-id <id> — Required. Polymarket CLOB token ID
Polymarket setup status (lfi predict polymarket-setup-status):
--wallet-address <addr> — Optional EVM address. Defaults to caller's TEE wallet when authenticated.
Polymarket setup (run) (lfi predict polymarket-setup):
- No flags. Requires authentication. Idempotent — safe to call repeatedly.
Polymarket deposit addresses (lfi predict polymarket-deposit-addresses):
--safe-address <addr> — Required. Safe wallet address (from polymarket-setup-status)
Polymarket place (TEE auto) (lfi predict polymarket-place):
--token-id <id> — Required. Polymarket CLOB token ID
--side BUY|SELL — Required.
--order-type GTC|GTD|FOK|FAK|MARKET — Required.
--price <p> — Limit price (limit orders only, e.g. 0.55). Required for GTC/GTD/FOK/FAK.
--size <sz> — Limit: shares; market BUY: USDC; market SELL: shares. Required for limit and market.
--expiration <epochSec> — Required for GTD.
--neg-risk true|false — Force NegRisk exchange. Auto-detected when omitted.
--fee-rate-bps <n> — Override fee rate (PS auto-resolves when omitted).
--tick-size <n> — Override tick size (PS auto-resolves when omitted).
--taker-address <addr> — Restrict the taker (advanced).
Kalshi place (TEE auto) (lfi predict kalshi-place):
--input-mint <addr> — Required. Input token mint
--output-mint <addr> — Required. Output token mint
--amount <amt> — Required. Amount in smallest unit
--slippage-bps <bps> — Slippage tolerance in basis points
Cancel order (lfi predict cancel <id>):
<id> — Required. Order ID
--source polymarket|kalshi — Required. For polymarket the L2 HMAC headers are derived from the caller's TEE wallet automatically.
Kalshi quote (lfi predict kalshi-quote):
--input-mint <address> — Required. Input token mint address
--output-mint <address> — Required. Output token mint address
--amount <amount> — Required. Swap amount
--user-public-key <key> — Required. User's Solana public key
--slippage-bps <bps> — Slippage tolerance in basis points
Kalshi submit (lfi predict kalshi-submit):
--signed-transaction <tx> — Required. Signed transaction data
--order-context <json> — Required. Order context as JSON string (contains user_public_key, market_slug, side, outcome, mints, amount, price, slippage_bps)
Polymarket order (lfi predict polymarket-order):
--body <json> — Required. Raw order JSON string
--poly-api-key <key> — Required. Polymarket API key
--poly-address <address> — Required. Polymarket address
--poly-signature <sig> — Required. Polymarket HMAC signature
--poly-passphrase <pass> — Required. Polymarket passphrase
--poly-timestamp <ts> — Required. Polymarket timestamp
Operation Flow
Browse Prediction Events
- Fetch events:
lfi predict events --with-markets true --limit 20 --json
- Present results: Show event title, status, number of markets, volume
- Suggest next step: "Want to see details for a specific event?" / "需要查看某个事件的详情?"
Browse Events by Source
- Determine source: Ask user for
kalshi or polymarket
- Fetch:
lfi predict events --source kalshi --with-markets true --limit 20 --json
- Present: Events filtered by provider
- Suggest next step: "Pick an event to view its markets and outcomes"
View Event Details
- Determine slug: From user selection or input
- Fetch event:
lfi predict event <slug> --source <source> --json
- Present: Event title, description, status, resolution sources, markets with outcomes and prices
- Suggest next step: "Want to check your balance or place an order?"
Check USDC Balance
If the user says "我的余额", "my balance", "我在 Polymarket/Kalshi 有多少钱"
or any first-person variant — DO NOT ask for a wallet address. Use the
"My ..." auto-flow below.
Generic flow (when the user explicitly provides someone else's address):
- Collect inputs: Source (kalshi/polymarket) and wallet address
- Fetch:
lfi predict balance --source <source> --user <address> --json
- Present: Available USDC balance
- Suggest next step: "Ready to place a prediction?" / "准备下注了吗?"
Kalshi Order Flow (Quote → Sign → Submit)
- Browse events:
lfi predict events --source kalshi --with-markets true --json
- View event:
lfi predict event <slug> --source kalshi --json — identify market, outcomes, and mints
- Check balance:
lfi predict balance --source kalshi --user <publicKey> --json
- Get quote:
lfi predict kalshi-quote --input-mint <inMint> --output-mint <outMint> --amount <amt> --user-public-key <key> --json
- Present quote: Show expected output amount, price, slippage
- (mandatory) Wait for explicit user confirmation
- User signs the transaction (externally, e.g. via wallet)
- Submit:
lfi predict kalshi-submit --signed-transaction <signedTx> --order-context '<contextJson>' --json
- Present result: Show signature, status
Polymarket Order Flow
- Browse events:
lfi predict events --source polymarket --with-markets true --json
- View event:
lfi predict event <slug> --source polymarket --json
- Check balance:
lfi predict balance --source polymarket --user <address> --json
- Prepare order body: Construct the Polymarket order JSON
- (mandatory) Show order summary and wait for explicit user confirmation
- Create order:
lfi predict polymarket-order --body '<orderJson>' --poly-api-key <key> --poly-address <addr> --poly-signature <sig> --poly-passphrase <pass> --poly-timestamp <ts> --json
- Present result: Show order response
View Positions
If the user says "我的持仓", "我现在押了哪些", "my positions", "我赌了什么"
or any first-person variant — DO NOT ask for a wallet address. Use the
"My ..." auto-flow below.
Generic flow (when the user explicitly provides someone else's address):
- Determine user: Get wallet address from user
- Fetch:
lfi predict positions --user <address> --json
- Present: Show event/market, outcome, size, entry price, current value
- Suggest next step: "Want to see your trade history?" / "需要查看交易历史?"
View Trade History
If the user says "我的交易", "我赚了多少", "我亏了多少", "my trades",
"我的盈亏" or any first-person variant — DO NOT ask for a wallet address.
Use the "My ..." auto-flow below.
Generic flow (when the user explicitly provides someone else's address):
- Determine wallet: Get wallet address from user
- Fetch:
lfi predict trades --wallet <address> --limit 20 --json
- Present: Show trade timestamp, event/market, side, price, size
- Suggest next step: "Want to check your current positions?" / "需要查看当前持仓?"
"My ..." auto-flow (CRITICAL — covers "我的", "my", "我自己")
Whenever the user asks about THEIR OWN prediction-market data — positions,
trades, balance, PnL, "我现在押了哪些", "我在预测市场赚了多少",
"我在 Polymarket 上的钱", etc. — run this exact sequence. NEVER ask the
user to type their wallet address.
- Check session:
lfi status --json
- If not authenticated (or
expired: true):
lfi login key --role AGENT --name "OpenClawAgent" --json
- Fetch TEE wallet addresses:
lfi whoami --json
→ returns evmAddress (use for Polymarket) and solAddress (use for Kalshi).
- Determine source(s):
- If the user named "Polymarket" → use
evmAddress only.
- If the user named "Kalshi" → use
solAddress only.
- If neither was named (e.g. "我在预测市场赚了多少") → query BOTH and merge.
- Run the matching query for each source — pass the TEE EOA / SOL pubkey
from step 3 DIRECTLY. NEVER convert to a Safe address first; the server
does that internally for Polymarket.
- Positions:
lfi predict positions --user <evmAddress|solAddress> [--source <s>] --json
- Trades:
lfi predict trades --wallet <evmAddress|solAddress> [--source <s>] --limit 50 --json
- Balance:
lfi predict balance --source <s> --user <evmAddress|solAddress> --json
- Present a single consolidated answer that names the source(s) used and,
for the "我赚了多少" / PnL question, sums realized + unrealized PnL across
the returned trades/positions.
Why this is mandatory: prediction queries always require an address parameter
in the CLI, but a normal user does NOT know their TEE wallet address — the
LiberFi server holds it. The skill must resolve "我" → TEE wallet via
whoami, transparently. The user should never have to type or even see the
hex/Base58 address unless they ask.
EOA vs Safe — critical distinction for Polymarket: The address from
whoami.evmAddress is the user's TEE EOA. For balance / positions /
trades queries, ALWAYS pass the EOA — the prediction-server derives the
Polymarket Safe via CREATE2 internally. The Safe address (returned by
polymarket-setup-status) is ONLY for polymarket-deposit-addresses --safe-address (Polymarket Bridge requires the actual Safe as bridge key).
Mixing these up → balance / positions / trades return EMPTY because the
server tries to derive a Safe from an already-Safe address.
Check Order Status
- List orders:
lfi predict orders --source <source> --wallet-address <address> --json
- Or get specific order:
lfi predict order <id> --source <source> --json
- Present: Show order status, side, price, filled amount
Cross-Skill Workflows
"Research an event and place a bet"
Full flow: predict → predict → predict → predict → predict
- predict →
lfi predict events --search "bitcoin" --with-markets true --json
- predict →
lfi predict event <slug> --source kalshi --json — view markets and outcomes
- predict →
lfi predict balance --source kalshi --user <publicKey> --json — check funds
- predict →
lfi predict kalshi-quote --input-mint <in> --output-mint <out> --amount <amt> --user-public-key <key> --json — get quote
- Present quote, wait for confirmation, user signs transaction
- predict →
lfi predict kalshi-submit --signed-transaction <tx> --order-context '<ctx>' --json
"Check my prediction portfolio and trade history"
Full flow: predict → predict
- predict →
lfi predict positions --user <address> --json — current positions
- predict →
lfi predict trades --wallet <address> --limit 50 --json — trade history
- Present consolidated portfolio view
"Browse events, then research the underlying token"
Full flow: predict → token → token
- predict →
lfi predict events --with-markets true --limit 10 --json
- User selects an event related to a specific token
- token →
lfi token info sol <tokenAddress> --json — token details
- token →
lfi token security sol <tokenAddress> --json — security audit
Suggest Next Steps
| Just completed | Suggest to user |
|---|
| Events list | "Want to view a specific event?" / "需要查看某个事件的详情?" |
| Event detail | "Want to check your balance or place an order?" / "需要查看余额或下单?" |
| Balance check | "Ready to place a prediction?" / "准备下注了吗?" |
| Kalshi quote | "Want to proceed with this trade?" / "要继续这笔交易吗?" |
| Kalshi submit | "Order submitted! Check your positions to verify." / "订单已提交!查看持仓确认。" |
| Polymarket order | "Order created! Check order status to confirm." / "订单已创建!查看订单状态确认。" |
| Positions view | "Want to see trade history?" / "需要查看交易历史?" |
| Trade history | "Want to check current positions?" / "需要查看当前持仓?" |
| Orders list | "Want to see details for a specific order?" / "需要查看某个订单的详情?" |
Edge Cases
- Invalid source: If the API returns an error about source, list valid sources (
kalshi, polymarket) and ask the user to choose
- No events found: Inform user: "No prediction events found matching your criteria. Try different filters or search terms."
- Empty positions: Inform user: "No open positions found for this wallet. You can browse events to find prediction opportunities."
- Insufficient balance: If balance is too low for a trade, inform the user and suggest depositing funds
- Invalid slug: If event not found, suggest searching events first via
lfi predict events --search <keyword>
- Polymarket auth missing: If POLY_* flags are missing for Polymarket operations, list all required flags and ask the user to provide them
- Invalid JSON in --body or --order-context: If JSON parsing fails, show the parse error and ask the user to correct the JSON
- Quote expired: Kalshi quotes have limited validity; if too much time passes, get a new quote
- Network timeout: Retry once after 3 seconds; if still fails, suggest checking connectivity via
lfi ping --json
Common Pitfalls
| Pitfall | Correct Approach |
|---|
Forgetting --source on event detail | Always specify --source kalshi or --source polymarket |
| Missing POLY_* flags for Polymarket | All five --poly-* flags are required for Polymarket orders and order queries |
| Modifying the quote response before submitting | Pass quote data through as-is in --order-context |
| Submitting without user confirmation | ALWAYS show order/quote summary and wait for explicit "yes" |
| Fabricating a signed transaction | The --signed-transaction must come from the user's actual wallet signing |
| Using wrong mint addresses | Verify mints from the event detail response before quoting |
Security Notes
See security-policy.md for global security rules.
Skill-specific rules:
- Polymarket CLOB credentials are sensitive — never log, display, or store POLY_* values beyond the immediate command execution
- Kalshi transactions involve real funds — never fabricate or guess signed transaction data
- NEVER place orders without explicit user confirmation — always show the order summary first
- The
--order-context and --body fields are opaque — pass them through as-is; do not interpret, modify, or display raw content beyond summarizing key fields (amount, side, market)
- After order submission, provide the result so the user can independently verify