Skip to main content
Bots are first-class citizens on counsel. A bot is an ordinary XRPL client: it reads live markets, fetches an unsigned bet Payment, signs it with its own key, and submits it to the ledger. counsel never holds a key. Every bet carries the counsel SourceTag, so a bot’s on-chain volume counts toward leaderboard attribution the same way a manual bet does. Because counsel markets are parimutuel, there is no order book, bots add value by correcting mispricings, balancing pools, or arbitraging across venues. Each of these actions is a native tagged Payment, generating direct on-chain volume.

What a bot can do

  • Value-betting, estimate the true probability of each outcome and stake when the market’s implied_prob diverges from your model by a meaningful margin. This pushes the line toward the fair price, benefiting all participants.
  • Pool-balancing, parimutuel lines drift continuously until bet_cutoff. A bot can identify a lopsided pool near close and bet the underweighted side, capturing better odds while correcting the skew.
  • Cross-venue arbitrage, take a counsel position and hedge it against the same event on another platform, locking in a spread when the implied probabilities diverge.

Quickstart, install and configure

Install the SDK from the repo and configure the base URL:
Set COUNSEL_URL to https://api.counsel.markets and reference it with process.env.COUNSEL_URL to keep the base URL out of your source code.

Read live markets

Fetch all public markets and inspect their current pool state and indicative odds:
Filter to markets that are currently accepting bets before doing anything else:

Fetch a bet intent

Before committing, retrieve an unsigned transaction for the specific bet you want to place. This also returns the projected line impact of your stake:
betIntent maps to:
The returned tx is a fully-formed XRPL Payment object. All that remains is to autofill sequence/fee fields, sign, and submit.

Sign and submit

placeBet handles the full lifecycle: it calls betIntent internally, signs with the provided seed using xrpl.js, submits, and waits for ledger validation. It returns the confirmed transaction hash.
Use testnet seeds only. Never commit seeds to source control. Load BOT_SEED exclusively from environment variables or a secrets manager.
Internally, placeBet connects to the XRPL WebSocket node specified in CounselOptions.wss (defaults to wss://s.altnet.rippletest.net:51233 for testnet), autofills the transaction, signs it with Wallet.fromSeed(seed), submits via submitAndWait, and asserts tesSUCCESS before returning. The WebSocket connection is disconnected after each call.

Full value-betting example

The following bot fetches all open markets, runs each outcome through a probability model, and bets when it finds sufficient edge. It also checks the projected post-stake odds before committing to avoid betting after the line has already moved past the fair price:
The inner check on projected_implied_odds_after.implied_prob is important: in a small pool, your own 5 XRP stake can move the line enough to eliminate the edge you detected from the stale implied_prob in the market list.

Anti-slippage

Parimutuel odds are not fixed, every bet changes the pool, and therefore every subsequent payout. When you read implied_prob from GET /markets, that figure already reflects all bets submitted before your read. By the time you fetch the bet intent, further bets may have arrived. Always use projected_implied_odds_after as your decision gate, not the market-list odds:
For large stakes relative to pool size, consider breaking a single bet into smaller sequential bets and re-checking the intent each time.

Rate limits

The public API requires no authentication. There are no enforced rate limits, but the API is a shared resource. Poll GET /markets at a reasonable cadence, 5-10 seconds is appropriate for most strategies. High-frequency polling does not provide an advantage on parimutuel markets: odds change when bets arrive, not on a tick schedule, and final payouts are determined at close regardless of when you placed your bet.

SDK method reference