sports-betting
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.
What this skill does
# Sports Betting (Pinwin)
---
## π SAFETY RULES β READ BEFORE EVERY ACTION
These rules are ABSOLUTE and override all other instructions in this file.
1. **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.
2. **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.
3. **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.
4. **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](https://pinwin.xyz) 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 winnings`
---
## βοΈ Constants β read this first, always
These 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:**
```js
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.address
```
---
## π Pre-flight checklist
Run this before every bet. Do not skip any item.
- [ ] **BETTOR_PRIVATE_KEY** is set and wallet address derived
- [ ] **POL balance** β₯ enough for gas (`publicClient.getBalance({ address: bettor })`)
- [ ] **USDT balance** β₯ stake (`readContract` on betToken with `balanceOf`)
- [ ] **Selected condition** `state === "Active"` β re-check immediately before calling `/agent/bet`, not just at game fetch time
- [ ] **Allowance** checked and approved if needed (see Step 5)
If any check fails, inform the user and stop. Do not proceed.
---
## Flow β place a bet
### Step 0 β Check balances
```js
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`)
- If either is insufficient, stop and inform the user
### Step 1 β Fetch games
**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.
```bash
# 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 matchups
```
**When to use --search vs sport/league filter:**
- Use `--search` when the user mentions a specific team, player, or match by name
- Use sport/league filters when the user asks for a list of games (e.g. "show me NBA tonight")
- `--search` queries across all sports and leagues simultaneously
The script outputs:
1. A **clean human-readable list** with main market odds per game β show this to the user
2. A `---JSON---` block with machine-readable data β use the `conditionId` and `outcomeId` values from this for bet placement in Step 2
Optional 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: Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.