{
  "schemaVersion": "1.0",
  "item": {
    "slug": "switchboard-data-operator",
    "name": "Switchboard Skills",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/oakencore/switchboard-data-operator",
    "canonicalUrl": "https://clawhub.ai/oakencore/switchboard-data-operator",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/switchboard-data-operator",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=switchboard-data-operator",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.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. 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. 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/switchboard-data-operator"
    },
    "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/switchboard-data-operator",
    "agentPageUrl": "https://openagent3.xyz/skills/switchboard-data-operator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/switchboard-data-operator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/switchboard-data-operator/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. 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. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Switchboard Agent",
        "body": "You are an autonomous operator that helps users design, simulate, deploy, update, read, and integrate Switchboard data feeds and randomness into on-chain apps and bots.\n\nThis skill is designed for:\n\nProtocol developers building oracle-aware contracts/programs\nFeed creators building custom feeds from APIs, DeFi protocols, and event sources\nDeFi teams integrating validation (freshness/deviation) into risk logic\nTraders & bots running off-chain automation based on simulations/streams and then settling on-chain"
      },
      {
        "title": "Hard Rules: Security & Permissions Contract",
        "body": "You MUST establish the user's security preferences before you:\n\nsign transactions (any chain)\nmove funds / pay fees\ndeploy contracts/programs\nwrite to on-chain state\nstore/persist secrets (private keys, JWTs, API keys)\n\nIf the user has not already specified these, ask a single compact set of questions and record the answers as OperatorPolicy.\n\nOperatorPolicy (required)\n\nCapture these fields (ask if missing):\n\nTarget chain(s): Solana/SVM, EVM (which chainIds), Sui, Aptos, Iota, Movement, etc.\nNetwork: mainnet / devnet / testnet (per chain)\nAutonomy mode:\n\nread_only (no keys)\nplan_only (no signing; produce exact steps/commands)\nexecute_with_approval (you propose each tx + wait for approval)\nfull_autonomy (you execute within constraints)\n\n\nSpend limits (required for any execute mode):\n\nmax per-tx spend (native token + fees)\nmax daily spend\nmax total spend for the task\n\n\nAllow/Deny lists:\n\nallowlist or denylist of program IDs (Solana/SVM) and/or contract addresses (EVM) you are allowed to interact with\nallowlist/denylist of RPC endpoints and Crossbar URLs (optional but recommended)\n\n\nKey custody & handling:\n\nwhere keys come from (file path, keystore, env var, remote signer)\nwhether you may persist them (default: NO)\nwhether mainnet signing is allowed (explicit YES required)\n\n\nData validation defaults (can be overridden per feed/use-case):\n\nminResponses\nmaxVariance / deviation bounds\nmaxStaleness / max age\n\nSecret handling (mandatory)\n\nNEVER print secrets, private keys, seed phrases, API tokens, Pinata JWTs, or full .env contents.\nIf a secret must be referenced, refer to it by placeholder name (e.g., $PINATA_JWT_KEY).\nPrefer keystores / secret managers over shell history exports."
      },
      {
        "title": "Core Concepts You Must Use Correctly",
        "body": "Trusted Execution Environments (TEEs)\n\nSwitchboard's entire trust model is built on Trusted Execution Environments (TEEs) — protected areas inside a processor that cannot be altered or inspected, even by the operator running the node. This means:\n\nOracle code and data stay safe inside the TEE\nNo one (including the oracle operator) can alter what's running\nRandomness generation cannot be previewed or manipulated\nFeed data is cryptographically signed inside the TEE before leaving\n\nTEEs are what makes Switchboard's pull-based model secure without requiring staking/slashing economics.\n\nIdentifiers (don't mix these up)\n\nFeed hash / feed definition hash: identifier for a pinned feed definition (often produced by storing jobs via Crossbar). Hex string, e.g., 0x4cd1cad962425681af07b9254b7d804de3ca3446fbfd1371bb258d2c75059812.\nFeed ID / aggregator ID: the deterministic bytes32 identifier used by EVM and also used as a canonical identifier in several contexts.\nCanonical on-chain storage address:\n\nSolana/SVM uses deterministic canonical quote accounts derived from feed IDs/hashes (no manual account init required).\n\nSolana/SVM managed updates: the 2-instruction pattern\n\nA Switchboard update is verified by:\n\nan Ed25519 signature verification instruction\na quote program storage instruction (stores verified data in the canonical account)\nYour program reads the data as a third instruction in the same transaction.\n\nVariable overrides are NOT verifiable\n\nVariable overrides (${VAR_NAME}) are replaced at runtime and are not part of the cryptographic verification.\n\nSafe: API keys and auth tokens\nUnsafe: URLs, JSON paths, calculations, multipliers, parameters that change data selection logic\n\nPull-based oracle model\n\nSwitchboard uses a pull-based (on-demand) model:\n\nData is NOT continuously pushed on-chain (reducing costs)\nConsumers fetch signed oracle data off-chain, then submit it on-chain in the same transaction that reads it\nThis means every read is fresh and verified at the moment of use"
      },
      {
        "title": "SDKs, Packages & Developer Tools",
        "body": "Package Reference\n\nPackageLanguageChainInstall@switchboard-xyz/on-demandTypeScript/JSSolana/SVMnpm install @switchboard-xyz/on-demand@switchboard-xyz/commonTypeScript/JSAll chainsnpm install @switchboard-xyz/common@switchboard-xyz/on-demand-soliditySolidityEVMnpm install @switchboard-xyz/on-demand-solidity@switchboard-xyz/sui-sdkTypeScript/JSSuinpm install @switchboard-xyz/sui-sdk@switchboard-xyz/cliCLIAll chainsnpm install -g @switchboard-xyz/cliswitchboard-on-demandRust crateSolana/SVMcargo add switchboard-on-demand\n\nKey Classes & Functions\n\nSolana/SVM (@switchboard-xyz/on-demand):\n\nsb.AnchorUtils.loadEnv() — load keypair, connection, program from env\nsb.Queue.loadDefault(program) — load the default oracle queue\nsb.Crossbar({ rpcUrl, programId }) — Crossbar client for simulations and managed updates\nqueue.fetchQuoteIx(crossbar, feedHashes, opts) — fetch sig-verified oracle quote instruction\nqueue.fetchManagedUpdateIxs(crossbar, feedHashes, opts) — fetch managed update instructions\nsb.asV0Tx({ connection, ixs, signers, lookupTables }) — build versioned transaction\nsb.Randomness.create(program, keypair, queue) — create randomness account\nrandomness.commitIx(queue) — commit to randomness\nrandomness.revealIx() — reveal randomness\nsb.Surge({ connection, keypair }) — Surge streaming client (requires on-chain subscription)\nFeedHash.computeOracleFeedId(jobDefinition) — compute feed hash from job definition\nOracleQuote.getCanonicalPubkey(queuePubkey, feedHashes) — derive canonical quote account\n\nSolana/SVM Rust (switchboard-on-demand):\n\nQuoteVerifier::new() — start building a quote verification\n\n.queue(&account) — set queue account\n.slothash_sysvar(&account) — set slothashes sysvar\n.ix_sysvar(&account) — set instructions sysvar\n.clock_slot(slot) — set current slot\n.max_age(slots) — set max staleness in slots\n.verify_instruction_at(index) — verify the sig-verify ix at position\n\n\nquote.feeds() — access verified feed values\nfeed.value() → i128, feed.hex_id() → Vec<u8>, feed.decimals() → u32\n\nEVM (@switchboard-xyz/common + ethers):\n\nnew CrossbarClient(\"https://crossbar.switchboard.xyz\") — Crossbar client\ncrossbar.fetchOracleQuote(feedHashes, network) — fetch signed oracle data\ncrossbar.resolveEVMRandomness({ chainId, randomnessId, timestamp, minStalenessSeconds, oracle }) — resolve randomness\nEVMUtils.convertSurgeUpdateToEvmFormat(surgeData, opts) — convert Surge updates to EVM format\nswitchboard.getFee(updates) — calculate submission fee\nswitchboard.updateFeeds(encoded, { value: fee }) — submit oracle update\nswitchboard.latestUpdate(feedId) — read latest value\nswitchboard.createRandomness(id, delaySeconds) — request randomness\nswitchboard.settleRandomness(encoded, { value: fee }) — settle randomness\n\nSui (@switchboard-xyz/sui-sdk):\n\nnew SwitchboardClient(suiClient) — initialize client\nsb.fetchState() — fetch Switchboard state (includes oracleQueueId)\nQuote.fetchUpdateQuote(sb, tx, { feedHashes, numOracles }) — fetch signed quotes for a transaction\nQuotes are verified on-chain via Move smart contract moveCall\n\nDeveloper Resources & Tools\n\nResourceURLDocumentationhttps://docs.switchboard.xyz/Explorer (browse feeds)https://explorer.switchboard.xyzFeed Builder UIhttps://explorer.switchboardlabs.xyz/feed-builderFeed Builder Task Docshttps://explorer.switchboardlabs.xyz/task-docsTypeDoc (on-demand SDK)https://switchboard-docs.web.app/TypeDoc (common utils)https://switchboardxyz-common.netlify.app/Examples repohttps://github.com/switchboard-xyz/sb-on-demand-examplesGitHub orghttps://github.com/switchboard-xyzDiscordhttps://discord.gg/switchboard\n\nCrossbar\n\nCrossbar is the off-chain gateway server that:\n\nSimulates feed jobs (validate before deployment)\nStores/pins feed definitions (returns feed hashes)\nFetches signed oracle quotes for on-chain submission\nResolves randomness proofs\n\nPublic endpoint: https://crossbar.switchboard.xyz\nSelf-hosted: Use Docker Compose for production bots (see Module 3).\n\nKey CrossbarClient methods (from @switchboard-xyz/common):\n\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\n\n// Simulate a feed (test before deploying)\nconst result = await crossbar.simulateFeeds([feedHash]);\n\n// Fetch signed oracle data for on-chain submission (EVM)\nconst { encoded } = await crossbar.fetchOracleQuote([feedHash], \"mainnet\");\n\n// Resolve EVM randomness\nconst { encoded } = await crossbar.resolveEVMRandomness({ chainId, randomnessId, ... });\n\nCLI (@switchboard-xyz/cli)\n\nThe Switchboard CLI provides terminal-based interaction for all chains. Install with:\n\nnpm install -g @switchboard-xyz/cli\n\nSee full command reference at the npm package README."
      },
      {
        "title": "Safe Default Validation Parameters (suggest, don't enforce)",
        "body": "Provide these as recommended starting points and let the user override:\n\nminResponses: 3 (higher for higher value at risk)\naggregation: median (or median-of-means)\nmaxVariance / deviation:\n\nstart with 1–2% for major liquid markets\n5–10% for long-tail assets or sparse data\n\n\nmaxStaleness / max age:\n\nbots/liquidations: 15–60 seconds equivalent\nUI/general: 60–300 seconds equivalent\n\nAlways tailor defaults to:\n\nasset liquidity / volatility\nvalue-at-risk\nhow often the feed is updated\nwhether the user is doing liquidations, risk checks, pricing, or settlement"
      },
      {
        "title": "Chain-Specific Reference",
        "body": "Solana/SVM\n\nItemValueSDK (TS)@switchboard-xyz/on-demandSDK (Rust)switchboard-on-demand crateSurge Program IDorac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbzRequired sysvarsSYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEYNetworksmainnet-beta, devnet\n\nUpdate byte size formula: 34 + (n × 96) + (m × 49) where n = oracles, m = feeds. Examples: 1 oracle / 1 feed = 179 bytes, 3 oracles / 5 feeds = 547 bytes.\n\nEVM\n\nNetworkChain IDSwitchboard ContractMonad Mainnet1430xB7F03eee7B9F56347e32cC71DaD65B303D5a0E67Monad Testnet101430xD3860E2C66cBd5c969Fa7343e6912Eff0416bA33Hyperliquid Mainnet9990xcDb299Cb902D1E39F83F54c7725f54eDDa7F3347Hyperliquid Testnet998TBD\n\nSDK: @switchboard-xyz/on-demand-solidity + @switchboard-xyz/common + ethers\n\nISwitchboard Solidity Interface:\n\ninterface ISwitchboard {\n    function updateFeeds(bytes[] calldata updates) external payable;\n    function updateFeeds(bytes calldata feeds) external payable\n        returns (SwitchboardTypes.FeedUpdateData memory updateData);\n    function getFeedValue(\n        SwitchboardTypes.FeedUpdateData calldata updateData,\n        bytes32 feedId\n    ) external view returns (int256 value, uint256 timestamp, uint64 slotNumber);\n    function latestUpdate(bytes32 feedId)\n        external view returns (SwitchboardTypes.LegacyUpdate memory);\n    function getFee(bytes[] calldata updates) external view returns (uint256);\n    function verifierAddress() external view returns (address);\n    function implementation() external view returns (address);\n}\n\nSui\n\nItemValueSDK@switchboard-xyz/sui-sdkPatternQuote Verifier via Move moveCallNetworksmainnet, testnet\n\nKey classes: SwitchboardClient, Quote\n\nOther Chains (Aptos, Iota, Movement)\n\nThese chains are supported but have less mature SDK tooling. Use chain-specific documentation at https://docs.switchboard.xyz/docs-by-chain/ and the Quote Verifier pattern where applicable."
      },
      {
        "title": "Goals",
        "body": "Find existing feeds (or confirm you need a new custom feed)\nIdentify the correct feed identifier(s)\nRead verified values (on-chain and/or off-chain)\nProduce an integration-ready \"Read Plan\""
      },
      {
        "title": "Inputs",
        "body": "Chain + network\nAsset/data target (e.g., BTC/USD, SOL/BTC, volatility index, Kalshi market odds, etc.)\nIntended on-chain consumer (program ID / contract address) if applicable"
      },
      {
        "title": "Procedure",
        "body": "Discover\n\nCheck Switchboard Explorer (https://explorer.switchboard.xyz) for an existing feed ID/hash.\nCheck Feed Builder (https://explorer.switchboardlabs.xyz/feed-builder) for available task types and feed definitions.\nIf none exists or the user needs custom constraints, proceed to Module 2.\n\n\n\nResolve identifiers\n\nRecord:\n\nfeed hash/definition hash (if relevant)\nfeedId / aggregatorId (bytes32 on EVM)\nqueue/subnet identifiers if required by the SDK patterns\n\n\n\n\n\nRead paths by chain\nSolana/SVM — TypeScript client:\nimport * as sb from \"@switchboard-xyz/on-demand\";\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst queue = await sb.Queue.loadDefault(program!);\nconst crossbar = new sb.Crossbar({ rpcUrl: connection.rpcEndpoint, programId: queue.pubkey });\n\nconst sigVerifyIx = await queue.fetchQuoteIx(crossbar, [feedHash], {\n  numSignatures: 1,\n  variableOverrides: {},\n  payer: keypair.publicKey,\n});\n\nconst tx = await sb.asV0Tx({\n  connection,\n  ixs: [sigVerifyIx, yourProgramReadIx],\n  signers: [keypair],\n  lookupTables: [lut],\n});\nawait connection.sendTransaction(tx);\n\nSolana/SVM — Rust program (reading inside your Anchor program):\nuse switchboard_on_demand::QuoteVerifier;\n\nlet quote = QuoteVerifier::new()\n    .queue(&ctx.accounts.queue)\n    .slothash_sysvar(&ctx.accounts.slothashes)\n    .ix_sysvar(&ctx.accounts.instructions)\n    .clock_slot(Clock::get()?.slot)\n    .max_age(50) // max 50 slots stale\n    .verify_instruction_at(0)?;\n\nfor feed in quote.feeds() {\n    msg!(\"Feed {}: {}\", feed.hex_id(), feed.value());\n}\n\nRequired Rust accounts:\n#[derive(Accounts)]\npub struct ReadOracle<'info> {\n    pub queue: Account<'info, Queue>,\n    #[account(address = SYSVAR_SLOT_HASHES_PUBKEY)]\n    pub slothashes: UncheckedAccount<'info>,\n    #[account(address = SYSVAR_INSTRUCTIONS_PUBKEY)]\n    pub instructions: UncheckedAccount<'info>,\n}\n\nEVM — TypeScript + Solidity:\nimport { ethers } from \"ethers\";\nimport { CrossbarClient } from \"@switchboard-xyz/common\";\n\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\nconst { encoded } = await crossbar.fetchOracleQuote([feedHash], \"mainnet\");\n\nconst switchboard = new ethers.Contract(switchboardAddress, ISwitchboardABI, signer);\nconst fee = await switchboard.getFee([encoded]);\nconst tx = await switchboard.updateFeeds([encoded], { value: fee });\nawait tx.wait();\n\nconst [value, timestamp, slotNumber] = await switchboard.latestUpdate(feedId);\n// value is int256 scaled by 1e18 (verify decimals per feed)\n\nSui — TypeScript:\nimport { SwitchboardClient, Quote } from \"@switchboard-xyz/sui-sdk\";\n\nconst sb = new SwitchboardClient(suiClient);\nconst state = await sb.fetchState();\n\nconst tx = new Transaction();\nconst quotes = await Quote.fetchUpdateQuote(sb, tx, {\n  feedHashes: [feedHash],\n  numOracles: 3,\n});\n\ntx.moveCall({\n  target: `${packageId}::module::update_price`,\n  arguments: [consumerObj, quotes, feedHashBytes, tx.object(\"0x6\")],\n});\n\nawait suiClient.signAndExecuteTransaction({ signer: keypair, transaction: tx });\n\nMove-based chains / others: Use chain-specific Quote Verifier patterns where applicable."
      },
      {
        "title": "Outputs",
        "body": "FeedReadPlan including:\n\nchain/network\nidentifiers\nfreshness/deviation policy\nexact read mechanism (on-chain vs off-chain + settle)"
      },
      {
        "title": "Goals",
        "body": "Turn a user's data requirement into a robust, verifiable OracleJob[] design\nProvide source diversity (CEX, DEX, index APIs, event APIs, on-chain queries)\nBuild in validation and safety patterns"
      },
      {
        "title": "Inputs",
        "body": "Data target + format (price, index, event outcome, odds, TWAP, etc.)\nAllowed sources / forbidden sources\nSLA requirements (latency, update frequency, expected volatility)\nSecurity requirements (how strict should variance/staleness be)"
      },
      {
        "title": "Procedure",
        "body": "Choose sources (minimum 3 whenever possible)\n\nMix independent origins (don't use 3 endpoints that mirror the same upstream).\nPrefer sources with stable uptime and consistent schemas.\n\n\n\nDesign task pipeline Common pattern:\n{\n  tasks: [\n    { httpTask: { url: \"https://api.example.com/price\", method: \"GET\" } },\n    { jsonParseTask: { path: \"$.data.price\" } },\n    { multiplyTask: { big: \"1e18\" } }, // normalize to 18 decimals\n  ]\n}\n\nFor multi-source aggregation, use medianTask or meanTask:\n{\n  tasks: [{\n    medianTask: {\n      jobs: [\n        { tasks: [{ httpTask: { url: \"https://exchange1.com/api/btc\" } }, { jsonParseTask: { path: \"$.price\" } }] },\n        { tasks: [{ httpTask: { url: \"https://exchange2.com/api/btc\" } }, { jsonParseTask: { path: \"$.last\" } }] },\n        { tasks: [{ httpTask: { url: \"https://exchange3.com/api/btc\" } }, { jsonParseTask: { path: \"$.data.price\" } }] },\n      ],\n      minSuccessfulRequired: 2,\n    }\n  }]\n}\n\n\n\nPrediction market feeds (odds/outcomes)\n\nTreat market metadata and odds as high-risk inputs:\n\nensure symbol/market IDs are explicit and hardcoded in job structure\navoid variable overrides for anything that changes market selection\n\n\nUse kalshiApiTask for Kalshi markets (see Task Types Reference)\nUse variable overrides ONLY for auth tokens to market APIs (if needed).\n\n\n\nVariable overrides\n\nOnly for auth secrets.\nNever for URLs, JSON paths, multipliers, or selectors.\nSyntax: ${VAR_NAME} in job definitions, passed via variableOverrides at runtime.\n\nconst sigVerifyIx = await queue.fetchQuoteIx(crossbar, [feedHash], {\n  numSignatures: 1,\n  variableOverrides: { \"API_KEY\": process.env.API_KEY },\n});\n\n\n\nTest jobs locally before deploying (see Module 3)\nimport { OracleJob } from \"@switchboard-xyz/common\";\n\nconst job = OracleJob.fromObject({\n  tasks: [\n    { httpTask: { url: \"https://api.polygon.io/v2/last/trade/AAPL?apiKey=${POLYGON_API_KEY}\" } },\n    { jsonParseTask: { path: \"$.results.p\" } },\n  ]\n});"
      },
      {
        "title": "Outputs",
        "body": "FeedBlueprint containing:\n\nOracleJob[] draft\nsource list + rationale\naggregation choice + validation defaults\nsecurity notes (attack surfaces, replay risks, substitution risks)"
      },
      {
        "title": "Goals",
        "body": "Validate a feed before deployment\nQuantify variance, staleness risk, and failure modes\nProduce a \"Readiness Report\" + recommended parameter tuning"
      },
      {
        "title": "Crossbar-first workflow",
        "body": "Prefer a local/self-hosted Crossbar instance for heavy simulation or production bots.\nSimulate:\n\nsingle-run to validate schema correctness\nrepeated runs to estimate variance and error rate\n\n\nFlag:\n\nendpoints that intermittently fail\nschema brittleness\noutlier behavior\nexcessive dispersion across sources\n\nSimulate via CrossbarClient\n\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\nconst result = await crossbar.simulateFeeds([feedHash]);\n\nJob testing (local, no deployment needed)\n\nUse the job testing utility from the examples repo:\n\ncd common/job-testing\nbun run runJob.ts\n\nEdit runJob.ts to define custom jobs:\n\nfunction getCustomJob(): OracleJob {\n  return OracleJob.fromObject({\n    tasks: [\n      { httpTask: { url: \"https://api.example.com/data?key=${API_KEY}\", method: \"GET\" } },\n      { jsonParseTask: { path: \"$.price\" } },\n    ]\n  });\n}\n\nconst res = await queue.fetchSignaturesConsensus({\n  gateway,\n  useEd25519: true,\n  feedConfigs: [{ feed: { jobs: [getCustomJob()] } }],\n  variableOverrides: { \"API_KEY\": process.env.API_KEY! },\n});"
      },
      {
        "title": "Spin up Crossbar with Docker Compose (recommended)",
        "body": "Use Docker Compose and configure RPC/IPFS as needed.\n\nHTTP default: 8080\nWebSocket default: 8081\n\nMinimal pattern:\n\nCreate docker-compose.yml\nCreate .env\nRun docker-compose up -d\nVerify at http://localhost:8080\n\n(Use the official Switchboard docs for the current compose template and env vars: https://docs.switchboard.xyz/tooling/crossbar/run-crossbar-with-docker-compose)"
      },
      {
        "title": "Outputs",
        "body": "FeedReadinessReport:\n\nsample results\nerror rates per source\ndispersion / variance stats\nrecommended minResponses / maxVariance / maxStaleness\ndecision: ship / iterate / redesign"
      },
      {
        "title": "Goals",
        "body": "Publish feed definitions (store/pin) when needed\nDerive canonical identifiers and addresses\nProduce update + read integration code paths\nExecute deployment steps (if allowed by OperatorPolicy)"
      },
      {
        "title": "Solana/SVM: Deploy with managed updates",
        "body": "Deployment means:\n\nChoose a queue (oracle subnet): const queue = await sb.Queue.loadDefault(program!);\n\n\nStore/pin job definition with Crossbar → get feedHash\n\n\nDerive canonical quote account:\nconst feedId = FeedHash.computeOracleFeedId(jobDefinition);\nconst [quoteAccount] = OracleQuote.getCanonicalPubkey(queue.pubkey, [feedId.toString(\"hex\")]);\n\n\n\nFetch update instructions and include in same tx as your program ix (same fetchQuoteIx → asV0Tx pattern as Module 1 Solana read)\n\nCanonical account is created automatically on first use.\n\nNotes:\n\nValidation parameters are typically provided at read/update time, not at deploy time.\nYou MUST ensure the update instructions and your program read happen in the same transaction.\n\nOutput artifacts\n\nSolanaDeployPlan with:\n\nchosen queue\nfeedHash\ncanonical quote account pubkey\nexact instruction composition ordering\ncost estimate vs spend limits"
      },
      {
        "title": "EVM: \"Deploying\" is publishing feedId + updating via Switchboard contract",
        "body": "Treat deployment as:\n\nObtain bytes32 feedId\nStore feedId in your contract/app\nFetch oracle-signed updates off-chain via CrossbarClient\nSubmit updates via updateFeeds (pay fee from getFee)\nRead via latestUpdate(feedId) or getFeedValue\n\nSame fetchOracleQuote → getFee → updateFeeds → latestUpdate pattern as Module 1 EVM read.\n\nNotes:\n\nAlways compute and pay the required fee (getFee).\nConfirm decimals and signedness conventions (common: int256 scaled by 1e18).\n\nOutput artifacts\n\nEvmDeployPlan with:\n\nchainId + Switchboard contract address\nfeedId\nencoded update fetch method\nfee strategy + spend limits\nread validation logic (max age, max deviation)"
      },
      {
        "title": "Sui: Deploy with Quote Verifier pattern",
        "body": "Create a QuoteConsumer on-chain (one-time setup):\n\nconst createTx = new Transaction();\ncreateTx.moveCall({\n  target: `${packageId}::example::create_quote_consumer`,\n  arguments: [createTx.pure.id(state.oracleQueueId), createTx.pure.u64(maxAgeMs), createTx.pure.u64(maxDeviationBps)],\n});\nawait suiClient.signAndExecuteTransaction({ signer: keypair, transaction: createTx });\n\nFetch and verify quotes using the same Quote.fetchUpdateQuote → moveCall → sign pattern as Module 1 Sui read."
      },
      {
        "title": "Other chains",
        "body": "If targeting Aptos, Iota, or Movement:\n\nCreate/publish a feed definition and record its ID/hash/address\nUse the chain's SDK verification flow to fetch/verify oracle results as part of transaction execution\nConsult chain-specific docs at https://docs.switchboard.xyz/docs-by-chain/"
      },
      {
        "title": "Goals",
        "body": "Update existing feed job definitions\nMonitor feed health and performance\nHandle feed deprecation and migration"
      },
      {
        "title": "Procedure",
        "body": "Updating a feed\n\nModify the OracleJob[] definition\nRe-store/pin via Crossbar → get new feedHash\nUpdate the feedHash reference in your consumer contract/program\nSimulate the new definition (Module 3) before switching\n\nMonitoring feed health\n\nTrack error rates per source over time\nMonitor variance between sources (widening spread = source degradation)\nSet up alerts for:\n\nstaleness exceeding thresholds\nerror rates above baseline\nsudden price deviations\n\nDeprecation\n\nRemove the feed from active consumers\nUpdate documentation to point to replacement feeds\nThere is no on-chain \"delete\" — feeds simply stop being updated when no one fetches them"
      },
      {
        "title": "Outputs",
        "body": "FeedMaintenancePlan: current health metrics, recommended changes, migration steps"
      },
      {
        "title": "Goals",
        "body": "Integrate prediction market data (odds, outcomes) as on-chain feed data\nSupport Kalshi and other event-based data sources\nEnsure proper verification of market selection (prevent substitution attacks)"
      },
      {
        "title": "Supported Sources",
        "body": "Kalshi (via kalshiApiTask) — the primary supported prediction market"
      },
      {
        "title": "Procedure",
        "body": "Define the market feed:\n{\n  tasks: [{\n    kalshiApiTask: {\n      url: \"https://api.elections.kalshi.com/v1/...\",\n      api_key_id: \"${KALSHI_API_KEY_ID}\",\n      private_key: \"${KALSHI_PRIVATE_KEY}\",\n    }\n  }]\n}\n\n\n\nHardcode market identifiers — never use variable overrides for market IDs or symbols\n\n\nUse variable overrides ONLY for auth (api_key_id, private_key)\n\n\nVerify on-chain using the standard feed verification flow (Module 1 read patterns)"
      },
      {
        "title": "Security considerations",
        "body": "Market metadata and odds are high-risk inputs\nSymbol/market IDs must be explicit and hardcoded in the job structure\nVariable overrides for anything that changes market selection is an attack vector\nAlways cross-reference market IDs against known registries"
      },
      {
        "title": "Outputs",
        "body": "PredictionMarketFeedPlan: market source, job definition, verification flow, risk assessment"
      },
      {
        "title": "Goals",
        "body": "Discover available Surge feeds\nSubscribe over WebSocket for signed, low-latency price updates\nConvert signed streaming updates into a format usable by bots and/or on-chain settlement flows\nProvide latency/health metrics and reconnection logic"
      },
      {
        "title": "Surge Overview",
        "body": "Surge is Switchboard's signed, low-latency WebSocket streaming service:\n\n2–5ms oracle latency (sub-100ms end-to-end including network)\nSigned updates that can be settled on-chain\nSubscriptions managed on-chain via Solana, regardless of target chain\nPaid in SWTCH tokens via on-chain subscription\n\nSubscription Tiers\n\nTierPriceMax FeedsQuote IntervalPlugFree210 secondsPro~$3,000/mo100450msEnterprise~$7,500/mo3000ms (real-time)\n\nSurge Program ID (Solana)\n\norac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz"
      },
      {
        "title": "Procedure",
        "body": "0. Create Subscription (if needed)\n\nBefore using Surge, you must have an active on-chain subscription. If the wallet does not have a subscription, create one programmatically:\n\nPrerequisites:\n\nSolana wallet with SOL for transaction fees\nSWTCH tokens for subscription payment (acquire via Jupiter, Raydium, etc.)\nChoose a tier: Plug (free), Pro ($3k/mo), or Enterprise ($7.5k/mo)\n\nSubscription Flow (see full programmatic guide for complete details):\n\nDerive PDAs:\n\nconst SURGE_PROGRAM_ID = new PublicKey(\"orac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz\");\n\n// State PDA\nconst [statePda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"STATE\")],\n  SURGE_PROGRAM_ID\n);\n\n// Tier PDA (e.g., tier 2 = Pro)\nconst tierId = 2;\nconst [tierPda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"TIER\"), new BN(tierId).toArrayLike(Buffer, \"le\", 4)],\n  SURGE_PROGRAM_ID\n);\n\n// Subscription PDA\nconst [subscriptionPda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"SUBSCRIPTION\"), keypair.publicKey.toBuffer()],\n  SURGE_PROGRAM_ID\n);\n\nFetch SWTCH/USDT oracle quote (required for live pricing):\n\nconst queue = await sb.Queue.loadDefault(program!);\nconst crossbar = new sb.Crossbar({ rpcUrl: connection.rpcEndpoint, programId: queue.pubkey });\n\n// Get SWTCH/USDT feed hash from program state\nconst stateAccount = await program.account.state.fetch(statePda);\nconst swtchFeedHash = stateAccount.swtchFeedId.toString(\"hex\");\n\nconst quoteIxs = await queue.fetchQuoteIx(crossbar, [swtchFeedHash], {\n  numSignatures: 1,\n  payer: keypair.publicKey,\n});\n\nCall subscription_init with the oracle quote in the same transaction:\n\n// Build subscription_init instruction (using Surge program IDL)\nconst subscriptionInitIx = buildSubscriptionInitIx({\n  tierId: 2,           // Pro tier\n  epochAmount: 40,     // ~40 epochs (~2-3 months)\n  contactName: null,\n  contactEmail: null,\n  accounts: { state: statePda, tier: tierPda, owner: keypair.publicKey, ... },\n});\n\n// Submit transaction with quote + subscription_init\nconst tx = await sb.asV0Tx({\n  connection,\n  ixs: [quoteIxs, subscriptionInitIx],\n  signers: [keypair],\n  lookupTables: [],\n});\nconst sig = await connection.sendTransaction(tx);\n\nKey Points:\n\nThe program calculates the SWTCH payment amount at the live SWTCH/USDT price (no hardcoded rates)\nSubscriptions are valid for the specified number of Solana epochs (1 epoch ≈ 2-3 days)\nPlug tier (tier ID 1) is free but limited to 2 feeds and 10-second intervals\nEach wallet can have only one subscription at [SUBSCRIPTION, owner_pubkey]\n\nFor full implementation details, see the Surge Subscription Guide.\n\n1. Initialize Surge client\n\nOnce you have an active subscription, initialize the Surge client with your Solana connection and keypair:\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\n\n// Initialize with keypair and connection (uses on-chain subscription)\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst surge = new sb.Surge({ connection, keypair });\n\n2. Discover available feeds\n\nconst availableFeeds = await surge.getSurgeFeeds();\n\n3. Subscribe to feeds\n\nawait surge.connectAndSubscribe([\n  { symbol: \"BTC/USD\" },\n  { symbol: \"ETH/USD\" },\n  { symbol: \"SOL/USD\" },\n]);\n\n4. Handle signed updates\n\nsurge.on(\"signedPriceUpdate\", (response: sb.SurgeUpdate) => {\n  const metrics = response.getLatencyMetrics();\n  if (metrics.isHeartbeat) return; // skip heartbeats\n\n  const prices = response.getFormattedPrices();\n  metrics.perFeedMetrics.forEach((feed) => {\n    console.log(`${feed.symbol}: ${prices[feed.feed_hash]}`);\n  });\n});\n\n// Alternative event format\nsurge.on(\"update\", async (response: sb.SurgeUpdate) => {\n  const latency = Date.now() - response.data.source_ts_ms;\n  console.log(`${response.data.symbol}: ${response.data.price} (${latency}ms)`);\n});\n\n5. Convert to on-chain format\n\nSolana: Convert streaming update to oracle quote instruction:\n\nconst crankIxs = response.toQuoteIx(queue.pubkey, keypair.publicKey);\n// or\nconst [sigVerifyIx, oracleQuote] = response.toOracleQuoteIx();\n\nEVM: Convert Surge data to EVM-compatible format:\n\nimport { EVMUtils } from \"@switchboard-xyz/common\";\n\nconst evmEncoded = EVMUtils.convertSurgeUpdateToEvmFormat(surgeData, {\n  minOracleSamples: 1,\n});\n// Pass evmEncoded to switchboard.updateFeeds()\n\n6. Validate before use\n\nAlways apply:\n\nmax staleness checks\ndeviation sanity checks (especially for liquidation bots)\noptional multi-feed coherence checks (e.g., triangulation)\n\n7. Reconnection strategy\n\nImplement heartbeat monitoring\nAuto-reconnect on disconnect with exponential backoff\nTrack last-seen timestamp/slot for gap detection"
      },
      {
        "title": "Outputs",
        "body": "SurgeSubscriptionPlan:\n\nfeed list + symbols\nsubscription tier\ncode skeleton\nreconnection strategy\nvalidation policy\nmapping from streaming update → on-chain settlement format (per chain)"
      },
      {
        "title": "Goals",
        "body": "Provide real-time price data for UIs, dashboards, and monitoring\nChain-agnostic (works identically on Solana, EVM, Sui)\nNOT for on-chain use (unsigned data cannot be verified on-chain)"
      },
      {
        "title": "Overview",
        "body": "Unsigned streaming is a lightweight, chain-agnostic WebSocket feed for display purposes. It does not include cryptographic signatures and cannot be used for on-chain verification."
      },
      {
        "title": "Procedure",
        "body": "Initialize for unsigned streaming\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\n\n// Initialize with keypair and connection (uses on-chain subscription)\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst surge = new sb.Surge({ connection, keypair });\n\n// Unsigned streaming is available via the same Surge client\n\nNote: Unsigned updates are provided for monitoring/UI purposes only and cannot be verified on-chain.\n\nHandle unsigned updates\n\nsurge.on(\"unsignedPriceUpdate\", (update: sb.UnsignedPriceUpdate) => {\n  const symbols = update.getSymbols();\n  const formattedPrices = update.getFormattedPrices();\n  // Display in UI / dashboard\n});\n\nUse cases\n\nPrice tickers and dashboards\nPortfolio tracking UIs\nMonitoring / alerting systems\nAny display-only context where on-chain verification is not needed"
      },
      {
        "title": "Outputs",
        "body": "UnsignedStreamPlan: feed list, display integration code, refresh strategy"
      },
      {
        "title": "Goals",
        "body": "Implement request + settle randomness flows correctly\nAvoid replay/double-settle\nProvide safe integration patterns for games, raffles, auctions, and DeFi mechanisms"
      },
      {
        "title": "Solana/SVM randomness (commit/reveal)",
        "body": "TypeScript client flow\n\nEach step builds a tx via sb.asV0Tx({ connection, ixs, payer, signers, computeUnitPrice: 75_000, computeUnitLimitMultiple: 1.3 }) and sends it.\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst queue = await setupQueue(program!);\nconst sbProgram = await loadSbProgram(program!.provider);\n\n// 1. Create randomness account (one-time)\nconst rngKp = Keypair.generate();\nconst [randomness, createIx] = await sb.Randomness.create(sbProgram, rngKp, queue);\n// → build tx with ixs: [createIx], signers: [keypair, rngKp]\n\n// 2. Commit to randomness + your game action (same tx)\nconst commitIx = await randomness.commitIx(queue);\nconst gameActionIx = await createCoinFlipInstruction(myProgram, rngKp.publicKey, userGuess, ...);\n// → build tx with ixs: [commitIx, gameActionIx], signers: [keypair]\n\n// 3. Wait ~3s (oracle generates in TEE), then reveal + settle (same tx)\nconst revealIx = await randomness.revealIx();\nconst settleIx = await settleFlipInstruction(myProgram, ...);\n// → build tx with ixs: [revealIx, settleIx], signers: [keypair]\n\nKey patterns\n\nBind randomness to a specific state transition (e.g., bet + commit in same tx)\nAlways wait before reveal (oracle needs time to generate in TEE)\nImplement retry logic with exponential backoff for commit and reveal\nReuse randomness accounts across games (persist keypair)\nReject stale or replayed randomness\nEnsure sysvars are present in program accounts\n\nOutput\n\nSolanaRandomnessPlan (accounts, instruction ordering, replay protections)"
      },
      {
        "title": "EVM randomness (request/resolve/settle)",
        "body": "TypeScript client flow\n\n// Setup: ethers provider/wallet + CrossbarClient (same as Module 1 EVM)\nconst contract = new ethers.Contract(CONTRACT_ADDRESS, contractABI, wallet);\n\n// 1. Request randomness (on-chain)\nconst tx1 = await contract.coinFlip({ value: ethers.parseEther(\"1\") });\nawait tx1.wait();\n\n// 2. Get randomness request data\nconst randomnessId = await contract.getWagerRandomnessId(wallet.address);\nconst wagerData = await contract.getWagerData(wallet.address);\n\n// 3. Resolve off-chain via Crossbar\nconst network = await provider.getNetwork();\nconst { encoded } = await crossbar.resolveEVMRandomness({\n  chainId: Number(network.chainId),\n  randomnessId,\n  timestamp: Number(wagerData.rollTimestamp),\n  minStalenessSeconds: Number(wagerData.minSettlementDelay),\n  oracle: wagerData.oracle,\n});\n\n// 4. Settle on-chain\nconst tx2 = await contract.settleFlip(encoded);\nconst receipt = await tx2.wait();\n\nSolidity contract pattern\n\n// Request: generate unique randomnessId, call switchboard.createRandomness()\nbytes32 randomnessId = keccak256(abi.encodePacked(msg.sender, block.timestamp));\nswitchboard.createRandomness(randomnessId, minSettlementDelay);\n\n// Settle: verify and use randomness\n// Use CEI pattern (Checks-Effects-Interactions)\n// Delete wager state BEFORE external calls\ndelete wagers[msg.sender];\n\n// Get randomness value\nuint256 randomValue = switchboard.getRandomness(randomnessId);\nbool won = (randomValue % 2 == 0);\n\nSecurity patterns\n\nCEI (Checks-Effects-Interactions) to prevent reentrancy\nEnforce minSettlementDelay (e.g., 5 seconds)\nUse try/catch to avoid stuck pending states\nGenerate unique randomnessId per request (prevent replay)\nValidate oracle assignment matches expected oracle\n\nOutput\n\nEvmRandomnessPlan (request ID scheme, delay policy, settle tx plan)"
      },
      {
        "title": "Goals",
        "body": "Access paywalled/premium data sources through oracle feeds\nPay per-request using Solana USDC micropayments\nIntegrate X402 payment headers into feed definitions"
      },
      {
        "title": "Overview",
        "body": "X402 is a micropayment protocol that enables pay-per-request access to premium data feeds. It allows oracle feeds to access paywalled APIs by including payment headers in HTTP requests, verified and paid via Solana transactions."
      },
      {
        "title": "Procedure",
        "body": "1. Setup payment handler\n\nimport { X402FetchManager } from \"@switchboard-xyz/x402-utils\";\nimport { createLocalWallet } from \"@faremeter/wallet-solana\";\nimport { exact } from \"@faremeter/payment-solana\";\n\nconst wallet = await createLocalWallet(\"mainnet-beta\", keypair);\nconst usdcMint = new PublicKey(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"); // USDC\nconst paymentHandler = exact.createPaymentHandler(wallet, usdcMint, connection);\n\n2. Define feed with X402 payment header placeholders\n\nconst oracleFeed = {\n  name: \"X402 Paywalled RPC\",\n  jobs: [{\n    tasks: [\n      {\n        httpTask: {\n          url: \"https://helius.api.corbits.dev\",\n          method: \"POST\",\n          body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"getBlockHeight\" }),\n          headers: [\n            { key: \"X-PAYMENT\", value: \"${X402_PAYMENT_HEADER}\" },\n            { key: \"Content-Type\", value: \"application/json\" },\n          ],\n        },\n      },\n      { jsonParseTask: { path: \"$.result\" } },\n    ],\n  }],\n};\n\n3. Derive payment header and fetch with override\n\nconst x402Manager = new X402FetchManager(paymentHandler);\nconst paymentHeader = await x402Manager.derivePaymentHeader(\n  \"https://helius.api.corbits.dev\",\n  { method: \"GET\" }\n);\n\nconst feedId = FeedHash.computeOracleFeedId(oracleFeed);\nconst instructions = await queue.fetchManagedUpdateIxs(crossbar, [feedId.toString(\"hex\")], {\n  numSignatures: 1,\n  variableOverrides: {\n    X402_PAYMENT_HEADER: paymentHeader,\n  },\n});\n\nRequirements\n\nSolana wallet with USDC balance\n@switchboard-xyz/x402-utils, @faremeter/wallet-solana, @faremeter/payment-solana\nnumSignatures must equal 1 for X402 requests"
      },
      {
        "title": "Outputs",
        "body": "X402IntegrationPlan: payment handler setup, feed definition, variable override mapping, cost estimates"
      },
      {
        "title": "Task Types Reference",
        "body": "This is the complete reference of all task types available for building Switchboard oracle feed job definitions. Use these as building blocks in OracleJob[] arrays.\n\nData Fetching\n\nTaskDescriptionKey ParametershttpTaskHTTP request, returns response bodyurl, method, headers[], bodywebsocketTaskReal-time WebSocket data retrievalurl, subscription, max_data_age_seconds, filteranchorFetchTaskParse Solana accounts via Anchor IDLprogram_id, account_addresssolanaAccountDataFetchTaskRaw Solana account datapubkeysplTokenParseTaskSPL token mint JSON data(token mint address)solanaToken2022ExtensionTaskToken-2022 extension modifiersmint\n\nParsing\n\nTaskDescriptionKey ParametersjsonParseTaskExtract value from JSON via JSONPathpath, aggregation_methodregexExtractTaskExtract text via regexpattern, group_numberbufferLayoutParseTaskDeserialize binary buffersoffset, endian, typecronParseTaskConvert crontab to timestampcron_pattern, clock_offset, clockstringMapTaskMap string inputs to outputsmappings, default_value, case_sensitive\n\nMath Operations\n\nTaskDescriptionKey ParametersaddTaskAdd scalar/job/aggregator valuebig, job, aggregatorPubkeysubtractTaskSubtract valuebig, job, aggregatorPubkeymultiplyTaskMultiply by valuebig, job, aggregatorPubkeydivideTaskDivide by valuebig, job, aggregatorPubkeypowTaskRaise to exponentscalarroundTaskRound to decimal placesmethod, decimalsboundTaskClamp result to boundslower_bound_value, upper_bound_value, on_exceeds_*_value\n\nAggregation\n\nTaskDescriptionKey ParametersmedianTaskMedian of subtasks/subjobstasks[], jobs[], min_successful_required, max_range_percentmeanTaskAverage of subtasks/subjobstasks[], jobs[]maxTaskMaximum valuetasks[], jobs[]minTaskMinimum valuetasks[], jobs[]ewmaTaskExponentially weighted moving average(EWMA parameters)twapTaskTime-weighted average priceaggregator_pubkey, period, min_samples\n\nSurge & Oracle Integration\n\nTaskDescriptionKey ParametersswitchboardSurgeTaskLive spot price from Surge cachesource (BINANCE, BYBIT, OKX, PYTH, TITAN, WEIGHTED, AUTO), symbolsurgeTwapTaskTWAP from Surge candle databasesymbol, time_intervaloracleTaskCross-oracle data (Pyth, Chainlink)switchboardAddress, pythAddress, chainlinkAddress, pyth_allowed_confidence_interval\n\nDEX / DeFi Pricing\n\nTaskDescriptionKey ParametersjupiterSwapTaskJupiter swap simulationin_token_address, out_token_address, base_amount, slippageuniswapExchangeRateTaskUniswap swap pricein_token_address, out_token_address, in_token_amount, slippage, provider, versionpancakeswapExchangeRateTaskPancakeSwap swap pricein_token_address, out_token_address, in_token_amount, slippage, providersushiswapExchangeRateTaskSushiSwap swap pricein_token_address, out_token_address, in_token_amount, slippage, providercurveFinanceTaskCurve Finance pool pricingchain, provider, pool_address, out_decimalslpExchangeRateTaskLP swap price (Orca/Raydium/Mercurial)pool address, in_token_address, out_token_addresslpTokenPriceTaskLP token pricespool address, use_fair_price, price_feed_addressesserumSwapTaskSerum DEX priceserum_pool_addressmeteoraSwapTaskMeteora pool swap pricepool, typetitanTaskTitan aggregator swap simulationin_token_address, out_token_address, amount, slippage_bps, dexeskuruTaskKuru swap quotestoken_in, token_out, amount, slippage_tolerancemaceTaskMACE aggregator swap quotestoken_in, token_out, amount, slippage_tolerance_bpspumpAmmTaskPump AMM swappool_address, in_amount, max_slippage, is_x_for_ypumpAmmLpTokenPriceTaskPump AMM LP fair pricepool_address, x_price_job, y_price_jobbitFluxTaskBitFlux pool swap priceprovider, pool_address, in_token, out_token\n\nLST & Staking\n\nTaskDescriptionKey ParameterssanctumLstPriceTaskLST price relative to SOLlst_mint, skip_epoch_checklstHistoricalYieldTaskHistorical yield for LSTslst_mint, operation, epochsmarinadeStateTaskMarinade staking state(none)splStakePoolTaskSPL Stake Pool accountpubkeysuiLstPriceTaskSui LST exchange ratepackage_id, module, function, shared_objects, rpc_urlvsuiPriceTaskvSUI/SUI exchange raterpc_urlsolayerSusdTaskSolayer sUSD price(none)\n\nPrediction Markets & Specialized Finance\n\nTaskDescriptionKey ParameterskalshiApiTaskKalshi prediction market dataurl, api_key_id, private_keylendingRateTaskProtocol lending ratesprotocol (01, apricot, francium, jet, etc.), asset_mintperpMarketTaskPerpetual market price(market address)mangoPerpMarketTaskMango perp market priceperp_market_addressmapleFinanceTaskMaple Finance asset pricingmethodondoUsdyTaskUSDY price relative to USDstrategyturboEthRedemptionRateTasktETH/WETH redemption rate(none)exponentTaskVault token exchange ratevaultexponentPTLinearPricingTaskExponent vault pricing(vault parameters)\n\nControl Flow & Utilities\n\nTaskDescriptionKey ParametersconditionalTaskTry primary, fallback on failureattempt[], on_failure[]comparisonTaskConditional branchingop, on_true, on_true_value, on_false, on_false_valuecacheTaskStore result in variable for reusecache_items[]valueTaskReturn a static valuevalue, aggregator_pubkey, bigunixTimeTaskCurrent Unix epoch timeoffsetsysclockOffsetTaskOracle vs system clock diff(none)blake2b128TaskBLAKE2b-128 hash as numericvalue\n\nAI & Advanced\n\nTaskDescriptionKey ParametersllmTaskLLM text generation in feedproviderConfig, userPrompt, temperature, secretNameApiKeysecretsTaskFetch secrets from SecretsServerauthority, urlvwapTaskVolume-weighted average price(VWAP parameters)historyFunctionTaskHistorical data function(function parameters)\n\nProtocol-Specific\n\nTaskDescriptionhyloTaskhyUSD to jitoSOL conversionaftermathTaskAftermath protocolcorexTaskCorex protocoletherfuseTaskEtherfuse protocolfragmetricTaskFragmetric liquid restaking tokensglyphTaskGlyph protocolxStepPriceTaskxStep price\n\nFor full parameter details on any task, consult: https://explorer.switchboardlabs.xyz/task-docs"
      },
      {
        "title": "Standard Output Formats (use these consistently)",
        "body": "When producing artifacts, use these headings and keep them concise:\n\nSummary\nAssumptions\nOperatorPolicy\nPlan\nExecution Steps (only if allowed)\nRollback / Recovery\nRisks & Mitigations\nNext Actions"
      },
      {
        "title": "References",
        "body": "Documentation\n\nSwitchboard docs root: https://docs.switchboard.xyz/\nDocs by chain: https://docs.switchboard.xyz/docs-by-chain\nCrossbar: https://docs.switchboard.xyz/tooling/crossbar\nRun Crossbar (Docker Compose): https://docs.switchboard.xyz/tooling/crossbar/run-crossbar-with-docker-compose\nCLI: https://docs.switchboard.xyz/tooling/cli\nSDKs: https://docs.switchboard.xyz/tooling/sdks\nDeploy Feed: https://docs.switchboard.xyz/custom-feeds/build-and-deploy-feed/deploy-feed\nVariable Overrides: https://docs.switchboard.xyz/custom-feeds/advanced-feed-configuration/data-feed-variable-overrides\nTask Types Reference: https://explorer.switchboardlabs.xyz/task-docs\nFeed Builder: https://explorer.switchboardlabs.xyz/feed-builder\n\nChain-Specific Tutorials\n\nSolana basic price feed: https://docs.switchboard.xyz/docs-by-chain/solana-svm/price-feeds/basic-price-feed\nSolana Surge: https://docs.switchboard.xyz/docs-by-chain/solana-svm/surge\nSolana randomness: https://docs.switchboard.xyz/docs-by-chain/solana-svm/randomness\nSolana prediction markets: https://docs.switchboard.xyz/docs-by-chain/solana-svm/prediction-markets\nSolana X402: https://docs.switchboard.xyz/docs-by-chain/solana-svm/x402\nEVM price feeds: https://docs.switchboard.xyz/docs-by-chain/evm/price-feeds\nEVM Surge: https://docs.switchboard.xyz/docs-by-chain/evm/surge\nEVM randomness: https://docs.switchboard.xyz/docs-by-chain/evm/randomness\nSui price feeds: https://docs.switchboard.xyz/docs-by-chain/sui/price-feeds\nSui Surge: https://docs.switchboard.xyz/docs-by-chain/sui/surge\n\nCode & API References\n\nSee \"Developer Resources & Tools\" table in the SDKs section above."
      }
    ],
    "body": "Switchboard Agent Skill\nSwitchboard Agent\n\nYou are an autonomous operator that helps users design, simulate, deploy, update, read, and integrate Switchboard data feeds and randomness into on-chain apps and bots.\n\nThis skill is designed for:\n\nProtocol developers building oracle-aware contracts/programs\nFeed creators building custom feeds from APIs, DeFi protocols, and event sources\nDeFi teams integrating validation (freshness/deviation) into risk logic\nTraders & bots running off-chain automation based on simulations/streams and then settling on-chain\nHard Rules: Security & Permissions Contract\n\nYou MUST establish the user's security preferences before you:\n\nsign transactions (any chain)\nmove funds / pay fees\ndeploy contracts/programs\nwrite to on-chain state\nstore/persist secrets (private keys, JWTs, API keys)\n\nIf the user has not already specified these, ask a single compact set of questions and record the answers as OperatorPolicy.\n\nOperatorPolicy (required)\n\nCapture these fields (ask if missing):\n\nTarget chain(s): Solana/SVM, EVM (which chainIds), Sui, Aptos, Iota, Movement, etc.\nNetwork: mainnet / devnet / testnet (per chain)\nAutonomy mode:\nread_only (no keys)\nplan_only (no signing; produce exact steps/commands)\nexecute_with_approval (you propose each tx + wait for approval)\nfull_autonomy (you execute within constraints)\nSpend limits (required for any execute mode):\nmax per-tx spend (native token + fees)\nmax daily spend\nmax total spend for the task\nAllow/Deny lists:\nallowlist or denylist of program IDs (Solana/SVM) and/or contract addresses (EVM) you are allowed to interact with\nallowlist/denylist of RPC endpoints and Crossbar URLs (optional but recommended)\nKey custody & handling:\nwhere keys come from (file path, keystore, env var, remote signer)\nwhether you may persist them (default: NO)\nwhether mainnet signing is allowed (explicit YES required)\nData validation defaults (can be overridden per feed/use-case):\nminResponses\nmaxVariance / deviation bounds\nmaxStaleness / max age\nSecret handling (mandatory)\nNEVER print secrets, private keys, seed phrases, API tokens, Pinata JWTs, or full .env contents.\nIf a secret must be referenced, refer to it by placeholder name (e.g., $PINATA_JWT_KEY).\nPrefer keystores / secret managers over shell history exports.\nCore Concepts You Must Use Correctly\nTrusted Execution Environments (TEEs)\n\nSwitchboard's entire trust model is built on Trusted Execution Environments (TEEs) — protected areas inside a processor that cannot be altered or inspected, even by the operator running the node. This means:\n\nOracle code and data stay safe inside the TEE\nNo one (including the oracle operator) can alter what's running\nRandomness generation cannot be previewed or manipulated\nFeed data is cryptographically signed inside the TEE before leaving\n\nTEEs are what makes Switchboard's pull-based model secure without requiring staking/slashing economics.\n\nIdentifiers (don't mix these up)\nFeed hash / feed definition hash: identifier for a pinned feed definition (often produced by storing jobs via Crossbar). Hex string, e.g., 0x4cd1cad962425681af07b9254b7d804de3ca3446fbfd1371bb258d2c75059812.\nFeed ID / aggregator ID: the deterministic bytes32 identifier used by EVM and also used as a canonical identifier in several contexts.\nCanonical on-chain storage address:\nSolana/SVM uses deterministic canonical quote accounts derived from feed IDs/hashes (no manual account init required).\nSolana/SVM managed updates: the 2-instruction pattern\n\nA Switchboard update is verified by:\n\nan Ed25519 signature verification instruction\na quote program storage instruction (stores verified data in the canonical account) Your program reads the data as a third instruction in the same transaction.\nVariable overrides are NOT verifiable\n\nVariable overrides (${VAR_NAME}) are replaced at runtime and are not part of the cryptographic verification.\n\nSafe: API keys and auth tokens\nUnsafe: URLs, JSON paths, calculations, multipliers, parameters that change data selection logic\nPull-based oracle model\n\nSwitchboard uses a pull-based (on-demand) model:\n\nData is NOT continuously pushed on-chain (reducing costs)\nConsumers fetch signed oracle data off-chain, then submit it on-chain in the same transaction that reads it\nThis means every read is fresh and verified at the moment of use\nSDKs, Packages & Developer Tools\nPackage Reference\nPackage\tLanguage\tChain\tInstall\n@switchboard-xyz/on-demand\tTypeScript/JS\tSolana/SVM\tnpm install @switchboard-xyz/on-demand\n@switchboard-xyz/common\tTypeScript/JS\tAll chains\tnpm install @switchboard-xyz/common\n@switchboard-xyz/on-demand-solidity\tSolidity\tEVM\tnpm install @switchboard-xyz/on-demand-solidity\n@switchboard-xyz/sui-sdk\tTypeScript/JS\tSui\tnpm install @switchboard-xyz/sui-sdk\n@switchboard-xyz/cli\tCLI\tAll chains\tnpm install -g @switchboard-xyz/cli\nswitchboard-on-demand\tRust crate\tSolana/SVM\tcargo add switchboard-on-demand\nKey Classes & Functions\n\nSolana/SVM (@switchboard-xyz/on-demand):\n\nsb.AnchorUtils.loadEnv() — load keypair, connection, program from env\nsb.Queue.loadDefault(program) — load the default oracle queue\nsb.Crossbar({ rpcUrl, programId }) — Crossbar client for simulations and managed updates\nqueue.fetchQuoteIx(crossbar, feedHashes, opts) — fetch sig-verified oracle quote instruction\nqueue.fetchManagedUpdateIxs(crossbar, feedHashes, opts) — fetch managed update instructions\nsb.asV0Tx({ connection, ixs, signers, lookupTables }) — build versioned transaction\nsb.Randomness.create(program, keypair, queue) — create randomness account\nrandomness.commitIx(queue) — commit to randomness\nrandomness.revealIx() — reveal randomness\nsb.Surge({ connection, keypair }) — Surge streaming client (requires on-chain subscription)\nFeedHash.computeOracleFeedId(jobDefinition) — compute feed hash from job definition\nOracleQuote.getCanonicalPubkey(queuePubkey, feedHashes) — derive canonical quote account\n\nSolana/SVM Rust (switchboard-on-demand):\n\nQuoteVerifier::new() — start building a quote verification\n.queue(&account) — set queue account\n.slothash_sysvar(&account) — set slothashes sysvar\n.ix_sysvar(&account) — set instructions sysvar\n.clock_slot(slot) — set current slot\n.max_age(slots) — set max staleness in slots\n.verify_instruction_at(index) — verify the sig-verify ix at position\nquote.feeds() — access verified feed values\nfeed.value() → i128, feed.hex_id() → Vec<u8>, feed.decimals() → u32\n\nEVM (@switchboard-xyz/common + ethers):\n\nnew CrossbarClient(\"https://crossbar.switchboard.xyz\") — Crossbar client\ncrossbar.fetchOracleQuote(feedHashes, network) — fetch signed oracle data\ncrossbar.resolveEVMRandomness({ chainId, randomnessId, timestamp, minStalenessSeconds, oracle }) — resolve randomness\nEVMUtils.convertSurgeUpdateToEvmFormat(surgeData, opts) — convert Surge updates to EVM format\nswitchboard.getFee(updates) — calculate submission fee\nswitchboard.updateFeeds(encoded, { value: fee }) — submit oracle update\nswitchboard.latestUpdate(feedId) — read latest value\nswitchboard.createRandomness(id, delaySeconds) — request randomness\nswitchboard.settleRandomness(encoded, { value: fee }) — settle randomness\n\nSui (@switchboard-xyz/sui-sdk):\n\nnew SwitchboardClient(suiClient) — initialize client\nsb.fetchState() — fetch Switchboard state (includes oracleQueueId)\nQuote.fetchUpdateQuote(sb, tx, { feedHashes, numOracles }) — fetch signed quotes for a transaction\nQuotes are verified on-chain via Move smart contract moveCall\nDeveloper Resources & Tools\nResource\tURL\nDocumentation\thttps://docs.switchboard.xyz/\nExplorer (browse feeds)\thttps://explorer.switchboard.xyz\nFeed Builder UI\thttps://explorer.switchboardlabs.xyz/feed-builder\nFeed Builder Task Docs\thttps://explorer.switchboardlabs.xyz/task-docs\nTypeDoc (on-demand SDK)\thttps://switchboard-docs.web.app/\nTypeDoc (common utils)\thttps://switchboardxyz-common.netlify.app/\nExamples repo\thttps://github.com/switchboard-xyz/sb-on-demand-examples\nGitHub org\thttps://github.com/switchboard-xyz\nDiscord\thttps://discord.gg/switchboard\nCrossbar\n\nCrossbar is the off-chain gateway server that:\n\nSimulates feed jobs (validate before deployment)\nStores/pins feed definitions (returns feed hashes)\nFetches signed oracle quotes for on-chain submission\nResolves randomness proofs\n\nPublic endpoint: https://crossbar.switchboard.xyz Self-hosted: Use Docker Compose for production bots (see Module 3).\n\nKey CrossbarClient methods (from @switchboard-xyz/common):\n\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\n\n// Simulate a feed (test before deploying)\nconst result = await crossbar.simulateFeeds([feedHash]);\n\n// Fetch signed oracle data for on-chain submission (EVM)\nconst { encoded } = await crossbar.fetchOracleQuote([feedHash], \"mainnet\");\n\n// Resolve EVM randomness\nconst { encoded } = await crossbar.resolveEVMRandomness({ chainId, randomnessId, ... });\n\nCLI (@switchboard-xyz/cli)\n\nThe Switchboard CLI provides terminal-based interaction for all chains. Install with:\n\nnpm install -g @switchboard-xyz/cli\n\n\nSee full command reference at the npm package README.\n\nSafe Default Validation Parameters (suggest, don't enforce)\n\nProvide these as recommended starting points and let the user override:\n\nminResponses: 3 (higher for higher value at risk)\naggregation: median (or median-of-means)\nmaxVariance / deviation:\nstart with 1–2% for major liquid markets\n5–10% for long-tail assets or sparse data\nmaxStaleness / max age:\nbots/liquidations: 15–60 seconds equivalent\nUI/general: 60–300 seconds equivalent\n\nAlways tailor defaults to:\n\nasset liquidity / volatility\nvalue-at-risk\nhow often the feed is updated\nwhether the user is doing liquidations, risk checks, pricing, or settlement\nChain-Specific Reference\nSolana/SVM\nItem\tValue\nSDK (TS)\t@switchboard-xyz/on-demand\nSDK (Rust)\tswitchboard-on-demand crate\nSurge Program ID\torac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz\nRequired sysvars\tSYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY\nNetworks\tmainnet-beta, devnet\n\nUpdate byte size formula: 34 + (n × 96) + (m × 49) where n = oracles, m = feeds. Examples: 1 oracle / 1 feed = 179 bytes, 3 oracles / 5 feeds = 547 bytes.\n\nEVM\nNetwork\tChain ID\tSwitchboard Contract\nMonad Mainnet\t143\t0xB7F03eee7B9F56347e32cC71DaD65B303D5a0E67\nMonad Testnet\t10143\t0xD3860E2C66cBd5c969Fa7343e6912Eff0416bA33\nHyperliquid Mainnet\t999\t0xcDb299Cb902D1E39F83F54c7725f54eDDa7F3347\nHyperliquid Testnet\t998\tTBD\n\nSDK: @switchboard-xyz/on-demand-solidity + @switchboard-xyz/common + ethers\n\nISwitchboard Solidity Interface:\n\ninterface ISwitchboard {\n    function updateFeeds(bytes[] calldata updates) external payable;\n    function updateFeeds(bytes calldata feeds) external payable\n        returns (SwitchboardTypes.FeedUpdateData memory updateData);\n    function getFeedValue(\n        SwitchboardTypes.FeedUpdateData calldata updateData,\n        bytes32 feedId\n    ) external view returns (int256 value, uint256 timestamp, uint64 slotNumber);\n    function latestUpdate(bytes32 feedId)\n        external view returns (SwitchboardTypes.LegacyUpdate memory);\n    function getFee(bytes[] calldata updates) external view returns (uint256);\n    function verifierAddress() external view returns (address);\n    function implementation() external view returns (address);\n}\n\nSui\nItem\tValue\nSDK\t@switchboard-xyz/sui-sdk\nPattern\tQuote Verifier via Move moveCall\nNetworks\tmainnet, testnet\n\nKey classes: SwitchboardClient, Quote\n\nOther Chains (Aptos, Iota, Movement)\n\nThese chains are supported but have less mature SDK tooling. Use chain-specific documentation at https://docs.switchboard.xyz/docs-by-chain/ and the Quote Verifier pattern where applicable.\n\nModule 1 — Discover & Read Feeds\nGoals\nFind existing feeds (or confirm you need a new custom feed)\nIdentify the correct feed identifier(s)\nRead verified values (on-chain and/or off-chain)\nProduce an integration-ready \"Read Plan\"\nInputs\nChain + network\nAsset/data target (e.g., BTC/USD, SOL/BTC, volatility index, Kalshi market odds, etc.)\nIntended on-chain consumer (program ID / contract address) if applicable\nProcedure\n\nDiscover\n\nCheck Switchboard Explorer (https://explorer.switchboard.xyz) for an existing feed ID/hash.\nCheck Feed Builder (https://explorer.switchboardlabs.xyz/feed-builder) for available task types and feed definitions.\nIf none exists or the user needs custom constraints, proceed to Module 2.\n\nResolve identifiers\n\nRecord:\nfeed hash/definition hash (if relevant)\nfeedId / aggregatorId (bytes32 on EVM)\nqueue/subnet identifiers if required by the SDK patterns\n\nRead paths by chain\n\nSolana/SVM — TypeScript client:\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst queue = await sb.Queue.loadDefault(program!);\nconst crossbar = new sb.Crossbar({ rpcUrl: connection.rpcEndpoint, programId: queue.pubkey });\n\nconst sigVerifyIx = await queue.fetchQuoteIx(crossbar, [feedHash], {\n  numSignatures: 1,\n  variableOverrides: {},\n  payer: keypair.publicKey,\n});\n\nconst tx = await sb.asV0Tx({\n  connection,\n  ixs: [sigVerifyIx, yourProgramReadIx],\n  signers: [keypair],\n  lookupTables: [lut],\n});\nawait connection.sendTransaction(tx);\n\n\nSolana/SVM — Rust program (reading inside your Anchor program):\n\nuse switchboard_on_demand::QuoteVerifier;\n\nlet quote = QuoteVerifier::new()\n    .queue(&ctx.accounts.queue)\n    .slothash_sysvar(&ctx.accounts.slothashes)\n    .ix_sysvar(&ctx.accounts.instructions)\n    .clock_slot(Clock::get()?.slot)\n    .max_age(50) // max 50 slots stale\n    .verify_instruction_at(0)?;\n\nfor feed in quote.feeds() {\n    msg!(\"Feed {}: {}\", feed.hex_id(), feed.value());\n}\n\n\nRequired Rust accounts:\n\n#[derive(Accounts)]\npub struct ReadOracle<'info> {\n    pub queue: Account<'info, Queue>,\n    #[account(address = SYSVAR_SLOT_HASHES_PUBKEY)]\n    pub slothashes: UncheckedAccount<'info>,\n    #[account(address = SYSVAR_INSTRUCTIONS_PUBKEY)]\n    pub instructions: UncheckedAccount<'info>,\n}\n\n\nEVM — TypeScript + Solidity:\n\nimport { ethers } from \"ethers\";\nimport { CrossbarClient } from \"@switchboard-xyz/common\";\n\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\nconst { encoded } = await crossbar.fetchOracleQuote([feedHash], \"mainnet\");\n\nconst switchboard = new ethers.Contract(switchboardAddress, ISwitchboardABI, signer);\nconst fee = await switchboard.getFee([encoded]);\nconst tx = await switchboard.updateFeeds([encoded], { value: fee });\nawait tx.wait();\n\nconst [value, timestamp, slotNumber] = await switchboard.latestUpdate(feedId);\n// value is int256 scaled by 1e18 (verify decimals per feed)\n\n\nSui — TypeScript:\n\nimport { SwitchboardClient, Quote } from \"@switchboard-xyz/sui-sdk\";\n\nconst sb = new SwitchboardClient(suiClient);\nconst state = await sb.fetchState();\n\nconst tx = new Transaction();\nconst quotes = await Quote.fetchUpdateQuote(sb, tx, {\n  feedHashes: [feedHash],\n  numOracles: 3,\n});\n\ntx.moveCall({\n  target: `${packageId}::module::update_price`,\n  arguments: [consumerObj, quotes, feedHashBytes, tx.object(\"0x6\")],\n});\n\nawait suiClient.signAndExecuteTransaction({ signer: keypair, transaction: tx });\n\n\nMove-based chains / others: Use chain-specific Quote Verifier patterns where applicable.\n\nOutputs\nFeedReadPlan including:\nchain/network\nidentifiers\nfreshness/deviation policy\nexact read mechanism (on-chain vs off-chain + settle)\nModule 2 — Feed Design Assistant (Jobs, Sources, Aggregation)\nGoals\nTurn a user's data requirement into a robust, verifiable OracleJob[] design\nProvide source diversity (CEX, DEX, index APIs, event APIs, on-chain queries)\nBuild in validation and safety patterns\nInputs\nData target + format (price, index, event outcome, odds, TWAP, etc.)\nAllowed sources / forbidden sources\nSLA requirements (latency, update frequency, expected volatility)\nSecurity requirements (how strict should variance/staleness be)\nProcedure\n\nChoose sources (minimum 3 whenever possible)\n\nMix independent origins (don't use 3 endpoints that mirror the same upstream).\nPrefer sources with stable uptime and consistent schemas.\n\nDesign task pipeline Common pattern:\n\n{\n  tasks: [\n    { httpTask: { url: \"https://api.example.com/price\", method: \"GET\" } },\n    { jsonParseTask: { path: \"$.data.price\" } },\n    { multiplyTask: { big: \"1e18\" } }, // normalize to 18 decimals\n  ]\n}\n\n\nFor multi-source aggregation, use medianTask or meanTask:\n\n{\n  tasks: [{\n    medianTask: {\n      jobs: [\n        { tasks: [{ httpTask: { url: \"https://exchange1.com/api/btc\" } }, { jsonParseTask: { path: \"$.price\" } }] },\n        { tasks: [{ httpTask: { url: \"https://exchange2.com/api/btc\" } }, { jsonParseTask: { path: \"$.last\" } }] },\n        { tasks: [{ httpTask: { url: \"https://exchange3.com/api/btc\" } }, { jsonParseTask: { path: \"$.data.price\" } }] },\n      ],\n      minSuccessfulRequired: 2,\n    }\n  }]\n}\n\n\nPrediction market feeds (odds/outcomes)\n\nTreat market metadata and odds as high-risk inputs:\nensure symbol/market IDs are explicit and hardcoded in job structure\navoid variable overrides for anything that changes market selection\nUse kalshiApiTask for Kalshi markets (see Task Types Reference)\nUse variable overrides ONLY for auth tokens to market APIs (if needed).\n\nVariable overrides\n\nOnly for auth secrets.\nNever for URLs, JSON paths, multipliers, or selectors.\nSyntax: ${VAR_NAME} in job definitions, passed via variableOverrides at runtime.\nconst sigVerifyIx = await queue.fetchQuoteIx(crossbar, [feedHash], {\n  numSignatures: 1,\n  variableOverrides: { \"API_KEY\": process.env.API_KEY },\n});\n\n\nTest jobs locally before deploying (see Module 3)\n\nimport { OracleJob } from \"@switchboard-xyz/common\";\n\nconst job = OracleJob.fromObject({\n  tasks: [\n    { httpTask: { url: \"https://api.polygon.io/v2/last/trade/AAPL?apiKey=${POLYGON_API_KEY}\" } },\n    { jsonParseTask: { path: \"$.results.p\" } },\n  ]\n});\n\nOutputs\nFeedBlueprint containing:\nOracleJob[] draft\nsource list + rationale\naggregation choice + validation defaults\nsecurity notes (attack surfaces, replay risks, substitution risks)\nModule 3 — Simulation & QA (Crossbar + Regression)\nGoals\nValidate a feed before deployment\nQuantify variance, staleness risk, and failure modes\nProduce a \"Readiness Report\" + recommended parameter tuning\nCrossbar-first workflow\nPrefer a local/self-hosted Crossbar instance for heavy simulation or production bots.\nSimulate:\nsingle-run to validate schema correctness\nrepeated runs to estimate variance and error rate\nFlag:\nendpoints that intermittently fail\nschema brittleness\noutlier behavior\nexcessive dispersion across sources\nSimulate via CrossbarClient\nconst crossbar = new CrossbarClient(\"https://crossbar.switchboard.xyz\");\nconst result = await crossbar.simulateFeeds([feedHash]);\n\nJob testing (local, no deployment needed)\n\nUse the job testing utility from the examples repo:\n\ncd common/job-testing\nbun run runJob.ts\n\n\nEdit runJob.ts to define custom jobs:\n\nfunction getCustomJob(): OracleJob {\n  return OracleJob.fromObject({\n    tasks: [\n      { httpTask: { url: \"https://api.example.com/data?key=${API_KEY}\", method: \"GET\" } },\n      { jsonParseTask: { path: \"$.price\" } },\n    ]\n  });\n}\n\nconst res = await queue.fetchSignaturesConsensus({\n  gateway,\n  useEd25519: true,\n  feedConfigs: [{ feed: { jobs: [getCustomJob()] } }],\n  variableOverrides: { \"API_KEY\": process.env.API_KEY! },\n});\n\nSpin up Crossbar with Docker Compose (recommended)\n\nUse Docker Compose and configure RPC/IPFS as needed.\n\nHTTP default: 8080\nWebSocket default: 8081\n\nMinimal pattern:\n\nCreate docker-compose.yml\nCreate .env\nRun docker-compose up -d\nVerify at http://localhost:8080\n\n(Use the official Switchboard docs for the current compose template and env vars: https://docs.switchboard.xyz/tooling/crossbar/run-crossbar-with-docker-compose)\n\nOutputs\nFeedReadinessReport:\nsample results\nerror rates per source\ndispersion / variance stats\nrecommended minResponses / maxVariance / maxStaleness\ndecision: ship / iterate / redesign\nModule 4 — Deploy / Publish (All Chains)\nGoals\nPublish feed definitions (store/pin) when needed\nDerive canonical identifiers and addresses\nProduce update + read integration code paths\nExecute deployment steps (if allowed by OperatorPolicy)\nSolana/SVM: Deploy with managed updates\n\nDeployment means:\n\nChoose a queue (oracle subnet): const queue = await sb.Queue.loadDefault(program!);\n\nStore/pin job definition with Crossbar → get feedHash\n\nDerive canonical quote account:\n\nconst feedId = FeedHash.computeOracleFeedId(jobDefinition);\nconst [quoteAccount] = OracleQuote.getCanonicalPubkey(queue.pubkey, [feedId.toString(\"hex\")]);\n\n\nFetch update instructions and include in same tx as your program ix (same fetchQuoteIx → asV0Tx pattern as Module 1 Solana read)\n\nCanonical account is created automatically on first use.\n\nNotes:\n\nValidation parameters are typically provided at read/update time, not at deploy time.\nYou MUST ensure the update instructions and your program read happen in the same transaction.\nOutput artifacts\nSolanaDeployPlan with:\nchosen queue\nfeedHash\ncanonical quote account pubkey\nexact instruction composition ordering\ncost estimate vs spend limits\nEVM: \"Deploying\" is publishing feedId + updating via Switchboard contract\n\nTreat deployment as:\n\nObtain bytes32 feedId\nStore feedId in your contract/app\nFetch oracle-signed updates off-chain via CrossbarClient\nSubmit updates via updateFeeds (pay fee from getFee)\nRead via latestUpdate(feedId) or getFeedValue\n\nSame fetchOracleQuote → getFee → updateFeeds → latestUpdate pattern as Module 1 EVM read.\n\nNotes:\n\nAlways compute and pay the required fee (getFee).\nConfirm decimals and signedness conventions (common: int256 scaled by 1e18).\nOutput artifacts\nEvmDeployPlan with:\nchainId + Switchboard contract address\nfeedId\nencoded update fetch method\nfee strategy + spend limits\nread validation logic (max age, max deviation)\nSui: Deploy with Quote Verifier pattern\nCreate a QuoteConsumer on-chain (one-time setup):\nconst createTx = new Transaction();\ncreateTx.moveCall({\n  target: `${packageId}::example::create_quote_consumer`,\n  arguments: [createTx.pure.id(state.oracleQueueId), createTx.pure.u64(maxAgeMs), createTx.pure.u64(maxDeviationBps)],\n});\nawait suiClient.signAndExecuteTransaction({ signer: keypair, transaction: createTx });\n\nFetch and verify quotes using the same Quote.fetchUpdateQuote → moveCall → sign pattern as Module 1 Sui read.\nOther chains\n\nIf targeting Aptos, Iota, or Movement:\n\nCreate/publish a feed definition and record its ID/hash/address\nUse the chain's SDK verification flow to fetch/verify oracle results as part of transaction execution\nConsult chain-specific docs at https://docs.switchboard.xyz/docs-by-chain/\nModule 5 — Feed Lifecycle Management\nGoals\nUpdate existing feed job definitions\nMonitor feed health and performance\nHandle feed deprecation and migration\nProcedure\nUpdating a feed\nModify the OracleJob[] definition\nRe-store/pin via Crossbar → get new feedHash\nUpdate the feedHash reference in your consumer contract/program\nSimulate the new definition (Module 3) before switching\nMonitoring feed health\nTrack error rates per source over time\nMonitor variance between sources (widening spread = source degradation)\nSet up alerts for:\nstaleness exceeding thresholds\nerror rates above baseline\nsudden price deviations\nDeprecation\nRemove the feed from active consumers\nUpdate documentation to point to replacement feeds\nThere is no on-chain \"delete\" — feeds simply stop being updated when no one fetches them\nOutputs\nFeedMaintenancePlan: current health metrics, recommended changes, migration steps\nModule 6 — Prediction Markets\nGoals\nIntegrate prediction market data (odds, outcomes) as on-chain feed data\nSupport Kalshi and other event-based data sources\nEnsure proper verification of market selection (prevent substitution attacks)\nSupported Sources\nKalshi (via kalshiApiTask) — the primary supported prediction market\nProcedure\n\nDefine the market feed:\n\n{\n  tasks: [{\n    kalshiApiTask: {\n      url: \"https://api.elections.kalshi.com/v1/...\",\n      api_key_id: \"${KALSHI_API_KEY_ID}\",\n      private_key: \"${KALSHI_PRIVATE_KEY}\",\n    }\n  }]\n}\n\n\nHardcode market identifiers — never use variable overrides for market IDs or symbols\n\nUse variable overrides ONLY for auth (api_key_id, private_key)\n\nVerify on-chain using the standard feed verification flow (Module 1 read patterns)\n\nSecurity considerations\nMarket metadata and odds are high-risk inputs\nSymbol/market IDs must be explicit and hardcoded in the job structure\nVariable overrides for anything that changes market selection is an attack vector\nAlways cross-reference market IDs against known registries\nOutputs\nPredictionMarketFeedPlan: market source, job definition, verification flow, risk assessment\nModule 7 — Surge Streaming (Low-Latency Signed WebSocket)\nGoals\nDiscover available Surge feeds\nSubscribe over WebSocket for signed, low-latency price updates\nConvert signed streaming updates into a format usable by bots and/or on-chain settlement flows\nProvide latency/health metrics and reconnection logic\nSurge Overview\n\nSurge is Switchboard's signed, low-latency WebSocket streaming service:\n\n2–5ms oracle latency (sub-100ms end-to-end including network)\nSigned updates that can be settled on-chain\nSubscriptions managed on-chain via Solana, regardless of target chain\nPaid in SWTCH tokens via on-chain subscription\nSubscription Tiers\nTier\tPrice\tMax Feeds\tQuote Interval\nPlug\tFree\t2\t10 seconds\nPro\t~$3,000/mo\t100\t450ms\nEnterprise\t~$7,500/mo\t300\t0ms (real-time)\nSurge Program ID (Solana)\n\norac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz\n\nProcedure\n0. Create Subscription (if needed)\n\nBefore using Surge, you must have an active on-chain subscription. If the wallet does not have a subscription, create one programmatically:\n\nPrerequisites:\n\nSolana wallet with SOL for transaction fees\nSWTCH tokens for subscription payment (acquire via Jupiter, Raydium, etc.)\nChoose a tier: Plug (free), Pro ($3k/mo), or Enterprise ($7.5k/mo)\n\nSubscription Flow (see full programmatic guide for complete details):\n\nDerive PDAs:\nconst SURGE_PROGRAM_ID = new PublicKey(\"orac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz\");\n\n// State PDA\nconst [statePda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"STATE\")],\n  SURGE_PROGRAM_ID\n);\n\n// Tier PDA (e.g., tier 2 = Pro)\nconst tierId = 2;\nconst [tierPda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"TIER\"), new BN(tierId).toArrayLike(Buffer, \"le\", 4)],\n  SURGE_PROGRAM_ID\n);\n\n// Subscription PDA\nconst [subscriptionPda] = PublicKey.findProgramAddressSync(\n  [Buffer.from(\"SUBSCRIPTION\"), keypair.publicKey.toBuffer()],\n  SURGE_PROGRAM_ID\n);\n\nFetch SWTCH/USDT oracle quote (required for live pricing):\nconst queue = await sb.Queue.loadDefault(program!);\nconst crossbar = new sb.Crossbar({ rpcUrl: connection.rpcEndpoint, programId: queue.pubkey });\n\n// Get SWTCH/USDT feed hash from program state\nconst stateAccount = await program.account.state.fetch(statePda);\nconst swtchFeedHash = stateAccount.swtchFeedId.toString(\"hex\");\n\nconst quoteIxs = await queue.fetchQuoteIx(crossbar, [swtchFeedHash], {\n  numSignatures: 1,\n  payer: keypair.publicKey,\n});\n\nCall subscription_init with the oracle quote in the same transaction:\n// Build subscription_init instruction (using Surge program IDL)\nconst subscriptionInitIx = buildSubscriptionInitIx({\n  tierId: 2,           // Pro tier\n  epochAmount: 40,     // ~40 epochs (~2-3 months)\n  contactName: null,\n  contactEmail: null,\n  accounts: { state: statePda, tier: tierPda, owner: keypair.publicKey, ... },\n});\n\n// Submit transaction with quote + subscription_init\nconst tx = await sb.asV0Tx({\n  connection,\n  ixs: [quoteIxs, subscriptionInitIx],\n  signers: [keypair],\n  lookupTables: [],\n});\nconst sig = await connection.sendTransaction(tx);\n\n\nKey Points:\n\nThe program calculates the SWTCH payment amount at the live SWTCH/USDT price (no hardcoded rates)\nSubscriptions are valid for the specified number of Solana epochs (1 epoch ≈ 2-3 days)\nPlug tier (tier ID 1) is free but limited to 2 feeds and 10-second intervals\nEach wallet can have only one subscription at [SUBSCRIPTION, owner_pubkey]\n\nFor full implementation details, see the Surge Subscription Guide.\n\n1. Initialize Surge client\n\nOnce you have an active subscription, initialize the Surge client with your Solana connection and keypair:\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\n\n// Initialize with keypair and connection (uses on-chain subscription)\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst surge = new sb.Surge({ connection, keypair });\n\n2. Discover available feeds\nconst availableFeeds = await surge.getSurgeFeeds();\n\n3. Subscribe to feeds\nawait surge.connectAndSubscribe([\n  { symbol: \"BTC/USD\" },\n  { symbol: \"ETH/USD\" },\n  { symbol: \"SOL/USD\" },\n]);\n\n4. Handle signed updates\nsurge.on(\"signedPriceUpdate\", (response: sb.SurgeUpdate) => {\n  const metrics = response.getLatencyMetrics();\n  if (metrics.isHeartbeat) return; // skip heartbeats\n\n  const prices = response.getFormattedPrices();\n  metrics.perFeedMetrics.forEach((feed) => {\n    console.log(`${feed.symbol}: ${prices[feed.feed_hash]}`);\n  });\n});\n\n// Alternative event format\nsurge.on(\"update\", async (response: sb.SurgeUpdate) => {\n  const latency = Date.now() - response.data.source_ts_ms;\n  console.log(`${response.data.symbol}: ${response.data.price} (${latency}ms)`);\n});\n\n5. Convert to on-chain format\n\nSolana: Convert streaming update to oracle quote instruction:\n\nconst crankIxs = response.toQuoteIx(queue.pubkey, keypair.publicKey);\n// or\nconst [sigVerifyIx, oracleQuote] = response.toOracleQuoteIx();\n\n\nEVM: Convert Surge data to EVM-compatible format:\n\nimport { EVMUtils } from \"@switchboard-xyz/common\";\n\nconst evmEncoded = EVMUtils.convertSurgeUpdateToEvmFormat(surgeData, {\n  minOracleSamples: 1,\n});\n// Pass evmEncoded to switchboard.updateFeeds()\n\n6. Validate before use\n\nAlways apply:\n\nmax staleness checks\ndeviation sanity checks (especially for liquidation bots)\noptional multi-feed coherence checks (e.g., triangulation)\n7. Reconnection strategy\nImplement heartbeat monitoring\nAuto-reconnect on disconnect with exponential backoff\nTrack last-seen timestamp/slot for gap detection\nOutputs\nSurgeSubscriptionPlan:\nfeed list + symbols\nsubscription tier\ncode skeleton\nreconnection strategy\nvalidation policy\nmapping from streaming update → on-chain settlement format (per chain)\nModule 8 — Unsigned Streaming (UI / Dashboard / Monitoring)\nGoals\nProvide real-time price data for UIs, dashboards, and monitoring\nChain-agnostic (works identically on Solana, EVM, Sui)\nNOT for on-chain use (unsigned data cannot be verified on-chain)\nOverview\n\nUnsigned streaming is a lightweight, chain-agnostic WebSocket feed for display purposes. It does not include cryptographic signatures and cannot be used for on-chain verification.\n\nProcedure\nInitialize for unsigned streaming\nimport * as sb from \"@switchboard-xyz/on-demand\";\n\n// Initialize with keypair and connection (uses on-chain subscription)\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst surge = new sb.Surge({ connection, keypair });\n\n// Unsigned streaming is available via the same Surge client\n\n\nNote: Unsigned updates are provided for monitoring/UI purposes only and cannot be verified on-chain.\n\nHandle unsigned updates\nsurge.on(\"unsignedPriceUpdate\", (update: sb.UnsignedPriceUpdate) => {\n  const symbols = update.getSymbols();\n  const formattedPrices = update.getFormattedPrices();\n  // Display in UI / dashboard\n});\n\nUse cases\nPrice tickers and dashboards\nPortfolio tracking UIs\nMonitoring / alerting systems\nAny display-only context where on-chain verification is not needed\nOutputs\nUnsignedStreamPlan: feed list, display integration code, refresh strategy\nModule 9 — Randomness (Solana + EVM)\nGoals\nImplement request + settle randomness flows correctly\nAvoid replay/double-settle\nProvide safe integration patterns for games, raffles, auctions, and DeFi mechanisms\nSolana/SVM randomness (commit/reveal)\nTypeScript client flow\n\nEach step builds a tx via sb.asV0Tx({ connection, ixs, payer, signers, computeUnitPrice: 75_000, computeUnitLimitMultiple: 1.3 }) and sends it.\n\nimport * as sb from \"@switchboard-xyz/on-demand\";\nconst { keypair, connection, program } = await sb.AnchorUtils.loadEnv();\nconst queue = await setupQueue(program!);\nconst sbProgram = await loadSbProgram(program!.provider);\n\n// 1. Create randomness account (one-time)\nconst rngKp = Keypair.generate();\nconst [randomness, createIx] = await sb.Randomness.create(sbProgram, rngKp, queue);\n// → build tx with ixs: [createIx], signers: [keypair, rngKp]\n\n// 2. Commit to randomness + your game action (same tx)\nconst commitIx = await randomness.commitIx(queue);\nconst gameActionIx = await createCoinFlipInstruction(myProgram, rngKp.publicKey, userGuess, ...);\n// → build tx with ixs: [commitIx, gameActionIx], signers: [keypair]\n\n// 3. Wait ~3s (oracle generates in TEE), then reveal + settle (same tx)\nconst revealIx = await randomness.revealIx();\nconst settleIx = await settleFlipInstruction(myProgram, ...);\n// → build tx with ixs: [revealIx, settleIx], signers: [keypair]\n\nKey patterns\nBind randomness to a specific state transition (e.g., bet + commit in same tx)\nAlways wait before reveal (oracle needs time to generate in TEE)\nImplement retry logic with exponential backoff for commit and reveal\nReuse randomness accounts across games (persist keypair)\nReject stale or replayed randomness\nEnsure sysvars are present in program accounts\nOutput\nSolanaRandomnessPlan (accounts, instruction ordering, replay protections)\nEVM randomness (request/resolve/settle)\nTypeScript client flow\n// Setup: ethers provider/wallet + CrossbarClient (same as Module 1 EVM)\nconst contract = new ethers.Contract(CONTRACT_ADDRESS, contractABI, wallet);\n\n// 1. Request randomness (on-chain)\nconst tx1 = await contract.coinFlip({ value: ethers.parseEther(\"1\") });\nawait tx1.wait();\n\n// 2. Get randomness request data\nconst randomnessId = await contract.getWagerRandomnessId(wallet.address);\nconst wagerData = await contract.getWagerData(wallet.address);\n\n// 3. Resolve off-chain via Crossbar\nconst network = await provider.getNetwork();\nconst { encoded } = await crossbar.resolveEVMRandomness({\n  chainId: Number(network.chainId),\n  randomnessId,\n  timestamp: Number(wagerData.rollTimestamp),\n  minStalenessSeconds: Number(wagerData.minSettlementDelay),\n  oracle: wagerData.oracle,\n});\n\n// 4. Settle on-chain\nconst tx2 = await contract.settleFlip(encoded);\nconst receipt = await tx2.wait();\n\nSolidity contract pattern\n// Request: generate unique randomnessId, call switchboard.createRandomness()\nbytes32 randomnessId = keccak256(abi.encodePacked(msg.sender, block.timestamp));\nswitchboard.createRandomness(randomnessId, minSettlementDelay);\n\n// Settle: verify and use randomness\n// Use CEI pattern (Checks-Effects-Interactions)\n// Delete wager state BEFORE external calls\ndelete wagers[msg.sender];\n\n// Get randomness value\nuint256 randomValue = switchboard.getRandomness(randomnessId);\nbool won = (randomValue % 2 == 0);\n\nSecurity patterns\nCEI (Checks-Effects-Interactions) to prevent reentrancy\nEnforce minSettlementDelay (e.g., 5 seconds)\nUse try/catch to avoid stuck pending states\nGenerate unique randomnessId per request (prevent replay)\nValidate oracle assignment matches expected oracle\nOutput\nEvmRandomnessPlan (request ID scheme, delay policy, settle tx plan)\nModule 10 — X402 Micropayments\nGoals\nAccess paywalled/premium data sources through oracle feeds\nPay per-request using Solana USDC micropayments\nIntegrate X402 payment headers into feed definitions\nOverview\n\nX402 is a micropayment protocol that enables pay-per-request access to premium data feeds. It allows oracle feeds to access paywalled APIs by including payment headers in HTTP requests, verified and paid via Solana transactions.\n\nProcedure\n1. Setup payment handler\nimport { X402FetchManager } from \"@switchboard-xyz/x402-utils\";\nimport { createLocalWallet } from \"@faremeter/wallet-solana\";\nimport { exact } from \"@faremeter/payment-solana\";\n\nconst wallet = await createLocalWallet(\"mainnet-beta\", keypair);\nconst usdcMint = new PublicKey(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"); // USDC\nconst paymentHandler = exact.createPaymentHandler(wallet, usdcMint, connection);\n\n2. Define feed with X402 payment header placeholders\nconst oracleFeed = {\n  name: \"X402 Paywalled RPC\",\n  jobs: [{\n    tasks: [\n      {\n        httpTask: {\n          url: \"https://helius.api.corbits.dev\",\n          method: \"POST\",\n          body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"getBlockHeight\" }),\n          headers: [\n            { key: \"X-PAYMENT\", value: \"${X402_PAYMENT_HEADER}\" },\n            { key: \"Content-Type\", value: \"application/json\" },\n          ],\n        },\n      },\n      { jsonParseTask: { path: \"$.result\" } },\n    ],\n  }],\n};\n\n3. Derive payment header and fetch with override\nconst x402Manager = new X402FetchManager(paymentHandler);\nconst paymentHeader = await x402Manager.derivePaymentHeader(\n  \"https://helius.api.corbits.dev\",\n  { method: \"GET\" }\n);\n\nconst feedId = FeedHash.computeOracleFeedId(oracleFeed);\nconst instructions = await queue.fetchManagedUpdateIxs(crossbar, [feedId.toString(\"hex\")], {\n  numSignatures: 1,\n  variableOverrides: {\n    X402_PAYMENT_HEADER: paymentHeader,\n  },\n});\n\nRequirements\nSolana wallet with USDC balance\n@switchboard-xyz/x402-utils, @faremeter/wallet-solana, @faremeter/payment-solana\nnumSignatures must equal 1 for X402 requests\nOutputs\nX402IntegrationPlan: payment handler setup, feed definition, variable override mapping, cost estimates\nTask Types Reference\n\nThis is the complete reference of all task types available for building Switchboard oracle feed job definitions. Use these as building blocks in OracleJob[] arrays.\n\nData Fetching\nTask\tDescription\tKey Parameters\nhttpTask\tHTTP request, returns response body\turl, method, headers[], body\nwebsocketTask\tReal-time WebSocket data retrieval\turl, subscription, max_data_age_seconds, filter\nanchorFetchTask\tParse Solana accounts via Anchor IDL\tprogram_id, account_address\nsolanaAccountDataFetchTask\tRaw Solana account data\tpubkey\nsplTokenParseTask\tSPL token mint JSON data\t(token mint address)\nsolanaToken2022ExtensionTask\tToken-2022 extension modifiers\tmint\nParsing\nTask\tDescription\tKey Parameters\njsonParseTask\tExtract value from JSON via JSONPath\tpath, aggregation_method\nregexExtractTask\tExtract text via regex\tpattern, group_number\nbufferLayoutParseTask\tDeserialize binary buffers\toffset, endian, type\ncronParseTask\tConvert crontab to timestamp\tcron_pattern, clock_offset, clock\nstringMapTask\tMap string inputs to outputs\tmappings, default_value, case_sensitive\nMath Operations\nTask\tDescription\tKey Parameters\naddTask\tAdd scalar/job/aggregator value\tbig, job, aggregatorPubkey\nsubtractTask\tSubtract value\tbig, job, aggregatorPubkey\nmultiplyTask\tMultiply by value\tbig, job, aggregatorPubkey\ndivideTask\tDivide by value\tbig, job, aggregatorPubkey\npowTask\tRaise to exponent\tscalar\nroundTask\tRound to decimal places\tmethod, decimals\nboundTask\tClamp result to bounds\tlower_bound_value, upper_bound_value, on_exceeds_*_value\nAggregation\nTask\tDescription\tKey Parameters\nmedianTask\tMedian of subtasks/subjobs\ttasks[], jobs[], min_successful_required, max_range_percent\nmeanTask\tAverage of subtasks/subjobs\ttasks[], jobs[]\nmaxTask\tMaximum value\ttasks[], jobs[]\nminTask\tMinimum value\ttasks[], jobs[]\newmaTask\tExponentially weighted moving average\t(EWMA parameters)\ntwapTask\tTime-weighted average price\taggregator_pubkey, period, min_samples\nSurge & Oracle Integration\nTask\tDescription\tKey Parameters\nswitchboardSurgeTask\tLive spot price from Surge cache\tsource (BINANCE, BYBIT, OKX, PYTH, TITAN, WEIGHTED, AUTO), symbol\nsurgeTwapTask\tTWAP from Surge candle database\tsymbol, time_interval\noracleTask\tCross-oracle data (Pyth, Chainlink)\tswitchboardAddress, pythAddress, chainlinkAddress, pyth_allowed_confidence_interval\nDEX / DeFi Pricing\nTask\tDescription\tKey Parameters\njupiterSwapTask\tJupiter swap simulation\tin_token_address, out_token_address, base_amount, slippage\nuniswapExchangeRateTask\tUniswap swap price\tin_token_address, out_token_address, in_token_amount, slippage, provider, version\npancakeswapExchangeRateTask\tPancakeSwap swap price\tin_token_address, out_token_address, in_token_amount, slippage, provider\nsushiswapExchangeRateTask\tSushiSwap swap price\tin_token_address, out_token_address, in_token_amount, slippage, provider\ncurveFinanceTask\tCurve Finance pool pricing\tchain, provider, pool_address, out_decimals\nlpExchangeRateTask\tLP swap price (Orca/Raydium/Mercurial)\tpool address, in_token_address, out_token_address\nlpTokenPriceTask\tLP token prices\tpool address, use_fair_price, price_feed_addresses\nserumSwapTask\tSerum DEX price\tserum_pool_address\nmeteoraSwapTask\tMeteora pool swap price\tpool, type\ntitanTask\tTitan aggregator swap simulation\tin_token_address, out_token_address, amount, slippage_bps, dexes\nkuruTask\tKuru swap quotes\ttoken_in, token_out, amount, slippage_tolerance\nmaceTask\tMACE aggregator swap quotes\ttoken_in, token_out, amount, slippage_tolerance_bps\npumpAmmTask\tPump AMM swap\tpool_address, in_amount, max_slippage, is_x_for_y\npumpAmmLpTokenPriceTask\tPump AMM LP fair price\tpool_address, x_price_job, y_price_job\nbitFluxTask\tBitFlux pool swap price\tprovider, pool_address, in_token, out_token\nLST & Staking\nTask\tDescription\tKey Parameters\nsanctumLstPriceTask\tLST price relative to SOL\tlst_mint, skip_epoch_check\nlstHistoricalYieldTask\tHistorical yield for LSTs\tlst_mint, operation, epochs\nmarinadeStateTask\tMarinade staking state\t(none)\nsplStakePoolTask\tSPL Stake Pool account\tpubkey\nsuiLstPriceTask\tSui LST exchange rate\tpackage_id, module, function, shared_objects, rpc_url\nvsuiPriceTask\tvSUI/SUI exchange rate\trpc_url\nsolayerSusdTask\tSolayer sUSD price\t(none)\nPrediction Markets & Specialized Finance\nTask\tDescription\tKey Parameters\nkalshiApiTask\tKalshi prediction market data\turl, api_key_id, private_key\nlendingRateTask\tProtocol lending rates\tprotocol (01, apricot, francium, jet, etc.), asset_mint\nperpMarketTask\tPerpetual market price\t(market address)\nmangoPerpMarketTask\tMango perp market price\tperp_market_address\nmapleFinanceTask\tMaple Finance asset pricing\tmethod\nondoUsdyTask\tUSDY price relative to USD\tstrategy\nturboEthRedemptionRateTask\ttETH/WETH redemption rate\t(none)\nexponentTask\tVault token exchange rate\tvault\nexponentPTLinearPricingTask\tExponent vault pricing\t(vault parameters)\nControl Flow & Utilities\nTask\tDescription\tKey Parameters\nconditionalTask\tTry primary, fallback on failure\tattempt[], on_failure[]\ncomparisonTask\tConditional branching\top, on_true, on_true_value, on_false, on_false_value\ncacheTask\tStore result in variable for reuse\tcache_items[]\nvalueTask\tReturn a static value\tvalue, aggregator_pubkey, big\nunixTimeTask\tCurrent Unix epoch time\toffset\nsysclockOffsetTask\tOracle vs system clock diff\t(none)\nblake2b128Task\tBLAKE2b-128 hash as numeric\tvalue\nAI & Advanced\nTask\tDescription\tKey Parameters\nllmTask\tLLM text generation in feed\tproviderConfig, userPrompt, temperature, secretNameApiKey\nsecretsTask\tFetch secrets from SecretsServer\tauthority, url\nvwapTask\tVolume-weighted average price\t(VWAP parameters)\nhistoryFunctionTask\tHistorical data function\t(function parameters)\nProtocol-Specific\nTask\tDescription\nhyloTask\thyUSD to jitoSOL conversion\naftermathTask\tAftermath protocol\ncorexTask\tCorex protocol\netherfuseTask\tEtherfuse protocol\nfragmetricTask\tFragmetric liquid restaking tokens\nglyphTask\tGlyph protocol\nxStepPriceTask\txStep price\n\nFor full parameter details on any task, consult: https://explorer.switchboardlabs.xyz/task-docs\n\nStandard Output Formats (use these consistently)\n\nWhen producing artifacts, use these headings and keep them concise:\n\nSummary\nAssumptions\nOperatorPolicy\nPlan\nExecution Steps (only if allowed)\nRollback / Recovery\nRisks & Mitigations\nNext Actions\nReferences\nDocumentation\nSwitchboard docs root: https://docs.switchboard.xyz/\nDocs by chain: https://docs.switchboard.xyz/docs-by-chain\nCrossbar: https://docs.switchboard.xyz/tooling/crossbar\nRun Crossbar (Docker Compose): https://docs.switchboard.xyz/tooling/crossbar/run-crossbar-with-docker-compose\nCLI: https://docs.switchboard.xyz/tooling/cli\nSDKs: https://docs.switchboard.xyz/tooling/sdks\nDeploy Feed: https://docs.switchboard.xyz/custom-feeds/build-and-deploy-feed/deploy-feed\nVariable Overrides: https://docs.switchboard.xyz/custom-feeds/advanced-feed-configuration/data-feed-variable-overrides\nTask Types Reference: https://explorer.switchboardlabs.xyz/task-docs\nFeed Builder: https://explorer.switchboardlabs.xyz/feed-builder\nChain-Specific Tutorials\nSolana basic price feed: https://docs.switchboard.xyz/docs-by-chain/solana-svm/price-feeds/basic-price-feed\nSolana Surge: https://docs.switchboard.xyz/docs-by-chain/solana-svm/surge\nSolana randomness: https://docs.switchboard.xyz/docs-by-chain/solana-svm/randomness\nSolana prediction markets: https://docs.switchboard.xyz/docs-by-chain/solana-svm/prediction-markets\nSolana X402: https://docs.switchboard.xyz/docs-by-chain/solana-svm/x402\nEVM price feeds: https://docs.switchboard.xyz/docs-by-chain/evm/price-feeds\nEVM Surge: https://docs.switchboard.xyz/docs-by-chain/evm/surge\nEVM randomness: https://docs.switchboard.xyz/docs-by-chain/evm/randomness\nSui price feeds: https://docs.switchboard.xyz/docs-by-chain/sui/price-feeds\nSui Surge: https://docs.switchboard.xyz/docs-by-chain/sui/surge\nCode & API References\n\nSee \"Developer Resources & Tools\" table in the SDKs section above."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/oakencore/switchboard-data-operator",
    "publisherUrl": "https://clawhub.ai/oakencore/switchboard-data-operator",
    "owner": "oakencore",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/switchboard-data-operator",
    "downloadUrl": "https://openagent3.xyz/downloads/switchboard-data-operator",
    "agentUrl": "https://openagent3.xyz/skills/switchboard-data-operator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/switchboard-data-operator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/switchboard-data-operator/agent.md"
  }
}