
Agenticbets
- 2 installs
- 1.2k repo stars
- Updated August 1, 2026
- bankrbot/openclaw-skills
AgenticBets is a Claude Code skill for placing UP/DOWN price-prediction bets on tokens on Base and claiming winnings, executing transactions via the Bankr Submit API.
About
AgenticBets is a Claude skill for betting on token price direction on Base. An agent uses it to bet UP or DOWN on whether a token price will rise or fall, check prediction-market odds, view open betting rounds and claim winnings from settled rounds. Bets and claims are executed with USDC through the Bankr Submit API.
- Place UP/DOWN prediction bets on token prices on Base via AgenticBets
- Check odds, view open rounds and claim winnings with USDC
- Executes bet and claim transactions through the Bankr Submit API
Agenticbets by the numbers
- 2 all-time installs (skills.sh)
- Ranked #408 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
agenticbets capabilities & compatibility
- Capabilities
- prediction betting · claim winnings · market odds · bankr transaction
- Use cases
- trading
- Runs
- Runs locally
- Pricing
- Bring your own API key
What agenticbets says it does
Prediction markets on Base. Bet UP or DOWN on token prices with USDC.
npx skills add https://github.com/bankrbot/openclaw-skills --skill agenticbetsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 1.2k |
| Last updated | August 1, 2026 |
| Repository | bankrbot/openclaw-skills ↗ |
What it does
Place UP/DOWN price-prediction bets on Base tokens and claim winnings from an agent using USDC.
Who is it for?
Betting UP or DOWN on token prices and claiming prediction-market winnings on Base.
Skip if: Tokens without an active AgenticBets market.
When should I use this skill?
The user wants to bet up or down on a token price, check odds, see open rounds, or claim winnings.
What you get
An executed bet or claim transaction and up-to-date market odds.
- Placed bet transaction
- Claimed winnings
- Market odds and open rounds
By the numbers
- Betting window typically 5 minutes
- 3% fee on the winning pool
Files
AgenticBets
Prediction markets on Base. Bet UP or DOWN on token prices with USDC.
When To Use
Use AgenticBets when the user wants to:
- Bet on whether a token price goes up or down (e.g., "bet $5 UP on AGBETS")
- Check prediction market odds (e.g., "what are the odds on AGBETS?")
- See which markets are open (e.g., "what prediction markets can I bet on?")
- Claim winnings from settled rounds
- Check their bet status or claimable winnings
Prerequisites
Bankr CLI
Install the Bankr CLI and log in to get an API key:
bun install -g @bankr/cli
# or: npm install -g @bankr/cliBankr API Key
The scripts read the API key from ~/.bankr/config.json (or $BANKR_CONFIG if set).
Option A: CLI login (recommended)
# Step 1 — send OTP
bankr login email user@example.com
# Step 2 — verify and generate key with write access
bankr login email user@example.com --code 123456 --accept-terms --key-name "AgenticBets" --read-writeOption B: Web login
1. Visit bankr.bot/api 2. Sign in with email + OTP 3. Generate an API key with Wallet API write access enabled
The API key must have write access (walletApiEnabled, not readOnly) to place bets and claim winnings. Read-only keys can still list markets and check odds.
USDC Balance
Make sure your Bankr wallet has USDC on Base before betting. Check with:
bankr wallet portfolioQuick Start
List Open Markets
What prediction markets are open on AgenticBets?scripts/agenticbets.py listCheck Odds
What are the odds on AGBETS?scripts/agenticbets.py odds AGBETSPlace a Bet
Bet $5 UP on AGBETSscripts/agenticbets.py bet AGBETS up 5Claim Winnings
Claim my AgenticBets winnings for AGBETS epoch 42scripts/agenticbets.py claim AGBETS 42Script Usage
agenticbets.py
Single script that handles all AgenticBets operations. Reads and writes use the Bankr Wallet API.
scripts/agenticbets.py <command> [args...]Commands:
| Command | Args | Description |
|---|---|---|
list | [status] | List markets. Status: all, open, locked, settled (default: open) |
odds | <symbol> | Show bull/bear odds and pool size for a market |
info | <symbol> | Detailed market info including contract, epoch, time to lock |
bet | `<symbol> <up\ | down> <amount>` |
claim | <symbol> <epoch> [epoch...] | Claim winnings for settled epochs |
claimable | <symbol> <epoch> | Check if an epoch is claimable |
Environment:
| Variable | Default | Description |
|---|---|---|
BANKR_CONFIG | ~/.bankr/config.json | Path to Bankr config file containing apiKey |
How It Works
Prediction Market Flow
1. A round opens for a token (e.g., $AGBETS) 2. Users bet UP (bull — price goes up) or DOWN (bear — price goes down) with USDC 3. Betting window closes (typically 5 minutes) 4. Price is locked at close 5. After the round duration, price is checked again 6. If price went up → bull wins. If down → bear wins. 7. Winners split the entire pool proportional to their bet size (minus 3% fee)
Transaction Flow (via Bankr Submit API)
All on-chain transactions go through the Bankr Wallet API:
1. Script fetches market data from GET https://agenticbets.dev/api/bankr/markets 2. Script gets wallet address from GET https://api.bankr.bot/wallet/me 3. For bets:
- Approve USDC spend:
POST https://api.bankr.bot/wallet/submitwith ERC20approve()calldata - Place bet:
POST https://api.bankr.bot/wallet/submitwithbet()calldata
4. For claims: POST https://api.bankr.bot/wallet/submit with claim() calldata 5. All transactions use waitForConfirmation: true and include a human-readable description
Bankr Submit API Reference
Endpoint: POST https://api.bankr.bot/wallet/submit
Headers:
X-API-Key: bk_YOUR_API_KEY
Content-Type: application/jsonRequest body:
{
"transaction": {
"to": "0xContractAddress",
"chainId": 8453,
"data": "0xCalldata...",
"value": "0"
},
"description": "Place $5 UP bet on AGBETS",
"waitForConfirmation": true
}Success response:
{
"success": true,
"transactionHash": "0x...",
"status": "success",
"blockNumber": "12345678",
"signer": "0xYourWalletAddress",
"chainId": 8453
}Wallet info: GET https://api.bankr.bot/wallet/me returns the wallet address and supported chains.
Contracts
| Contract | Address | Tokens |
|---|---|---|
| BankrBetsPrediction V1 | 0xABADeb002247f2bd908Eeedb32918aEc304A0233 | CLAWD, MOLT, WCHAN |
| BankrBetsPrediction V2 | 0x2CD785Ba87e0841A8458141bc43d23a56a00557f | AGBETS |
| USDC (Base) | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | 6 decimals |
Contract Functions
bet(address _token, uint256 _amount, uint8 _position)
_token— token contract address_amount— USDC amount in raw units (multiply by 1e6)_position—0= Bull (UP),1= Bear (DOWN)- Selector:
0x37a02e62
claim(address _token, uint256[] _epochs)
_token— token contract address_epochs— array of epoch numbers to claim- Selector:
0x45718278
claimable(address _token, uint256 _epoch, address _user) -> bool
- Returns true if the user has unclaimed winnings for that epoch
- Selector:
0xd3c035fc
USDC Approval
Before betting, the script approves USDC spend on the prediction contract:
ERC20.approve(predictionContractAddress, betAmount)- Selector:
0x095ea7b3
Token Addresses
| Token | Address | Prediction Contract |
|---|---|---|
| AGBETS | 0x37d183FCf1DA460a64D21E754b3E6144C4e11BA3 | V2 (0x2CD785...) |
| All others | Varies (from API) | V1 (0xABADeb...) |
Use the /api/bankr/markets endpoint to get current token addresses — don't hardcode.
Markets API
GET https://agenticbets.dev/api/bankr/markets
Returns:
{
"markets": [
{
"token": "0x37d183FCf1DA460a64D21E754b3E6144C4e11BA3",
"symbol": "AGBETS",
"marketUrl": "https://agenticbets.dev/market#...",
"poolUsdc": 42.50,
"bullPct": 61.0,
"bearPct": 39.0,
"lockTimestamp": 1713100000,
"secondsToLock": 83,
"predictionContract": "0x2CD785Ba87e0841A8458141bc43d23a56a00557f",
"status": "open",
"epoch": "5",
"poolAddress": "0x...",
"creator": "0x...",
"createdAt": 1700000000,
"contractVersion": "v2"
}
],
"count": 4,
"updatedAt": "2026-04-14T12:00:00.000Z"
}Key fields:
status—"open"(accepting bets),"locked"(waiting for settlement),"settled"(done)secondsToLock— seconds until betting closes.nullif not open.poolUsdc— total USDC in the round poolbullPct/bearPct— current odds splitpredictionContract— which contract to call for this token
Strategy Tips
- Check odds before betting. If 90% of the pool is on one side, the other side pays ~10x if it wins.
- Pool size matters. Larger pools = more reliable odds. Small pools can swing wildly with one bet.
- Time your bet. Betting late (< 30s to lock) lets you see the final odds but risks missing the window.
- Minimum bet is $1 USDC. No maximum.
- Check balance first. Make sure you have enough USDC on Base before betting (
bankr wallet portfolio).
Examples
User: "What prediction markets can I bet on?"
scripts/agenticbets.py list openResponse format:
Open Markets:
$AGBETS — Pool: $42.50 | UP: 61% DOWN: 39% | Closes in 83s
$CLAWD — Pool: $18.00 | UP: 50% DOWN: 50% | Closes in 210sUser: "Bet $10 on AGBETS going up"
scripts/agenticbets.py bet AGBETS up 10Steps: 1. Fetch market data → get token address + prediction contract 2. Approve USDC via Bankr Submit: ERC20.approve(0x2CD785..., 10000000) 3. Place bet via Bankr Submit: BankrBetsPrediction.bet(0x37d183..., 10000000, 0) 4. Return tx hashes
User: "Do I have any claimable winnings?"
scripts/agenticbets.py claimable AGBETS 5Calls claimable(token, epoch, walletAddress) — returns true/false.
User: "Claim my AGBETS winnings from epoch 5"
scripts/agenticbets.py claim AGBETS 5Steps: 1. Call claim(0x37d183..., [5]) via Bankr Submit 2. Return tx hash
References
- [references/agent-usage.md](references/agent-usage.md) — Full agent guide: intent mapping, example conversations, pre-flight checks, error recovery, Markets API schema, and contract reference (calldata encoding, fees, round lifecycle)
Resources
- Website: https://agenticbets.dev
- Telegram Alerts: https://t.me/agenticbets
- GitHub: https://github.com/viraj124/agentic-bets
- MCP Server:
npx agenticbets-mcp(for Claude/Cursor users)
Agent Usage Guide
How an AI agent should use the AgenticBets skill — plus the full API and contract reference.
Core Principles
1. Always fetch live market data first — never hardcode token addresses, pool sizes, or odds. 2. Check the user's intent before acting — reads are free, writes cost USDC + gas. 3. Confirm destructive actions — always echo back what you're about to do before bet or claim. 4. Report tx hashes — after any write, surface the Basescan link so the user can verify.
Intent → Command Mapping
| User intent | Script command | Example |
|---|---|---|
| "What markets are open?" | list open | agenticbets.py list open |
| "Show me all markets" | list all | agenticbets.py list all |
| "What are the odds on X?" | odds <symbol> | agenticbets.py odds AGBETS |
| "Tell me about the X market" | info <symbol> | agenticbets.py info AGBETS |
| "Bet $N UP on X" | bet <symbol> up <amount> | agenticbets.py bet AGBETS up 5 |
| "Bet $N DOWN on X" | bet <symbol> down <amount> | agenticbets.py bet AGBETS down 5 |
| "Claim my winnings from X epoch N" | claim <symbol> <epoch> | agenticbets.py claim AGBETS 42 |
| "Can I claim X epoch N?" | claimable <symbol> <epoch> | agenticbets.py claimable AGBETS 42 |
Example Conversations
Example 1 — Discovery → Bet
User: "What prediction markets should I look at?"
Agent: 1. Run scripts/agenticbets.py list open 2. Parse output, identify markets with poolUsdc >= 5 and imbalanced odds (e.g., one side > 70%) 3. Respond with ranked options:
"Here are the open markets:
- $AGBETS — Pool: $42.50, UP: 61% / DOWN: 39%, closes in 83s
- $CLAWD — Pool: $18.00, 50/50 split, closes in 210s
>
$AGBETS has the biggest pool and leans bullish. If you think the price will drop, DOWN pays ~2.5x. Want me to place a bet?"
Example 2 — Explicit Bet
User: "Bet $5 UP on AGBETS"
Agent: 1. Run scripts/agenticbets.py odds AGBETS to confirm market is open 2. Confirm with user: "Placing $5 UP on $AGBETS at current 61/39 odds. Proceed?" 3. On approval, run scripts/agenticbets.py bet AGBETS up 5 4. Report both tx hashes (approve + bet) with Basescan links
Example 3 — Claim Flow
User: "Did I win on AGBETS epoch 5?"
Agent: 1. Run scripts/agenticbets.py claimable AGBETS 5 2. If claimable, ask: "You have winnings on epoch 5. Claim now?" 3. On approval, run scripts/agenticbets.py claim AGBETS 5
Example 4 — Strategy Question
User: "Is it a good idea to bet on 90/10 splits?"
Agent: (no script call needed — this is general strategy)
"When odds are 90/10, the 10% side pays roughly 9x if it wins — but those odds usually reflect real signal. Good reasons to bet the underdog:
- The pool is small (one big bet can swing it back)
- You have specific info contradicting the consensus
- You're near lock time and can see final odds
>
Against the underdog:
- Winners side's whales usually have better info
- Fees eat into small pools
>
Rule of thumb: only bet the underdog if pool < $20 OR you have an informational edge."
Pre-flight Checks Before Writes
Before placing a bet, an agent should:
1. Verify Bankr config exists:
test -f ~/.bankr/config.json && echo "OK" || echo "Run: bankr login email <email>"2. Verify write access — the script will return 403 if key is read-only. On 403, instruct user to regenerate key with --read-write or toggle off "Read-only" at bankr.bot/api.
3. Verify ETH balance for gas — /wallet/submit broadcasts raw txs, so the Bankr wallet needs native ETH on Base. If the tx fails with "insufficient funds for gas," surface this clearly.
4. Verify USDC balance — bankr wallet portfolio shows Base USDC. Compare to bet amount + existing approvals.
Error Recovery
| Error | Cause | Fix |
|---|---|---|
Read-only API key | API key lacks write permission | Regenerate with --read-write |
insufficient funds for gas | Bankr wallet has no ETH on Base | Send ETH to the wallet address |
ERC20: transfer amount exceeds allowance | Approve tx not yet indexed, or spender mismatch | Retry once; if persistent, check V1 vs V2 routing |
BelowMinBet | Bet < 1 USDC | Raise amount to at least $1 |
TokenNotEligible | Market is inactive or paused | Check info <symbol> to confirm status |
No market found for 'X' | Symbol typo or market doesn't exist | Run list all to see all symbols |
What NOT to Do
- Don't loop bets automatically without user approval each time
- Don't claim on every settled epoch without checking
claimablefirst — wasted gas if nothing to claim - Don't hardcode AGBETS → V2 routing in new code — read
predictionContractfrom the Markets API so future V3/V4 work without changes - Don't retry failed txs more than once — if the second attempt fails with the same error, stop and ask the user
- Don't bet within 10 seconds of lock unless the user explicitly asks — high risk the tx misses the window
---
Markets API Reference
Read-only API for fetching current prediction market state. No auth required.
GET /api/bankr/markets
Base URL: https://agenticbets.dev
Returns all prediction markets with live odds, pool sizes, timing, and contract info.
Request
curl https://agenticbets.dev/api/bankr/marketsNo parameters. No headers required (JSON is returned by default).
Response
{
"markets": [
{
"token": "0x37d183FCf1DA460a64D21E754b3E6144C4e11BA3",
"symbol": "AGBETS",
"marketUrl": "https://agenticbets.dev/market#AGBETS",
"poolUsdc": 42.50,
"bullPct": 61.0,
"bearPct": 39.0,
"lockTimestamp": 1713100000,
"secondsToLock": 83,
"predictionContract": "0x2CD785Ba87e0841A8458141bc43d23a56a00557f",
"status": "open",
"epoch": "5",
"poolAddress": "0x...",
"creator": "0x...",
"createdAt": 1700000000,
"contractVersion": "v2"
}
],
"count": 4,
"updatedAt": "2026-04-14T12:00:00.000Z"
}Fields
| Field | Type | Description |
|---|---|---|
token | address | ERC20 token contract address (the asset being bet on) |
symbol | string | Token ticker (e.g., "AGBETS", "CLAWD") |
marketUrl | string | Direct link to place bets via the web UI |
poolUsdc | number | Current USDC pool size for this round |
bullPct | number | % of pool on UP (0–100) |
bearPct | number | % of pool on DOWN (0–100) |
lockTimestamp | number | Unix seconds when betting closes |
secondsToLock | number \ | null |
predictionContract | address | Which prediction contract to call for this token |
status | string | "open" \ |
epoch | string | Current round number for this token |
poolAddress | address | Uniswap V4 pool used for price oracle |
creator | address | Wallet that created this market |
createdAt | number | Unix seconds of market creation |
contractVersion | string | "v1" (CLAWD, MOLT, WCHAN) or "v2" (AGBETS) |
Status Values
| Status | Meaning | Can Bet? |
|---|---|---|
open | Betting window active | Yes |
locked | Bets closed, waiting for settlement | No |
settled | Round finished, winners can claim | No (a new round will start on next bet) |
cancelled | Round cancelled (tie or error) — refunds | No |
not_started | Market exists but no round has started yet | Yes (first bet starts the round) |
Notes
- Data is cached for ~10 seconds server-side. Don't poll faster than that.
bullPct + bearPctalways sums to 100.0.- Token addresses are canonical — never hardcode; always fetch from this API.
---
Contract Reference
Binary prediction market contracts on Base. Users bet UP or DOWN on token prices using USDC.
Deployed Contracts
| Contract | Address | Version | Tokens |
|---|---|---|---|
| BankrBetsPrediction V1 | 0xABADeb002247f2bd908Eeedb32918aEc304A0233 | v1 | CLAWD, MOLT, WCHAN, etc. |
| BankrBetsPrediction V2 | 0x2CD785Ba87e0841A8458141bc43d23a56a00557f | v2 | AGBETS |
| USDC (Base) | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | — | 6 decimals |
Pick the right contract: use predictionContract field from the Markets API, or route AGBETS→V2 and everything else→V1.
Write Functions
bet(address _token, uint256 _amount, uint8 _position)
Place a bet on a token's price direction. Requires prior USDC approval.
Selector: 0x37a02e62
Parameters:
_token— ERC20 token to bet on (e.g., AGBETS address)_amount— USDC amount in raw units (multiply by1e6). Minimum:1_000_000(1 USDC)_position—0= Bull (UP),1= Bear (DOWN)
Behavior:
- Transfers
_amountUSDC from caller to contract viasafeTransferFrom - Starts a new round if current round is settled/cancelled
- Reverts if token is not active, amount below minimum, round is locked, or pool cap exceeded
Calldata encoding:
0x37a02e62
+ padLeft32(token) // 32 bytes
+ padLeft32(amount) // 32 bytes
+ padLeft32(position) // 32 bytesclaim(address _token, uint256[] _epochs)
Claim winnings for one or more settled epochs.
Selector: 0x45718278
Parameters:
_token— token the bet was placed on_epochs— array of epoch numbers to claim
Behavior:
- Iterates epochs, transfers USDC winnings to caller
- Skips already-claimed epochs
- Reverts if any epoch is not claimable
Calldata encoding (dynamic array):
0x45718278
+ padLeft32(token) // 32 bytes
+ padLeft32(0x40) // offset to array (64)
+ padLeft32(epochs.length) // array length
+ padLeft32(epoch[0]) // first element
+ ...Read Functions
claimable(address _token, uint256 _epoch, address _user) → bool
Returns true if _user has unclaimed winnings for _token at _epoch.
Selector: 0xd3c035fc
USDC Approval
Before bet(), approve the prediction contract to spend USDC:
ERC20.approve(predictionContract, amount)Selector: 0x095ea7b3
Calldata:
0x095ea7b3
+ padLeft32(predictionContract) // spender
+ padLeft32(amount) // uint256 amount in raw unitsFees
Total fee: 2.1% of losers' pool, split:
- 1.5% → treasury
- 0.5% → market creator
- 0.1% → settler (whoever calls
closeRound())
Winners split the remaining 97.9% pro-rata based on their bet size vs. winning-side total.
Round Lifecycle
Open → Locked → Settled
↑ ↓
(betWindow) (next bet starts new round)1. Open — startTimestamp to lockTimestamp - 60s. Bets accepted. 2. Locked — lockRound() called → lockPrice recorded 3. Settled — closeRound() called at closeTimestamp → winner determined 4. Next bet() call on this token starts a new round
Constraints
- Minimum bet:
1_000_000raw units = 1 USDC. Below this reverts withBelowMinBet(). - Max round pool (V2 only): 10,000 USDC per round. Exceeding reverts with
ExceedsMaxRoundPool().
#!/usr/bin/env python3
"""AgenticBets CLI — list markets, check odds, place bets, claim winnings.
Uses the AgenticBets Markets API for reads and Bankr Submit API for writes.
Usage: scripts/agenticbets.py <command> [args...]
Environment:
BANKR_CONFIG Path to Bankr config file (default: ~/.bankr/config.json)
"""
import json
import os
import sys
import urllib.request
import urllib.error
MARKETS_API = "https://agenticbets.dev/api/bankr/markets"
BANKR_API = "https://api.bankr.bot"
USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
USDC_DECIMALS = 6
BASE_CHAIN_ID = 8453
# V1 — existing markets; V2 — AGBETS
PREDICTION_V1 = "0xABADeb002247f2bd908Eeedb32918aEc304A0233"
PREDICTION_V2 = "0x2CD785Ba87e0841A8458141bc43d23a56a00557f"
AGBETS_TOKEN = "0x37d183FCf1DA460a64D21E754b3E6144C4e11BA3"
def load_bankr_key():
"""Read Bankr API key from config."""
config_path = os.environ.get("BANKR_CONFIG", os.path.expanduser("~/.bankr/config.json"))
if not os.path.exists(config_path):
print(f"ERROR: Bankr config not found at {config_path}", file=sys.stderr)
print("Run `bankr login email <your-email>` to set up.", file=sys.stderr)
sys.exit(1)
with open(config_path) as f:
config = json.load(f)
key = config.get("apiKey") or config.get("api_key")
if not key:
print(f"ERROR: No apiKey in {config_path}", file=sys.stderr)
sys.exit(1)
return key
def bankr_request(method, path, body=None):
"""Make an authenticated request to Bankr Wallet API."""
api_key = load_bankr_key()
url = f"{BANKR_API}{path}"
data = json.dumps(body).encode() if body else None
req = urllib.request.Request(
url,
data=data,
headers={
"X-API-Key": api_key,
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": "agenticbets-bankr-skill/1.0",
},
method=method,
)
try:
with urllib.request.urlopen(req, timeout=60) as resp:
return json.loads(resp.read())
except urllib.error.HTTPError as e:
body_text = e.read().decode() if e.fp else ""
print(f"Bankr API error: {e.code} {e.reason} — {body_text}", file=sys.stderr)
sys.exit(1)
def get_wallet_address():
"""Get the user's Bankr wallet address."""
data = bankr_request("GET", "/wallet/me")
return data.get("address") or data.get("walletAddress")
def submit_tx(to, data_hex, description="", value="0"):
"""Submit a transaction via Bankr Submit API."""
tx = {
"to": to,
"chainId": BASE_CHAIN_ID,
"data": data_hex,
"value": value,
}
result = bankr_request("POST", "/wallet/submit", {
"transaction": tx,
"description": description,
"waitForConfirmation": True,
})
tx_hash = result.get("transactionHash") or result.get("hash") or result.get("txHash")
status = result.get("status", "unknown")
if status == "reverted":
print(f" WARNING: Transaction reverted! Hash: {tx_hash}", file=sys.stderr)
return tx_hash
def fetch_markets():
"""Fetch markets from AgenticBets API."""
req = urllib.request.Request(
MARKETS_API,
headers={"Accept": "application/json", "User-Agent": "agenticbets-bankr-skill/1.0"},
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
data = json.loads(resp.read())
return data["markets"]
except Exception as e:
print(f"ERROR: Failed to fetch markets — {e}", file=sys.stderr)
sys.exit(1)
def find_market(symbol_or_address):
"""Find a market by symbol or token address."""
markets = fetch_markets()
q = symbol_or_address.lower()
for m in markets:
if m["symbol"].lower() == q or m["token"].lower() == q:
return m
return None
def get_prediction_contract(token_address):
"""Return the correct prediction contract for a token."""
if token_address.lower() == AGBETS_TOKEN.lower():
return PREDICTION_V2
return PREDICTION_V1
def encode_approve(spender, amount_raw):
"""Encode ERC20 approve(address,uint256) calldata."""
# approve(address,uint256) selector = 0x095ea7b3
spender_padded = spender.lower().replace("0x", "").zfill(64)
amount_hex = hex(amount_raw)[2:].zfill(64)
return f"0x095ea7b3{spender_padded}{amount_hex}"
def encode_bet(token, amount_raw, position):
"""Encode bet(address,uint256,uint8) calldata."""
# bet(address,uint256,uint8) selector = 0x37a02e62
token_padded = token.lower().replace("0x", "").zfill(64)
amount_hex = hex(amount_raw)[2:].zfill(64)
position_hex = hex(position)[2:].zfill(64)
return f"0x37a02e62{token_padded}{amount_hex}{position_hex}"
def encode_claim(token, epochs):
"""Encode claim(address,uint256[]) calldata."""
# claim(address,uint256[]) selector = 0x45718278
token_padded = token.lower().replace("0x", "").zfill(64)
# ABI encode dynamic array: offset, length, elements
offset_hex = hex(64)[2:].zfill(64) # offset to array data (2 * 32 bytes)
length_hex = hex(len(epochs))[2:].zfill(64)
elements = "".join(hex(e)[2:].zfill(64) for e in epochs)
return f"0x45718278{token_padded}{offset_hex}{length_hex}{elements}"
def encode_claimable(token, epoch, user):
"""Encode claimable(address,uint256,address) calldata."""
# claimable(address,uint256,address) selector = 0xd3c035fc
token_padded = token.lower().replace("0x", "").zfill(64)
epoch_hex = hex(epoch)[2:].zfill(64)
user_padded = user.lower().replace("0x", "").zfill(64)
return f"0xd3c035fc{token_padded}{epoch_hex}{user_padded}"
# -- Commands ----------------------------------------------------------------
def cmd_list(status="open"):
"""List markets filtered by status."""
markets = fetch_markets()
if status != "all":
markets = [m for m in markets if m["status"] == status]
if not markets:
print(f"No {status} markets found.")
return
print(f"{'Symbol':<10} {'Pool':>10} {'UP':>5} {'DOWN':>5} {'Status':<10} {'Time Left'}")
print("-" * 60)
for m in markets:
bull = round(m["bullPct"])
bear = 100 - bull
time_left = f"{m['secondsToLock']}s" if m.get("secondsToLock") and m["secondsToLock"] > 0 else "-"
print(f"${m['symbol']:<9} ${m['poolUsdc']:>9.2f} {bull:>4}% {bear:>4}% {m['status']:<10} {time_left}")
def cmd_odds(symbol):
"""Show odds for a market."""
market = find_market(symbol)
if not market:
print(f"No market found for '{symbol}'")
sys.exit(1)
bull = round(market["bullPct"])
bear = 100 - bull
time_info = f"{market['secondsToLock']}s to lock" if market.get("secondsToLock") and market["secondsToLock"] > 0 else market["status"]
print(f"${market['symbol']} — Epoch {market['epoch']}")
print(f" UP: {bull}%")
print(f" DOWN: {bear}%")
print(f" Pool: ${market['poolUsdc']:.2f} USDC")
print(f" {time_info}")
def cmd_info(symbol):
"""Detailed market info."""
market = find_market(symbol)
if not market:
print(f"No market found for '{symbol}'")
sys.exit(1)
print(json.dumps(market, indent=2))
def cmd_bet(symbol, direction, amount):
"""Place a bet."""
market = find_market(symbol)
if not market:
print(f"No market found for '{symbol}'")
sys.exit(1)
token = market["token"]
prediction = get_prediction_contract(token)
position = 0 if direction.lower() in ("up", "bull") else 1
direction_label = "UP" if position == 0 else "DOWN"
amount_raw = int(float(amount) * (10 ** USDC_DECIMALS))
print(f"Placing ${amount} {direction_label} bet on ${market['symbol']}...")
# 1. Approve USDC for this bet amount
print(" Approving USDC...")
approve_data = encode_approve(prediction, amount_raw)
approve_hash = submit_tx(
USDC_ADDRESS,
approve_data,
description=f"Approve ${amount} USDC for AgenticBets {market['symbol']} bet",
)
print(f" Approve tx: https://basescan.org/tx/{approve_hash}")
# 2. Place bet
print(" Submitting bet...")
bet_data = encode_bet(token, amount_raw, position)
bet_hash = submit_tx(
prediction,
bet_data,
description=f"Place ${amount} {direction_label} bet on {market['symbol']} epoch {market['epoch']}",
)
print(f" Bet tx: https://basescan.org/tx/{bet_hash}")
print(f" Done! ${amount} {direction_label} on ${market['symbol']} epoch {market['epoch']}")
def cmd_claim(symbol, *epoch_args):
"""Claim winnings."""
market = find_market(symbol)
if not market:
print(f"No market found for '{symbol}'")
sys.exit(1)
epochs = [int(e) for e in epoch_args]
token = market["token"]
prediction = get_prediction_contract(token)
print(f"Claiming ${market['symbol']} epochs {epochs}...")
claim_data = encode_claim(token, epochs)
tx_hash = submit_tx(
prediction,
claim_data,
description=f"Claim {market['symbol']} winnings for epochs {epochs}",
)
print(f" Claim tx: https://basescan.org/tx/{tx_hash}")
print(" Done!")
def cmd_claimable(symbol, epoch):
"""Check if an epoch is claimable."""
market = find_market(symbol)
if not market:
print(f"No market found for '{symbol}'")
sys.exit(1)
wallet = get_wallet_address()
token = market["token"]
print(f"Checking claimable: ${market['symbol']} epoch {epoch} for {wallet}")
print("(Use the AgenticBets website to check — contract reads via Bankr API coming soon)")
# -- Entry point -------------------------------------------------------------
COMMANDS = {
"list": lambda args: cmd_list(args[0] if args else "open"),
"odds": lambda args: cmd_odds(args[0]) if args else print("Usage: odds <symbol>"),
"info": lambda args: cmd_info(args[0]) if args else print("Usage: info <symbol>"),
"bet": lambda args: cmd_bet(args[0], args[1], args[2]) if len(args) >= 3 else print("Usage: bet <symbol> <up|down> <amount>"),
"claim": lambda args: cmd_claim(args[0], *args[1:]) if len(args) >= 2 else print("Usage: claim <symbol> <epoch> [epoch...]"),
"claimable": lambda args: cmd_claimable(args[0], int(args[1])) if len(args) >= 2 else print("Usage: claimable <symbol> <epoch>"),
}
def main():
if len(sys.argv) < 2 or sys.argv[1] not in COMMANDS:
print("AgenticBets — Prediction markets on Base")
print()
print("Commands:")
print(" list [status] List markets (open/locked/settled/all)")
print(" odds <symbol> Show bull/bear odds")
print(" info <symbol> Detailed market info (JSON)")
print(" bet <symbol> <up|down> <$> Place a USDC bet")
print(" claim <symbol> <epoch...> Claim settled winnings")
print(" claimable <symbol> <epoch> Check if epoch is claimable")
sys.exit(0)
cmd = sys.argv[1]
args = sys.argv[2:]
COMMANDS[cmd](args)
if __name__ == "__main__":
main()
Related skills
FAQ
How do winnings work?
Winners split the entire pool proportional to their bet size, minus a 3% fee.
How are bets executed?
All on-chain bet and claim transactions go through the Bankr Wallet/Submit API using USDC on Base.