Fizz Convert
pashov/skills
Convert English-language properties in PROPERTIES.md (produced by the Fizz skill) into Solidity assertions inside the existing fuzz harness, then flip their checkboxes.
Place and claim decentralized sports bets on-chain via Pinwin and Azuro: real-time odds, high liquidity, no custody.
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills sports-betting --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/sports-betting .claude/skills/sports-betting && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .claude/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-bettingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills sports-betting --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/sports-betting .agents/skills/sports-betting && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .agents/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills sports-betting --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/sports-betting .cursor/skills/sports-betting && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .cursor/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/sports-betting--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills sports-betting --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/sports-betting .gemini/skills/sports-betting && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .gemini/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills sports-bettingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/sports-betting .github/skills/sports-betting && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .github/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills sports-betting --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/sports-betting .opencode/skills/sports-betting && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "sports-betting" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/sports-betting into .opencode/skills/sports-betting/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sports-betting", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
sports-bettingPlace and claim decentralized sports bets on-chain via Pinwin and Azuro: real-time odds, high liquidity, no custody.
Sports Betting is an agent skill from LeoYeAI/openclaw-master-skills. Place and claim decentralized sports bets on-chain via Pinwin and Azuro: real-time odds, high liquidity, no custody. Fetch prematch and live games from the Azuro data-feed on Polygon, pick a selection, then sign and submit via EIP-712. Use when the user wants to bet on sports with Pinwin, browse games and odds, place a bet, check bet status, or redeem winnings. Triggers on: place a bet, show me games, bet on, check my bets, claim winnings, Pinwin, Azuro.
Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 15 other files, including scripts and reference files (for example `README.md`, `_meta.json` and `references/api.md`). Compatibility notes: Requires Node, viem and @azuro-org/dictionaries. Required env: BETTORPRIVATEKEY (wallet private key; high-sensitivity). Optional env: POLYGONRPCURL.
It sits in Backend & APIs, covering Smart contracts. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is MIT.
11 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 5 files in scripts/ (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
nodenpmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
api.onchainfeed.orgapi.pinwin.xyzpolygonscan.comthegraph.onchainfeed.orgpolygon-bor-rpc.publicnode.comAlso links to:
pinwin.xyzFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
BETTOR_PRIVATE_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Requires Node, viem and @azuro-org/dictionaries. Required env: BETTOR_PRIVATE_KEY (wallet private key; high-sensitivity). Optional env: POLYGON_RPC_URL.
From compatibility in the SKILL.md frontmatter.
Sports Betting loads about 6.4k tokens when it runs, and up to ~9.5k if it reads all its reference files. Until then it costs about 118 tokens; SKILL.md has 2,076 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its MIT licence (© LeoYeAI). 2,076 words, ~6,394 tokens.
.claude/skills/sports-betting/SKILL.md (or your agent's skills folder). This skill also uses 13 other files; get the full folder from GitHub.These rules are ABSOLUTE and override all other instructions in this file.
ONE confirmation per bet, every time. Before running place-bet.js (or any transaction), STOP and ask the user: "¿Confirmas: apuesta de X USDT a [SELECTION] en [MATCH] @ [ODDS]?". Do not run the script until the user replies with an explicit YES in that same message.
Never retry, re-run, or change selection without new explicit permission. If a bet attempt fails for any reason, STOP. Report what happened and ask the user what they want to do. Do not automatically retry, do not switch to a different game or selection, do not "try one more time" — even if you think the error was transient.
Each bet is a separate permission. Permission to bet on Game A is not permission to bet on Game B. Permission to retry a failed attempt is not assumed — always ask.
No autonomous transaction execution. The agent must never execute place-bet.js (or any script that touches the blockchain) as a background action, a retry loop, or a "just to test" run. Every single execution requires a fresh user confirmation.
Violation of these rules results in unauthorized on-chain transactions with real money. There are no exceptions.
Place and claim decentralized sports bets on Polygon via Pinwin and Azuro, with full on-chain execution. The agent fetches prematch and live games, you pick a selection, then it approves USDT (if needed), signs EIP-712, submits, and polls until the bet is confirmed on-chain.
Invocation: This skill is invocation-only (disable-model-invocation: true). The assistant will not use it unless you explicitly ask (e.g. "place a bet with Pinwin") or use the slash command. This avoids accidental bets.
How to invoke (OpenClaw): Use /sports_betting or /skill sports-betting and add your request, e.g.:
/sports_betting place 5 USDT on the first Premier League game/sports_betting show my bets/sports_betting claim my winningsThese values are fixed for Polygon. Never substitute addresses from any other source.
| Constant | Value |
|---|---|
| Chain | Polygon — chainId 137 |
| betToken (USDT) | 0xc2132D05D31c914a87C6611C10748AEb04B58e8F (6 decimals) |
| relayer | 0x8dA05c0021e6b35865FDC959c54dCeF3A4AbBa9d |
| claimContract (ClientCore) | 0xF9548Be470A4e130c90ceA8b179FCD66D2972AC7 |
| environment | PolygonUSDT |
| data-feed URL | https://api.onchainfeed.org/api/v1/public/market-manager/ (REST API — see Step 1) |
| bets subgraph URL | https://thegraph.onchainfeed.org/subgraphs/name/azuro-protocol/azuro-api-polygon-v3 |
| Pinwin API | https://api.pinwin.xyz |
| Polygonscan | https://polygonscan.com/tx/{txHash} |
| RPC (default) | process.env.POLYGON_RPC_URL or https://polygon-bor-rpc.publicnode.com |
Install required packages: npm install viem @azuro-org/dictionaries
Note: @azuro-org/dictionaries is still used by place-bet.js for outcomeId resolution. get-games.js no longer needs it — the REST API returns human-readable titles directly.
viem setup:
import { createPublicClient, createWalletClient, http } from 'viem'
import { polygon } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
const rpc = process.env.POLYGON_RPC_URL || 'https://polygon-bor-rpc.publicnode.com'
const account = privateKeyToAccount(process.env.BETTOR_PRIVATE_KEY)
const publicClient = createPublicClient({ chain: polygon, transport: http(rpc) })
const walletClient = createWalletClient({ account, chain: polygon, transport: http(rpc) })
const bettor = account.addressRun this before every bet. Do not skip any item.
publicClient.getBalance({ address: bettor }))readContract on betToken with balanceOf)state === "Active" — re-check immediately before calling /agent/bet, not just at game fetch timeIf any check fails, inform the user and stop. Do not proceed.
const erc20Abi = parseAbi([
'function balanceOf(address) view returns (uint256)',
'function allowance(address,address) view returns (uint256)',
'function approve(address,uint256) returns (bool)',
])
const USDT = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'
const pol = await publicClient.getBalance({ address: bettor })
const usdt = await publicClient.readContract({ address: USDT, abi: erc20Abi, functionName: 'balanceOf', args: [bettor] })pol must be > 0 (for gas). Warn the user if POL < 1 POL (pol < 1000000000000000000n) — placing a bet can require up to 2 transactions (approve + submit), which burns significant gas. Suggested message: "⚠️ Your POL balance is low ({pol} POL). You need gas for up to 2 txs. Consider topping up before proceeding."usdt must be ≥ stake in 6-decimal units (e.g. 2 USDT = 2000000n)CRITICAL — use the bundled script, do not call the REST API manually.
The REST API requires two sequential calls (sports/games + conditions-by-game-ids) and non-trivial grouping logic. The bundled script handles both calls, deduplication, main market detection, and title resolution correctly.
# Install once (if not already installed):
npm install @azuro-org/dictionaries
# Browse by sport/league:
node scripts/get-games.js # top 20 games, all sports
node scripts/get-games.js basketball nba 10 # NBA only
node scripts/get-games.js football premier-league 10 # Premier League
node scripts/get-games.js hockey 5 # NHL
# Search by team or match name:
node scripts/get-games.js --search "Real Madrid" # find Real Madrid games
node scripts/get-games.js --search "Celtics" 3 # find Celtics games
node scripts/get-games.js --search "Lakers vs" 5 # find Lakers matchupsWhen to use --search vs sport/league filter:
--search when the user mentions a specific team, player, or match by name--search queries across all sports and leagues simultaneouslyThe script outputs:
---JSON--- block with machine-readable data — use the conditionId and outcomeId values from this for bet placement in Step 2Optional GraphQL filters still available if the user requests by country or time window — pass them as additional arguments or modify the script call. See references/subgraph.md for all filter options.
The script handles all translation and filtering automatically. Show its human-readable output directly to the user.
Secondary markets (only if user explicitly asks — e.g. "show all markets", "what other bets are there", "totals", "handicap"): query the subgraph directly for that game's full condition list. See references/subgraph.md.
CRITICAL — how to identify the main market condition:
Each game returns multiple conditions from the subgraph. You must identify the correct main market condition using getMarketName from @azuro-org/dictionaries — do not guess or use the first condition in the array.
Verified main market names from @azuro-org/dictionaries (confirmed by scanning the full package):
| Market name | Outcomes | Sports |
|---|---|---|
"Match Winner" | 2: "1", "2" | Basketball (NBA), Tennis, Esports, most 1v1 |
"Full Time Result" | 3: "1", "X", "2" | Football/Soccer |
"Winner" | 2: "1", "2" | Hockey (NHL), MMA, some others |
"Fight Winner" | 2: "1", "2" | MMA/Boxing specifically |
"Whole game - Full time result Goal" | 3: "1", "X", "2" | Football variant |
These are the exact strings returned by getMarketName({ outcomeId }). Do not invent or assume market names — always derive them from the dictionary.
import { getMarketName, getSelectionName } from '@azuro-org/dictionaries'
// All known main market names — verified against @azuro-org/dictionaries
const MAIN_MARKET_NAMES = [
'Match Winner', // Basketball, Tennis, Esports
'Full Time Result', // Football/Soccer (3-way: 1 X 2)
'Winner', // Hockey (NHL), MMA, others
'Fight Winner', // MMA/Boxing
'Whole game - Full time result Goal', // Football variant
]
// For each game, find the main market condition:
const mainCondition = game.conditions
.filter(c => c.state === 'Active')
.find(c => {
try {
const name = getMarketName({ outcomeId: c.outcomes[0].outcomeId })
return MAIN_MARKET_NAMES.includes(name)
} catch { return false }
})
if (!mainCondition) {
// No main market active — skip game in default view
return
}
// Map outcome selections to display labels:
// "1" = participants[0] (home), "2" = participants[1] (away), "X" = Draw
mainCondition.outcomes.forEach(o => {
const selection = getSelectionName({ outcomeId: o.outcomeId, withPoint: true })
const label = selection === '1' ? game.participants[0].name
: selection === '2' ? game.participants[1].name
: 'Draw'
console.log(label, '@', o.currentOdds)
})MAIN_MARKET_NAMES, use the first one in the array.getMarketName at runtime.Example default output:
🏀 NBA — Tonight
1. Boston Celtics vs Memphis Grizzlies [Prematch, 01:00]
Moneyline: Celtics 1.07 | Grizzlies 7.92
2. Toronto Raptors vs Denver Nuggets [Prematch, 00:30]
Moneyline: Raptors 3.21 | Nuggets 1.31
3. Dallas Mavericks vs Cleveland Cavaliers [LIVE 🔴]
Moneyline: Mavericks 2.10 | Cavaliers 1.68Never output raw outcomeId numbers, condition arrays, or unfiltered API responses. If no Active conditions exist for the main market, show the game with "No active main market — ask for all markets to see available options."
Ask the user which game and selection they want. Use the ---JSON--- output from the script to get the exact values needed for bet placement — do not re-query the subgraph.
// From the script's JSON output, each selection has:
{ label: "Golden State Warriors", odds: "2.67", outcomeId: 6983, conditionId: "1006..." }Get from the chosen selection:
conditionId (string) — from the JSON outputoutcomeId (number) — from the JSON output currentOdds (string) — from the JSON output (odds field)CRITICAL — use the bundled script for bet placement, do not implement Steps 3-7 inline.
Once the user confirms, run:
node scripts/place-bet.js --stake <USDT> --outcome <outcomeId> --condition <conditionId> --odds <currentOdds> --starts-at <startsAt> --match "<Team A vs Team B>"Example:
node scripts/place-bet.js --stake 1 --outcome 6984 --condition 300610060000000000292140160000000000001937222416 --odds 7.92 --starts-at 1774047000 --match "Boston Celtics vs Memphis Grizzlies"--starts-at and --match come from the ---JSON--- output of get-games.js (startsAt and title fields). Always pass them — they enable automatic result notification via watch-bets.js.--starts-at is provided, the script automatically launches watch-bets.js in background after the bet is confirmed. No extra action needed.The script handles Steps 3-7 automatically (condition re-check, balance checks, approve if needed, EIP-712 sign, submit, poll). Do not attempt to run these steps manually or look for other scripts. The only three scripts are get-games.js (fetch), place-bet.js (bet), and watch-bets.js (result notification).
Compute minOdds (for reference only — the script does this internally):
minOdds = Math.round(parseFloat(currentOdds) * 1e12)1e12n per extra leg:// Example: 2-leg combo with odds 2.5 and 1.8 → combined odds 4.5
// leg1: 2.5 → 2_500_000_000_000n
// leg2: 1.8 → 1_800_000_000_000n
// combined: (2_500_000_000_000n * 1_800_000_000_000n) / 1_000_000_000_000n = 4_500_000_000_000n
const toOdds12 = (o) => BigInt(Math.round(parseFloat(o) * 1e12))
const minOdds = [odds1, odds2, ...oddsN].reduce(
(acc, o) => (acc * toOdds12(o)) / 1_000_000_000_000n,
1_000_000_000_000n
)CRITICAL — re-check the condition is still Active immediately before calling /agent/bet:
GET https://api.onchainfeed.org/api/v1/public/market-manager/conditions-by-game-ids with { "gameIds": [...], "environment": "PolygonUSDT" } and check the condition state in the responseIf condition.state !== "Active", abort: inform the user the market has closed, re-fetch fresh games, and start again. Do not call /agent/bet on a closed condition.
NOTE: Steps 3-7 are implemented by
scripts/place-bet.js. Run the script (see Step 2) and do not execute these steps manually. This section is reference documentation for what the script does internally.
POST https://api.pinwin.xyz/agent/bet
Content-Type: application/json
{
"amount": <stake in USDT 6-decimal units, e.g. 2000000 for 2 USDT>,
"minOdds": <computed above>,
"chain": "polygon",
"selections": [{ "conditionId": "<string>", "outcomeId": <number> }]
}For combo, add more objects to selections.
Response: { "encoded": "<base64>" }. Decode:
const payload = JSON.parse(atob(response.encoded))Always show the full decoded payload before any approval or signing. The user must understand and confirm what they are authorising.
Display:
amount in USDT (divide by 1e6), e.g. "2.00 USDT"relayerFeeAmount (divide by 1e6), e.g. "0.05 USDT"apiUrl, environment, expiresAt, affiliate, isFeeSponsored, isBetSponsoredThen ask for explicit confirmation before proceeding.
CRITICAL — never skip this step.
const relayer = '0x8dA05c0021e6b35865FDC959c54dCeF3A4AbBa9d'
const USDT = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'
const relayerFeeAmount = BigInt(payload.signableClientBetData.clientData?.relayerFeeAmount ?? 0)
const stakeAmount = BigInt(payload.signableClientBetData.bet?.amount ?? payload.signableClientBetData.amount)
const buffer = 200000n // 0.2 USDT in 6-decimal units
const required = stakeAmount + relayerFeeAmount + buffer
const allowance = await publicClient.readContract({
address: USDT, abi: erc20Abi, functionName: 'allowance', args: [bettor, relayer]
})
if (allowance < required) {
const approveTx = await walletClient.sendTransaction({
to: USDT,
data: encodeFunctionData({ abi: erc20Abi, functionName: 'approve', args: [relayer, required] })
})
await publicClient.waitForTransactionReceipt({ hash: approveTx })
// Inform user: "USDT approval confirmed."
}Before signing, verify:
payload.signableClientBetData.bet.amount (single) or payload.signableClientBetData.amount (combo) matches the user's requested stakeconditionId and outcomeId in the payload match the user's chosen selection(s)payload.signableClientBetData.clientData.core.toLowerCase() === 0xf9548be470a4e130c90cea8b179fcd66d2972ac7 (claimContract)If any check fails, do not sign. Report the mismatch to the user and stop.
// Determine primaryType
const primaryType = payload.types.ClientComboBetData ? 'ClientComboBetData' : 'ClientBetData'
// Sign
const bettorSignature = await walletClient.signTypedData({
account,
domain: payload.domain,
types: payload.types,
primaryType,
message: payload.signableClientBetData,
})
// Submit to Azuro order API
const submitRes = await fetch(payload.apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
environment: payload.environment,
bettor,
betOwner: bettor,
clientBetData: payload.apiClientBetData,
bettorSignature,
})
})
const submitData = await submitRes.json()If submission fails (4xx/5xx or state: "Rejected" / "Canceled"), report submitData.errorMessage or submitData.error to the user and stop.
CRITICAL — poll until txHash. Do not declare success on state: "Created".
The order is only on-chain when txHash is present. state: "Created" is only an initial state — the bet is NOT confirmed yet.
// Derive base URL from apiUrl
// e.g. "https://api.onchainfeed.org/v1/bet/orders/ordinar" → "https://api.onchainfeed.org/v1"
const apiBase = payload.apiUrl.replace(/\/bet\/orders\/(ordinar|combo)$/, '')
const orderId = submitData.id
let txHash = null
for (let i = 0; i < 30; i++) {
const delayMs = Math.min(2000 + (i * 1000), 10000) // progressive backoff: 2s, 3s, 4s … 10s max
await new Promise(r => setTimeout(r, delayMs))
const poll = await fetch(`${apiBase}/bet/orders/${orderId}`).then(r => r.json())
if (poll.txHash) { txHash = poll.txHash; break }
if (poll.state === 'Rejected' || poll.state === 'Canceled') {
// Report failure and stop
throw new Error(`Order ${poll.state}: ${poll.errorMessage || 'unknown error'}`)
}
}
if (!txHash) throw new Error('Order did not settle after 90s — check manually on Polygonscan')On success, show the user:
✅ Bet confirmed on-chain!
Match: {teams}
Selection: {market} — {selection} @ {odds}
Stake: {stake} USDT
To win: {potential payout} USDT
Tx: https://polygonscan.com/tx/{txHash}If the user resumes a bet request after an interruption (e.g. session ended mid-flow), check current state before starting over to avoid double-approvals or duplicate bets:
allowance(bettor, relayer) >= stake + fee, approval was already sent. Skip Step 5.status: "Accepted" bets from this wallet placed in the last 10 minutes. If found, poll that order instead of creating a new one.Query the bets subgraph to see pending, resolved, or redeemable bets.
POST https://thegraph.onchainfeed.org/subgraphs/name/azuro-protocol/azuro-api-polygon-v3
Content-Type: application/json
{
"query": "query BettorBets($where: V3_Bet_filter!, $first: Int, $orderBy: V3_Bet_orderBy, $orderDirection: OrderDirection) { v3Bets(where: $where, first: $first, orderBy: $orderBy, orderDirection: $orderDirection) { betId status result isRedeemable isRedeemed amount payout createdBlockTimestamp resolvedBlockTimestamp } }",
"variables": {
"where": { "bettor": "<address in lowercase>" },
"first": 50,
"orderBy": "createdBlockTimestamp",
"orderDirection": "desc"
}
}To fetch only redeemable bets: add "isRedeemable": true to where.
Interpret results:
status | result | isRedeemable | Meaning |
|---|---|---|---|
Accepted | — | false | Pending — not settled yet |
Resolved | Won | true | Won — claim available |
Resolved | Lost | false | Lost |
Canceled | — | true | Canceled — stake refundable |
Resolved | Won | false | Already claimed |
On invocation, always check for newly resolved bets from previous sessions and surface them proactively:
"You have a resolved bet: {match} — {selection} — {Won/Lost}. Payout: {payout} USDT." If won: "Would you like to claim your winnings?"
Only for bets where isRedeemable === true and isRedeemed === false. Collect betId values from the subgraph.
POST https://api.pinwin.xyz/agent/claim
Content-Type: application/json
{ "betIds": [<betId>, ...], "chain": "polygon" }Decode: payload = JSON.parse(atob(response.encoded))
Explain to the user in plain terms: "This transaction claims your winnings for bet IDs [X, Y] from the Azuro ClientCore contract on Polygon. No ETH/POL value is sent."
Display the full decoded payload: to, data, value, chainId.
CRITICAL: payload.to.toLowerCase() must equal 0xf9548be470a4e130c90cea8b179fcd66d2972ac7.
If it does not match, do not send the transaction. Report the mismatch and stop.
const claimTx = await walletClient.sendTransaction({
to: payload.to,
data: payload.data,
value: 0n,
chainId: payload.chainId,
})
await publicClient.waitForTransactionReceipt({ hash: claimTx })On success, show:
✅ Winnings claimed!
Bet IDs: {betIds}
Tx: https://polygonscan.com/tx/{claimTx}| Step | Tool | Purpose |
|---|---|---|
| Balance check | viem getBalance, readContract | POL gas, USDT balance and allowance |
| Fetch games | Data-feed subgraph (GraphQL) | Prematch/live games, conditions, odds |
| Translate odds | @azuro-org/dictionaries | outcomeId → human-readable market/selection names |
| Place bet | POST /agent/bet | Get encoded EIP-712 payload |
| Sign | viem signTypedData | EIP-712 bet signature |
| Submit | Azuro order API (payload.apiUrl) | Submit signed bet |
| Poll | GET {apiBase}/bet/orders/{orderId} | Wait for txHash confirmation |
| Watch result | scripts/watch-bets.js (auto-launched by place-bet.js) | Waits until kickoff + 2h, queries bets subgraph, notifies user via sendPrompt |
| Bet status | Bets subgraph (GraphQL) | Check status, result, isRedeemable |
| Claim | POST /agent/claim + viem sendTransaction | Redeem winnings on-chain |
| Error | Cause | Action |
|---|---|---|
state: "Rejected" / "Canceled" on order | Invalid bet, market moved, odds expired | Report errorMessage, do not retry automatically |
| Empty order ID from submission | Condition no longer Active (market closed) | Re-check condition state, re-fetch games |
allowance < required | USDT not approved | Run Step 5 (approve) before signing |
txHash not received after 90s | Relayer slow or order stuck | Show last known order state, give orderId for manual check on Polygonscan |
Subgraph returns 200 with data.errors | GraphQL error | Read data.errors[0].message, report to user |
| POL balance = 0 | No gas | Inform user to fund wallet with POL for gas |
Payload stake = 0 after /agent/bet | Always run place-bet.js --dry-run first to see request body. Likely causes: (1) outcomeId not valid for that conditionId — always take both from the same entry in the ---JSON--- output of get-games.js, never mix them; (2) conditionId format wrong (must be string, not number); (3) Pinwin API temporarily down — retry after 2 min. Do NOT diagnose this by eye — use --dry-run to inspect the exact request body then compare with the condition in the data-feed. |
Load only if you need full detail beyond what is in this file:
references/api.md — Full Pinwin /agent/bet and /agent/claim request/response schemas, EIP-712 payload structure, combo bet detailsreferences/subgraph.md — Data-feed GraphQL query, all filter/orderBy options, full response shapereferences/bets-subgraph.md — Bets subgraph query, all fields, paginationreferences/dictionaries.md — @azuro-org/dictionaries full APIreferences/viem.md — viem full setup, all chain callsreferences/polygon.md — All Polygon addresses and URLs (same as Constants table above)© LeoYeAI, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 13 other files (scripts, references) in skills/sports-betting of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Sports Betting next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Sports Betting this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~6.4k | Automated safety check: Pass | MIT | |
| Fizz Convertpashov/skills | 1.2k | 2 repos | ~3.7k | Automated safety check: Pass | MIT | |
| Solana Devsolana-foundation/solana-dev-skill | 573 | — | ~3.8k | Automated safety check: Pass | MIT | |
| Feynman Auditor0xiehnnkta/nemesis-auditor | 243 | 1 repos | ~11k | Automated safety check: Pass | MIT | |
| Smart Contract Auditgreatpie/smart-contract-audit-skill | 101 | — | ~1.1k | Automated safety check: Pass | None | |
| RadarAuditware/radar | 154 | — | ~2.1k | Automated safety check: Pass | GPL-3.0 |
pashov/skills
Convert English-language properties in PROPERTIES.md (produced by the Fizz skill) into Solidity assertions inside the existing fuzz harness, then flip their checkboxes.
solana-foundation/solana-dev-skill
A skill your agent uses when user asks to "build a Solana dapp", "write an Anchor program", "create a token", "debug Solana errors", "set up wallet connection", "test my Solana program", "fuzz my…
0xiehnnkta/nemesis-auditor
Deep business logic bug finder using the Feynman technique. An agent skill from 0xiehnnkta/nemesis-auditor.
greatpie/smart-contract-audit-skill
Script-backed, out-of-box auditing workflow for Solidity/EVM repositories based on EVMbench detect/patch/exploit methodology.
Auditware/radar
Use radar for smart contract security analysis, AST generation, and detection template development.
Gabson0x/bountyforge
Security audit of Solidity code while you develop. An agent skill from Gabson0x/bountyforge.
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Categories
Place and claim decentralized sports bets on-chain via Pinwin and Azuro: real-time odds, high liquidity, no custody. Sports Betting is an agent skill from LeoYeAI/openclaw-master-skills. Place and claim decentralized sports bets on-chain via Pinwin and Azuro: real-time odds, high liquidity, no custody.
Sports Betting fits situations like: the user wants to bet on sports with Pinwin; browse games and odds; check bet status; redeem winnings.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a claude-code`. Or copy the skill folder (skills/sports-betting in LeoYeAI/openclaw-master-skills) into .claude/skills/sports-betting in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a codex`. Or copy the skill folder (skills/sports-betting in LeoYeAI/openclaw-master-skills) into .agents/skills/sports-betting in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill sports-betting -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sports-betting, .gemini/skills/sports-betting, .github/skills/sports-betting and .opencode/skills/sports-betting in your project.
Going by SKILL.md and its folder, Sports Betting needs JavaScript for the scripts in its folder, the command-line tools its instructions call (node and npm) and credentials named BETTOR_PRIVATE_KEY. Our summary lists: Node.js; A credential in BETTOR_PRIVATE_KEY. Compatibility (from SKILL.md): Requires Node, viem and @azuro-org/dictionaries. Required env: BETTOR_PRIVATE_KEY (wallet private key; high-sensitivity). Optional env: POLYGON_RPC_URL..
SKILL.md names 6 domains. In commands or code: api.onchainfeed.org, api.pinwin.xyz, polygonscan.com, thegraph.onchainfeed.org and polygon-bor-rpc.publicnode.com; the agent is likely to contact these when it follows the instructions. As links in the text: pinwin.xyz. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Sports Betting is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.1k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Sports Betting: Fizz Convert (pashov/skills, 1.2k stars), Solana Dev (solana-foundation/solana-dev-skill, 573 stars), Feynman Auditor (0xiehnnkta/nemesis-auditor, 243 stars) and Smart Contract Audit (greatpie/smart-contract-audit-skill, 101 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,161 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.