{
  "schemaVersion": "1.0",
  "item": {
    "slug": "sports-betting",
    "name": "Sports Betting",
    "source": "tencent",
    "type": "skill",
    "category": "内容创作",
    "sourceUrl": "https://clawhub.ai/skinnynoizze/sports-betting",
    "canonicalUrl": "https://clawhub.ai/skinnynoizze/sports-betting",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/sports-betting",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=sports-betting",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "references/api.md",
      "references/bets-subgraph.md",
      "references/dictionaries.md",
      "references/polygon.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/sports-betting"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/sports-betting",
    "agentPageUrl": "https://openagent3.xyz/skills/sports-betting/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sports-betting/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sports-betting/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Sports betting (Pinwin)",
        "body": "Place and claim decentralized sports bets on Polygon via Pinwin and Azuro, with on-chain execution. The agent fetches prematch and live games from the data-feed, you pick a selection, then it calls Pinwin, signs (and optionally approves USDT), and submits.\n\nInvocation: This skill is invocation-only: the assistant will not use it unless you explicitly ask (e.g. “place a bet with Pinwin”) or use the slash command. That avoids accidental bets."
      },
      {
        "title": "How to use (OpenClaw)",
        "body": "Invoke: Use the slash command /sports_betting (or /skill sports-betting) and optionally add your request, e.g. /sports_betting place 5 USDT on the first Premier League game or /sports_betting show my bets.\nVersatility: The assistant should ask you for preferences when not specified: how many games to fetch (first), order (turnover vs startsAt), sport/country/league filters, and which selection you want. It should not suggest or pick a bet unless you explicitly ask for a suggestion (meaningful suggestions would require external data, e.g. news or stats, and could be a separate skill)."
      },
      {
        "title": "When to use",
        "body": "User wants to place a bet on a game (prematch or live): fetch games → choose a selection → call Pinwin /agent/bet → approve token if needed → sign EIP-712 → POST signature to returned apiUrl.\nUser wants to check bet status (pending / resolved / won or lost) or redeem winnings: query the bets subgraph for the bettor’s bets (see Check bet status); when a bet has isRedeemable && !isRedeemed, call Pinwin /agent/claim with those betIds → sign and send the returned transaction with viem."
      },
      {
        "title": "Credentials (required env)",
        "body": "BETTOR_PRIVATE_KEY — Wallet private key (hex) for signing bets and claim transactions. High-sensitivity; do not log or expose. Required for placing and claiming. Use a dedicated betting wallet with minimal funds; do not use your primary wallet."
      },
      {
        "title": "Optional",
        "body": "POLYGON_RPC_URL — Polygon RPC endpoint. If unset, the agent uses the default RPC(s) in references/polygon.md (e.g. Pocket Network, PublicNode)."
      },
      {
        "title": "Other",
        "body": "@azuro-org/dictionaries — required. The subgraph returns only outcomeId and odds; this package is the only way to map them to human-readable market and selection names (e.g. \"Total Goals\", \"Over (2.5)\"). See references/dictionaries.md.\nAddresses: relayer, bet token, native gas token (POL), data-feed URL, and bets subgraph URL are in references/polygon.md.\nBalances: The agent can use viem to check POL (gas) and USDT (stake + relayer fee) before placing a bet; if insufficient, inform the user and do not proceed. See references/viem.md."
      },
      {
        "title": "Flow (place a bet)",
        "body": "Optional — check balances: Ensure USDT ≥ stake and POL for gas; exact USDT = stake + payload’s relayerFeeAmount. See references/viem.md.\nFetch games – POST data-feed per references/subgraph.md (state Prematch or Live). Get games with conditions (conditionId, outcomes: outcomeId, currentOdds). Names via references/dictionaries.md (getSelectionName({ outcomeId, withPoint: true })). Respect first, orderBy, filters or defaults.\nChoose selection – Pick one (or more for combo) conditionId + outcomeId from an Active condition. minOdds: single = Math.round(parseFloat(currentOdds) * 1e12); combo = product of each selection’s odds in 12-decimal space (e.g. (odds1×1e12 × odds2×1e12) / 1e12).\nCall Pinwin – POST https://api.pinwin.xyz/agent/bet with JSON body (see references/api.md). Response: { \"encoded\": \"<base64>\" }. Decode: payload = JSON.parse(atob(response.encoded)).\nExplain to user (before signing) – Display payload: amount and selections from signableClientBetData.bets, relayerFeeAmount, apiUrl, environment, clientData (human-readable names per references/dictionaries.md); then a short summary. See references/api.md.\nApproval (if needed) – Check bet token’s allowance(bettor, relayer) on Polygon. If < bet amount + relayer fee + 0.2 USDT, sign approve(relayer, bet amount + relayer fee + 0.2 USDT) on the bet token. Approval is bounded to this bet plus a small buffer for security; the agent may need to approve again for the next bet. Addresses: references/polygon.md. Steps: references/viem.md.\nVerify payload vs user intent – Amount and selections (from bets), clientData.core = claimContract, relayer from references/polygon.md only. See references/api.md. If anything does not match, do not sign and inform the user.\nSign and submit – Use viem signTypedData with payload.domain, payload.types, primaryType (see references/api.md), and message: payload.signableClientBetData. Then POST to payload.apiUrl with environment, bettor, betOwner, clientBetData (= payload.apiClientBetData), bettorSignature. The order id is in the POST response: use response.id. If you get an order id, poll until the order settles (see references/api.md): GET {apiBase}/bet/orders/{orderId}. Success = response has txHash; failure = state is Rejected or Canceled (use errorMessage)."
      },
      {
        "title": "Check bet status (before redeem)",
        "body": "To know when a bet is resolved and whether it won or lost, and whether the user can redeem, query the bets subgraph (different from the data-feed). See references/bets-subgraph.md.\n\nQuery bets – POST a GraphQL query to the bets subgraph URL (Polygon: in references/polygon.md). Query v3Bets with where: { bettor: \"<bettor address>\" } (address in lowercase). To fetch only bets that can be claimed, add isRedeemable: true to the where clause (see references/bets-subgraph.md). Request at least: betId, status, result, isRedeemable, isRedeemed, amount, payout.\nInterpret – status = Accepted (pending) | Resolved (settled) | Canceled. When status === Resolved, result = Won or Lost. When isRedeemable === true and isRedeemed === false, the user can claim; collect those bets’ betId values for the claim flow."
      },
      {
        "title": "Flow (claim)",
        "body": "Only for bets that are resolved (or canceled) and have isRedeemable true and isRedeemed false; get betIds from the bets subgraph (see Check bet status).\n\nCall Pinwin – POST https://api.pinwin.xyz/agent/claim with betIds (array of on-chain bet ids) and chain: \"polygon\". Decode the response encoded payload. Explain to the user in human-readable terms what they are sending: e.g. claiming winnings for bet IDs X, Y; the transaction will go to the Azuro ClientCore contract on Polygon; no value (ETH/POL) is sent. Display the full decoded claim payload (to, chainId, value, and any other keys returned) for transparency.\nVerify claim contract – Ensure payload.to (lowercase) equals the documented claimContract (ClientCore) for Polygon in references/polygon.md. This is the redeem contract for won/canceled bets, not the Cashout (early-exit) contract. If it does not match, do not send the tx and report the mismatch.\nSend tx – Use viem sendTransaction with { to: payload.to, data: payload.data, value: 0n, chainId: payload.chainId }. Wait for receipt. Details: references/viem.md."
      },
      {
        "title": "Example (place a single bet)",
        "body": "After fetching games and choosing one outcome:\n\nPOST https://api.pinwin.xyz/agent/bet\n{ \"amount\": 1000000, \"minOdds\": 1500000000000, \"chain\": \"polygon\", \"selections\": [{ \"conditionId\": \"<from data-feed>\", \"outcomeId\": 21 }] }\n\nDecode response.encoded, sign payload.signableClientBetData with viem signTypedData, then POST to payload.apiUrl with clientBetData and bettorSignature."
      },
      {
        "title": "Example (claim)",
        "body": "Get betIds from the bets subgraph (e.g. query with isRedeemable: true). Then:\n\nPOST https://api.pinwin.xyz/agent/claim\n{ \"betIds\": [215843], \"chain\": \"polygon\" }\n\nDecode response.encoded → payload. Display payload to the user; verify payload.to equals the claimContract (ClientCore) in references/polygon.md. Then send tx with viem: sendTransaction({ to: payload.to, data: payload.data, value: 0n, chainId: payload.chainId }). Wait for receipt."
      },
      {
        "title": "Tools",
        "body": "StepToolPurposeGamesData-feed subgraph (GraphQL)Get games, conditions, outcomes, oddsBet statusBets subgraph (GraphQL)Get bettor’s bets: status (Accepted/Resolved/Canceled), result (Won/Lost), isRedeemable, betIdNames@azuro-org/dictionaries (required)Map outcomeId → human-readable market/selection names; only way to get labels from subgraph data.Bet/claimPinwin APIGet encoded payload and apiUrlChainviem + RPCgetBalance (POL), readContract (allowance, balanceOf USDT), sendTransaction (approve, claim), signTypedData (bet)\n\nRequired packages: npm install viem @azuro-org/dictionaries. Setup and chain calls: references/viem.md. Dictionaries usage: references/dictionaries.md."
      },
      {
        "title": "Errors",
        "body": "Pinwin 4xx/5xx: read error or message in the response body.\nSubgraph: check both HTTP status and data.errors in the JSON body (GraphQL can return 200 with data.errors).\nChain: tx reverted, insufficient funds — report tx hash."
      },
      {
        "title": "Reference files",
        "body": "Load these when you need full request/response shapes, queries, or addresses:\n\nreferences/api.md – Pinwin POST /agent/bet and /agent/claim (request, response, decoded payload).\nreferences/subgraph.md – Data-feed URL, canonical GraphQL query, example variables, filtering, response shape.\nreferences/bets-subgraph.md – Bets subgraph URL, query for bettor’s bets, status/result/isRedeemable, betId for claim.\nreferences/dictionaries.md – @azuro-org/dictionaries (getMarketName, getSelectionName; use withPoint: true for selection lines).\nreferences/polygon.md – Polygon data-feed URL, bets subgraph URL, native gas token (POL), relayer, betToken (USDT), environment.\nreferences/viem.md – viem install, setup, getBalance (POL), balanceOf (USDT), allowance, approve, signTypedData, claim tx."
      }
    ],
    "body": "Sports betting (Pinwin)\n\nPlace and claim decentralized sports bets on Polygon via Pinwin and Azuro, with on-chain execution. The agent fetches prematch and live games from the data-feed, you pick a selection, then it calls Pinwin, signs (and optionally approves USDT), and submits.\n\nInvocation: This skill is invocation-only: the assistant will not use it unless you explicitly ask (e.g. “place a bet with Pinwin”) or use the slash command. That avoids accidental bets.\n\nHow to use (OpenClaw)\nInvoke: Use the slash command /sports_betting (or /skill sports-betting) and optionally add your request, e.g. /sports_betting place 5 USDT on the first Premier League game or /sports_betting show my bets.\nVersatility: The assistant should ask you for preferences when not specified: how many games to fetch (first), order (turnover vs startsAt), sport/country/league filters, and which selection you want. It should not suggest or pick a bet unless you explicitly ask for a suggestion (meaningful suggestions would require external data, e.g. news or stats, and could be a separate skill).\nWhen to use\nUser wants to place a bet on a game (prematch or live): fetch games → choose a selection → call Pinwin /agent/bet → approve token if needed → sign EIP-712 → POST signature to returned apiUrl.\nUser wants to check bet status (pending / resolved / won or lost) or redeem winnings: query the bets subgraph for the bettor’s bets (see Check bet status); when a bet has isRedeemable && !isRedeemed, call Pinwin /agent/claim with those betIds → sign and send the returned transaction with viem.\nPrerequisites\nCredentials (required env)\nBETTOR_PRIVATE_KEY — Wallet private key (hex) for signing bets and claim transactions. High-sensitivity; do not log or expose. Required for placing and claiming. Use a dedicated betting wallet with minimal funds; do not use your primary wallet.\nOptional\nPOLYGON_RPC_URL — Polygon RPC endpoint. If unset, the agent uses the default RPC(s) in references/polygon.md (e.g. Pocket Network, PublicNode).\nOther\n@azuro-org/dictionaries — required. The subgraph returns only outcomeId and odds; this package is the only way to map them to human-readable market and selection names (e.g. \"Total Goals\", \"Over (2.5)\"). See references/dictionaries.md.\nAddresses: relayer, bet token, native gas token (POL), data-feed URL, and bets subgraph URL are in references/polygon.md.\nBalances: The agent can use viem to check POL (gas) and USDT (stake + relayer fee) before placing a bet; if insufficient, inform the user and do not proceed. See references/viem.md.\nFlow (place a bet)\nOptional — check balances: Ensure USDT ≥ stake and POL for gas; exact USDT = stake + payload’s relayerFeeAmount. See references/viem.md.\nFetch games – POST data-feed per references/subgraph.md (state Prematch or Live). Get games with conditions (conditionId, outcomes: outcomeId, currentOdds). Names via references/dictionaries.md (getSelectionName({ outcomeId, withPoint: true })). Respect first, orderBy, filters or defaults.\nChoose selection – Pick one (or more for combo) conditionId + outcomeId from an Active condition. minOdds: single = Math.round(parseFloat(currentOdds) * 1e12); combo = product of each selection’s odds in 12-decimal space (e.g. (odds1×1e12 × odds2×1e12) / 1e12).\nCall Pinwin – POST https://api.pinwin.xyz/agent/bet with JSON body (see references/api.md). Response: { \"encoded\": \"<base64>\" }. Decode: payload = JSON.parse(atob(response.encoded)).\nExplain to user (before signing) – Display payload: amount and selections from signableClientBetData.bets, relayerFeeAmount, apiUrl, environment, clientData (human-readable names per references/dictionaries.md); then a short summary. See references/api.md.\nApproval (if needed) – Check bet token’s allowance(bettor, relayer) on Polygon. If < bet amount + relayer fee + 0.2 USDT, sign approve(relayer, bet amount + relayer fee + 0.2 USDT) on the bet token. Approval is bounded to this bet plus a small buffer for security; the agent may need to approve again for the next bet. Addresses: references/polygon.md. Steps: references/viem.md.\nVerify payload vs user intent – Amount and selections (from bets), clientData.core = claimContract, relayer from references/polygon.md only. See references/api.md. If anything does not match, do not sign and inform the user.\nSign and submit – Use viem signTypedData with payload.domain, payload.types, primaryType (see references/api.md), and message: payload.signableClientBetData. Then POST to payload.apiUrl with environment, bettor, betOwner, clientBetData (= payload.apiClientBetData), bettorSignature. The order id is in the POST response: use response.id. If you get an order id, poll until the order settles (see references/api.md): GET {apiBase}/bet/orders/{orderId}. Success = response has txHash; failure = state is Rejected or Canceled (use errorMessage).\nCheck bet status (before redeem)\n\nTo know when a bet is resolved and whether it won or lost, and whether the user can redeem, query the bets subgraph (different from the data-feed). See references/bets-subgraph.md.\n\nQuery bets – POST a GraphQL query to the bets subgraph URL (Polygon: in references/polygon.md). Query v3Bets with where: { bettor: \"<bettor address>\" } (address in lowercase). To fetch only bets that can be claimed, add isRedeemable: true to the where clause (see references/bets-subgraph.md). Request at least: betId, status, result, isRedeemable, isRedeemed, amount, payout.\nInterpret – status = Accepted (pending) | Resolved (settled) | Canceled. When status === Resolved, result = Won or Lost. When isRedeemable === true and isRedeemed === false, the user can claim; collect those bets’ betId values for the claim flow.\nFlow (claim)\n\nOnly for bets that are resolved (or canceled) and have isRedeemable true and isRedeemed false; get betIds from the bets subgraph (see Check bet status).\n\nCall Pinwin – POST https://api.pinwin.xyz/agent/claim with betIds (array of on-chain bet ids) and chain: \"polygon\". Decode the response encoded payload. Explain to the user in human-readable terms what they are sending: e.g. claiming winnings for bet IDs X, Y; the transaction will go to the Azuro ClientCore contract on Polygon; no value (ETH/POL) is sent. Display the full decoded claim payload (to, chainId, value, and any other keys returned) for transparency.\nVerify claim contract – Ensure payload.to (lowercase) equals the documented claimContract (ClientCore) for Polygon in references/polygon.md. This is the redeem contract for won/canceled bets, not the Cashout (early-exit) contract. If it does not match, do not send the tx and report the mismatch.\nSend tx – Use viem sendTransaction with { to: payload.to, data: payload.data, value: 0n, chainId: payload.chainId }. Wait for receipt. Details: references/viem.md.\nExample (place a single bet)\n\nAfter fetching games and choosing one outcome:\n\nPOST https://api.pinwin.xyz/agent/bet\n{ \"amount\": 1000000, \"minOdds\": 1500000000000, \"chain\": \"polygon\", \"selections\": [{ \"conditionId\": \"<from data-feed>\", \"outcomeId\": 21 }] }\n\n\nDecode response.encoded, sign payload.signableClientBetData with viem signTypedData, then POST to payload.apiUrl with clientBetData and bettorSignature.\n\nExample (claim)\n\nGet betIds from the bets subgraph (e.g. query with isRedeemable: true). Then:\n\nPOST https://api.pinwin.xyz/agent/claim\n{ \"betIds\": [215843], \"chain\": \"polygon\" }\n\n\nDecode response.encoded → payload. Display payload to the user; verify payload.to equals the claimContract (ClientCore) in references/polygon.md. Then send tx with viem: sendTransaction({ to: payload.to, data: payload.data, value: 0n, chainId: payload.chainId }). Wait for receipt.\n\nTools\nStep\tTool\tPurpose\nGames\tData-feed subgraph (GraphQL)\tGet games, conditions, outcomes, odds\nBet status\tBets subgraph (GraphQL)\tGet bettor’s bets: status (Accepted/Resolved/Canceled), result (Won/Lost), isRedeemable, betId\nNames\t@azuro-org/dictionaries (required)\tMap outcomeId → human-readable market/selection names; only way to get labels from subgraph data.\nBet/claim\tPinwin API\tGet encoded payload and apiUrl\nChain\tviem + RPC\tgetBalance (POL), readContract (allowance, balanceOf USDT), sendTransaction (approve, claim), signTypedData (bet)\n\nRequired packages: npm install viem @azuro-org/dictionaries. Setup and chain calls: references/viem.md. Dictionaries usage: references/dictionaries.md.\n\nErrors\nPinwin 4xx/5xx: read error or message in the response body.\nSubgraph: check both HTTP status and data.errors in the JSON body (GraphQL can return 200 with data.errors).\nChain: tx reverted, insufficient funds — report tx hash.\nReference files\n\nLoad these when you need full request/response shapes, queries, or addresses:\n\nreferences/api.md – Pinwin POST /agent/bet and /agent/claim (request, response, decoded payload).\nreferences/subgraph.md – Data-feed URL, canonical GraphQL query, example variables, filtering, response shape.\nreferences/bets-subgraph.md – Bets subgraph URL, query for bettor’s bets, status/result/isRedeemable, betId for claim.\nreferences/dictionaries.md – @azuro-org/dictionaries (getMarketName, getSelectionName; use withPoint: true for selection lines).\nreferences/polygon.md – Polygon data-feed URL, bets subgraph URL, native gas token (POL), relayer, betToken (USDT), environment.\nreferences/viem.md – viem install, setup, getBalance (POL), balanceOf (USDT), allowance, approve, signTypedData, claim tx."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/skinnynoizze/sports-betting",
    "publisherUrl": "https://clawhub.ai/skinnynoizze/sports-betting",
    "owner": "skinnynoizze",
    "version": "1.0.3",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/sports-betting",
    "downloadUrl": "https://openagent3.xyz/downloads/sports-betting",
    "agentUrl": "https://openagent3.xyz/skills/sports-betting/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sports-betting/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sports-betting/agent.md"
  }
}