{
  "version": 5,
  "catalogVersion": 5,
  "homepage": "https://js.fastnear.com",
  "source": "recipes/source.mjs",
  "catalogUrl": "https://js.fastnear.com/recipes.json",
  "packages": [
    "@fastnear/api",
    "@fastnear/wallet",
    "@fastnear/utils",
    "@fastnear/seed-phrase",
    "@fastnear/ml-dsa-65",
    "@fastnear/x402",
    "@fastnear/intents"
  ],
  "support": {
    "apiKeyEnvVar": "FASTNEAR_API_KEY",
    "apiKeySummary": "Set FASTNEAR_API_KEY before running the authenticated snippets.",
    "hostedCatalogUrl": "https://js.fastnear.com/recipes.json",
    "hostedCatalogLabel": "js.fastnear.com/recipes.json",
    "hostedAgentEntry": "https://js.fastnear.com/agents.js",
    "hostedLlmsUrl": "https://js.fastnear.com/llms.txt",
    "hostedLlmsFullUrl": "https://js.fastnear.com/llms-full.txt",
    "loaders": {
      "browserGlobal": {
        "summary": "Load the IIFE bundles with script tags. Each defines one locked global.",
        "scripts": [
          {
            "url": "https://js.fastnear.com/near.js",
            "global": "near",
            "package": "@fastnear/api"
          },
          {
            "url": "https://js.fastnear.com/wallet.js",
            "global": "nearWallet",
            "package": "@fastnear/wallet"
          }
        ],
        "example": "<script src=\"https://js.fastnear.com/near.js\"></script>\n<script src=\"https://js.fastnear.com/wallet.js\"></script>"
      },
      "esm": {
        "summary": "Install from npm and import the namespaces.",
        "example": "npm install @fastnear/api @fastnear/wallet\n\nimport * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";"
      },
      "terminal": {
        "summary": "No install needed — the hosted wrapper pulls the API and evaluates the snippet on stdin.",
        "example": "node -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n…\nEOF"
      }
    },
    "trialCreditsUrl": "https://dashboard.fastnear.com",
    "trialCreditsLabel": "dashboard.fastnear.com",
    "trialCreditsSummary": "Free trial credits are available at dashboard.fastnear.com.",
    "hostedPages": [
      {
        "url": "https://js.fastnear.com/transactions.html",
        "topic": "Constructing a transaction",
        "summary": "Build a NEAR transaction end to end with zero BigInt snags: actions, unit gas/deposit strings, local-key and wallet signing, and inspecting via near.utils.txToJson. Wide integers are decimal strings."
      },
      {
        "url": "https://js.fastnear.com/meta-transactions.html",
        "topic": "Gasless meta-transactions",
        "summary": "Sign a NEP-366 delegate action locally with near.signDelegate (no wallet) and broadcast it via near.relayDelegate or any relayer that pays the gas."
      },
      {
        "url": "https://js.fastnear.com/accounts.html",
        "topic": "Keys and accounts",
        "summary": "Generate or recover NEAR keys from a BIP-39 seed phrase with @fastnear/seed-phrase, derive implicit account ids, and create + fund a testnet account with near.createFundedTestnetAccount."
      },
      {
        "url": "https://js.fastnear.com/x402.html",
        "topic": "x402 payments on NEAR",
        "summary": "Integration map, payer quickstarts, constraints, and wallet-compatibility status for @fastnear/x402."
      },
      {
        "url": "https://js.fastnear.com/post-quantum.html",
        "topic": "Post-quantum ML-DSA-65 keys",
        "summary": "Enrollment flow, key forms, wire sizes, and safety rules for @fastnear/ml-dsa-65."
      },
      {
        "url": "https://js.fastnear.com/retries.html",
        "topic": "Retries and bulk reads",
        "summary": "Transient-failure retry defaults and the near.batch / near.view.many settled-results surface."
      },
      {
        "url": "https://js.fastnear.com/intents.html",
        "topic": "NEAR Intents",
        "summary": "Multichain intent swaps: 1Click quotes, NEP-413 intent signing, and verifier deposits/withdrawals with @fastnear/intents."
      }
    ],
    "discoveryOrder": [
      {
        "step": 1,
        "label": "Read llms.txt",
        "url": "https://js.fastnear.com/llms.txt",
        "detail": "Start with the concise repo and runtime map."
      },
      {
        "step": 2,
        "label": "Fetch recipes.json",
        "url": "https://js.fastnear.com/recipes.json",
        "detail": "Use the hosted machine-readable recipe catalog with stable IDs, families, auth, returns, and snippets."
      },
      {
        "step": 3,
        "label": "Run agents.js",
        "url": "https://js.fastnear.com/agents.js",
        "detail": "Use the hosted terminal wrapper when you want the FastNear JS surface."
      },
      {
        "step": 4,
        "label": "Read llms-full.txt",
        "url": "https://js.fastnear.com/llms-full.txt",
        "detail": "Go here for the complete reference when the concise map is not enough."
      },
      {
        "step": 5,
        "label": "Fall back to curl + jq",
        "detail": "Use raw transport when survey scripting or HTTP-level inspection is more useful."
      }
    ],
    "captureExample": {
      "title": "Capture and chain one result",
      "summary": "Keep the object work in JS, then hand the emitted JSON back to shell tooling when you need one more filter step. Every `near.recipes.*`, `near.view`, `near.ft.*`, and `near.nft.*` accepts a per-call `{ network: \"testnet\" }` override; see the `connect-testnet` and `function-call-testnet` recipes for the end-to-end testnet flow.",
      "language": "bash",
      "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_SUMMARY=\"$(node -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst account = await near.recipes.viewAccount(\"root.near\");\n\nconst { block_hash, storage_usage } = account;\n\nnear.print({ block_hash, storage_usage });\nEOF\n)\"\nBLOCK_HASH=\"$(printf '%s\\n' \"$ACCOUNT_SUMMARY\" | jq -r '.block_hash')\"\nSTORAGE_USAGE=\"$(printf '%s\\n' \"$ACCOUNT_SUMMARY\" | jq -r '.storage_usage')\"\n\nprintf 'block_hash=%s\\nstorage_usage=%s\\n' \"$BLOCK_HASH\" \"$STORAGE_USAGE\""
    },
    "versions": {
      "current": "2.3.0",
      "policy": "All @fastnear/* packages share one version. The hosted /*.js aliases and bare unpkg URLs resolve to the latest release; pin an exact version in production (for example https://unpkg.com/@fastnear/api@2.3.0/dist/umd/browser.global.js)."
    }
  },
  "families": [
    {
      "id": "rpc",
      "summary": "Canonical NEAR JSON-RPC defaults for direct contract views, account state, and transaction status checks.",
      "authStyle": "query",
      "defaultBaseUrls": {
        "mainnet": "https://rpc.mainnet.fastnear.com/",
        "testnet": "https://rpc.testnet.fastnear.com/"
      },
      "bestFor": [
        "Direct contract view calls with exact method names and args.",
        "Canonical account state and access key reads.",
        "Low-level RPC questions before you need indexed or aggregated surfaces."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "entrypoints": [
        "near.view",
        "near.queryAccount",
        "near.queryAccessKey",
        "near.queryAccessKeyList",
        "near.queryProtocolVersion",
        "near.queryBlock",
        "near.queryTx",
        "near.gasPrice",
        "near.status",
        "near.validators",
        "near.sendTx",
        "near.ft.balance",
        "near.ft.metadata",
        "near.ft.totalSupply",
        "near.ft.storageBalance",
        "near.nft.metadata",
        "near.nft.token",
        "near.nft.forOwner",
        "near.nft.supplyForOwner",
        "near.nft.totalSupply",
        "near.nft.tokens"
      ]
    },
    {
      "id": "api",
      "summary": "FastNear REST aggregations for account holdings, staking, and public-key oriented lookups.",
      "authStyle": "bearer",
      "defaultBaseUrls": {
        "mainnet": "https://api.fastnear.com",
        "testnet": "https://test.api.fastnear.com"
      },
      "bestFor": [
        "Combined account snapshots with fungible tokens, NFTs, and staking.",
        "Public-key-to-account discovery.",
        "Questions where one aggregated response is better than stitching multiple RPC calls."
      ],
      "pagination": {
        "kind": "page_token",
        "requestFields": [
          "page_token"
        ],
        "responseFields": [
          "page_token"
        ],
        "filtersMustStayStable": true
      },
      "entrypoints": [
        "near.api.v1.accountFull",
        "near.api.v1.accountFt",
        "near.api.v1.accountNft",
        "near.api.v1.accountStaking",
        "near.api.v1.publicKey",
        "near.api.v1.publicKeyAll",
        "near.api.v1.ftTop",
        "near.ft.inventory",
        "near.nft.inventory"
      ]
    },
    {
      "id": "tx",
      "summary": "Indexed transaction and receipt lookups for readable execution history by hash, account, or block.",
      "authStyle": "bearer",
      "defaultBaseUrls": {
        "mainnet": "https://tx.main.fastnear.com",
        "testnet": "https://tx.test.fastnear.com"
      },
      "bestFor": [
        "Starting from one transaction hash or receipt id.",
        "Readable execution stories with receipts already joined in.",
        "Recent account or block-centered transaction history queries."
      ],
      "pagination": {
        "kind": "resume_token",
        "requestFields": [
          "resume_token"
        ],
        "responseFields": [
          "resume_token"
        ],
        "filtersMustStayStable": true
      },
      "entrypoints": [
        "near.tx.transactions",
        "near.tx.receipt",
        "near.tx.account",
        "near.tx.block",
        "near.tx.blocks"
      ]
    },
    {
      "id": "transfers",
      "summary": "Asset-movement-focused history for accounts when the question is specifically about transfers, not full execution.",
      "authStyle": "bearer",
      "defaultBaseUrls": {
        "mainnet": "https://transfers.main.fastnear.com",
        "testnet": null
      },
      "bestFor": [
        "Recent transfer feeds for one account.",
        "Asset movement summaries across FT, NFT, and native transfers.",
        "Survey scripting where transfer rows matter more than transaction internals."
      ],
      "pagination": {
        "kind": "resume_token",
        "requestFields": [
          "resume_token"
        ],
        "responseFields": [
          "resume_token"
        ],
        "filtersMustStayStable": true
      },
      "entrypoints": [
        "near.transfers.query"
      ]
    },
    {
      "id": "neardata",
      "summary": "Block and shard documents for recent chain-state inspection without reconstructing shard layouts yourself.",
      "authStyle": "query",
      "defaultBaseUrls": {
        "mainnet": "https://mainnet.neardata.xyz",
        "testnet": "https://testnet.neardata.xyz"
      },
      "bestFor": [
        "Recent block inspection and shard-aware exploration.",
        "Questions about network recency or recent transaction volume.",
        "Walking block-height ranges and chunk layouts."
      ],
      "pagination": {
        "kind": "range",
        "requestFields": [
          "blockHeight",
          "from_block_height",
          "to_block_height"
        ],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "entrypoints": [
        "near.neardata.lastBlockFinal",
        "near.neardata.lastBlockOptimistic",
        "near.neardata.block",
        "near.neardata.blockHeaders",
        "near.neardata.blockShard",
        "near.neardata.blockChunk",
        "near.neardata.blockOptimistic",
        "near.neardata.firstBlock",
        "near.neardata.health"
      ]
    },
    {
      "id": "fastdata.kv",
      "summary": "Indexed key-value history for exact keys, predecessor scans, and account-scoped storage exploration.",
      "authStyle": "bearer",
      "defaultBaseUrls": {
        "mainnet": "https://kv.main.fastnear.com",
        "testnet": "https://kv.test.fastnear.com"
      },
      "bestFor": [
        "Exact-key lookups when you already know the contract, predecessor, and key.",
        "Storage history scans keyed by predecessor or current account.",
        "Questions about SocialDB-style writes and indexed storage history."
      ],
      "pagination": {
        "kind": "resume_token",
        "requestFields": [
          "resume_token"
        ],
        "responseFields": [
          "resume_token"
        ],
        "filtersMustStayStable": true
      },
      "entrypoints": [
        "near.fastdata.kv.getLatestKey",
        "near.fastdata.kv.getHistoryKey",
        "near.fastdata.kv.latestByAccount",
        "near.fastdata.kv.historyByAccount",
        "near.fastdata.kv.latestByPredecessor",
        "near.fastdata.kv.historyByPredecessor",
        "near.fastdata.kv.allByPredecessor",
        "near.fastdata.kv.multi"
      ]
    },
    {
      "id": "wallet",
      "summary": "Browser wallet session and signing surface from @fastnear/wallet: connect, send transactions, sign NEP-413 messages, and sign NEP-366 delegate actions.",
      "authStyle": "wallet-session",
      "defaultBaseUrls": null,
      "bestFor": [
        "Anything that needs a user to approve a signature in their own wallet.",
        "Browser dApps where the key never leaves the wallet.",
        "Sign-in plus proof-of-ownership in a single prompt via signMessageParams."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "entrypoints": [
        "near.recipes.connect",
        "near.recipes.functionCall",
        "near.recipes.transfer",
        "near.recipes.signMessage",
        "nearWallet.connect",
        "nearWallet.disconnect",
        "nearWallet.restore",
        "nearWallet.sendTransaction",
        "nearWallet.sendTransactions",
        "nearWallet.signMessage",
        "nearWallet.signDelegateActions",
        "nearWallet.addFunctionCallKey"
      ]
    }
  ],
  "runtimes": {
    "api": {
      "config": [
        "near.config({ networkId })",
        "near.config({ apiKey })",
        "near.config({ nodeUrl })"
      ],
      "types": [
        "FastNearRecipeDiscoveryEntry",
        "AccessKeyListResponse",
        "RpcStatusResponse",
        "SendTxParams",
        "FastNearApiV1AccountFullResponse",
        "FastNearApiV1AccountFtResponse",
        "FastNearApiV1AccountNftResponse",
        "FastNearApiV1AccountStakingResponse",
        "FastNearApiV1PublicKeyResponse",
        "FastNearApiV1PublicKeyAllResponse",
        "FastNearApiV1FtTopResponse",
        "FastNearTxTransactionsResponse",
        "FastNearTxReceiptResponse",
        "FastNearTxAccountResponse",
        "FastNearTxBlockResponse",
        "FastNearTxBlocksResponse",
        "FastNearTransfersQueryResponse",
        "FastNearNeardataLastBlockFinalResponse",
        "FastNearNeardataLastBlockOptimisticResponse",
        "FastNearNeardataBlockResponse",
        "FastNearNeardataBlockHeadersResponse",
        "FastNearNeardataBlockShardResponse",
        "FastNearNeardataBlockChunkResponse",
        "FastNearNeardataBlockOptimisticResponse",
        "FastNearNeardataFirstBlockResponse",
        "FastNearNeardataHealthResponse",
        "FastNearKvGetLatestKeyResponse",
        "FastNearKvGetHistoryKeyResponse",
        "FastNearKvLatestByAccountResponse",
        "FastNearKvHistoryByAccountResponse",
        "FastNearKvLatestByPredecessorResponse",
        "FastNearKvHistoryByPredecessorResponse",
        "FastNearKvAllByPredecessorResponse",
        "FastNearKvMultiResponse"
      ],
      "recipes": [
        "near.recipes.viewContract",
        "near.recipes.viewAccount",
        "near.recipes.connect",
        "near.recipes.functionCall",
        "near.recipes.transfer",
        "near.recipes.signMessage",
        "near.recipes.connect",
        "near.recipes.connect",
        "near.recipes.functionCall"
      ],
      "explain": [
        "near.explain.action",
        "near.explain.tx",
        "near.explain.error"
      ],
      "lowLevel": [
        "near.view",
        "near.view.many",
        "near.batch",
        "near.queryAccount",
        "near.queryAccessKey",
        "near.queryAccessKeyList",
        "near.queryProtocolVersion",
        "near.queryTx",
        "near.sendTx",
        "near.requestSignIn",
        "near.signMessage",
        "near.ft.balance",
        "near.ft.metadata",
        "near.ft.totalSupply",
        "near.ft.storageBalance",
        "near.ft.inventory",
        "near.nft.metadata",
        "near.nft.token",
        "near.nft.forOwner",
        "near.nft.supplyForOwner",
        "near.nft.totalSupply",
        "near.nft.tokens",
        "near.nft.inventory",
        "near.api.v1.accountFull",
        "near.api.v1.accountFt",
        "near.api.v1.accountNft",
        "near.api.v1.accountStaking",
        "near.api.v1.publicKey",
        "near.api.v1.publicKeyAll",
        "near.api.v1.ftTop",
        "near.tx.transactions",
        "near.tx.receipt",
        "near.tx.account",
        "near.tx.block",
        "near.tx.blocks",
        "near.transfers.query",
        "near.neardata.lastBlockFinal",
        "near.neardata.lastBlockOptimistic",
        "near.neardata.block",
        "near.neardata.blockHeaders",
        "near.neardata.blockShard",
        "near.neardata.blockChunk",
        "near.neardata.blockOptimistic",
        "near.neardata.firstBlock",
        "near.neardata.health",
        "near.fastdata.kv.getLatestKey",
        "near.fastdata.kv.getHistoryKey",
        "near.fastdata.kv.latestByAccount",
        "near.fastdata.kv.historyByAccount",
        "near.fastdata.kv.latestByPredecessor",
        "near.fastdata.kv.historyByPredecessor",
        "near.fastdata.kv.allByPredecessor",
        "near.fastdata.kv.multi"
      ]
    }
  },
  "recipes": [
    {
      "id": "view-contract",
      "title": "What does this contract method return?",
      "summary": "Start with one view call when you already know the contract, method, and arguments.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.recipes.viewContract",
      "example": {
        "contractId": "berryclub.ek.near",
        "methodName": "get_account",
        "args": {
          "account_id": "root.near"
        }
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst result = await near.recipes.viewContract({\n  contractId: \"berryclub.ek.near\",\n  methodName: \"get_account\",\n  args: { account_id: \"root.near\" },\n});\n\nnear.print({\n  account_id: result.account_id,\n  avocado_balance: result.avocado_balance,\n  num_pixels: result.num_pixels,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\nARGS_BASE64=\"$(jq -nc --arg account_id \"$ACCOUNT_ID\" '{account_id: $account_id}' | base64 | tr -d '\\n')\"\n\ncurl -sS \"https://rpc.mainnet.fastnear.com?apiKey=$FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg args \"$ARGS_BASE64\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{\n      request_type:\"call_function\",\n      finality:\"final\",\n      account_id:\"berryclub.ek.near\",\n      method_name:\"get_account\",\n      args_base64:$args\n    }\n  }')\"   | jq '.result.result | implode | fromjson | {account_id, avocado_balance, num_pixels}'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const result = await near.recipes.viewContract({\n  contractId: \"berryclub.ek.near\",\n  methodName: \"get_account\",\n  args: { account_id: \"root.near\" },\n});\n\nnear.print({\n  account_id: result.account_id,\n  avocado_balance: result.avocado_balance,\n  num_pixels: result.num_pixels,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst result = await near.recipes.viewContract({\n  contractId: \"berryclub.ek.near\",\n  methodName: \"get_account\",\n  args: { account_id: \"root.near\" },\n});\n\nnear.print({\n  account_id: result.account_id,\n  avocado_balance: result.avocado_balance,\n  num_pixels: result.num_pixels,\n});"
        }
      ],
      "service": "rpc",
      "returns": "BerryClubAccountView",
      "outputKeys": [
        "account_id",
        "avocado_balance",
        "num_pixels"
      ],
      "responseNotes": [
        "This recipe returns the parsed JSON value from the contract method, not the raw RPC wrapper.",
        "Use the curl + jq variant when you want to inspect the encoded args or the raw RPC envelope."
      ],
      "chooseWhen": [
        "Choose this when you already know the exact contract method and want the smallest answer quickly.",
        "Stay on RPC when the question is still about one direct view call rather than indexed history."
      ],
      "followUps": [
        "If the method output looks wrong, compare it with the canonical account state from near.recipes.viewAccount.",
        "If you need a broader ownership snapshot, move to near.api.v1.accountFull."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "view-account",
        "account-full"
      ]
    },
    {
      "id": "view-account",
      "title": "What does this account look like on chain?",
      "summary": "Use canonical RPC account state when the question is still about one account record.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.recipes.viewAccount",
      "example": {
        "accountId": "root.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst account = await near.recipes.viewAccount(\"root.near\");\n\nconst { amount, locked, storage_usage, block_height, block_hash } = account;\n\nnear.print({\n  amount,\n  locked,\n  storage_usage,\n  block_height,\n  block_hash,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\n\ncurl -sS \"https://rpc.mainnet.fastnear.com?apiKey=$FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg account_id \"$ACCOUNT_ID\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{request_type:\"view_account\",account_id:$account_id,finality:\"final\"}\n  }')\"   | jq '.result | {amount, locked, storage_usage, block_height, block_hash}'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const account = await near.recipes.viewAccount(\"root.near\");\n\nconst { amount, locked, storage_usage, block_height, block_hash } = account;\n\nnear.print({\n  amount,\n  locked,\n  storage_usage,\n  block_height,\n  block_hash,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst account = await near.recipes.viewAccount(\"root.near\");\n\nconst { amount, locked, storage_usage, block_height, block_hash } = account;\n\nnear.print({\n  amount,\n  locked,\n  storage_usage,\n  block_height,\n  block_hash,\n});"
        }
      ],
      "service": "rpc",
      "returns": "RpcViewAccountResponse",
      "outputKeys": [
        "amount",
        "locked",
        "storage_usage",
        "block_height",
        "block_hash"
      ],
      "responseNotes": [
        "This is the canonical on-chain account record from JSON-RPC.",
        "The snippet keeps the object work in JS and emits only the fields most useful for survey scripting."
      ],
      "chooseWhen": [
        "Choose this when the question is about one account's chain state rather than token holdings or transfers.",
        "Use this before reaching for aggregations if you need the raw account state answer first."
      ],
      "followUps": [
        "If the account is active but you need holdings, switch to near.api.v1.accountFull.",
        "If you need recent transfer activity, continue with near.transfers.query."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "account-full",
        "transfers-query"
      ]
    },
    {
      "id": "inspect-transaction",
      "title": "What happened in this transaction?",
      "summary": "Start with the indexed transaction family when all you have is the hash and you want the readable story.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.tx.transactions",
      "example": {
        "txHashes": [
          "7ZKnhzt2MqMNmsk13dV8GAjGu3Db8aHzSBHeNeu9MJCq"
        ]
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst tx = await near.recipes.inspectTransaction(\n  \"7ZKnhzt2MqMNmsk13dV8GAjGu3Db8aHzSBHeNeu9MJCq\"\n);\n\nnear.print(\n  tx\n    ? {\n        hash: tx.transaction.hash,\n        signer_id: tx.transaction.signer_id,\n        receiver_id: tx.transaction.receiver_id,\n        included_block_height: tx.execution_outcome.block_height,\n        receipt_count: tx.receipts.length,\n      }\n    : null\n);\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nTX_HASH=7ZKnhzt2MqMNmsk13dV8GAjGu3Db8aHzSBHeNeu9MJCq\n\ncurl -sS \"https://tx.main.fastnear.com/v0/transactions\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg tx_hash \"$TX_HASH\" '{tx_hashes: [$tx_hash]}')\"   | jq '{\n      hash: .transactions[0].transaction.hash,\n      signer_id: .transactions[0].transaction.signer_id,\n      receiver_id: .transactions[0].transaction.receiver_id,\n      included_block_height: .transactions[0].execution_outcome.block_height,\n      receipt_count: (.transactions[0].receipts | length)\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const tx = await near.recipes.inspectTransaction(\n  \"7ZKnhzt2MqMNmsk13dV8GAjGu3Db8aHzSBHeNeu9MJCq\"\n);\n\nnear.print(\n  tx\n    ? {\n        hash: tx.transaction.hash,\n        signer_id: tx.transaction.signer_id,\n        receiver_id: tx.transaction.receiver_id,\n        included_block_height: tx.execution_outcome.block_height,\n        receipt_count: tx.receipts.length,\n      }\n    : null\n);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst tx = await near.recipes.inspectTransaction(\n  \"7ZKnhzt2MqMNmsk13dV8GAjGu3Db8aHzSBHeNeu9MJCq\"\n);\n\nnear.print(\n  tx\n    ? {\n        hash: tx.transaction.hash,\n        signer_id: tx.transaction.signer_id,\n        receiver_id: tx.transaction.receiver_id,\n        included_block_height: tx.execution_outcome.block_height,\n        receipt_count: tx.receipts.length,\n      }\n    : null\n);"
        }
      ],
      "service": "tx",
      "returns": "FastNearTxTransactionsResponse",
      "outputKeys": [
        "transactions[].transaction.hash",
        "transactions[].transaction.signer_id",
        "transactions[].transaction.receiver_id",
        "transactions[].execution_outcome.block_height",
        "transactions[].receipts"
      ],
      "responseNotes": [
        "The low-level tx family returns raw indexed JSON with receipts already attached.",
        "This recipe narrows that response to the one transaction row and prints a compact human-readable summary."
      ],
      "chooseWhen": [
        "Choose this when the only durable identifier you have is the transaction hash.",
        "Prefer this over transfers when you need the execution story, receipts, or included block details."
      ],
      "followUps": [
        "If you care only about asset movement, pivot to near.transfers.query.",
        "If you need a block-centered history scan, continue with near.tx.account or near.tx.blocks."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "transfers-query",
        "last-block-final"
      ]
    },
    {
      "id": "account-full",
      "title": "What does this account own?",
      "summary": "Use the FastNear account aggregator when the question is about holdings, NFTs, or staking in one response.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.api.v1.accountFull",
      "example": {
        "accountId": "root.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst account = await near.api.v1.accountFull({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  account_id: account.account_id,\n  near_balance_yocto: account.state.balance,\n  ft_contracts: account.tokens.length,\n  nft_contracts: account.nfts.length,\n  staking_pool_contracts: account.pools.length,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\n\ncurl -sS \"https://api.fastnear.com/v1/account/$ACCOUNT_ID/full\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   | jq '{\n      account_id,\n      near_balance_yocto: .state.balance,\n      ft_contracts: (.tokens | length),\n      nft_contracts: (.nfts | length),\n      staking_pool_contracts: (.pools | length)\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const account = await near.api.v1.accountFull({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  account_id: account.account_id,\n  near_balance_yocto: account.state.balance,\n  ft_contracts: account.tokens.length,\n  nft_contracts: account.nfts.length,\n  staking_pool_contracts: account.pools.length,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst account = await near.api.v1.accountFull({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  account_id: account.account_id,\n  near_balance_yocto: account.state.balance,\n  ft_contracts: account.tokens.length,\n  nft_contracts: account.nfts.length,\n  staking_pool_contracts: account.pools.length,\n});"
        }
      ],
      "service": "api",
      "returns": "FastNearApiV1AccountFullResponse",
      "outputKeys": [
        "account_id",
        "state.balance",
        "tokens",
        "nfts",
        "pools"
      ],
      "responseNotes": [
        "This is the aggregated account surface for holdings and staking, not a raw RPC account object.",
        "It is the best one-response answer when the task is portfolio-style discovery."
      ],
      "chooseWhen": [
        "Choose this when you want holdings, NFTs, and staking without stitching multiple calls together.",
        "Use it after a canonical RPC account check when the next question becomes 'what does this account own?'."
      ],
      "followUps": [
        "If you need movement history instead of holdings, continue with near.transfers.query.",
        "If you need one exact contract state read, go back to near.recipes.viewContract."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "view-account",
        "transfers-query"
      ]
    },
    {
      "id": "transfers-query",
      "title": "What is this account's recent transfer activity?",
      "summary": "Use the transfers family when the question is specifically about asset movement, not the broader execution story.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.transfers.query",
      "example": {
        "accountId": "root.near",
        "desc": true,
        "limit": 5
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst feed = await near.transfers.query({\n  accountId: \"root.near\",\n  desc: true,\n  limit: 5,\n});\n\nnear.print({\n  recent: (feed.transfers || []).map((entry) => ({\n    block_height: entry.block_height,\n    asset_id: entry.asset_id,\n    human_amount: entry.human_amount,\n    other_account_id: entry.other_account_id,\n    transfer_type: entry.transfer_type,\n    tx: entry.transaction_id,\n  })),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\n\ncurl -sS \"https://transfers.main.fastnear.com/v0/transfers\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg account_id \"$ACCOUNT_ID\" '{account_id: $account_id, desc: true, limit: 5}')\"   | jq '{\n      recent: [.transfers[] | {\n        block_height,\n        asset_id,\n        human_amount,\n        other_account_id,\n        transfer_type,\n        tx: .transaction_id\n      }]\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const feed = await near.transfers.query({\n  accountId: \"root.near\",\n  desc: true,\n  limit: 5,\n});\n\nnear.print({\n  recent: (feed.transfers || []).map((entry) => ({\n    block_height: entry.block_height,\n    asset_id: entry.asset_id,\n    human_amount: entry.human_amount,\n    other_account_id: entry.other_account_id,\n    transfer_type: entry.transfer_type,\n    tx: entry.transaction_id,\n  })),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst feed = await near.transfers.query({\n  accountId: \"root.near\",\n  desc: true,\n  limit: 5,\n});\n\nnear.print({\n  recent: (feed.transfers || []).map((entry) => ({\n    block_height: entry.block_height,\n    asset_id: entry.asset_id,\n    human_amount: entry.human_amount,\n    other_account_id: entry.other_account_id,\n    transfer_type: entry.transfer_type,\n    tx: entry.transaction_id,\n  })),\n});"
        }
      ],
      "service": "transfers",
      "returns": "FastNearTransfersQueryResponse",
      "outputKeys": [
        "transfers[].block_height",
        "transfers[].asset_id",
        "transfers[].human_amount",
        "transfers[].other_account_id",
        "transfers[].transaction_id",
        "resume_token"
      ],
      "responseNotes": [
        "Transfers answers the asset-movement question directly and returns raw rows plus resume-token pagination when available.",
        "It is intentionally narrower than the tx family and better suited to feed-style scripting."
      ],
      "chooseWhen": [
        "Choose this when the question is about who sent what asset and when.",
        "Prefer this over near.tx when you do not need receipt details or execution outcomes."
      ],
      "followUps": [
        "If one transfer row needs a deeper execution story, pivot to near.tx.transactions with the related hash.",
        "If you need holdings instead of movement, switch to near.api.v1.accountFull."
      ],
      "pagination": {
        "kind": "resume_token",
        "requestFields": [
          "resume_token"
        ],
        "responseFields": [
          "resume_token"
        ],
        "filtersMustStayStable": true
      },
      "relatedRecipes": [
        "inspect-transaction",
        "account-full"
      ]
    },
    {
      "id": "last-block-final",
      "title": "What block is NEAR on right now?",
      "summary": "Use the NEAR Data family when you want a recent block document without stitching shards together yourself.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.neardata.lastBlockFinal",
      "example": {},
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst block = await near.neardata.lastBlockFinal();\n\n// shard.chunk is null when a shard missed this block — guard before reading.\nnear.print({\n  height: block.block.header.height,\n  timestamp_nanosec: block.block.header.timestamp_nanosec,\n  txs_per_shard: block.shards.map((shard) => ({\n    shard_id: shard.shard_id,\n    tx_count: shard.chunk?.transactions.length ?? 0,\n  })),\n  total_txs: block.shards.reduce(\n    (count, shard) => count + (shard.chunk?.transactions.length ?? 0),\n    0\n  ),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\ncurl -sSL \"https://mainnet.neardata.xyz/v0/last_block/final?apiKey=$FASTNEAR_API_KEY\"   | jq '{\n      height: .block.header.height,\n      timestamp_nanosec: .block.header.timestamp_nanosec,\n      txs_per_shard: [.shards[] | {shard_id, tx_count: (.chunk.transactions | length)}],\n      total_txs: ([.shards[].chunk.transactions[]?] | length)\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const block = await near.neardata.lastBlockFinal();\n\n// shard.chunk is null when a shard missed this block — guard before reading.\nnear.print({\n  height: block.block.header.height,\n  timestamp_nanosec: block.block.header.timestamp_nanosec,\n  txs_per_shard: block.shards.map((shard) => ({\n    shard_id: shard.shard_id,\n    tx_count: shard.chunk?.transactions.length ?? 0,\n  })),\n  total_txs: block.shards.reduce(\n    (count, shard) => count + (shard.chunk?.transactions.length ?? 0),\n    0\n  ),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst block = await near.neardata.lastBlockFinal();\n\n// shard.chunk is null when a shard missed this block — guard before reading.\nnear.print({\n  height: block.block.header.height,\n  timestamp_nanosec: block.block.header.timestamp_nanosec,\n  txs_per_shard: block.shards.map((shard) => ({\n    shard_id: shard.shard_id,\n    tx_count: shard.chunk?.transactions.length ?? 0,\n  })),\n  total_txs: block.shards.reduce(\n    (count, shard) => count + (shard.chunk?.transactions.length ?? 0),\n    0\n  ),\n});"
        }
      ],
      "service": "neardata",
      "returns": "FastNearNeardataLastBlockFinalResponse",
      "outputKeys": [
        "block.header.height",
        "block.header.timestamp_nanosec",
        "shards[].shard_id",
        "shards[].chunk.transactions"
      ],
      "responseNotes": [
        "NEAR Data returns block documents with shard content already grouped for block-level inspection.",
        "This recipe highlights the smallest useful block recency summary while keeping the full response available in JS."
      ],
      "chooseWhen": [
        "Choose this when the question starts with recent block recency or transaction volume.",
        "Use the family-level block endpoints when you want to walk heights or inspect one shard or chunk next."
      ],
      "followUps": [
        "If one transaction in the block matters, continue with near.tx.transactions.",
        "If you need a specific historical block, move to near.neardata.block or near.neardata.blockChunk."
      ],
      "pagination": {
        "kind": "range",
        "requestFields": [
          "blockHeight",
          "from_block_height",
          "to_block_height"
        ],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "inspect-transaction"
      ]
    },
    {
      "id": "kv-latest-key",
      "title": "What is the latest indexed value for this exact key?",
      "summary": "Start narrow with KV FastData when you already know the contract, predecessor, and exact storage key.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.fastdata.kv.getLatestKey",
      "example": {
        "currentAccountId": "social.near",
        "predecessorId": "james.near",
        "key": "graph/follow/sleet.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst result = await near.fastdata.kv.getLatestKey({\n  currentAccountId: \"social.near\",\n  predecessorId: \"james.near\",\n  key: \"graph/follow/sleet.near\",\n});\n\nconst latest = result.entries?.[0] || null;\n\nnear.print({\n  latest: latest\n    ? {\n        current_account_id: latest.current_account_id,\n        predecessor_id: latest.predecessor_id,\n        block_height: latest.block_height,\n        key: latest.key,\n        value: latest.value,\n      }\n    : null,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nCURRENT_ACCOUNT_ID=social.near\nPREDECESSOR_ID=james.near\nKEY='graph/follow/sleet.near'\n\nENCODED_KEY=\"$(jq -rn --arg key \"$KEY\" '$key | @uri')\"\n\ncurl -sS \"https://kv.main.fastnear.com/v0/latest/$CURRENT_ACCOUNT_ID/$PREDECESSOR_ID/$ENCODED_KEY\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   | jq '{\n      latest: (\n        .entries[0]\n        | {\n            current_account_id,\n            predecessor_id,\n            block_height,\n            key,\n            value\n          }\n      )\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const result = await near.fastdata.kv.getLatestKey({\n  currentAccountId: \"social.near\",\n  predecessorId: \"james.near\",\n  key: \"graph/follow/sleet.near\",\n});\n\nconst latest = result.entries?.[0] || null;\n\nnear.print({\n  latest: latest\n    ? {\n        current_account_id: latest.current_account_id,\n        predecessor_id: latest.predecessor_id,\n        block_height: latest.block_height,\n        key: latest.key,\n        value: latest.value,\n      }\n    : null,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst result = await near.fastdata.kv.getLatestKey({\n  currentAccountId: \"social.near\",\n  predecessorId: \"james.near\",\n  key: \"graph/follow/sleet.near\",\n});\n\nconst latest = result.entries?.[0] || null;\n\nnear.print({\n  latest: latest\n    ? {\n        current_account_id: latest.current_account_id,\n        predecessor_id: latest.predecessor_id,\n        block_height: latest.block_height,\n        key: latest.key,\n        value: latest.value,\n      }\n    : null,\n});"
        }
      ],
      "service": "fastdata.kv",
      "returns": "FastNearKvGetLatestKeyResponse",
      "outputKeys": [
        "entries[].current_account_id",
        "entries[].predecessor_id",
        "entries[].block_height",
        "entries[].key",
        "entries[].value"
      ],
      "responseNotes": [
        "KV FastData keeps the exact indexed storage history question narrow and fast when you already know the key.",
        "The raw response keeps the full entry list; the example snippet extracts the most informative first entry."
      ],
      "chooseWhen": [
        "Choose this when you already know the exact key and want the latest indexed value immediately.",
        "Use the broader history or predecessor scans only after this exact-key lookup stops being enough."
      ],
      "followUps": [
        "If you need history for the same key, continue with near.fastdata.kv.getHistoryKey.",
        "If you only know the predecessor and need discovery, continue with near.fastdata.kv.allByPredecessor."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "view-contract"
      ]
    },
    {
      "id": "connect-wallet",
      "title": "How do I connect a wallet?",
      "summary": "Open the wallet picker and attach a signer to the FastNear runtime.",
      "network": "mainnet",
      "auth": "wallet",
      "api": "near.recipes.connect",
      "example": {
        "contractId": "berryclub.ek.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Opening the wallet picker needs a browser environment.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const result = await near.recipes.connect({\n  contractId: \"berryclub.ek.near\",\n});\n\nnear.print(result ?? near.selected());"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst result = await near.recipes.connect({\n  contractId: \"berryclub.ek.near\",\n});\n\nnear.print(result ?? near.selected());"
        }
      ],
      "service": "wallet",
      "returns": "{ accountId: string } | undefined",
      "outputKeys": [
        "accountId"
      ],
      "responseNotes": [
        "Wallet-backed recipes are browser-first because they need an interactive signer.",
        "This recipe is the smallest explicit connect step before sending transactions or signing messages."
      ],
      "chooseWhen": [
        "Choose this when the task crosses from read-only inspection into user-approved signing.",
        "Use it once per browser session before function calls, transfers, or message signatures."
      ],
      "followUps": [
        "After connecting, send one contract action with near.recipes.functionCall.",
        "If the next step is a simple NEAR payment, continue with near.recipes.transfer."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "function-call",
        "transfer",
        "sign-message",
        "sign-delegate-actions"
      ]
    },
    {
      "id": "function-call",
      "title": "How do I send one function call?",
      "summary": "Sign and broadcast a single contract call with readable gas units.",
      "network": "mainnet",
      "auth": "wallet",
      "api": "near.recipes.functionCall",
      "example": {
        "receiverId": "berryclub.ek.near",
        "methodName": "draw",
        "args": {
          "pixels": [
            {
              "x": 10,
              "y": 20,
              "color": 65280
            }
          ]
        },
        "gas": "100 Tgas",
        "deposit": "0"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Signing and broadcasting a contract call needs a wallet session.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const cu = near.utils.convertUnit;\n\nconst result = await near.recipes.functionCall({\n  receiverId: \"berryclub.ek.near\",\n  methodName: \"draw\",\n  args: {\n    pixels: [{ x: 10, y: 20, color: 65280 }],\n  },\n  gas: cu(\"100 Tgas\"),\n  deposit: \"0\",\n});\n\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst cu = near.utils.convertUnit;\n\nconst result = await near.recipes.functionCall({\n  receiverId: \"berryclub.ek.near\",\n  methodName: \"draw\",\n  args: {\n    pixels: [{ x: 10, y: 20, color: 65280 }],\n  },\n  gas: cu(\"100 Tgas\"),\n  deposit: \"0\",\n});\n\nnear.print(result);"
        }
      ],
      "service": "wallet",
      "returns": "WalletTransactionResult",
      "outputKeys": [
        "transaction",
        "outcomes",
        "status"
      ],
      "responseNotes": [
        "This is the thinnest wallet-backed transaction recipe and keeps the action declaration explicit.",
        "The example uses readable unit conversion before handing the transaction to the runtime."
      ],
      "chooseWhen": [
        "Choose this when you need one contract call and already know the receiver, method, and args.",
        "Prefer this recipe over the lower-level sendTx path when you want the smallest wallet-backed API surface."
      ],
      "followUps": [
        "If the user only needs a native NEAR transfer, continue with near.recipes.transfer.",
        "If you want to preview the action before signing, use near.explain.tx on the same action list."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "transfer",
        "sign-message"
      ]
    },
    {
      "id": "transfer",
      "title": "How do I transfer NEAR?",
      "summary": "Send a simple NEAR transfer with a wallet-backed signature.",
      "network": "mainnet",
      "auth": "wallet+deposit",
      "api": "near.recipes.transfer",
      "example": {
        "receiverId": "escrow.ai.near",
        "amount": "0.1 NEAR"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Sending NEAR needs a wallet-backed signature flow.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const cu = near.utils.convertUnit;\n\nconst result = await near.recipes.transfer({\n  receiverId: \"escrow.ai.near\",\n  amount: cu(\"0.1 NEAR\"),\n});\n\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst cu = near.utils.convertUnit;\n\nconst result = await near.recipes.transfer({\n  receiverId: \"escrow.ai.near\",\n  amount: cu(\"0.1 NEAR\"),\n});\n\nnear.print(result);"
        }
      ],
      "service": "wallet",
      "returns": "WalletTransactionResult",
      "outputKeys": [
        "transaction",
        "outcomes",
        "status"
      ],
      "responseNotes": [
        "This recipe keeps a simple NEAR transfer readable without constructing the action list manually.",
        "The transaction still goes through the same wallet-backed approval flow as other signing tasks."
      ],
      "chooseWhen": [
        "Choose this when the task is a plain NEAR payment and not a contract method call.",
        "Use the function-call recipe instead when the receiver expects method args or custom gas settings."
      ],
      "followUps": [
        "If you want to explain the transfer before sending it, use near.explain.tx with a Transfer action.",
        "If the next task is another signed action, keep the same wallet session and continue with near.recipes.functionCall."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "function-call"
      ]
    },
    {
      "id": "sign-message",
      "title": "How do I sign a message?",
      "summary": "Request a wallet-backed NEP-413 signature for an app message.",
      "network": "mainnet",
      "auth": "wallet",
      "api": "near.recipes.signMessage",
      "example": {
        "message": "Sign in to FastNear Berry Club"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Message signing depends on a connected wallet provider.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const result = await near.recipes.signMessage({\n  message: \"Sign in to FastNear Berry Club\",\n  recipient: window.location.host,\n  nonce: crypto.getRandomValues(new Uint8Array(32)),\n});\n\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst result = await near.recipes.signMessage({\n  message: \"Sign in to FastNear Berry Club\",\n  recipient: window.location.host,\n  nonce: crypto.getRandomValues(new Uint8Array(32)),\n});\n\nnear.print(result);"
        }
      ],
      "service": "wallet",
      "returns": "WalletMessageSignatureResult",
      "outputKeys": [
        "signature",
        "accountId",
        "publicKey"
      ],
      "responseNotes": [
        "This is the wallet-backed message-signing path for NEP-413 style app messages.",
        "It stays separate from transaction recipes because no chain write is involved."
      ],
      "chooseWhen": [
        "Choose this when you need user-approved application auth without broadcasting a transaction.",
        "Prefer this over functionCall or transfer when the task is strictly off-chain signing."
      ],
      "followUps": [
        "If you need to connect the wallet first, start with near.recipes.connect.",
        "If the flow turns into an on-chain action, move to near.recipes.functionCall or near.recipes.transfer."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "sign-delegate-actions"
      ]
    },
    {
      "id": "sign-delegate-actions",
      "title": "How do I sign delegate actions for gasless transactions?",
      "summary": "Sign NEP-366 delegate actions via the connected wallet so a relayer can submit them on-chain without the user paying gas.",
      "network": "mainnet",
      "auth": "wallet",
      "api": "nearWallet.signDelegateActions",
      "example": {
        "delegateActions": [
          {
            "receiverId": "berryclub.ek.near",
            "actions": [
              {
                "type": "FunctionCall",
                "methodName": "draw",
                "args": {
                  "pixels": [
                    {
                      "x": 10,
                      "y": 20,
                      "color": 65280
                    }
                  ]
                },
                "gas": "100 Tgas",
                "deposit": "0"
              }
            ]
          }
        ]
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Signing delegate actions depends on a connected wallet provider.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const cu = near.utils.convertUnit;\n\nconst result = await nearWallet.signDelegateActions({\n  delegateActions: [\n    {\n      receiverId: \"berryclub.ek.near\",\n      actions: [\n        {\n          type: \"FunctionCall\",\n          methodName: \"draw\",\n          args: { pixels: [{ x: 10, y: 20, color: 65280 }] },\n          gas: cu(\"100 Tgas\"),\n          deposit: \"0\",\n        },\n      ],\n    },\n  ],\n});\n\nnear.print({\n  count: result.signedDelegateActions.length,\n  first_delegate_borsh_base64:\n    result.signedDelegateActions[0]?.borshSerializedBase64,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst cu = near.utils.convertUnit;\n\nconst result = await nearWallet.signDelegateActions({\n  delegateActions: [\n    {\n      receiverId: \"berryclub.ek.near\",\n      actions: [\n        {\n          type: \"FunctionCall\",\n          methodName: \"draw\",\n          args: { pixels: [{ x: 10, y: 20, color: 65280 }] },\n          gas: cu(\"100 Tgas\"),\n          deposit: \"0\",\n        },\n      ],\n    },\n  ],\n});\n\nnear.print({\n  count: result.signedDelegateActions.length,\n  first_delegate_borsh_base64:\n    result.signedDelegateActions[0]?.borshSerializedBase64,\n});"
        }
      ],
      "service": "wallet",
      "returns": "SignDelegateActionsResponse",
      "outputKeys": [
        "signedDelegateActions[].borshSerializedBase64"
      ],
      "responseNotes": [
        "The canonical result is { borshSerializedBase64: string }; legacy structured delegates and bare base64 strings remain in the public union for compatibility.",
        "Returns signed delegate actions that a relayer can submit on-chain, enabling gasless transactions for the user.",
        "Relay it directly: near.relayDelegate({ signedDelegate: result.signedDelegateActions[0] }). Under the hood near.utils.parseSignedDelegate turns the wallet's borshSerializedBase64 into the { delegateAction, signature } shape relayDelegate needs — decoding the borsh yourself via near.exp.borsh.deserialize(near.exp.borshSchema.SignedDelegate, bytes) yields chain-schema action shapes the action builders reject with 'Not implemented action: undefined', so prefer parseSignedDelegate.",
        "The wallet must support the signDelegateActions feature (check WalletFeatures.signDelegateActions).",
        "Requests that include blockHeightTtl additionally require WalletFeatures.signDelegateActionsWithTtl."
      ],
      "chooseWhen": [
        "Choose this when building gasless or relay-based flows where a third party submits the transaction on the user's behalf.",
        "Prefer sign-message when you only need an off-chain signature, or function-call when the user can pay gas directly."
      ],
      "followUps": [
        "Relay the result with near.relayDelegate({ signedDelegate: result.signedDelegateActions[0], relayerSigner, relayerId }) to submit it on-chain without the signer paying gas.",
        "To inspect or transform the delegate first, near.utils.parseSignedDelegate(result.signedDelegateActions[0]) returns the { delegateAction, signature } pair (plus borshBase64).",
        "If the flow does not need a relayer, use near.recipes.functionCall for a standard wallet-signed transaction instead."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "sign-message",
        "function-call"
      ]
    },
    {
      "id": "connect-and-sign-message",
      "title": "How do I connect a wallet and sign a message in one step?",
      "summary": "Combine sign-in and NEP-413 message signing into a single wallet popup instead of two.",
      "network": "mainnet",
      "auth": "wallet",
      "api": "near.recipes.connect",
      "example": {
        "contractId": "berryclub.ek.near",
        "signMessageParams": {
          "message": "Sign in to FastNear Berry Club",
          "recipient": "example.com",
          "nonce": "(32-byte Uint8Array)"
        }
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Connecting and signing a message needs a browser environment with a wallet.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const result = await near.recipes.connect({\n  contractId: \"berryclub.ek.near\",\n  signMessageParams: {\n    message: \"Sign in to FastNear Berry Club\",\n    recipient: window.location.host,\n    nonce: crypto.getRandomValues(new Uint8Array(32)),\n  },\n});\n\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"mainnet\",\n  contractId: \"berryclub.ek.near\",\n});\n\nconst result = await near.recipes.connect({\n  contractId: \"berryclub.ek.near\",\n  signMessageParams: {\n    message: \"Sign in to FastNear Berry Club\",\n    recipient: window.location.host,\n    nonce: crypto.getRandomValues(new Uint8Array(32)),\n  },\n});\n\nnear.print(result);"
        }
      ],
      "service": "wallet",
      "returns": "{ accountId: string; publicKey?: string; signedMessage?: SignedMessage } | undefined",
      "outputKeys": [
        "accountId",
        "signedMessage.accountId",
        "signedMessage.publicKey",
        "signedMessage.signature"
      ],
      "responseNotes": [
        "signedMessage is only present when signMessageParams was supplied and the wallet completed both steps.",
        "The wallet picker is filtered to wallets advertising the signInAndSignMessage feature, so fewer wallets are offered than a plain connect.",
        "Read the signing key from signedMessage.publicKey — several wallets omit publicKey on the account itself in this flow.",
        "Verify the signature with near.utils.verifyNep413Signature before trusting it as proof of account ownership."
      ],
      "chooseWhen": [
        "Choose this when a session needs both a connected wallet and a proof-of-ownership signature, and you want one prompt rather than two.",
        "Prefer plain connect-wallet when no signature is needed, or sign-message when the wallet is already connected."
      ],
      "followUps": [
        "Verify the returned signature with near.utils.verifyNep413Signature to authenticate the session server-side.",
        "Once connected, send contract actions with near.recipes.functionCall."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "sign-message",
        "function-call"
      ]
    },
    {
      "id": "explain-transaction",
      "title": "How do I build and preview a transaction before signing?",
      "summary": "Declare actions with readable unit gas/deposit and get a stable JSON summary from near.explain.tx — no wallet, no network, no BigInt.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.explain.tx",
      "example": {
        "signerId": "root.near",
        "receiverId": "berryclub.ek.near",
        "actions": [
          {
            "type": "FunctionCall",
            "methodName": "draw",
            "args": {
              "pixels": [
                {
                  "x": 10,
                  "y": 20,
                  "color": 65280
                }
              ]
            },
            "gas": "100 Tgas",
            "deposit": "0"
          }
        ]
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Build actions with readable units — string, number, or bigint all work.\nconst actions = [\n  near.actions.functionCall({\n    methodName: \"draw\",\n    args: { pixels: [{ x: 10, y: 20, color: 65280 }] },\n    gas: \"100 Tgas\",\n    deposit: \"0\",\n  }),\n];\n\n// Preview before signing: a pure, JSON-safe summary — no network, no wallet.\n// Wide integers stay decimal strings, so this never trips on BigInt.\nnear.print(near.explain.tx({\n  signerId: \"root.near\",\n  receiverId: \"berryclub.ek.near\",\n  actions,\n}));\nEOF"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Build actions with readable units — string, number, or bigint all work.\nconst actions = [\n  near.actions.functionCall({\n    methodName: \"draw\",\n    args: { pixels: [{ x: 10, y: 20, color: 65280 }] },\n    gas: \"100 Tgas\",\n    deposit: \"0\",\n  }),\n];\n\n// Preview before signing: a pure, JSON-safe summary — no network, no wallet.\n// Wide integers stay decimal strings, so this never trips on BigInt.\nnear.print(near.explain.tx({\n  signerId: \"root.near\",\n  receiverId: \"berryclub.ek.near\",\n  actions,\n}));"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Build actions with readable units — string, number, or bigint all work.\nconst actions = [\n  near.actions.functionCall({\n    methodName: \"draw\",\n    args: { pixels: [{ x: 10, y: 20, color: 65280 }] },\n    gas: \"100 Tgas\",\n    deposit: \"0\",\n  }),\n];\n\n// Preview before signing: a pure, JSON-safe summary — no network, no wallet.\n// Wide integers stay decimal strings, so this never trips on BigInt.\nnear.print(near.explain.tx({\n  signerId: \"root.near\",\n  receiverId: \"berryclub.ek.near\",\n  actions,\n}));"
        }
      ],
      "service": "api",
      "returns": "ExplainedTransaction",
      "outputKeys": [
        "kind",
        "signerId",
        "receiverId",
        "actionCount",
        "actions"
      ],
      "responseNotes": [
        "near.explain.tx is a pure function — it never opens a wallet or hits the network.",
        "Wide integers (gas, deposit, amounts) are decimal strings in and out; you never need BigInt to build or inspect a transaction.",
        "Gas and deposit are echoed exactly as written, including unit strings like \"100 Tgas\" — convert with near.utils.convertUnit only if you need the yocto value."
      ],
      "chooseWhen": [
        "Choose this to sanity-check exactly what you are about to sign before handing actions to a wallet or sendTx.",
        "Use near.explain.action for a single action, or near.utils.txToJson to JSON-serialize a full signed transaction object."
      ],
      "followUps": [
        "Sign and broadcast the same actions with near.recipes.functionCall (wallet) or sendTx (local key).",
        "See the hosted /transactions explainer for the full construct-and-send flow."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "function-call",
        "transfer",
        "sign-delegate-actions"
      ]
    },
    {
      "id": "ft-balance",
      "title": "What is this account's FT balance?",
      "summary": "Read a NEP-141 token balance with a one-line wrapper that fills in the standard method name.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.ft.balance",
      "example": {
        "contractId": "berryclub.ek.near",
        "accountId": "root.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst balance = await near.ft.balance({\n  contractId: \"berryclub.ek.near\",\n  accountId: \"root.near\",\n});\n\nconst meta = await near.ft.metadata({ contractId: \"berryclub.ek.near\" });\n\nnear.print({\n  raw_balance: balance,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  // scaleDecimal shifts the decimal point on the STRING. Number(balance)\n  // would round anything past 2^53 — most real FT balances.\n  human_amount: near.utils.scaleDecimal(balance, -meta.decimals),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\nARGS_BASE64=\"$(jq -nc --arg account_id \"$ACCOUNT_ID\" '{account_id: $account_id}' | base64 | tr -d '\\n')\"\n\ncurl -sS \"https://rpc.mainnet.fastnear.com?apiKey=$FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg args \"$ARGS_BASE64\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{\n      request_type:\"call_function\",\n      finality:\"final\",\n      account_id:\"berryclub.ek.near\",\n      method_name:\"ft_balance_of\",\n      args_base64:$args\n    }\n  }')\"   | jq -r '.result.result | implode'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const balance = await near.ft.balance({\n  contractId: \"berryclub.ek.near\",\n  accountId: \"root.near\",\n});\n\nconst meta = await near.ft.metadata({ contractId: \"berryclub.ek.near\" });\n\nnear.print({\n  raw_balance: balance,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  // scaleDecimal shifts the decimal point on the STRING. Number(balance)\n  // would round anything past 2^53 — most real FT balances.\n  human_amount: near.utils.scaleDecimal(balance, -meta.decimals),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst balance = await near.ft.balance({\n  contractId: \"berryclub.ek.near\",\n  accountId: \"root.near\",\n});\n\nconst meta = await near.ft.metadata({ contractId: \"berryclub.ek.near\" });\n\nnear.print({\n  raw_balance: balance,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  // scaleDecimal shifts the decimal point on the STRING. Number(balance)\n  // would round anything past 2^53 — most real FT balances.\n  human_amount: near.utils.scaleDecimal(balance, -meta.decimals),\n});"
        }
      ],
      "service": "rpc",
      "returns": "string",
      "outputKeys": [
        "raw_balance",
        "symbol",
        "decimals",
        "human_amount"
      ],
      "responseNotes": [
        "near.ft.balance returns the raw integer balance string from ft_balance_of, scaled by the token's decimals.",
        "Pair with near.ft.metadata to format the human-readable amount in one shot.",
        "Convert raw to human with near.utils.scaleDecimal(raw, -decimals) — it shifts the decimal point on the string and returns an exact decimal string. Number(raw) / 10 ** decimals silently rounds any balance above 2^53, which is most real balances; scaleDecimal also trims trailing zeros, so pad the fraction yourself if you need fixed width."
      ],
      "chooseWhen": [
        "Choose this when you already know the FT contract and want one account's balance.",
        "Use ft-inventory instead when you need every FT balance an account holds."
      ],
      "followUps": [
        "If you need every token the account holds, switch to near.ft.inventory.",
        "If you need a historical balance, add useArchival: true and a blockId — see archival-snapshot."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "ft-metadata",
        "ft-inventory",
        "archival-snapshot"
      ]
    },
    {
      "id": "ft-metadata",
      "title": "What does this NEP-141 token call itself?",
      "summary": "Fetch name, symbol, decimals, and icon for a fungible token in one call.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.ft.metadata",
      "example": {
        "contractId": "berryclub.ek.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst meta = await near.ft.metadata({\n  contractId: \"berryclub.ek.near\",\n});\n\nnear.print({\n  name: meta.name,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  icon_present: !!meta.icon,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nEMPTY_ARGS_BASE64=\"$(printf '{}' | base64)\"\n\ncurl -sS \"https://rpc.mainnet.fastnear.com?apiKey=$FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg args \"$EMPTY_ARGS_BASE64\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{\n      request_type:\"call_function\",\n      finality:\"final\",\n      account_id:\"berryclub.ek.near\",\n      method_name:\"ft_metadata\",\n      args_base64:$args\n    }\n  }')\"   | jq '.result.result | implode | fromjson | {name, symbol, decimals}'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const meta = await near.ft.metadata({\n  contractId: \"berryclub.ek.near\",\n});\n\nnear.print({\n  name: meta.name,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  icon_present: !!meta.icon,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst meta = await near.ft.metadata({\n  contractId: \"berryclub.ek.near\",\n});\n\nnear.print({\n  name: meta.name,\n  symbol: meta.symbol,\n  decimals: meta.decimals,\n  icon_present: !!meta.icon,\n});"
        }
      ],
      "service": "rpc",
      "returns": "{ name: string; symbol: string; decimals: number; icon?: string; reference?: string; reference_hash?: string }",
      "outputKeys": [
        "name",
        "symbol",
        "decimals",
        "icon"
      ],
      "responseNotes": [
        "Wraps the standard NEP-141 ft_metadata view call so the method name does not have to be remembered.",
        "Decimals comes back as a number; multiply or divide raw balances accordingly."
      ],
      "chooseWhen": [
        "Choose this when you need to format a balance, label a token, or display branding.",
        "Pair with ft-balance whenever you also need a human-readable amount."
      ],
      "followUps": [
        "If you also need an account balance, continue with near.ft.balance.",
        "If you want a portfolio view across all tokens, use near.ft.inventory."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "ft-balance",
        "ft-inventory"
      ]
    },
    {
      "id": "ft-inventory",
      "title": "Which fungible tokens does this account hold?",
      "summary": "List every NEP-141 contract the account holds via the FastNear indexer in one call.",
      "network": "mainnet",
      "auth": "bearer",
      "api": "near.ft.inventory",
      "example": {
        "accountId": "root.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.ft.inventory({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  ft_contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 5).map((entry) => ({\n    contract_id: entry.contract_id,\n    balance: entry.balance,\n  })),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\n\ncurl -sS \"https://api.fastnear.com/v1/account/$ACCOUNT_ID/ft\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   | jq '{\n      ft_contract_count: (.tokens | length),\n      preview: [.tokens[0:5][] | {contract_id, balance}]\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.ft.inventory({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  ft_contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 5).map((entry) => ({\n    contract_id: entry.contract_id,\n    balance: entry.balance,\n  })),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.ft.inventory({\n  accountId: \"root.near\",\n});\n\nnear.print({\n  ft_contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 5).map((entry) => ({\n    contract_id: entry.contract_id,\n    balance: entry.balance,\n  })),\n});"
        }
      ],
      "service": "api",
      "returns": "{ tokens: Array<{ contract_id: string; balance: string; last_update_block_height?: number }> }",
      "outputKeys": [
        "ft_contract_count",
        "preview[].contract_id",
        "preview[].balance"
      ],
      "responseNotes": [
        "near.ft.inventory hits the FastNear indexer (api.fastnear.com) — set near.config({ apiKey }) to avoid the public rate limit.",
        "Returns one row per FT contract the account currently holds; balances are raw integer strings."
      ],
      "chooseWhen": [
        "Choose this when the question is 'what tokens does this account own?' rather than one specific contract.",
        "Use ft-balance instead when you already know the contract id."
      ],
      "followUps": [
        "If you need NFTs as well, switch to near.nft.inventory.",
        "If you need staking and aggregate state too, use near.api.v1.accountFull."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "ft-balance",
        "nft-inventory",
        "account-full"
      ]
    },
    {
      "id": "nft-for-owner",
      "title": "Which NFTs does this account own on this contract?",
      "summary": "List the tokens an account owns under one NEP-171 contract with metadata included.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.nft.forOwner",
      "example": {
        "contractId": "x.paras.near",
        "accountId": "root.near",
        "limit": 5
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\nconst tokens = await near.nft.forOwner({\n  contractId: \"x.paras.near\",\n  accountId: \"root.near\",\n  limit: 5,\n});\n\nnear.print({\n  count: tokens.length,\n  preview: tokens.map((token) => ({\n    token_id: token.token_id,\n    title: token.metadata?.title,\n  })),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\nARGS_BASE64=\"$(jq -nc --arg account_id \"$ACCOUNT_ID\" '{account_id: $account_id, limit: 5}' | base64 | tr -d '\\n')\"\n\ncurl -sS \"https://rpc.mainnet.fastnear.com?apiKey=$FASTNEAR_API_KEY\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg args \"$ARGS_BASE64\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{\n      request_type:\"call_function\",\n      finality:\"final\",\n      account_id:\"x.paras.near\",\n      method_name:\"nft_tokens_for_owner\",\n      args_base64:$args\n    }\n  }')\"   | jq '.result.result | implode | fromjson | [.[] | {token_id, title: .metadata.title}]'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "const tokens = await near.nft.forOwner({\n  contractId: \"x.paras.near\",\n  accountId: \"root.near\",\n  limit: 5,\n});\n\nnear.print({\n  count: tokens.length,\n  preview: tokens.map((token) => ({\n    token_id: token.token_id,\n    title: token.metadata?.title,\n  })),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\nconst tokens = await near.nft.forOwner({\n  contractId: \"x.paras.near\",\n  accountId: \"root.near\",\n  limit: 5,\n});\n\nnear.print({\n  count: tokens.length,\n  preview: tokens.map((token) => ({\n    token_id: token.token_id,\n    title: token.metadata?.title,\n  })),\n});"
        }
      ],
      "service": "rpc",
      "returns": "Array<{ token_id: string; owner_id: string; metadata?: { title?: string; media?: string; description?: string } }>",
      "outputKeys": [
        "count",
        "preview[].token_id",
        "preview[].title"
      ],
      "responseNotes": [
        "Wraps NEP-171 nft_tokens_for_owner; the contract decides what metadata fields to embed.",
        "Pass from_index and limit (numbers, sometimes strings depending on the contract) for pagination."
      ],
      "chooseWhen": [
        "Choose this when you already know the NFT contract and want one account's collection on it.",
        "Use nft-inventory instead when you want NFTs across every contract for an account."
      ],
      "followUps": [
        "If you need contract-level metadata, call near.nft.metadata.",
        "If you need cross-contract NFT discovery, switch to near.nft.inventory."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "nft-inventory"
      ]
    },
    {
      "id": "nft-inventory",
      "title": "Which NFT contracts does this account hold tokens on?",
      "summary": "Discover every NEP-171 contract the account holds tokens under via the FastNear indexer.",
      "network": "mainnet",
      "auth": "bearer",
      "api": "near.nft.inventory",
      "example": {
        "accountId": "root.near"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.nft.inventory({\n  accountId: \"root.near\",\n});\n\n// The inventory endpoint returns contract-level rows only (no per-token\n// ids) — use the nft-for-owner recipe to list tokens on one contract.\nnear.print({\n  contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 3).map((entry) => ({\n    contract_id: entry.contract_id,\n    last_update_block_height: entry.last_update_block_height,\n  })),\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nACCOUNT_ID=root.near\n\ncurl -sS \"https://api.fastnear.com/v1/account/$ACCOUNT_ID/nft\"   -H \"Authorization: Bearer $FASTNEAR_API_KEY\"   | jq '{\n      contract_count: (.tokens | length),\n      preview: [.tokens[0:3][] | {contract_id, last_update_block_height}]\n    }'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.nft.inventory({\n  accountId: \"root.near\",\n});\n\n// The inventory endpoint returns contract-level rows only (no per-token\n// ids) — use the nft-for-owner recipe to list tokens on one contract.\nnear.print({\n  contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 3).map((entry) => ({\n    contract_id: entry.contract_id,\n    last_update_block_height: entry.last_update_block_height,\n  })),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Tip: `near.config({ apiKey: \"<your_key>\" })` raises rate limits.\nconst inventory = await near.nft.inventory({\n  accountId: \"root.near\",\n});\n\n// The inventory endpoint returns contract-level rows only (no per-token\n// ids) — use the nft-for-owner recipe to list tokens on one contract.\nnear.print({\n  contract_count: inventory.tokens.length,\n  preview: inventory.tokens.slice(0, 3).map((entry) => ({\n    contract_id: entry.contract_id,\n    last_update_block_height: entry.last_update_block_height,\n  })),\n});"
        }
      ],
      "service": "api",
      "returns": "{ tokens: Array<{ contract_id: string; last_update_block_height: number | null }> }",
      "outputKeys": [
        "contract_count",
        "preview[].contract_id",
        "preview[].last_update_block_height"
      ],
      "responseNotes": [
        "near.nft.inventory hits the FastNear indexer — set near.config({ apiKey }) to avoid the public rate limit.",
        "One row per NFT contract the account holds — contract ids only, no per-token ids; follow up with nft-for-owner per contract for token details."
      ],
      "chooseWhen": [
        "Choose this when the question is 'what NFT contracts does this account hold tokens on?'.",
        "Use nft-for-owner when you already know the specific contract id."
      ],
      "followUps": [
        "Drill into one contract with near.nft.forOwner for the per-token details.",
        "Pull holdings + staking + native NEAR with near.api.v1.accountFull."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "nft-for-owner",
        "ft-inventory",
        "account-full"
      ]
    },
    {
      "id": "archival-snapshot",
      "title": "What did this account look like at a specific block?",
      "summary": "Read canonical account state at a historical block by setting useArchival on the query.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.queryAccount",
      "example": {
        "accountId": "root.near",
        "blockId": 100000000,
        "useArchival": true
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Reads canonical account state at a specific historical block via the\n// archival RPC. Add useArchival to any view/query when blockId predates\n// the regular RPC's retention window (~5 epochs / a few days).\nconst past = await near.queryAccount({\n  accountId: \"root.near\",\n  blockId: 100_000_000,\n  useArchival: true,\n});\n\n// near.query* returns the raw JSON-RPC envelope — the data lives in .result.\nconst acct = past.result;\n\nnear.print({\n  amount: acct.amount,\n  storage_usage: acct.storage_usage,\n  block_hash: acct.block_hash,\n  block_height: acct.block_height,\n});\nEOF"
        },
        {
          "id": "curl-jq",
          "label": "curl + jq",
          "environment": "curl",
          "language": "bash",
          "runnable": true,
          "code": "# NEAR's public archival RPC — no apiKey required.\nACCOUNT_ID=root.near\nBLOCK_ID=100000000\n\ncurl -sS \"https://archival-rpc.mainnet.near.org\"   -H 'content-type: application/json'   --data \"$(jq -nc --arg account_id \"$ACCOUNT_ID\" --argjson block \"$BLOCK_ID\" '{\n    jsonrpc:\"2.0\",id:\"fastnear\",method:\"query\",\n    params:{request_type:\"view_account\",account_id:$account_id,block_id:$block}\n  }')\"   | jq '.result | {amount, storage_usage, block_height, block_hash}'"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Reads canonical account state at a specific historical block via the\n// archival RPC. Add useArchival to any view/query when blockId predates\n// the regular RPC's retention window (~5 epochs / a few days).\nconst past = await near.queryAccount({\n  accountId: \"root.near\",\n  blockId: 100_000_000,\n  useArchival: true,\n});\n\n// near.query* returns the raw JSON-RPC envelope — the data lives in .result.\nconst acct = past.result;\n\nnear.print({\n  amount: acct.amount,\n  storage_usage: acct.storage_usage,\n  block_hash: acct.block_hash,\n  block_height: acct.block_height,\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Reads canonical account state at a specific historical block via the\n// archival RPC. Add useArchival to any view/query when blockId predates\n// the regular RPC's retention window (~5 epochs / a few days).\nconst past = await near.queryAccount({\n  accountId: \"root.near\",\n  blockId: 100_000_000,\n  useArchival: true,\n});\n\n// near.query* returns the raw JSON-RPC envelope — the data lives in .result.\nconst acct = past.result;\n\nnear.print({\n  amount: acct.amount,\n  storage_usage: acct.storage_usage,\n  block_hash: acct.block_hash,\n  block_height: acct.block_height,\n});"
        }
      ],
      "service": "rpc",
      "returns": "RpcViewAccountResponse",
      "outputKeys": [
        "amount",
        "storage_usage",
        "block_hash",
        "block_height"
      ],
      "responseNotes": [
        "useArchival: true routes a single call to NEAR's archival RPC (archival-rpc.{mainnet,testnet}.near.org) which retains state past the regular RPC's ~5-epoch window.",
        "The same flag works on near.view, near.queryAccount, near.queryBlock, near.queryAccessKey, near.queryTx, and the lower-level near.sendRpc — falls back to the regular RPC if archival isn't configured for the network."
      ],
      "chooseWhen": [
        "Choose this when blockId predates the regular RPC's retention window or you specifically want a historical snapshot.",
        "Combine with the FT or NFT helpers (`useArchival: true` is forwarded) when you need a historical token balance."
      ],
      "followUps": [
        "Pair with near.ft.balance({ blockId, useArchival: true }) for a historical token balance.",
        "If you need a full holdings snapshot at a block, walk near.api.v1.accountFull with the blockId once it's supported on that surface."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "view-account",
        "ft-balance"
      ]
    },
    {
      "id": "connect-testnet",
      "title": "How do I open a testnet wallet session alongside mainnet?",
      "summary": "Use the per-network connect parameter to keep mainnet and testnet sessions side by side.",
      "network": "testnet",
      "auth": "wallet",
      "api": "near.recipes.connect",
      "example": {
        "network": "testnet",
        "contractId": "guest-book.testnet"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Opening the wallet picker needs a browser environment.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// near.recipes.connect honors a per-call network override\n// (@fastnear/api 1.1.1+), so this opens a testnet session alongside any\n// existing mainnet session — wallet state is keyed per network.\nconst result = await near.recipes.connect({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\nnear.print({\n  connected: result,\n  active_networks: nearWallet.connectedNetworks(),\n});"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\n// near.recipes.connect honors a per-call network override\n// (@fastnear/api 1.1.1+), so this opens a testnet session alongside any\n// existing mainnet session — wallet state is keyed per network.\nconst result = await near.recipes.connect({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\nnear.print({\n  connected: result,\n  active_networks: nearWallet.connectedNetworks(),\n});"
        }
      ],
      "service": "wallet",
      "returns": "{ accountId: string; network?: \"mainnet\" | \"testnet\" } | undefined",
      "outputKeys": [
        "connected.accountId",
        "connected.network",
        "active_networks"
      ],
      "responseNotes": [
        "@fastnear/wallet 1.1.0 keys session state per network, so signing in on testnet does not evict an active mainnet session.",
        "@fastnear/api 1.1.1 added a `network` parameter to near.recipes.connect (and signOut) — earlier versions silently used near.config().networkId.",
        "nearWallet.connectedNetworks() returns the list of networks with an active session."
      ],
      "chooseWhen": [
        "Choose this when the task spans both networks in the same page (mainnet read + testnet write, or A/B testing).",
        "Use connect-wallet when one network at a time is enough."
      ],
      "followUps": [
        "Send a function call on the testnet contract with near.recipes.functionCall({ network: \"testnet\", … }) — see the function-call-testnet recipe.",
        "Read the active session per network with nearWallet.accountId({ network: \"testnet\" }) and nearWallet.getActiveNetwork()."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-wallet",
        "function-call",
        "function-call-testnet"
      ]
    },
    {
      "id": "function-call-testnet",
      "title": "How do I send a function call on testnet without losing my mainnet session?",
      "summary": "Pair near.recipes.connect({ network: \"testnet\" }) with near.recipes.functionCall({ network: \"testnet\" }) — connect honors the per-network override added in 1.1.1; functionCall does the same thanks to per-network account state in 1.1.2.",
      "network": "testnet",
      "auth": "wallet",
      "api": "near.recipes.functionCall",
      "example": {
        "network": "testnet",
        "receiverId": "guest-book.testnet",
        "methodName": "add_message",
        "args": {
          "text": "hello from a per-network call"
        },
        "gas": "30000000000000",
        "deposit": "0"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "browser_required",
          "code": "# Browser wallet required.\n# Signing a transaction needs the wallet picker, which needs a browser.\n# Use the browser-global or ESM snippet for this task."
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// near.recipes.functionCall accepts a per-call network override\n// (@fastnear/api 1.1.2+) — once a testnet session is open, the api reads\n// the testnet account from its per-network state map and dispatches the\n// signed transaction through the wallet's testnet slot. The mainnet\n// session, if any, is untouched.\nawait near.recipes.connect({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\nconst result = await near.recipes.functionCall({\n  network: \"testnet\",\n  receiverId: \"guest-book.testnet\",\n  methodName: \"add_message\",\n  args: { text: \"hello from a per-network call\" },\n  gas: \"30000000000000\",\n  deposit: \"0\",\n});\n\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\nimport * as nearWallet from \"@fastnear/wallet\";\n\nnear.useWallet(nearWallet);\n\n// The wallet owns the session; near.sendTx reads the signer from\n// @fastnear/api's per-network state. Without this bridge every send throws\n// \"Must sign in\" even with an active wallet session.\nnearWallet.onConnect((session) =>\n  near.state.updateAccountState({ accountId: session.accountId }, session.network),\n);\n\n// Resume a session the user already approved — no popup. Snippets that call\n// near.recipes.connect below open the picker themselves.\nawait nearWallet.restore({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\n// near.recipes.functionCall accepts a per-call network override\n// (@fastnear/api 1.1.2+) — once a testnet session is open, the api reads\n// the testnet account from its per-network state map and dispatches the\n// signed transaction through the wallet's testnet slot. The mainnet\n// session, if any, is untouched.\nawait near.recipes.connect({\n  network: \"testnet\",\n  contractId: \"guest-book.testnet\",\n});\n\nconst result = await near.recipes.functionCall({\n  network: \"testnet\",\n  receiverId: \"guest-book.testnet\",\n  methodName: \"add_message\",\n  args: { text: \"hello from a per-network call\" },\n  gas: \"30000000000000\",\n  deposit: \"0\",\n});\n\nnear.print(result);"
        }
      ],
      "service": "wallet",
      "returns": "{ outcomes?: any[] } | { rejected: true } | undefined",
      "outputKeys": [
        "outcomes[].transaction.hash",
        "outcomes[].status"
      ],
      "responseNotes": [
        "@fastnear/api 1.1.2 keys account state per network, so near.recipes.functionCall reads the testnet signer from its testnet slot regardless of which network is currently active.",
        "Local-signing also honors the network override in 1.1.2 — the RPC helpers, queryAccessKey/queryBlock/sendTxToRpc, and the nonce/block caches are all keyed per network.",
        "nearWallet.connectedNetworks() returns the list of networks with an active session if you want to gate the call on testnet being signed in first."
      ],
      "chooseWhen": [
        "Choose this when an action lives on testnet but the page also holds a live mainnet session.",
        "Use function-call when only one network is involved."
      ],
      "followUps": [
        "Sign a NEP-413 message with the testnet session via near.recipes.signMessage(message, { network: \"testnet\" }).",
        "Send NEAR with near.recipes.transfer({ network: \"testnet\", … }) — same per-network surface."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "connect-testnet",
        "function-call",
        "transfer"
      ]
    },
    {
      "id": "gas-price",
      "title": "What is the current gas price?",
      "summary": "Read the current gas price from the RPC with a one-line wrapper; retries and 429-handling are built in.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.gasPrice",
      "example": {},
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Current gas price straight from the RPC.\n// Retries and 429-handling are on by default (see near.config({ retry })).\nnear.print(await near.gasPrice());\nEOF"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Current gas price straight from the RPC.\n// Retries and 429-handling are on by default (see near.config({ retry })).\nnear.print(await near.gasPrice());"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Current gas price straight from the RPC.\n// Retries and 429-handling are on by default (see near.config({ retry })).\nnear.print(await near.gasPrice());"
        }
      ],
      "service": "rpc",
      "returns": "{ result: { gas_price: string } }",
      "outputKeys": [
        "result.gas_price"
      ],
      "responseNotes": [
        "near.gasPrice returns the raw JSON-RPC envelope; read the value from result.gas_price.",
        "gas_price is a yoctoNEAR-per-gas decimal string — multiply by gas to estimate a fee, no BigInt required beyond your own math.",
        "Omit the argument for the latest block, or pass { blockId } to price a specific height or hash."
      ],
      "chooseWhen": [
        "Choose this to estimate transaction fees or to show the live network gas price.",
        "Use near.status for node/sync info or near.validators for the validator set."
      ],
      "followUps": [
        "Build and preview a transaction with near.explain.tx, then sign it with sendTx or a wallet.",
        "Inspect broader chain state with near.status() and near.validators()."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "explain-transaction",
        "last-block-final",
        "function-call"
      ]
    },
    {
      "id": "format-near-amount",
      "title": "How do I show a yoctoNEAR balance as human-readable NEAR?",
      "summary": "Render a yoctoNEAR integer as a human NEAR string with near.utils.formatNearAmount — the reverse of convertUnit, no BigInt.",
      "network": "mainnet",
      "auth": "none",
      "api": "near.utils.formatNearAmount",
      "example": {
        "yocto": "1500000000000000000000000"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": true,
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Reverse of near.utils.convertUnit: render a yoctoNEAR integer as human NEAR.\n// Wide integers are decimal strings in and out — you never touch BigInt.\nconst yocto = \"1500000000000000000000000\";\nnear.print(near.utils.formatNearAmount(yocto)); // \"1.5\"\nEOF"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": true,
          "code": "// Reverse of near.utils.convertUnit: render a yoctoNEAR integer as human NEAR.\n// Wide integers are decimal strings in and out — you never touch BigInt.\nconst yocto = \"1500000000000000000000000\";\nnear.print(near.utils.formatNearAmount(yocto)); // \"1.5\""
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": true,
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Reverse of near.utils.convertUnit: render a yoctoNEAR integer as human NEAR.\n// Wide integers are decimal strings in and out — you never touch BigInt.\nconst yocto = \"1500000000000000000000000\";\nnear.print(near.utils.formatNearAmount(yocto)); // \"1.5\""
        }
      ],
      "service": "api",
      "returns": "string",
      "outputKeys": [],
      "responseNotes": [
        "near.utils.formatNearAmount is pure — no network, no wallet.",
        "IN accepts a decimal string or bigint yoctoNEAR value; OUT is always a decimal string like \"1.5\", never a number or BigInt.",
        "Pass { fracDigits } to cap decimals, or { trimZeros: false } to pad; formatUnit(amount, unit) formats other units (e.g. \"tgas\")."
      ],
      "chooseWhen": [
        "Choose this to display a balance read from near.view / near.ft.balance / decoded borsh as human NEAR.",
        "Use near.utils.convertUnit for the other direction (\"1.5 NEAR\" -> yocto)."
      ],
      "followUps": [
        "Read a balance to format with near.ft.balance or near.queryAccount.",
        "Construct a transfer of a parsed amount with near.actions.transfer(near.utils.convertUnit(\"1.5 NEAR\"))."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "ft-balance",
        "transfer",
        "explain-transaction"
      ]
    },
    {
      "id": "sign-delegate-local",
      "title": "How do I sign a gasless delegate transaction without a wallet?",
      "summary": "Sign a NEP-366 delegate action with a local key so a relayer can broadcast it and pay the gas — the meta-transaction path for servers and agents.",
      "network": "mainnet",
      "auth": "local-key",
      "api": "near.signDelegate",
      "example": {
        "receiverId": "guest-book.near",
        "actions": [
          {
            "type": "FunctionCall",
            "methodName": "add_message",
            "args": {
              "text": "gasless hello"
            },
            "gas": "30 Tgas",
            "deposit": "0"
          }
        ],
        "blockHeightTtl": 600
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "needs_onchain_key",
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Sign a NEP-366 delegate action with a local key — no wallet. A relayer\n// broadcasts it and pays the gas. Requires a signed-in local key\n// (near.config + near.state) or an explicit { signer, signerId }.\nconst signed = await near.signDelegate({\n  receiverId: \"guest-book.near\",\n  actions: [\n    near.actions.functionCall({\n      methodName: \"add_message\",\n      args: { text: \"gasless hello\" },\n      gas: \"30 Tgas\",\n      deposit: \"0\",\n    }),\n  ],\n  blockHeightTtl: 600,\n});\n\n// nonce and maxBlockHeight come back as decimal strings; borshBase64 is what\n// a relayer transports. Hand it to near.relayDelegate (or any relayer).\nnear.print(signed.delegateAction);\nEOF"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": false,
          "reason": "needs_onchain_key",
          "code": "// Sign a NEP-366 delegate action with a local key — no wallet. A relayer\n// broadcasts it and pays the gas. Requires a signed-in local key\n// (near.config + near.state) or an explicit { signer, signerId }.\nconst signed = await near.signDelegate({\n  receiverId: \"guest-book.near\",\n  actions: [\n    near.actions.functionCall({\n      methodName: \"add_message\",\n      args: { text: \"gasless hello\" },\n      gas: \"30 Tgas\",\n      deposit: \"0\",\n    }),\n  ],\n  blockHeightTtl: 600,\n});\n\n// nonce and maxBlockHeight come back as decimal strings; borshBase64 is what\n// a relayer transports. Hand it to near.relayDelegate (or any relayer).\nnear.print(signed.delegateAction);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": false,
          "reason": "needs_onchain_key",
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Sign a NEP-366 delegate action with a local key — no wallet. A relayer\n// broadcasts it and pays the gas. Requires a signed-in local key\n// (near.config + near.state) or an explicit { signer, signerId }.\nconst signed = await near.signDelegate({\n  receiverId: \"guest-book.near\",\n  actions: [\n    near.actions.functionCall({\n      methodName: \"add_message\",\n      args: { text: \"gasless hello\" },\n      gas: \"30 Tgas\",\n      deposit: \"0\",\n    }),\n  ],\n  blockHeightTtl: 600,\n});\n\n// nonce and maxBlockHeight come back as decimal strings; borshBase64 is what\n// a relayer transports. Hand it to near.relayDelegate (or any relayer).\nnear.print(signed.delegateAction);"
        }
      ],
      "service": "rpc",
      "returns": "{ delegateAction, signature, signatureBytes, borshBase64 }",
      "outputKeys": [
        "delegateAction.senderId",
        "delegateAction.nonce",
        "delegateAction.maxBlockHeight",
        "signature",
        "borshBase64"
      ],
      "responseNotes": [
        "near.signDelegate signs locally — it never opens a wallet. The sender's nonce comes from its access key; maxBlockHeight defaults to the final block height plus blockHeightTtl (600).",
        "nonce and maxBlockHeight are returned as decimal strings; borshBase64 is the NEP-366 SignedDelegate a relayer transports.",
        "Hand the result to near.relayDelegate (or any relayer) to broadcast — the relayer's full-access key pays the gas, not the sender.",
        "A WALLET-signed delegate (nearWallet.signDelegateActions → borshSerializedBase64) relays the same way: pass it as near.relayDelegate({ signedDelegate }), or normalize it first with near.utils.parseSignedDelegate. Both signers converge on the same { delegateAction, signature } shape."
      ],
      "chooseWhen": [
        "Choose this to build gasless / meta-transactions from a server or agent that holds a key but shouldn't pay gas.",
        "Use nearWallet.signDelegateActions when a browser wallet holds the key, or near.sendTx to sign and pay yourself."
      ],
      "followUps": [
        "Broadcast the signed delegate with near.relayDelegate({ delegateAction, signature, relayerSigner, relayerId }).",
        "Preview the wrapped actions first with near.explain.tx."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "sign-delegate-actions",
        "explain-transaction",
        "function-call"
      ]
    },
    {
      "id": "create-testnet-account",
      "title": "How do I create and fund a new testnet account?",
      "summary": "Generate a key and create + fund a fresh testnet account through the NEAR testnet helper faucet — the common agent onboarding step. Testnet only.",
      "network": "testnet",
      "auth": "none",
      "api": "near.createFundedTestnetAccount",
      "example": {
        "newAccountId": "my-agent.testnet"
      },
      "snippets": [
        {
          "id": "terminal",
          "label": "Terminal",
          "environment": "terminal",
          "language": "bash",
          "runnable": false,
          "reason": "faucet_rate_limited",
          "code": "# Assumes FASTNEAR_API_KEY is already set in your shell.\nnode -e \"$(curl -fsSL https://js.fastnear.com/agents.js)\" <<'EOF'\n// Make a key, then create + fund a fresh testnet account via the faucet.\nconst privateKey = near.utils.privateKeyFromRandom();\nconst publicKey = near.utils.publicKeyFromPrivate(privateKey);\n\nconst result = await near.createFundedTestnetAccount({\n  newAccountId: \"my-agent.testnet\",\n  publicKey,\n});\n\n// Account state is keyed per network and the default is mainnet, so pass\n// \"testnet\" explicitly — otherwise the testnet key lands in the mainnet\n// slot. Then near.sendTx signs locally from here on, no wallet, no popup:\n//   await near.sendTx({ network: \"testnet\", receiverId, actions: [near.actions.transfer(cu(\"0.1 NEAR\"))] });\nnear.state.updateAccountState({ accountId: \"my-agent.testnet\", privateKey }, \"testnet\");\nnear.print(result);\nEOF"
        },
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": false,
          "reason": "faucet_rate_limited",
          "code": "// Make a key, then create + fund a fresh testnet account via the faucet.\nconst privateKey = near.utils.privateKeyFromRandom();\nconst publicKey = near.utils.publicKeyFromPrivate(privateKey);\n\nconst result = await near.createFundedTestnetAccount({\n  newAccountId: \"my-agent.testnet\",\n  publicKey,\n});\n\n// Account state is keyed per network and the default is mainnet, so pass\n// \"testnet\" explicitly — otherwise the testnet key lands in the mainnet\n// slot. Then near.sendTx signs locally from here on, no wallet, no popup:\n//   await near.sendTx({ network: \"testnet\", receiverId, actions: [near.actions.transfer(cu(\"0.1 NEAR\"))] });\nnear.state.updateAccountState({ accountId: \"my-agent.testnet\", privateKey }, \"testnet\");\nnear.print(result);"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": false,
          "reason": "faucet_rate_limited",
          "code": "import * as near from \"@fastnear/api\";\n\nnear.config({ apiKey: process.env.FASTNEAR_API_KEY || undefined });\n\n// Make a key, then create + fund a fresh testnet account via the faucet.\nconst privateKey = near.utils.privateKeyFromRandom();\nconst publicKey = near.utils.publicKeyFromPrivate(privateKey);\n\nconst result = await near.createFundedTestnetAccount({\n  newAccountId: \"my-agent.testnet\",\n  publicKey,\n});\n\n// Account state is keyed per network and the default is mainnet, so pass\n// \"testnet\" explicitly — otherwise the testnet key lands in the mainnet\n// slot. Then near.sendTx signs locally from here on, no wallet, no popup:\n//   await near.sendTx({ network: \"testnet\", receiverId, actions: [near.actions.transfer(cu(\"0.1 NEAR\"))] });\nnear.state.updateAccountState({ accountId: \"my-agent.testnet\", privateKey }, \"testnet\");\nnear.print(result);"
        }
      ],
      "service": "rpc",
      "returns": "{ account_id?: string }",
      "outputKeys": [
        "account_id"
      ],
      "responseNotes": [
        "near.createFundedTestnetAccount is testnet-only — it POSTs to the NEAR testnet helper faucet; there is no mainnet equivalent.",
        "Generate the key with near.utils.privateKeyFromRandom + near.utils.publicKeyFromPrivate, or recover one from a seed phrase (see account-from-seed-phrase).",
        "After creation, persist the private key with near.state.updateAccountState so near.sendTx signs locally for that account (@fastnear/api 2.1.1+). A full-access key signs any action; a slot that also sets accessKeyContractId is treated as a function-call key and only signs zero-deposit calls to that contract.",
        "Account state is keyed per network and the default active network is mainnet, so pass \"testnet\" as the second argument to updateAccountState and network: \"testnet\" to sendTx — otherwise the testnet key is written to the mainnet slot and the send signs against mainnet RPC for an account that does not exist there."
      ],
      "chooseWhen": [
        "Choose this for the 'make me a testnet account' onboarding step in an agent or script.",
        "For an existing account, add a key instead of creating one; for mainnet, fund the account another way."
      ],
      "followUps": [
        "Sign a transaction locally with the new key via near.sendTx.",
        "Derive a recoverable key from a seed phrase with account-from-seed-phrase."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "account-from-seed-phrase",
        "function-call",
        "explain-transaction"
      ]
    },
    {
      "id": "account-from-seed-phrase",
      "title": "How do I create or recover a key from a seed phrase?",
      "summary": "Generate a BIP-39 seed phrase and its NEAR key, or recover the key from an existing phrase, with @fastnear/seed-phrase — byte-identical to near-cli.",
      "network": "mainnet",
      "auth": "local-key",
      "api": "generateSeedPhrase",
      "example": {
        "seedPhrase": "shoot island position soft burden budget tooth cruel issue economy destroy above"
      },
      "snippets": [
        {
          "id": "browser-global",
          "label": "Browser Global",
          "environment": "browserGlobal",
          "language": "js",
          "runnable": false,
          "reason": "needs_second_package",
          "code": "// Load @fastnear/seed-phrase (the NearSeedPhrase global) next to near.js.\n// Create a fresh key pair and its 12-word recovery phrase.\nconst { seedPhrase, publicKey, privateKey } = NearSeedPhrase.generateSeedPhrase();\n\n// Recover the exact same keys later — byte-identical to near-cli / near-seed-phrase.\nconst recovered = NearSeedPhrase.parseSeedPhrase(seedPhrase);\n\n// Store the recovered full-access key; near.sendTx signs locally from here on.\nnear.state.updateAccountState({ accountId: \"you.near\", privateKey: recovered.privateKey });\nnear.print({ seedPhrase, publicKey });"
        },
        {
          "id": "esm",
          "label": "ESM",
          "environment": "esm",
          "language": "js",
          "runnable": false,
          "reason": "needs_second_package",
          "code": "import { generateSeedPhrase, parseSeedPhrase } from \"@fastnear/seed-phrase\";\nimport * as near from \"@fastnear/api\";\n\n// Create a fresh key pair and its 12-word recovery phrase.\nconst { seedPhrase, publicKey, privateKey } = generateSeedPhrase();\n\n// Recover the exact same keys later — byte-identical to near-cli / near-seed-phrase.\nconst recovered = parseSeedPhrase(seedPhrase);\n\nnear.state.updateAccountState({ accountId: \"you.near\", privateKey: recovered.privateKey });\nnear.print({ seedPhrase, publicKey });"
        }
      ],
      "service": "api",
      "returns": "{ seedPhrase, publicKey, privateKey }",
      "outputKeys": [
        "seedPhrase",
        "publicKey",
        "privateKey"
      ],
      "responseNotes": [
        "@fastnear/seed-phrase is a separate package (not on the near global) so the bip39 wordlist never bloats @fastnear/api; load it as the NearSeedPhrase global or import it in ESM/Node.",
        "Derivation matches near-seed-phrase / near-cli (SLIP-0010 ed25519 at m/44'/397'/0'), so a phrase recovers the same key across every NEAR tool.",
        "generateSeedPhrase(256) makes a 24-word phrase; hand both accountId and privateKey to near.state.updateAccountState and near.sendTx signs locally with it (@fastnear/api 2.1.1+) — a slot holding a key but no accountId has nobody to sign as and throws Must sign in. Or pass near.utils.signerFromPrivateKey(privateKey) with a matching signerId to sign without touching stored state."
      ],
      "chooseWhen": [
        "Choose this to onboard or recover an account key from a human-writable phrase.",
        "Use near.utils.privateKeyFromRandom when you don't need a recovery phrase."
      ],
      "followUps": [
        "Create + fund a testnet account for the derived key with create-testnet-account.",
        "Sign a transaction locally with near.sendTx once the key is in account state."
      ],
      "pagination": {
        "kind": "none",
        "requestFields": [],
        "responseFields": [],
        "filtersMustStayStable": false
      },
      "relatedRecipes": [
        "create-testnet-account",
        "sign-delegate-local",
        "function-call"
      ]
    }
  ],
  "mlDsa65": {
    "package": "@fastnear/ml-dsa-65",
    "protocolVersion": 85,
    "runtime": "Node.js 20.19+ or a modern browser",
    "scope": "NEAR account access keys and transaction signatures only; validator and staking keys remain Ed25519.",
    "sizes": {
      "seed": 32,
      "publicKey": 1952,
      "expandedSecretKey": 4032,
      "signature": 3309
    },
    "verificationCharge": {
      "gas": "100000000000",
      "display": "100 Ggas",
      "appliesTo": "each outer or delegated ML-DSA-65 signature verification"
    },
    "keyForms": {
      "full": "ml-dsa-65:<base58 public key>",
      "handle": "ml-dsa-65-hash:<base58 SHA3-256 digest>",
      "domainTag": "near:ml-dsa-65-pubkey-hash:v1",
      "derivation": "SHA3-256 of the ASCII domain tag followed by the raw 1,952-byte public key",
      "rule": "Use the full public key for AddKey, direct access-key lookup, signing, and DeleteKey. Access-key list responses expose the compact handle; derive it with publicKeyToHandle() before comparing."
    },
    "safety": [
      "Check the selected RPC's active protocol_version and require 85 or later before adding or using an ML-DSA-65 key; do not use node software versions or latest_protocol_version as activation signals.",
      "Never print or persist generated seeds or expanded secret keys. Keep a temporary recovery record public-only: network, account ID, full public key, and hash handle.",
      "Public keys, secret keys, and signatures all use the same ml-dsa-65: string prefix, so signer.exportSecretKey() is indistinguishable by shape from signer.publicKey. Distinguish them by decoded byte length (1,952 vs 4,032), never by prefix, and never let a secret reach a log line or a recovery record.",
      "After an AddKey attempt, do not trust a single absence read: submit a finalized classical DeleteKey nonce barrier, confirm absence at finality, and only then remove the public recovery record.",
      "ML-DSA-65 public keys are 1,952 bytes and signatures are 3,309 bytes, so transactions and key-management actions are substantially larger than classical equivalents.",
      "NEAR charges 100 Ggas (100,000,000,000 gas) for each outer or delegated ML-DSA-65 signature verification.",
      "The selected @noble/post-quantum backend describes itself as self-audited and does not claim constant-time side-channel protection. Prefer a native, WASM, HSM, or hardware TransactionSigner when that threat model requires one.",
      "destroy() provides best-effort zeroization of package-owned JavaScript buffers, not a hard memory-erasure guarantee. Constrained QuickJS and MCU runtimes are not a v1 compatibility target."
    ],
    "quickstarts": [
      {
        "id": "ml-dsa-65-generate",
        "title": "Generate an in-memory ML-DSA-65 signer",
        "summary": "Generate the opt-in signer, retain only public recovery metadata, and always destroy the signer when its lifecycle ends.",
        "language": "js",
        "code": "import { generateSigner } from \"@fastnear/ml-dsa-65\";\n\nconst signer = generateSigner();\n\ntry {\n  // Public values are safe to retain for enrollment and cleanup.\n  const recovery = {\n    network: \"testnet\",\n    accountId: \"device.testnet\",\n    publicKey: signer.publicKey,\n    publicKeyHandle: signer.publicKeyHandle,\n  };\n\n  console.log(recovery);\n  // Never log or persist signer.exportSeed() or signer.exportSecretKey().\n} finally {\n  signer.destroy();\n}"
      },
      {
        "id": "ml-dsa-65-enroll",
        "title": "Enroll an ML-DSA-65 public key with a classical AddKey",
        "summary": "Add the signer's full public key to the account using an existing classical full-access key. Enrollment always starts from a classical signer; an ML-DSA-65 key cannot add itself.",
        "language": "js",
        "code": "import {\n  actions,\n  queryAccessKey,\n  queryProtocolVersion,\n  sendTx,\n} from \"@fastnear/api\";\nimport { signerFromPrivateKey } from \"@fastnear/utils\";\n\nexport async function enrollMlDsa65Key({ accountId, classicalPrivateKey, signer }) {\n  const protocolVersion = await queryProtocolVersion({ network: \"testnet\" });\n  if (protocolVersion < 85) {\n    throw new Error(`testnet protocol ${protocolVersion} does not support ML-DSA-65`);\n  }\n\n  // The AddKey itself is signed by an existing classical full-access key.\n  const classicalSigner = signerFromPrivateKey(classicalPrivateKey);\n\n  await sendTx({\n    signerId: accountId,\n    signer: classicalSigner,\n    receiverId: accountId,\n    // Pass the full ml-dsa-65:<base58> key. Never the ml-dsa-65-hash: handle.\n    actions: [actions.addFullAccessKey({ publicKey: signer.publicKey })],\n    waitUntil: \"FINAL\",\n    network: \"testnet\",\n  });\n\n  // Read back with the full key: direct access-key lookup accepts it, while\n  // access-key list responses expose only signer.publicKeyHandle.\n  return queryAccessKey({\n    accountId,\n    publicKey: signer.publicKey,\n    blockId: \"final\",\n    network: \"testnet\",\n  });\n}"
      },
      {
        "id": "ml-dsa-65-explicit-send",
        "title": "Send with an enrolled ML-DSA-65 signer",
        "summary": "Use the explicit-signer branch of sendTx after the signer's full public key has been enrolled on the account.",
        "language": "js",
        "code": "import {\n  actions,\n  queryProtocolVersion,\n  sendTx,\n} from \"@fastnear/api\";\n\nexport async function sendOneYoctoWithMlDsa65({ accountId, signer }) {\n  const protocolVersion = await queryProtocolVersion({ network: \"testnet\" });\n  if (protocolVersion < 85) {\n    throw new Error(`testnet protocol ${protocolVersion} does not support ML-DSA-65`);\n  }\n\n  return sendTx({\n    signerId: accountId,\n    signer,\n    receiverId: accountId,\n    actions: [actions.transfer(\"1\")],\n    waitUntil: \"FINAL\",\n    network: \"testnet\",\n  });\n}"
      },
      {
        "id": "ml-dsa-65-enroll-delete",
        "title": "Enroll and delete a temporary testnet key",
        "summary": "Persist public-only recovery metadata, use an authorized classical full-access signer for both mutations, and establish finalized deletion before removing the record.",
        "language": "js",
        "code": "import {\n  actions,\n  queryAccessKeyList,\n  queryProtocolVersion,\n  sendTx,\n} from \"@fastnear/api\";\nimport {\n  generateSigner,\n} from \"@fastnear/ml-dsa-65\";\n\nexport async function withTemporaryMlDsa65Key({\n  accountId,\n  classicalSigner,\n  run,\n  saveRecovery,\n  removeRecovery,\n}) {\n  if (!accountId.endsWith(\".testnet\")) {\n    throw new Error(\"This safety-oriented recipe is testnet-only\");\n  }\n\n  const protocolVersion = await queryProtocolVersion({ network: \"testnet\" });\n  if (protocolVersion < 85) {\n    throw new Error(`testnet protocol ${protocolVersion} does not support ML-DSA-65`);\n  }\n\n  const signer = generateSigner();\n  const publicRecovery = {\n    network: \"testnet\",\n    accountId,\n    publicKey: signer.publicKey,\n    publicKeyHandle: signer.publicKeyHandle,\n  };\n  let addAttempted = false;\n\n  async function deleteWithFinalizedBarrier() {\n    let lastError;\n    for (let attempt = 1; attempt <= 3; attempt += 1) {\n      try {\n        // Submit even when one read says the key is absent. A finalized\n        // classical transaction prevents an ambiguous earlier AddKey from\n        // landing later with the same or a lower nonce.\n        await sendTx({\n          signerId: accountId,\n          signer: classicalSigner,\n          receiverId: accountId,\n          actions: [actions.deleteKey({ publicKey: signer.publicKey })],\n          waitUntil: \"FINAL\",\n          network: \"testnet\",\n        });\n        const list = await queryAccessKeyList({\n          accountId,\n          blockId: \"final\",\n          network: \"testnet\",\n        });\n        const stillPresent = list.result.keys.some(\n          (entry) => entry.public_key === publicRecovery.publicKeyHandle,\n        );\n        if (!stillPresent) return;\n        lastError = new Error(\"ML-DSA-65 key remains after finalized deletion\");\n      } catch (error) {\n        lastError = error;\n      }\n    }\n    throw lastError ?? new Error(\"Could not establish ML-DSA-65 key absence\");\n  }\n\n  try {\n    // Implement these callbacks with durable application storage. On Node,\n    // create the public-only file with mode 0600. Never include secret bytes.\n    await saveRecovery(publicRecovery);\n    addAttempted = true;\n    await sendTx({\n      signerId: accountId,\n      signer: classicalSigner,\n      receiverId: accountId,\n      actions: [actions.addFullAccessKey({ publicKey: signer.publicKey })],\n      waitUntil: \"FINAL\",\n      network: \"testnet\",\n    });\n\n    return await run(signer);\n  } finally {\n    try {\n      if (addAttempted) {\n        await deleteWithFinalizedBarrier();\n        await removeRecovery(publicRecovery);\n      }\n    } finally {\n      signer.destroy();\n    }\n  }\n}"
      },
      {
        "id": "ml-dsa-65-reconcile",
        "title": "Reconcile a full key with its access-key-list handle",
        "summary": "Query the full key directly, then match its locally derived hash handle against the compact list response.",
        "language": "js",
        "code": "import {\n  queryAccessKey,\n  queryAccessKeyList,\n} from \"@fastnear/api\";\nimport { publicKeyToHandle } from \"@fastnear/ml-dsa-65\";\n\nexport async function findMlDsa65AccessKey({ accountId, publicKey }) {\n  const [direct, list] = await Promise.all([\n    queryAccessKey({ accountId, publicKey, network: \"testnet\" }),\n    queryAccessKeyList({ accountId, network: \"testnet\" }),\n  ]);\n  const publicKeyHandle = publicKeyToHandle(publicKey);\n  const listed = list.result.keys.find(\n    (entry) => entry.public_key === publicKeyHandle,\n  );\n\n  return { direct: direct.result, publicKeyHandle, listed };\n}"
      }
    ]
  },
  "x402": {
    "package": "@fastnear/x402",
    "runtime": "Package-only; not included in agents.js or near.js.",
    "guideUrl": "https://github.com/fastnear/js-monorepo/blob/main/packages/x402/README.md",
    "protocol": {
      "version": 2,
      "scheme": "exact",
      "networks": [
        "near:mainnet",
        "near:testnet"
      ],
      "authorization": "NEP-366 SignedDelegate",
      "paymentAsset": "NEP-141 fungible tokens"
    },
    "browserGlobal": "nearX402",
    "browserStatus": "Stable with tested Meteor Wallet support; other wallets must advertise both timeout-aware delegate-signing capabilities and pass the x402 testnet harness before being documented as compatible.",
    "walletFeatures": [
      "signDelegateActions",
      "signDelegateActionsWithTtl"
    ],
    "chooseByTask": [
      {
        "task": "Pay an x402 URL from Node.js",
        "use": [
          "createLocalNearSigner",
          "createNearPaymentFetch"
        ],
        "imports": [
          "@fastnear/x402/node",
          "@fastnear/x402"
        ],
        "status": "stable"
      },
      {
        "task": "Pay an x402 URL from a browser wallet",
        "use": [
          "createFastNearWalletSigner",
          "createNearPaymentFetch"
        ],
        "imports": [
          "@fastnear/wallet",
          "@fastnear/x402"
        ],
        "status": "stable with a compatible timeout-aware wallet; Meteor Wallet is the tested production path"
      },
      {
        "task": "Protect a seller resource",
        "use": [
          "createNearResourceServer"
        ],
        "imports": [
          "@fastnear/x402/server"
        ],
        "status": "requires an explicit facilitator"
      },
      {
        "task": "Operate a NEAR facilitator",
        "use": [
          "createNearFacilitator"
        ],
        "imports": [
          "@fastnear/x402/facilitator"
        ],
        "status": "HTTP framework and secret storage are operator choices"
      },
      {
        "task": "Integrate below the paid-fetch helper",
        "use": [
          "createNearX402Client"
        ],
        "imports": [
          "@fastnear/x402"
        ],
        "status": "lower-level client path"
      }
    ],
    "entrypoints": [
      {
        "subpath": "@fastnear/x402",
        "exports": [
          "createFastNearWalletSigner",
          "createNearX402Client",
          "createNearPaymentFetch"
        ],
        "purpose": "injected FastNEAR wallet signer, NEAR-only x402 client, and paid fetch"
      },
      {
        "subpath": "@fastnear/x402/node",
        "exports": [
          "createLocalNearSigner"
        ],
        "purpose": "official RPC-backed local full-access-key signer"
      },
      {
        "subpath": "@fastnear/x402/server",
        "exports": [
          "createNearResourceServer"
        ],
        "purpose": "resource server with one or more explicitly configured facilitators"
      },
      {
        "subpath": "@fastnear/x402/facilitator",
        "exports": [
          "createNearFacilitator"
        ],
        "purpose": "self-hosted facilitator registration for concrete NEAR networks"
      }
    ],
    "constraints": [
      "Only x402 v2 exact payments on near:mainnet and near:testnet are supported.",
      "Payments use NEP-141 tokens; native NEAR is not a direct payment asset.",
      "Wallet and local-key payers require full-access keys, and recipients need token storage registration.",
      "Resource servers require an explicit facilitator; no x402.org or other default is selected.",
      "Browser wallet access is injected explicitly and payment occurs only when the application calls the paid fetch function."
    ],
    "safeDefaults": [
      "Pin near:testnet during development and a concrete NEAR network in production; use near:* only for an intentionally cross-network client.",
      "Keep payer and relayer secret keys in server-side secret storage, never browser code.",
      "String and number seller prices use the official USDC contract; wNEAR and custom tokens require an explicit { amount, asset } price.",
      "Always configure a facilitator explicitly."
    ],
    "quickstarts": [
      {
        "id": "x402-node-paid-fetch",
        "title": "Pay an x402 URL from Node.js",
        "summary": "Use the upstream local full-access-key signer with the high-level paid-fetch helper.",
        "language": "js",
        "code": "import { createNearPaymentFetch } from \"@fastnear/x402\";\nimport { createLocalNearSigner } from \"@fastnear/x402/node\";\n\nconst { NEAR_PAYER_ACCOUNT_ID, NEAR_PAYER_SECRET_KEY, X402_RESOURCE_URL } = process.env;\nif (!NEAR_PAYER_ACCOUNT_ID || !NEAR_PAYER_SECRET_KEY || !X402_RESOURCE_URL) {\n  throw new Error(\"NEAR_PAYER_ACCOUNT_ID, NEAR_PAYER_SECRET_KEY, and X402_RESOURCE_URL are required\");\n}\n\nconst signer = createLocalNearSigner({\n  accountId: NEAR_PAYER_ACCOUNT_ID,\n  secretKey: NEAR_PAYER_SECRET_KEY,\n  rpcUrls: { \"near:testnet\": \"https://rpc.testnet.fastnear.com\" },\n});\nconst paidFetch = createNearPaymentFetch({ signer, network: \"near:testnet\" });\nconst response = await paidFetch(X402_RESOURCE_URL);\nif (!response.ok) throw new Error(`Paid request failed: ${response.status}`);\nconsole.log(await response.json());"
      },
      {
        "id": "x402-remote-facilitator-seller",
        "title": "Configure a seller with an explicit remote facilitator",
        "summary": "Create the NEAR resource-server core, then pass it to the x402 HTTP framework adapter you choose.",
        "language": "js",
        "code": "import { createNearResourceServer } from \"@fastnear/x402/server\";\n\nconst { X402_FACILITATOR_URL } = process.env;\nif (!X402_FACILITATOR_URL) throw new Error(\"X402_FACILITATOR_URL is required\");\n\nexport const resourceServer = createNearResourceServer({\n  facilitators: { url: X402_FACILITATOR_URL },\n});\nawait resourceServer.initialize();"
      }
    ]
  },
  "intents": {
    "package": "@fastnear/intents",
    "runtime": "Package-only; not included in agents.js or near.js.",
    "guideUrl": "https://github.com/fastnear/js-monorepo/blob/main/packages/intents/README.md",
    "protocol": {
      "verifierContract": "intents.near",
      "network": "mainnet",
      "ledger": "NEP-245 multi-token; token ids nep141:<contract>, nep171:<contract>:<id>, nep245:<contract>:<id>",
      "signing": "NEP-413 signed messages (full-access keys only); the verifier also accepts erc191, tip191, raw_ed25519, webauthn, ton_connect, and sep53 payloads",
      "oneClickBaseUrl": "https://1click.chaindefuser.com",
      "solverRelayUrl": "https://solver-relay-v2.chaindefuser.com/rpc"
    },
    "browserGlobal": "nearIntents",
    "browserStatus": "The wallet signing path uses nearWallet.signMessage (NEP-413), which every near-connect executor implements; the funded end-to-end swap path is verified by the mainnet smoke runbook before being documented further.",
    "walletFeatures": [
      "signMessage"
    ],
    "chooseByTask": [
      {
        "task": "Quote and track a swap",
        "use": [
          "createOneClickClient"
        ],
        "imports": [
          "@fastnear/intents"
        ],
        "status": "stable; keyless use adds a 0.2% platform fee to quotes"
      },
      {
        "task": "Sign intents from a browser wallet",
        "use": [
          "createWalletIntentSigner"
        ],
        "imports": [
          "@fastnear/wallet",
          "@fastnear/intents"
        ],
        "status": "NEP-413 via the connected wallet's full-access key; FunctionCall session keys cannot sign intents"
      },
      {
        "task": "Sign intents from Node.js or an agent",
        "use": [
          "createLocalIntentSigner"
        ],
        "imports": [
          "@fastnear/intents/node"
        ],
        "status": "raw full-access key, server-side only"
      },
      {
        "task": "Deposit, check balances, withdraw on the verifier",
        "use": [
          "ftDepositAction",
          "wrapNearAction",
          "mtBatchBalances",
          "ftWithdrawAction"
        ],
        "imports": [
          "@fastnear/intents",
          "@fastnear/api"
        ],
        "status": "action builders for near.sendTx plus NEP-245 views over injected near.view"
      },
      {
        "task": "Talk to the solver relay directly",
        "use": [
          "createSolverRelayClient"
        ],
        "imports": [
          "@fastnear/intents/relay"
        ],
        "status": "quotes require a partner API key in practice; the 1Click path is the default"
      }
    ],
    "entrypoints": [
      {
        "subpath": "@fastnear/intents",
        "exports": [
          "createOneClickClient",
          "createWalletIntentSigner",
          "createSolverRelayClient",
          "ftDepositAction",
          "wrapNearAction",
          "ftWithdrawAction",
          "mtBalance",
          "mtBatchBalances",
          "toSignedIntent",
          "randomNonce"
        ],
        "purpose": "browser-safe 1Click client, wallet intent signer, verifier helpers, and relay client"
      },
      {
        "subpath": "@fastnear/intents/relay",
        "exports": [
          "createSolverRelayClient"
        ],
        "purpose": "solver-relay JSON-RPC client (quote, publish_intent, publish_intents, get_status)"
      },
      {
        "subpath": "@fastnear/intents/node",
        "exports": [
          "createLocalIntentSigner"
        ],
        "purpose": "local full-access-key NEP-413 intent signer for servers and agents"
      }
    ],
    "constraints": [
      "The verifier is intents.near on NEAR mainnet; there is no public testnet deployment of the intents stack.",
      "NEP-413 intent signatures require a full-access key, and the verifier checks the key is authorized for signer_id.",
      "Submitted signatures use ed25519:<base58> encoding — not the base64 NEAR wallets return; the signers own that conversion.",
      "Native NEAR is not a verifier asset: wrap to wNEAR before depositing, and exit native NEAR only via the native_withdraw intent.",
      "Amounts are base-unit strings, and token_diff diffs must net to zero per token across the executed batch."
    ],
    "safeDefaults": [
      "Quote with dry:true first; commit with dry:false only when ready to fund the deposit address before it expires.",
      "Keep local signer private keys in server-side secret storage, never browser code.",
      "Use a partner API key from partners.near-intents.org to remove the 0.2% keyless platform fee.",
      "Poll /v0/status to a terminal state (SUCCESS, REFUNDED, FAILED) and surface swapDetails on non-success.",
      "Omit msg on ft_withdraw so failed withdrawals stay refundable."
    ],
    "quickstarts": [
      {
        "id": "intents-one-click-quote",
        "title": "Quote a swap and read live pricing",
        "summary": "Discover assets and price a swap with a free dry-run quote — no auth, no funds, no commitment.",
        "language": "js",
        "code": "import { createOneClickClient } from \"@fastnear/intents\";\n\nconst oneClick = createOneClickClient();\n\nconst tokens = await oneClick.tokens();\nconst quote = await oneClick.quote({\n  dry: true,\n  swapType: \"EXACT_INPUT\",\n  slippageTolerance: 100,\n  originAsset: \"nep141:wrap.near\",\n  destinationAsset: \"nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1\",\n  amount: \"1000000000000000000000000\",\n  depositType: \"ORIGIN_CHAIN\",\n  refundTo: \"you.near\",\n  refundType: \"ORIGIN_CHAIN\",\n  recipient: \"you.near\",\n  recipientType: \"DESTINATION_CHAIN\",\n  deadline: new Date(Date.now() + 10 * 60_000).toISOString(),\n});\n\nconsole.log(quote.quote.amountOutFormatted);"
      },
      {
        "id": "intents-wallet-sign",
        "title": "Sign a token_diff intent with a browser wallet",
        "summary": "NEP-413 through the connected wallet, re-encoded to the MultiPayload the verifier accepts.",
        "language": "js",
        "code": "import { createWalletIntentSigner } from \"@fastnear/intents\";\n// window.nearWallet from https://js.fastnear.com/wallet.js, already connected.\n\nconst signer = createWalletIntentSigner({ wallet: nearWallet });\n\nconst signed = await signer.signIntents({\n  intents: [{\n    intent: \"token_diff\",\n    diff: {\n      \"nep141:usdc.near\": \"-1000000\",\n      \"nep141:usdt.near\": \"1000000\",\n    },\n  }],\n});\n// signed = { standard: \"nep413\", payload, public_key, signature } — submit via\n// oneClick.submitIntent, relay.publishIntent, or intents.near execute_intents."
      },
      {
        "id": "intents-node-swap",
        "title": "Swap intents.near balances from Node.js",
        "summary": "The INTENTS deposit type: 1Click builds the payload, the local signer signs it verbatim, no deposit transaction needed.",
        "language": "js",
        "code": "import { createOneClickClient } from \"@fastnear/intents\";\nimport { createLocalIntentSigner } from \"@fastnear/intents/node\";\n\nconst { NEAR_ACCOUNT_ID, NEAR_PRIVATE_KEY } = process.env;\nconst oneClick = createOneClickClient();\nconst signer = createLocalIntentSigner({\n  accountId: NEAR_ACCOUNT_ID,\n  privateKey: NEAR_PRIVATE_KEY, // full-access, server-side only\n});\n\n// Quote with depositType/refundType/recipientType \"INTENTS\" — the input\n// funds already sit inside intents.near, so no deposit transaction is needed.\nconst quote = await oneClick.quote({\n  dry: false,\n  swapType: \"EXACT_INPUT\",\n  slippageTolerance: 100,\n  originAsset: \"nep141:wrap.near\",\n  destinationAsset: \"nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1\",\n  amount: \"1000000000000000000000000\",\n  depositType: \"INTENTS\",\n  refundTo: NEAR_ACCOUNT_ID,\n  refundType: \"INTENTS\",\n  recipient: NEAR_ACCOUNT_ID,\n  recipientType: \"INTENTS\",\n  deadline: new Date(Date.now() + 10 * 60_000).toISOString(),\n});\nconst { intent } = await oneClick.generateIntent({\n  signerId: NEAR_ACCOUNT_ID,\n  depositAddress: quote.quote.depositAddress,\n});\n// signPayload pins the recipient to intents.near and signs verbatim.\nconst signed = await signer.signPayload(intent);\nconst { intentHash } = await oneClick.submitIntent({ signedData: signed });\nconsole.log(intentHash);"
      },
      {
        "id": "intents-deposit-balances",
        "title": "Deposit wNEAR and read verifier balances",
        "summary": "Action builders for near.sendTx plus NEP-245 ledger views over the injected near.view.",
        "language": "js",
        "code": "import { ftDepositAction, wrapNearAction, mtBatchBalances } from \"@fastnear/intents\";\n\nawait near.sendTx({\n  receiverId: \"wrap.near\",\n  actions: [wrapNearAction({ amountYocto: \"1000000000000000000000000\" })],\n});\nawait near.sendTx({\n  receiverId: \"wrap.near\",\n  actions: [ftDepositAction({ amount: \"1000000000000000000000000\" })],\n});\n\nconst balances = await mtBatchBalances({\n  accountId: near.accountId(),\n  tokenIds: [\"nep141:wrap.near\"],\n  view: near.view,\n});\nnear.print(balances);"
      }
    ]
  },
  "explain": [
    {
      "api": "near.explain.action",
      "summary": "Normalize one action into a stable JSON summary.",
      "example": "{\n  \"kind\": \"action\",\n  \"type\": \"FunctionCall\",\n  \"methodName\": \"draw\",\n  \"gas\": \"100000000000000\",\n  \"deposit\": \"0\",\n  \"args\": {\n    \"pixels\": [\n      {\n        \"x\": 10,\n        \"y\": 20,\n        \"color\": 65280\n      }\n    ]\n  },\n  \"argsBase64\": null,\n  \"params\": {\n    \"methodName\": \"draw\",\n    \"gas\": \"100000000000000\",\n    \"deposit\": \"0\",\n    \"args\": {\n      \"pixels\": [\n        {\n          \"x\": 10,\n          \"y\": 20,\n          \"color\": 65280\n        }\n      ]\n    },\n    \"argsBase64\": null\n  }\n}"
    },
    {
      "api": "near.explain.tx",
      "summary": "Summarize a signer, receiver, and action list into stable JSON.",
      "example": "{\n  \"kind\": \"transaction\",\n  \"signerId\": \"root.near\",\n  \"receiverId\": \"berryclub.ek.near\",\n  \"actionCount\": 1,\n  \"actions\": [\n    {\n      \"kind\": \"action\",\n      \"type\": \"FunctionCall\",\n      \"methodName\": \"draw\",\n      \"gas\": \"100000000000000\",\n      \"deposit\": \"0\",\n      \"args\": {\n        \"pixels\": [\n          {\n            \"x\": 10,\n            \"y\": 20,\n            \"color\": 65280\n          }\n        ]\n      },\n      \"argsBase64\": null,\n      \"params\": {\n        \"methodName\": \"draw\",\n        \"gas\": \"100000000000000\",\n        \"deposit\": \"0\",\n        \"args\": {\n          \"pixels\": [\n            {\n              \"x\": 10,\n              \"y\": 20,\n              \"color\": 65280\n            }\n          ]\n        },\n        \"argsBase64\": null\n      }\n    }\n  ]\n}"
    },
    {
      "api": "near.explain.error",
      "summary": "Turn thrown RPC, wallet, or transport failures into a predictable JSON object.",
      "example": "{\n  \"kind\": \"rpc_error\",\n  \"code\": -32000,\n  \"name\": \"FastNearError\",\n  \"message\": \"Server error\",\n  \"data\": {\n    \"name\": \"HANDLER_ERROR\"\n  },\n  \"retryable\": true\n}"
    }
  ]
}
