- Duplicate guard checks recent on-chain poll questions and blocks repeats unless `--allow-duplicate` is set.
Install
npx skillscat add xoanonxo/pandora-cli-skills Install via the SkillsCat registry.
Pandora CLI & Skills
Create and publish Pandora prediction markets from deployed contracts.
Purpose
Use this skill to launch Parimutuel or AMM markets with explicit market parameters, strict DAO-ready resolution rules, and optional scripted bet placement.
Safety & Resolution Rules (enforced)
- At least 2 public source URLs are required (
http/httpsonly). --rulesmust include explicit Yes/No outcomes and edge-case handling (cancel/postpone/abandoned/unresolved cases).--target-timestampuses a+1hbuffer by default (--target-timestamp-offset-hoursto override).deadlinemust be in the future (12h+ window strongly recommended).distribution-yes + distribution-no = 1_000_000_000.--liquidityminimum is 10 USDC.--arbitercannot be zero-address.
Setup
# Node.js >=18 required
npm install
npm run init-env
# or one-shot setup + diagnostics:
npm run setup
# edit scripts/.env with your values
npm run build
npm run doctor
# optional: expose "pandora" command globally in this checkout
npm linkCLI ergonomics
- Global output mode:
--output table|json(defaulttable) --output jsonapplies to non-execution commands;launch/clone-betstream script output directly.- Guided setup command:
pandora setup - Phase 1 discovery command:
pandora scan - Phase 1 lifecycle filters:
pandora markets list --active|--resolved|--expiring-soon - Phase 2 trading commands:
pandora quote,pandora trade - Phase 2 risk guardrails:
--max-amount-usdc,--min-probability-pct,--max-probability-pct - Phase 3 analytics command:
pandora portfolio - Phase 3 monitoring command:
pandora watch - Phase 3 watch alerts:
--alert-yes-*,--alert-net-liquidity-*,--fail-on-alert - Doctor checks:
- env presence + format validation
- RPC reachability and chain id match
- bytecode checks for
ORACLE+FACTORY(--check-usdc-codeoptional)
Read-only indexer commands
Indexer URL resolution order:
--indexer-urlPANDORA_INDEXER_URLINDEXER_URL- default public indexer
pandora markets list --limit 20 --order-by createdAt --order-direction desc
pandora markets list --active --with-odds --limit 20
pandora markets list --expand --limit 20
pandora markets list --with-odds --limit 20
pandora markets get --id <market-id>
pandora markets get --id <market-id-a> --id <market-id-b>
pandora scan --limit 25
pandora quote --market-address <0x...> --side yes --amount-usdc 50
pandora trade --dry-run --market-address <0x...> --side no --amount-usdc 25 --max-amount-usdc 30 --min-probability-pct 20
pandora portfolio --wallet <0x...> --chain-id 1
pandora watch --wallet <0x...> --iterations 5 --interval-ms 2000 --alert-net-liquidity-below -100
pandora polls list --status 1 --category 3
pandora polls get --id <poll-id>
pandora events list --type all --wallet <0x...> --limit 25
pandora events get --id <event-id>
pandora positions list --wallet <0x...> --limit 50JSON mode for automation:
pandora --output json polls list --limit 5
pandora --output json markets list --expand --with-odds --limit 5
pandora --output json scan --limit 25
pandora --output json quote --market-address <0x...> --side yes --amount-usdc 10
pandora --output json trade --dry-run --market-address <0x...> --side no --amount-usdc 10 --max-amount-usdc 20
pandora --output json portfolio --wallet <0x...> --chain-id 1
pandora --output json watch --wallet <0x...> --iterations 3 --interval-ms 1000 --alert-net-liquidity-above 1000 --fail-on-alertPhase 1 JSON contracts
markets list --expand:- each item includes
pollwithid,question,status,category,deadlineEpoch.
- each item includes
markets list --with-odds:- each item includes
oddswith numericyesPctandnoPct(normalized to 100 total).
- each item includes
scan:- response envelope is
ok=true,command="scan", withdata.indexerUrl,data.generatedAt,data.count, anddata.items[]. - each scan item includes at minimum
id,chainId,marketType,question,marketCloseTimestamp, andodds.
- response envelope is
Phase 1 limitations
--expandand--with-oddsare supported onmarkets listonly.--active|--resolved|--expiring-soonare client-side filters over fetched pages.- Odds are indexer-derived and read-only; missing upstream liquidity/price fields can produce partial odds in some environments.
scanis indexer-backed only (no direct chain reads); freshness depends on indexer sync state.
Phase 2 JSON contracts
quote:- envelope is
ok=true,command="quote", withdata.marketAddress,data.side,data.amountUsdc,data.odds,data.quoteAvailable, anddata.estimate(ornull).
- envelope is
trade --dry-run:- envelope is
ok=true,command="trade", withdata.mode="dry-run",data.quote,data.selectedProbabilityPct,data.riskGuards, anddata.executionPlan.steps.
- envelope is
trade --execute:- envelope is
ok=true,command="trade", with tx metadata (approveTxHashoptional,buyTxHashrequired on success) plusselectedProbabilityPctandriskGuards.
- envelope is
Phase 2 limitations
tradecurrently targets PariMutuel-compatiblebuy(bool,uint256,uint256)markets.--min-shares-out-rawis the explicit slippage guard input for on-chain execution.- If indexer odds are unavailable,
quotestill returns structured output withquoteAvailable=false. trade --executeblocks unquoted execution by default unless--min-shares-out-rawor--allow-unquoted-executeis provided.
Phase 3 JSON contracts
portfolio:- envelope is
ok=true,command="portfolio", withdata.wallet,data.summary,data.positions[], anddata.events.{liquidity,claims}. - summary includes
positionCount,uniqueMarkets,liquidityAdded,liquidityRemoved,netLiquidity,claims,cashflowNet, andpnlProxy.
- envelope is
watch:- envelope is
ok=true,command="watch", withdata.parameters,data.iterationsRequested,data.snapshots[], and aggregateddata.alerts[]. - snapshots include timestamped
portfolioSummaryand/orquoteblocks based on chosen targets, plusalertCount/alerts.
- envelope is
Phase 3 limitations
- P&L values are indexer-derived activity metrics, not full realized/unrealized accounting.
- Claim events are not chain-filtered by indexer schema and may include cross-chain entries.
- Use
--no-eventswhen you only need position snapshots. watchis polling-based and terminal-oriented, not a long-running background service manager.--fail-on-alertexits non-zero when any configured threshold triggers.
Release verification
- CI coverage includes Linux, macOS, and Windows.
- Release artifacts are signed keylessly with cosign in the release workflow.
- Installer verifies checksum + cosign signature by default:
scripts/release/install_release.sh --repo <owner/repo> --tag <tag>
cosignis required unless you explicitly pass--skip-signature-verifyfor legacy unsigned tags.
Launch Parimutuel + auto-bet
Use --allow-duplicate only if you intentionally want to bypass duplicate-question checks.
pandora clone-bet \
--dry-run \
--question "Will Arsenal FC win against Chelsea FC on 2026-03-01?" \
--rules "Resolves YES if Arsenal FC wins in regulation time on March 1, 2026. Resolves NO for draw/Chelsea win. If cancelled, postponed beyond 48h, abandoned, or unresolved by official competition records, resolves NO." \
--sources "https://www.premierleague.com" "https://www.bbc.com/sport/football" \
--target-timestamp 1772323200 \
--target-timestamp-offset-hours 1 \
--arbiter 0x818457C9e2b18D87981CCB09b75AE183D107b257 \
--category 3 \
--liquidity 10 \
--curve-flattener 7 \
--curve-offset 30000 \
--bet-usd 10 \
--bet-on yesFor live execution, replace --dry-run with --execute.
If pandora is not linked yet, use node cli/pandora.cjs clone-bet ....
Default arbiter (whitelisted): 0x818457C9e2b18D87981CCB09b75AE183D107b257
Launch AMM/Parimutuel (market launcher)
pandora launch \
--dry-run \
--market-type amm \
--question "Will BTC close above $100k by end of 2026?" \
--rules "Resolves YES if BTC/USD closes above 100000 on 2026-12-31 per listed public sources. Resolves NO otherwise. If data feed is cancelled, postponed, abandoned, or unresolved by 2027-01-02, resolves NO." \
--sources "https://coinmarketcap.com/currencies/bitcoin/" "https://www.coingecko.com/en/coins/bitcoin" \
--target-timestamp 1798675200 \
--target-timestamp-offset-hours 1 \
--category 3 \
--liquidity 100 \
--fee-tier 3000 \
--distribution-yes 600000000 \
--distribution-no 400000000If pandora is not linked yet, use node cli/pandora.cjs launch ....
Notes
- For AMM launch:
--market-type amm --fee-tier .... - For PariMutuel launch:
--market-type parimutuelwith--curve-flattenerand--curve-offset. - If
createPariMutuelreverts withtransfer amount exceeds balance, top up USDC and retry. - Duplicate guard checks recent on-chain poll questions and blocks repeats unless
--allow-duplicateis set.