{
  "components": {
    "responses": {
      "Error": {
        "content": {
          "application/json": {
            "schema": {
              "properties": {
                "error": {
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ],
                  "type": "object"
                }
              },
              "required": [
                "error"
              ],
              "type": "object"
            }
          }
        },
        "description": "Error envelope"
      }
    },
    "securitySchemes": {
      "apiKeyHeader": {
        "in": "header",
        "name": "X-Api-Key",
        "type": "apiKey"
      },
      "apiKeyQuery": {
        "in": "query",
        "name": "apikey",
        "type": "apiKey"
      },
      "internalToken": {
        "in": "header",
        "name": "X-Internal-Token",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "GENERATED — do not hand-edit. Produced by walking the router tree in crates/ps-api/tests/openapi.rs; run `PSV2_OPENAPI_WRITE=1 cargo test -p ps-api --test openapi` to regenerate.\n\nThe API and its data are provided as is, without warranty of any kind, and are not financial advice. Data comes from public blockchain networks and third-party sources and may be delayed, incomplete or wrong; unfinalized data can change. We accept no liability for loss arising from its use. API use is subject to your plan's limits. See the [Terms of Use](/terms).\n\n99% monthly uptime SLA: if the API's availability falls below 99% in a calendar month, the downtime is credited back to your plan at 2×, automatically. Details: https://pulsescanner.io/terms#sla",
    "termsOfService": "https://pulsescanner.io/terms",
    "title": "PulseScanner V2 API",
    "version": "2.0.0-dev"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api": {
      "get": {
        "description": "Always HTTP 200; failures ride in the envelope as `{\"status\":\"0\"}`. GET query params and an x-www-form-urlencoded body are both accepted, body wins on collision.\n\n**`module=proxy&action=eth_sendrawtransaction`** no longer forwards to the local node, which accepts and holds transactions without propagating them. It uses the wallet endpoint's public submission upstream. Three consequences:\n\n- With no submission upstream configured: HTTP 200 `{\"status\":\"0\",\"message\":\"NOTOK\",\"result\":\"eth_sendRawTransaction is not available on this endpoint: no public submission upstream is configured...\"}`.\n- The success leg now carries an always-present `\"error\": null` beside `result`, so a client can branch on one shape.\n- An unreachable submission upstream is HTTP 503 where it was 500: the request was well-formed and the estate could not serve it.\n\nSupported pairs:\n\n- `account.addresstokenbalance` — class Lm, requires a key (Starter+)\n- `account.balance` — class Lm, requires a key (Starter+)\n- `account.balancemulti` — class Lm, requires a key (Starter+)\n- `account.tokenbalance` — class Lm, requires a key (Starter+)\n- `account.tokentx` — class Lm, requires a key (Starter+)\n- `account.txlist` — class Lm, requires a key (Starter+)\n- `account.txlistinternal` — class Lm, requires a key (Starter+)\n- `block.getblockcountdown` — class Lm, requires a key (Starter+)\n- `block.getblocknobytime` — class Lm, requires a key (Starter+)\n- `block.getblockreward` — class Lm, requires a key (Starter+)\n- `logs.getlogs` — class Lm, requires a key (Starter+)\n- `proxy.eth_blockNumber` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_call` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_estimateGas` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_gasPrice` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getBalance` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getBlockByNumber` — class RpcHeavy, requires a key (Starter+)\n- `proxy.eth_getCode` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getStorageAt` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getTransactionByHash` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getTransactionReceipt` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_sendRawTransaction` — class RpcLight, requires a key (Starter+)\n- `stats.plsprice` — class Lm, requires a key (Starter+)\n- `stats.plssupply` — class Lm, requires a key (Starter+)\n- `token.tokenholderlist` — class H, requires Lite or higher\n- `token.tokeninfo` — class Lm, requires a key (Starter+)\n- `token.tokensupply` — class Lm, requires a key (Starter+)\n- `transaction.getstatus` — class Lm, requires a key (Starter+)\n- `transaction.gettxreceiptstatus` — class Lm, requires a key (Starter+)",
        "operationId": "getApi",
        "parameters": [
          {
            "in": "query",
            "name": "module",
            "required": true,
            "schema": {
              "enum": [
                "account",
                "block",
                "logs",
                "proxy",
                "stats",
                "token",
                "transaction"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": true,
            "schema": {
              "enum": [
                "addresstokenbalance",
                "balance",
                "balancemulti",
                "eth_blockNumber",
                "eth_call",
                "eth_estimateGas",
                "eth_gasPrice",
                "eth_getBalance",
                "eth_getBlockByNumber",
                "eth_getCode",
                "eth_getStorageAt",
                "eth_getTransactionByHash",
                "eth_getTransactionReceipt",
                "eth_sendRawTransaction",
                "getblockcountdown",
                "getblocknobytime",
                "getblockreward",
                "getlogs",
                "getstatus",
                "gettxreceiptstatus",
                "plsprice",
                "plssupply",
                "tokenbalance",
                "tokenholderlist",
                "tokeninfo",
                "tokensupply",
                "tokentx",
                "txlist",
                "txlistinternal"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "apikey",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "result": {},
                    "status": {
                      "enum": [
                        "0",
                        "1"
                      ],
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "message",
                    "result"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Etherscan envelope"
          }
        },
        "summary": "Etherscan-compatible query surface: the module, action and address parameters an existing client already sends",
        "tags": [
          "etherscan-compat"
        ],
        "x-auth": "api-key",
        "x-cu-budget": "plan",
        "x-cu-class": "Lm; H for token.tokenholderlist; RpcLight for proxy.*; RpcHeavy for proxy.eth_getBlockByNumber; 3 units when the block span >= 2000 (logs.getlogs); 1 unit for an invalid module/action",
        "x-cu-units": [
          1,
          2,
          3,
          5
        ],
        "x-min-tier": "Anon"
      },
      "post": {
        "description": "Always HTTP 200; failures ride in the envelope as `{\"status\":\"0\"}`. GET query params and an x-www-form-urlencoded body are both accepted, body wins on collision.\n\n**`module=proxy&action=eth_sendrawtransaction`** no longer forwards to the local node, which accepts and holds transactions without propagating them. It uses the wallet endpoint's public submission upstream. Three consequences:\n\n- With no submission upstream configured: HTTP 200 `{\"status\":\"0\",\"message\":\"NOTOK\",\"result\":\"eth_sendRawTransaction is not available on this endpoint: no public submission upstream is configured...\"}`.\n- The success leg now carries an always-present `\"error\": null` beside `result`, so a client can branch on one shape.\n- An unreachable submission upstream is HTTP 503 where it was 500: the request was well-formed and the estate could not serve it.\n\nSupported pairs:\n\n- `account.addresstokenbalance` — class Lm, requires a key (Starter+)\n- `account.balance` — class Lm, requires a key (Starter+)\n- `account.balancemulti` — class Lm, requires a key (Starter+)\n- `account.tokenbalance` — class Lm, requires a key (Starter+)\n- `account.tokentx` — class Lm, requires a key (Starter+)\n- `account.txlist` — class Lm, requires a key (Starter+)\n- `account.txlistinternal` — class Lm, requires a key (Starter+)\n- `block.getblockcountdown` — class Lm, requires a key (Starter+)\n- `block.getblocknobytime` — class Lm, requires a key (Starter+)\n- `block.getblockreward` — class Lm, requires a key (Starter+)\n- `logs.getlogs` — class Lm, requires a key (Starter+)\n- `proxy.eth_blockNumber` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_call` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_estimateGas` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_gasPrice` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getBalance` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getBlockByNumber` — class RpcHeavy, requires a key (Starter+)\n- `proxy.eth_getCode` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getStorageAt` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getTransactionByHash` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_getTransactionReceipt` — class RpcLight, requires a key (Starter+)\n- `proxy.eth_sendRawTransaction` — class RpcLight, requires a key (Starter+)\n- `stats.plsprice` — class Lm, requires a key (Starter+)\n- `stats.plssupply` — class Lm, requires a key (Starter+)\n- `token.tokenholderlist` — class H, requires Lite or higher\n- `token.tokeninfo` — class Lm, requires a key (Starter+)\n- `token.tokensupply` — class Lm, requires a key (Starter+)\n- `transaction.getstatus` — class Lm, requires a key (Starter+)\n- `transaction.gettxreceiptstatus` — class Lm, requires a key (Starter+)",
        "operationId": "postApi",
        "parameters": [
          {
            "in": "query",
            "name": "module",
            "required": true,
            "schema": {
              "enum": [
                "account",
                "block",
                "logs",
                "proxy",
                "stats",
                "token",
                "transaction"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": true,
            "schema": {
              "enum": [
                "addresstokenbalance",
                "balance",
                "balancemulti",
                "eth_blockNumber",
                "eth_call",
                "eth_estimateGas",
                "eth_gasPrice",
                "eth_getBalance",
                "eth_getBlockByNumber",
                "eth_getCode",
                "eth_getStorageAt",
                "eth_getTransactionByHash",
                "eth_getTransactionReceipt",
                "eth_sendRawTransaction",
                "getblockcountdown",
                "getblocknobytime",
                "getblockreward",
                "getlogs",
                "getstatus",
                "gettxreceiptstatus",
                "plsprice",
                "plssupply",
                "tokenbalance",
                "tokenholderlist",
                "tokeninfo",
                "tokensupply",
                "tokentx",
                "txlist",
                "txlistinternal"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "apikey",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "result": {},
                    "status": {
                      "enum": [
                        "0",
                        "1"
                      ],
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "message",
                    "result"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Etherscan envelope"
          }
        },
        "summary": "Etherscan-compatible query surface: the module, action and address parameters an existing client already sends",
        "tags": [
          "etherscan-compat"
        ],
        "x-auth": "api-key",
        "x-cu-budget": "plan",
        "x-cu-class": "Lm; H for token.tokenholderlist; RpcLight for proxy.*; RpcHeavy for proxy.eth_getBlockByNumber; 3 units when the block span >= 2000 (logs.getlogs); 1 unit for an invalid module/action",
        "x-cu-units": [
          1,
          2,
          3,
          5
        ],
        "x-min-tier": "Anon"
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Liveness probe: 503 once the indexed head is older than the configured staleness limit",
        "tags": [
          "health"
        ],
        "x-auth": "open",
        "x-cu-budget": "none",
        "x-cu-class": "none",
        "x-cu-units": 0,
        "x-min-tier": "None"
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenapiJson",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "This API description, served from the same document the build publishes",
        "tags": [
          "openapi.json"
        ],
        "x-auth": "open",
        "x-cu-budget": "none",
        "x-cu-class": "none",
        "x-cu-units": 0,
        "x-min-tier": "None"
      }
    },
    "/rpc": {
      "post": {
        "description": "Raw JSON-RPC 2.0 over POST. A wallet cannot send a custom header, so the API key rides in the path (`/rpc/<key>`) or as `?apikey=`.\n\n**Add this network in your wallet:**\n\n- RPC URL: `https://api.pulsescanner.io/rpc/<key>`\n- Chain ID: `369`\n- Currency symbol: `PLS`\n- Block explorer: `https://pulsescanner.io`\n\nBatches of up to 10 calls. `eth_getLogs` takes EITHER a `blockHash` OR a `fromBlock`/`toBlock` range (both bounds required, tags resolved against the indexed head, the range capped, and the node receives explicit hex block numbers); a filter carrying `blockHash` beside a range is refused (-32602); with no indexed head a block tag is refused. It is bounded by your plan's block range, 10 addresses and 4 topic positions.\n\nA method outside the list below is answered `-32601` at HTTP 200; an invalid key is HTTP 401 and a rate limit HTTP 429, both carrying a JSON-RPC error object.\n\nSupported methods:\n\n- eth_chainId\n- net_version\n- eth_blockNumber\n- eth_getBalance\n- eth_getCode\n- eth_getTransactionCount\n- eth_gasPrice\n- eth_feeHistory\n- eth_maxPriorityFeePerGas\n- eth_estimateGas\n- eth_call\n- eth_getBlockByNumber\n- eth_getBlockByHash\n- eth_getTransactionByHash\n- eth_getTransactionReceipt\n- eth_getLogs\n- eth_sendRawTransaction\n- web3_clientVersion",
        "operationId": "postRpc",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "A JSON-RPC 2.0 request object, or an array of them.",
                "oneOf": [
                  {
                    "properties": {
                      "id": {},
                      "jsonrpc": {
                        "enum": [
                          "2.0"
                        ],
                        "type": "string"
                      },
                      "method": {
                        "enum": [
                          "eth_chainId",
                          "net_version",
                          "eth_blockNumber",
                          "eth_getBalance",
                          "eth_getCode",
                          "eth_getTransactionCount",
                          "eth_gasPrice",
                          "eth_feeHistory",
                          "eth_maxPriorityFeePerGas",
                          "eth_estimateGas",
                          "eth_call",
                          "eth_getBlockByNumber",
                          "eth_getBlockByHash",
                          "eth_getTransactionByHash",
                          "eth_getTransactionReceipt",
                          "eth_getLogs",
                          "eth_sendRawTransaction",
                          "web3_clientVersion"
                        ],
                        "type": "string"
                      },
                      "params": {
                        "type": "array"
                      }
                    },
                    "required": [
                      "jsonrpc",
                      "method"
                    ],
                    "type": "object"
                  },
                  {
                    "maxItems": 10,
                    "type": "array"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    },
                    "id": {},
                    "jsonrpc": {
                      "enum": [
                        "2.0"
                      ],
                      "type": "string"
                    },
                    "result": {}
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A JSON-RPC 2.0 response, or an array of them for a batch. Protocol-level refusals (-32600, -32601, -32602) and upstream error objects both ride here at HTTP 200."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "JSON-RPC 2.0 for wallets — key in the `X-Api-Key` header or `?apikey=`",
        "tags": [
          "wallet-rpc"
        ],
        "x-auth": "api-key",
        "x-cu-budget": "plan",
        "x-cu-class": "RpcLight; RpcHeavy for eth_getBlockByNumber, eth_getBlockByHash, eth_getLogs",
        "x-cu-units": [
          2,
          5
        ],
        "x-cu-units-note": "per CALL; a batch of N charges the sum of its calls, up to 10 calls and 50 CU per request",
        "x-min-tier": "Free"
      }
    },
    "/rpc/{key}": {
      "post": {
        "description": "Raw JSON-RPC 2.0 over POST. A wallet cannot send a custom header, so the API key rides in the path (`/rpc/<key>`) or as `?apikey=`.\n\n**Add this network in your wallet:**\n\n- RPC URL: `https://api.pulsescanner.io/rpc/<key>`\n- Chain ID: `369`\n- Currency symbol: `PLS`\n- Block explorer: `https://pulsescanner.io`\n\nBatches of up to 10 calls. `eth_getLogs` takes EITHER a `blockHash` OR a `fromBlock`/`toBlock` range (both bounds required, tags resolved against the indexed head, the range capped, and the node receives explicit hex block numbers); a filter carrying `blockHash` beside a range is refused (-32602); with no indexed head a block tag is refused. It is bounded by your plan's block range, 10 addresses and 4 topic positions.\n\nA method outside the list below is answered `-32601` at HTTP 200; an invalid key is HTTP 401 and a rate limit HTTP 429, both carrying a JSON-RPC error object.\n\nSupported methods:\n\n- eth_chainId\n- net_version\n- eth_blockNumber\n- eth_getBalance\n- eth_getCode\n- eth_getTransactionCount\n- eth_gasPrice\n- eth_feeHistory\n- eth_maxPriorityFeePerGas\n- eth_estimateGas\n- eth_call\n- eth_getBlockByNumber\n- eth_getBlockByHash\n- eth_getTransactionByHash\n- eth_getTransactionReceipt\n- eth_getLogs\n- eth_sendRawTransaction\n- web3_clientVersion\n\n**The key appears in the URL: proxies and logs may record it; prefer the header form.**",
        "operationId": "postRpcByKey",
        "parameters": [
          {
            "in": "path",
            "name": "key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "A JSON-RPC 2.0 request object, or an array of them.",
                "oneOf": [
                  {
                    "properties": {
                      "id": {},
                      "jsonrpc": {
                        "enum": [
                          "2.0"
                        ],
                        "type": "string"
                      },
                      "method": {
                        "enum": [
                          "eth_chainId",
                          "net_version",
                          "eth_blockNumber",
                          "eth_getBalance",
                          "eth_getCode",
                          "eth_getTransactionCount",
                          "eth_gasPrice",
                          "eth_feeHistory",
                          "eth_maxPriorityFeePerGas",
                          "eth_estimateGas",
                          "eth_call",
                          "eth_getBlockByNumber",
                          "eth_getBlockByHash",
                          "eth_getTransactionByHash",
                          "eth_getTransactionReceipt",
                          "eth_getLogs",
                          "eth_sendRawTransaction",
                          "web3_clientVersion"
                        ],
                        "type": "string"
                      },
                      "params": {
                        "type": "array"
                      }
                    },
                    "required": [
                      "jsonrpc",
                      "method"
                    ],
                    "type": "object"
                  },
                  {
                    "maxItems": 10,
                    "type": "array"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    },
                    "id": {},
                    "jsonrpc": {
                      "enum": [
                        "2.0"
                      ],
                      "type": "string"
                    },
                    "result": {}
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A JSON-RPC 2.0 response, or an array of them for a batch. Protocol-level refusals (-32600, -32601, -32602) and upstream error objects both ride here at HTTP 200."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "JSON-RPC 2.0 for wallets — key in the URL path segment (`/rpc/<key>`)",
        "tags": [
          "wallet-rpc"
        ],
        "x-auth": "api-key",
        "x-cu-budget": "plan",
        "x-cu-class": "RpcLight; RpcHeavy for eth_getBlockByNumber, eth_getBlockByHash, eth_getLogs",
        "x-cu-units": [
          2,
          5
        ],
        "x-cu-units-note": "per CALL; a batch of N charges the sum of its calls, up to 10 calls and 50 CU per request",
        "x-min-tier": "Free"
      }
    },
    "/v2/account": {
      "get": {
        "operationId": "getV2Account",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The signed-in account: its wallet, tier and current limits",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/entitlements": {
      "get": {
        "operationId": "getV2AccountEntitlements",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Every entitlement on the signed-in account, with its tier, bonus and effective window",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/keys": {
      "get": {
        "operationId": "getV2AccountKeys",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The account's API keys by prefix and status; a key's secret is shown once at creation and never again",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      },
      "post": {
        "operationId": "postV2AccountKeys",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Create an API key and return its secret once",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/keys/{id}": {
      "delete": {
        "operationId": "deleteV2AccountKeysById",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Revoke an API key",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/lists": {
      "get": {
        "operationId": "getV2AccountLists",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One of this account's address lists.",
                        "properties": {
                          "created_at": {
                            "description": "Unix seconds.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "list_id": {
                            "type": "string"
                          },
                          "member_count": {
                            "description": "How many addresses are in it. Bounded by `LISTS_MAX_MEMBERS`.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "created_at",
                          "list_id",
                          "member_count",
                          "name"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The account's address lists, each with its member count",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      },
      "post": {
        "operationId": "postV2AccountLists",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "Body of `POST /v2/account/lists` and `PATCH /v2/account/lists/{id}`.",
                "properties": {
                  "name": {
                    "description": "1..=64 characters after trimming, no control characters. Case-insensitively unique within the account: \"Whales\" and \"whales\" are one list.",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One of this account's address lists.",
                      "properties": {
                        "created_at": {
                          "description": "Unix seconds.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "list_id": {
                          "type": "string"
                        },
                        "member_count": {
                          "description": "How many addresses are in it. Bounded by `LISTS_MAX_MEMBERS`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "created_at",
                        "list_id",
                        "member_count",
                        "name"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "lists_full",
                            "name_rejected",
                            "name_taken",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Create an address list",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/lists/{id}": {
      "delete": {
        "operationId": "deleteV2AccountListsById",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No body."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Delete an address list and its members",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      },
      "get": {
        "operationId": "getV2AccountListsById",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One list with its members. `GET /v2/account/lists/{id}`.",
                      "properties": {
                        "addresses": {
                          "description": "Every address in the list, lowercase `0x`-prefixed, ordered. Complete — `LISTS_MAX_MEMBERS` is what makes \"all of them\" a bounded answer, so there is no cursor and no truncation.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "created_at": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "list_id": {
                          "type": "string"
                        },
                        "member_count": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "addresses",
                        "created_at",
                        "list_id",
                        "member_count",
                        "name"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One address list and its members",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      },
      "patch": {
        "operationId": "patchV2AccountListsById",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "Body of `POST /v2/account/lists` and `PATCH /v2/account/lists/{id}`.",
                "properties": {
                  "name": {
                    "description": "1..=64 characters after trimming, no control characters. Case-insensitively unique within the account: \"Whales\" and \"whales\" are one list.",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One of this account's address lists.",
                      "properties": {
                        "created_at": {
                          "description": "Unix seconds.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "list_id": {
                          "type": "string"
                        },
                        "member_count": {
                          "description": "How many addresses are in it. Bounded by `LISTS_MAX_MEMBERS`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "created_at",
                        "list_id",
                        "member_count",
                        "name"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "name_rejected",
                            "name_taken",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Rename an address list",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/lists/{id}/addresses": {
      "post": {
        "operationId": "postV2AccountListsByIdAddresses",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "Body of `POST /v2/account/lists/{id}/addresses`.",
                "properties": {
                  "address": {
                    "description": "`0x`-prefixed 20-byte address. Case-insensitive.",
                    "type": "string"
                  }
                },
                "required": [
                  "address"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One address added to a list.",
                      "properties": {
                        "added_at": {
                          "description": "Unix seconds.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "address": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "added_at",
                        "address"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "list_full",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Add an address to a list",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/lists/{id}/addresses/{address}": {
      "delete": {
        "operationId": "deleteV2AccountListsByIdAddressesByAddress",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No body."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Remove an address from a list",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/logout": {
      "post": {
        "operationId": "postV2AccountLogout",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "End the current session",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/pending": {
      "get": {
        "operationId": "getV2AccountPending",
        "parameters": [
          {
            "description": "The wallet to check for unclaimed on-chain purchases, `0x`-prefixed and 20 bytes. REQUIRED — this route answers for one wallet and has no session to infer it from.",
            "in": "query",
            "name": "wallet",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Tier credits paid for by this wallet and not yet claimed",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/siwe/nonce": {
      "post": {
        "operationId": "postV2AccountSiweNonce",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Issue a single-use nonce for a Sign-In With Ethereum message",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/siwe/verify": {
      "post": {
        "operationId": "postV2AccountSiweVerify",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Verify a signed Sign-In With Ethereum message and open a session",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/tags": {
      "get": {
        "operationId": "getV2AccountTags",
        "parameters": [
          {
            "description": "Keyset cursor: the `address` of the last row on the previous page. Exclusive — the next page starts strictly after it.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One of this account's tags.",
                        "properties": {
                          "address": {
                            "description": "The tagged address, lowercase `0x`-prefixed.",
                            "type": "string"
                          },
                          "created_at": {
                            "description": "Unix seconds. For an imported tag this is V1's original creation time, not the time of the import.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "label": {
                            "description": "The label this account gave it. 1..=64 characters.",
                            "type": "string"
                          },
                          "source": {
                            "description": "`v1_import` — carried over from the V1 portal and never edited here. `user` — created or last edited in V2. Editing an imported tag flips it to `user`, because after the edit the label is no longer what V1 held.",
                            "type": "string"
                          },
                          "updated_at": {
                            "description": "Unix seconds.",
                            "format": "int64",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "address",
                          "created_at",
                          "label",
                          "source",
                          "updated_at"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The account's private address labels",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/tags/lookup": {
      "get": {
        "operationId": "getV2AccountTagsLookup",
        "parameters": [
          {
            "description": "Comma-separated addresses, at most 100. Case-insensitive.",
            "in": "query",
            "name": "addresses",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "additionalProperties": {
                        "type": "string"
                      },
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Private labels for a batch of addresses, for annotating a page the account is viewing",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/tags/{address}": {
      "delete": {
        "operationId": "deleteV2AccountTagsByAddress",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No body."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Delete the account's private label for one address",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      },
      "put": {
        "operationId": "putV2AccountTagsByAddress",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "Body of `PUT /v2/account/tags/{address}`.",
                "properties": {
                  "label": {
                    "description": "1..=64 characters after trimming. Stored verbatim.",
                    "type": "string"
                  }
                },
                "required": [
                  "label"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One of this account's tags.",
                      "properties": {
                        "address": {
                          "description": "The tagged address, lowercase `0x`-prefixed.",
                          "type": "string"
                        },
                        "created_at": {
                          "description": "Unix seconds. For an imported tag this is V1's original creation time, not the time of the import.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "label": {
                          "description": "The label this account gave it. 1..=64 characters.",
                          "type": "string"
                        },
                        "source": {
                          "description": "`v1_import` — carried over from the V1 portal and never edited here. `user` — created or last edited in V2. Editing an imported tag flips it to `user`, because after the edit the label is no longer what V1 held.",
                          "type": "string"
                        },
                        "updated_at": {
                          "description": "Unix seconds.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "address",
                        "created_at",
                        "label",
                        "source",
                        "updated_at"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "label_rejected",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Create or replace the account's private label for one address",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/account/usage": {
      "get": {
        "operationId": "getV2AccountUsage",
        "parameters": [
          {
            "description": "Window in days. Default 30, clamped to 400.\n\nCLAMPED, not refused: `days=100000` answers 400 days of data and the response echoes `days: 400`, so the caller is told what it actually got rather than being corrected silently. Values below 1 fall back to the 30-day default the same way. A NON-NUMERIC `days` is a 400 (`bad_request`) — it means the caller believes it set a window and did not, which is the case worth failing (`util::empty_as_none`'s rule).",
            "in": "query",
            "name": "days",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Restrict the charts to one API key, as a uuid. Absent = every key on the account. A value that is not a uuid is refused rather than ignored.",
            "in": "query",
            "name": "key_id",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {}
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Call units and request counts for the signed-in account, by day and endpoint class",
        "tags": [
          "v2"
        ],
        "x-auth": "siwe-session",
        "x-cu-budget": "per-ip",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "None"
      }
    },
    "/v2/beacon/stats": {
      "get": {
        "operationId": "getV2BeaconStats",
        "parameters": [
          {
            "description": "`1d` (default) | `7d` | `30d` | `90d`. **`1d` is the last COMPLETE UTC day**, so at 23:00 UTC it describes yesterday.",
            "in": "query",
            "name": "window",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The stat bar. Every ratio ships with its numerator AND its denominator.",
                      "properties": {
                        "active_validators": {
                          "description": "**`status LIKE 'active%'`** — `active_ongoing + active_exiting + active_slashed`, which is the registry's own definition of active and is **NOT** `status_mix.groups[\"active_ongoing\"]`. The two answer different questions and a consumer comparing them will find them unequal on a healthy chain; `status_mix.raw` is what lets it see why.\n\n**AND IT IS NOT `queue_estimates.churn.active_validators` EITHER.** That one is the reader-facing panel's `active` fold — ongoing + exiting, WITHOUT slashed. Both are right for their own question: this field answers \"how many rows does the registry call active\", the churn one answers \"how many validators does the churn limit divide over\". The difference between them is exactly `status_mix.groups[\"slashed\"]`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "as_of_ts": {
                          "description": "Unix seconds at which the window CLOSES — the end of `epoch_to`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "attestation_pct": {
                          "description": "`attestations_included / epochs_observed`. **Null when observed is 0 or null** — never 0, which would read as total failure.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "attestations_included": {
                          "description": "Attestations included over the window. Numerator.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "backfill_frontier_epoch": {
                          "description": "How far the historical walk has got. Null = it has never run.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "blocks_proposed": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "cl_reward_gwei": {
                          "description": "Signed string: CL rewards are legitimately negative under penalties.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "daily_rows_through": {
                          "description": "**THE DIVERGENCE DISCLOSURE.** `max(day)` in `beacon.validator_daily`.\n\nWhen this is **below `day_to`**, the per-entity aggregate covers fewer days than the window states — `ROLL_DAY_SQL` emits no `validator_daily` row for a day with no detail and no attributable blocks, so a total-ingestion-outage day rolls 270 `epoch_totals` rows and none here. The stat bar (which reads `epoch_totals`) still covers that day; the entity rows cannot. **A client comparing the two must read this field**, and `entity_days_missing` gives the gap as a number.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "day_from": {
                          "description": "The FIRST UTC day of the window: `day_to - (days - 1)`. Exact, because a UTC day is exactly 270 epochs.",
                          "type": "string"
                        },
                        "day_to": {
                          "description": "The LAST UTC day of the window, `YYYY-MM-DD` — the day containing `epoch_to`. **Every day range on every surface is derived from this**, so the envelope and the entity rows cannot describe different windows.",
                          "type": "string"
                        },
                        "entity_days_missing": {
                          "description": "`day_to − daily_rows_through` in days, or null when the disclosure does not apply. **0 is the healthy case**; above 0 is the outage shape above.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "epoch_from": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epoch_to": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_assigned": {
                          "description": "Validator-epochs that SHOULD have attested, from the activation/exit overlap. Pure arithmetic, zero IO. `assigned - observed` is the gap.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "epochs_captured": {
                          "description": "How many of those epochs `beacon.epoch_totals` reports as `captured`. **Below `epochs_expected` means the reward sums are partial** — and for a RANKING, a coverage fraction understates the problem: order can differ, not just magnitude.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_expected": {
                          "description": "`epoch_to - epoch_from + 1`. Equal to `window_epochs` except where the window would run below genesis.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_observed": {
                          "description": "Validator-epochs we have a RECORD for. **This is `attestation_pct`'s denominator** (§12 decision 1) — dividing by `epochs_assigned` instead would conflate the chain's behaviour with our ingestion coverage.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "exec_reward_wei": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "missed_attributed": {
                          "description": "Missed slots whose proposer is known — `missed_slots` minus the unattributable part, which is why the identity holds structurally.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "missed_slots": {
                          "description": "The whole. `missed_attributed + missed_unattributable == missed_slots` by construction.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "missed_unattributable": {
                          "description": "Missed slots with no proposer recorded. Falls as the walk's attribution leg progresses; read it with `backfill_frontier_epoch`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "queue_estimates": {
                          "description": "**HOW LONG THE QUEUES TAKE**, from the consensus spec the NODE reports. Additive: every field above is unchanged. See `crate::v2::queues` for why the spec is fetched and never compiled in, and why the activation cap is a Deneb rule rather than a constant's presence.",
                          "properties": {
                            "churn": {
                              "description": "`null` when there is no spec to compute it from.",
                              "properties": {
                                "activation_cap_applied": {
                                  "type": "boolean"
                                },
                                "activation_lookahead_epochs": {
                                  "description": "`1 + MAX_SEED_LOOKAHEAD` — `compute_activation_exit_epoch` is `current + 1 + MAX_SEED_LOOKAHEAD`, so a validator that clears the queue still waits this many epochs before it is active.",
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "active_validators": {
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "epoch_seconds": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "governing_fork": {
                                  "description": "Which fork's rules govern at `current_epoch`.\n\nOnly the distinction this arithmetic turns on is modelled: at or past Deneb the activation cap applies, before it the cap does not. A finer ladder would be a schema this module cannot justify.",
                                  "oneOf": [
                                    {
                                      "description": "At or past `DENEB_FORK_EPOCH`.",
                                      "enum": [
                                        "deneb"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "Before it, or Deneb not scheduled (`2^64-1`), or not reported.",
                                      "enum": [
                                        "capella"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                "per_epoch": {
                                  "description": "`max(min_per_epoch_churn_limit, active div churn_limit_quotient)`.",
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "per_epoch_entering": {
                                  "description": "`per_epoch`, capped by EIP-7514 only when the cap GOVERNS.",
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "withdrawability_delay_epochs": {
                                  "description": "`MIN_VALIDATOR_WITHDRAWABILITY_DELAY`.",
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "activation_cap_applied",
                                "activation_lookahead_epochs",
                                "active_validators",
                                "epoch_seconds",
                                "governing_fork",
                                "per_epoch",
                                "per_epoch_entering",
                                "withdrawability_delay_epochs"
                              ],
                              "type": [
                                "object",
                                "null"
                              ]
                            },
                            "entering": {
                              "properties": {
                                "absent_reason": {
                                  "description": "**WHY THERE IS NO READING AT ALL — which is not the same as a read that FAILED** (OPS-84).\n\n`awaiting_inclusion_error` is reserved for a failure the TICK ITSELF recorded: a `DepositError` ps-core stored on a tick that ran. This field carries the other case — `meta.config['beacon.narrow_poll']` is simply ABSENT, because ps-core has not written a tick yet. Production sat in exactly that state between OPS-84 and the ps-core deploy, and with the sentence in `awaiting_inclusion_error` a client could not tell \"not yet\" from \"a read failed\" — the first is a deploy still in flight, the second is an execution client to go and look at.\n\nExactly one of the two is ever set, and both are null once a tick has recorded a reading.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "age_secs": {
                                  "format": "int64",
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "awaiting_inclusion": {
                                  "description": "**DEPOSITS THE EL CONTRACT HAS ACCEPTED THAT THE BEACON CHAIN'S `eth1_data` VOTE HAS NOT YET REACHED.**\n\nThese validators are not in `count` and not in `not_yet_queued` — they are not in the registry at all yet, because the beacon chain has not seen their deposits. **Inclusion follows the eth1 vote: hours, not minutes** (`ETH1_FOLLOW_DISTANCE` plus the voting period), and only then do they appear as `pending_initialized` and start the wait `estimated_seconds` describes.\n\n`null` when ps-core's narrow poll could not read it; the reason is in [`EnteringEstimate::awaiting_inclusion_error`].",
                                  "properties": {
                                    "as_of_block": {
                                      "description": "The EL block `el_deposit_count` was read AT. The `eth_call` is pinned to it, so the two are one reading rather than two that straddled a block.",
                                      "format": "int64",
                                      "type": [
                                        "integer",
                                        "null"
                                      ]
                                    },
                                    "as_of_slot": {
                                      "description": "The CL head slot `eth1_deposit_count` came from.",
                                      "format": "int64",
                                      "type": [
                                        "integer",
                                        "null"
                                      ]
                                    },
                                    "basis": {
                                      "description": "Always [`AWAITING_BASIS`]. The field exists because an exact pending-deposit-queue basis is a real possibility on a later fork, and a silent switch would be invisible.",
                                      "type": "string"
                                    },
                                    "count": {
                                      "description": "`el_deposit_count - eth1_deposit_count`, floored at zero: our EL client can trail the one the chain voted from, and a negative count would read as deposits being un-made.",
                                      "format": "int64",
                                      "type": "integer"
                                    },
                                    "el_deposit_count": {
                                      "description": "`get_deposit_count()` on the chain's own deposit contract — the address ps-core reads from `GET /eth/v1/config/deposit_contract`, never a compiled-in one.",
                                      "format": "int64",
                                      "type": [
                                        "integer",
                                        "null"
                                      ]
                                    },
                                    "eth1_deposit_count": {
                                      "description": "`eth1_data.deposit_count` from the CL head block.",
                                      "format": "int64",
                                      "type": [
                                        "integer",
                                        "null"
                                      ]
                                    },
                                    "tick_at": {
                                      "description": "When the poll tick that read these ran, unix seconds.",
                                      "format": "int64",
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "basis",
                                    "count",
                                    "tick_at"
                                  ],
                                  "type": [
                                    "object",
                                    "null"
                                  ]
                                },
                                "awaiting_inclusion_error": {
                                  "description": "Why [`EnteringEstimate::awaiting_inclusion`] is null. **Never a number** — a reason a client might parse as a value is the failure this field exists to avoid, the same rule `spec_error` follows.\n\n**AND NEVER A HOST, PORT OR URL.** One of a fixed set of sentences, produced by [`awaiting_wire_reason`] from a closed-set enum. It shipped as ps-core's formatted error chain, which published the execution client's address on a route with no `security` entry (audit §134 HIGH 1); the detail now goes to ps-core's warn log, where the operator is.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "count": {
                                  "description": "`pending_queued`.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "estimate_basis": {
                                  "description": "Why an estimate is (or is not) a number.",
                                  "oneOf": [
                                    {
                                      "description": "A queue with entries, estimated from the churn limit.",
                                      "enum": [
                                        "queued"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "The queue is empty. `estimated_seconds` is null — a validator joining now waits the lookahead, not zero, and the FE renders that from `epoch_seconds` rather than from a number this module invents.",
                                      "enum": [
                                        "empty"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "No spec: the node was unreachable and nothing was cached.",
                                      "enum": [
                                        "unavailable"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                "estimated_seconds": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "not_yet_queued": {
                                  "description": "`pending_initialized` — seen, not yet in the churn queue.",
                                  "format": "int64",
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "count",
                                "estimate_basis",
                                "not_yet_queued"
                              ],
                              "type": "object"
                            },
                            "exiting": {
                              "properties": {
                                "age_secs": {
                                  "format": "int64",
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "count": {
                                  "description": "`active_exiting`.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "estimate_basis": {
                                  "description": "Why an estimate is (or is not) a number.",
                                  "oneOf": [
                                    {
                                      "description": "A queue with entries, estimated from the churn limit.",
                                      "enum": [
                                        "queued"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "The queue is empty. `estimated_seconds` is null — a validator joining now waits the lookahead, not zero, and the FE renders that from `epoch_seconds` rather than from a number this module invents.",
                                      "enum": [
                                        "empty"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "No spec: the node was unreachable and nothing was cached.",
                                      "enum": [
                                        "unavailable"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                "estimated_seconds": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "count",
                                "estimate_basis"
                              ],
                              "type": "object"
                            },
                            "spec": {
                              "description": "The consensus-spec fields these estimates need, as the node reports them.\n\nEvery value in the CL's `/eth/v1/config/spec` JSON is a STRING — including the numbers — so each is parsed rather than deserialized as an integer.",
                              "properties": {
                                "churn_limit_quotient": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "deneb_fork_epoch": {
                                  "description": "**A DECIMAL STRING ON THE WIRE, AND THE ATTRIBUTE IS WHAT MAKES IT ONE.** `DENEB_FORK_EPOCH` is `2^64-1` on PulseChain (\"not scheduled\"), and that does not survive a JSON number: a JS consumer parses it into an `f64`, whose 53-bit mantissa rounds it to 18446744073709551616 — a DIFFERENT epoch, and one in the PAST, which would flip the activation cap on for a chain that has not forked.\n\nAn earlier revision carried this paragraph over a bare `Option<u64>` with NO attribute, so the claim was documentation and the wire was a number: the parse side handled the string and the serialize side did not. `serialize_with` + `schemars(with)` are what make the sentence true, and `the_deneb_fork_epoch_is_a_string_on_the_wire` asserts it.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "fetched_at": {
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "max_per_epoch_activation_churn_limit": {
                                  "description": "EIP-7514's activation cap. `None` when the node does not report it.",
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "max_seed_lookahead": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "min_per_epoch_churn_limit": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "min_validator_withdrawability_delay": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "seconds_per_slot": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "slots_per_epoch": {
                                  "format": "uint64",
                                  "minimum": 0.0,
                                  "type": "integer"
                                },
                                "source": {
                                  "description": "Always `cl:/eth/v1/config/spec`, so a reader knows the provenance without asking.",
                                  "type": "string"
                                }
                              },
                              "required": [
                                "churn_limit_quotient",
                                "fetched_at",
                                "max_seed_lookahead",
                                "min_per_epoch_churn_limit",
                                "min_validator_withdrawability_delay",
                                "seconds_per_slot",
                                "slots_per_epoch",
                                "source"
                              ],
                              "type": [
                                "object",
                                "null"
                              ]
                            },
                            "spec_error": {
                              "description": "Why `spec`/`churn` are null, or a note about the spec that a reader needs. **Never a number** — a reason a client might parse as a value is the failure this field exists to avoid.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "entering",
                            "exiting"
                          ],
                          "type": "object"
                        },
                        "slashed_24h": {
                          "description": "**SLASHED VALIDATORS IN THIS WINDOW — and read the basis, because the estate cannot count slashing EVENTS.**\n\n# WHAT IT COUNTS\n\n**Slashed = `status` is `active_slashed` or `exited_slashed`**, matched EXACTLY. `exited_unslashed` is a VOLUNTARY exit and is not slashed, however much the word looks like it.\n\nValidators whose `status` is slashed (`active_slashed` or `exited_slashed`) AND whose `exit_epoch` falls inside the window's epochs. Nothing else in this schema is time-anchored to a slashing:\n\n* **No slashing feed exists.** `grep -i slash` over `schema-v2/migrations/` and over ps-core/ps-batch returns NOTHING — the beacon block body's `proposer_slashings`/`attester_slashings` are not ingested, so there is no event to count in a block window. * `beacon.validators.status` is a CURRENT snapshot: it says a validator is slashed, never when. * `updated_at` (`0008:40`) is the row's last REFRESH, not the slashing.\n\n`exit_epoch` is the only column a slashing writes that carries a time, and it is therefore what this uses.\n\n# THE DISTORTION, STATED RATHER THAN HIDDEN\n\nA slashing assigns a FUTURE `exit_epoch` — roughly the current epoch plus one plus a churn-limited queue — so this counts validators whose forced exit LANDS in the window, not validators slashed during it. The two differ by the queue depth at slashing time. **It is an honest proxy and it is not the event count**, which is why `slashed_basis` ships beside it: a consumer that must not confuse the two can branch on the field rather than on a comment.\n\nMaking it exact needs a slashing feed, which is a ps-core change and is not in this scope.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "slashed_basis": {
                          "description": "What `slashed_24h` was computed from. **Slashed = `status` is `active_slashed` or `exited_slashed`**, matched EXACTLY; `exited_unslashed` is a voluntary exit and is not slashed. Always `\"exit_epoch_window\"` today; the field exists because an exact `slashing_event` basis is a real possibility and a silent switch would be invisible.",
                          "type": "string"
                        },
                        "staked_gwei": {
                          "description": "`SUM(effective_balance_gwei)` over active validators (`0055`), as a signed string. **Null when every row is null** — which is what a cluster whose registry refresh has not yet written the column looks like. **Never 0**: 0 would claim the validators hold nothing.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "staked_source": {
                          "description": "`\"balances\"` when `staked_gwei` is non-null, else null — so a client can tell \"no stake\" from \"no data\" without inspecting the number.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status_mix": {
                          "description": "**Slashed = `status` is `active_slashed` or `exited_slashed`**, matched EXACTLY. `exited_unslashed` is a VOLUNTARY exit and is not slashed.\n\n**NOT WINDOWED.** The registry is a snapshot of the CHAIN AS IT IS NOW, and there is no per-day history of it — so unlike every other figure on this envelope, `status_mix` does not change with `?window=`. It sits beside them rather than inside `window` for exactly that reason.",
                          "properties": {
                            "groups": {
                              "additionalProperties": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "description": "The panel's states, keyed by [`STATUS_GROUPS`]. Every key is always present, with 0 where the registry has none — a missing key and a zero are different statements and only one of them is true here.",
                              "type": "object"
                            },
                            "queues": {
                              "description": "**QUEUE LENGTHS, AND NOTHING THE STATUSES CANNOT SAY.**\n\nThese are COUNTS, not waits. How long a validator will sit in the activation queue is a function of the churn limit, the queue position and the current epoch — none of which `beacon.validators.status` records — so no ETA can be inferred from THESE NUMBERS.\n\n**THE ETA NOW EXISTS, IN `queue_estimates`.** That object derives it from the consensus spec the NODE reports (`crate::v2::queues`), which is exactly the input this struct does not have. Read the waits there and the counts here; the two are computed from the same census, so they cannot disagree.",
                              "properties": {
                                "entering": {
                                  "description": "`pending_queued` — deposits in the activation churn queue.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "entering_not_yet_queued": {
                                  "description": "`pending_initialized` — a deposit the chain has seen that is not yet eligible for the queue. Separate because it is a DIFFERENT wait.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "exiting": {
                                  "description": "`active_exiting` — a VOLUNTARY exit initiated, still attesting until its exit epoch. **Forced (slashed) exits are not counted here**; they are in `groups.slashed`, and blending the two would call a slashing a resignation.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "withdrawable": {
                                  "description": "`withdrawal_possible` — exited, balance sweepable, not yet swept.",
                                  "format": "int64",
                                  "type": "integer"
                                }
                              },
                              "required": [
                                "entering",
                                "entering_not_yet_queued",
                                "exiting",
                                "withdrawable"
                              ],
                              "type": "object"
                            },
                            "raw": {
                              "additionalProperties": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "description": "**THE RAW LIGHTHOUSE STRINGS, UNGROUPED**, so a consumer never has to guess at the grouping above or wait for a backend change to see a status this build did not anticipate. Only keys the registry actually holds.",
                              "type": "object"
                            },
                            "status_panel": {
                              "description": "**THE READER-FACING BUCKETS**, beside `groups`/`raw`/`queues` and replacing none of them. See [`StatusPanel`] and the mapping table on [`status_bucket`] for where the two groupings disagree and why.",
                              "properties": {
                                "active": {
                                  "description": "`active_ongoing` + `active_exiting` — the validators actually securing the chain. See the table on [`status_bucket`] for why an exiting validator is counted here.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "active_exiting": {
                                  "description": "**AN ANNOTATION ON `active`, NOT A PEER OF IT.** Already included in `active`; adding it again double-counts. It answers the operator's question — is the exit queue moving — without making the headline `active` figure wrong for the reader's.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "age_secs": {
                                  "description": "How old that reading is, in seconds, at the moment this response was built.\n\n**READ `refreshed_basis` BEFORE READING A LARGE VALUE.** Under `poll_tick` this is bounded by ps-core's `cl.narrow_refresh_secs` (default 60) plus this response's own 30 s cache. Under `last_write` it is the age of the last CHANGE, which on a quiet chain grows toward the hourly full refresh — at 320 s per epoch an hour is 11.25 epochs, long enough for a validator to traverse the activation queue entirely between two samples.",
                                  "format": "int64",
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "entering": {
                                  "description": "`pending_initialized` + `pending_queued`.\n\n**THE TWO ARE COLLAPSED ON PURPOSE.** Served apart, a chain whose deposits are all still `pending_initialized` reads `entering: 0` while the deposits sit in the sibling field — the exact reading that made this panel necessary. `queues.entering` / `queues.entering_not_yet_queued` still carry the split for a consumer that wants it.\n\n**A ZERO HERE IS NOT \"NO ONE IS JOINING\".** A deposit is invisible to the consensus layer until it clears `ETH1_FOLLOW_DISTANCE` and an eth1 voting period — hours, not minutes — and this estate does not decode the deposit contract's logs, so it cannot see one before the CL does.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "exited": {
                                  "description": "`exited_unslashed` + `withdrawal_possible` + `withdrawal_done`. Whether the balance has been swept is not a different state to a reader.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "refreshed_at": {
                                  "description": "**WHEN THESE COUNTS WERE LAST CHECKED** — unix seconds. Read [`StatusPanel::refreshed_basis`] to know WHICH clock this is.\n\n`poll_tick` is ps-core's narrow poll saying \"I looked, sixty seconds ago\"; `last_write` is the newest `beacon.validators.updated_at`, i.e. the last time a row actually MOVED. Null only when there is neither.\n\n**UNDER `poll_tick` THIS IS ps-core's WALL CLOCK, AND `age_secs` IS ps-api's** (audit §134 LOW 6). The two services can run on different hosts, so a skew between their clocks lands in the difference. Skew in one direction — a ps-core clock AHEAD of ps-api's — would make the age negative, and `age_secs` floors at zero rather than serving a refresh from the future; skew the other way inflates the age by the offset. The estate runs both against the same NTP source, so the term is small, but it is a real term and a reader comparing `refreshed_at` against their own clock should know which clock produced it. `last_write` has no such term: it is `now()` inside the DATABASE, and ps-api reads it from there.",
                                  "format": "int64",
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "refreshed_basis": {
                                  "anyOf": [
                                    {
                                      "description": "**WHICH CLOCK `refreshed_at` CAME FROM — an enum, so the compiler owns the set** and `JsonSchema` publishes it.",
                                      "oneOf": [
                                        {
                                          "description": "ps-core's narrow poll wrote `meta.config['beacon.narrow_poll']` at this time. **The poll looked; it did not necessarily find a change.** This is the freshness of the CHECK, which is what a reader asking \"how current are these counts\" means.",
                                          "enum": [
                                            "poll_tick"
                                          ],
                                          "type": "string"
                                        },
                                        {
                                          "description": "No tick row exists, so this is `max(beacon.validators.updated_at)` — the last time a validator row MOVED, which on a quiet chain is much older than the last check.",
                                          "enum": [
                                            "last_write"
                                          ],
                                          "type": "string"
                                        }
                                      ]
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Which clock [`StatusPanel::refreshed_at`] came from, or null when there is no reading at all.\n\n**THE FIELD EXISTS BECAUSE THE FALLBACK IS NOT THE SAME FACT.** Before ps-core wrote a tick stamp this panel had only `max(updated_at)`, which on a quiet chain does not move: the 60 s poll writes NOTHING when the queues are empty, so the age climbed toward the HOURLY pass while the poll ran perfectly, and the page said \"counts as of 47 minutes ago\" under a sentence promising a 60-second re-read. A silent switch between the two would be the same defect one layer up — a client could not tell \"checked a minute ago, nothing changed\" from \"last checked an hour ago\"."
                                },
                                "slashed": {
                                  "description": "`active_slashed` + `exited_slashed`.\n\n**LIFETIME, NOT RECENT.** This is every validator the chain has ever slashed and still has a registry row for — not a 24-hour figure and not a windowed one. `beacon.validators` carries no `slashed_epoch`, so WHEN a slashing happened is not derivable here at all; the stat bar's `slashed_24h` uses an `exit_epoch` proxy and says so in `slashed_basis`. Do not present this number as activity.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "total": {
                                  "description": "Every row in `beacon.validators`.\n\n**THE SUM-TO-TOTAL PROPERTY**: `entering + active + exited + slashed + sum(unrecognised.values()) == total`, exactly. `active_exiting` is NOT in that sum — it is already inside `active`.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "unrecognised": {
                                  "additionalProperties": {
                                    "format": "int64",
                                    "type": "integer"
                                  },
                                  "description": "**THE UNKNOWN-NEVER-SPELLED GUARD (§111).** Any status outside the mapping table, keyed by its own literal lighthouse string with its own count — `{\"pending_frobnicated\": 3}`.\n\nThere is no `other` bucket: a name that says nothing is how an unrecognised state becomes invisible. When the mapping is complete this map is EMPTY and a client renders nothing, so the ordinary page loses the label without the estate ever losing a validator.",
                                  "type": "object"
                                }
                              },
                              "required": [
                                "active",
                                "active_exiting",
                                "entering",
                                "exited",
                                "slashed",
                                "total",
                                "unrecognised"
                              ],
                              "type": "object"
                            },
                            "total": {
                              "description": "Every row in `beacon.validators`. **`groups` sums to exactly this.**",
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "groups",
                            "queues",
                            "raw",
                            "status_panel",
                            "total"
                          ],
                          "type": "object"
                        },
                        "window": {
                          "description": "`\"1d\" | \"7d\" | \"30d\" | \"90d\"`. **`\"1d\"` is YESTERDAY** — the last complete UTC day — not a rolling 24 hours. `epoch_to` and `as_of_ts` say so exactly.",
                          "type": "string"
                        },
                        "window_epochs": {
                          "description": "`270 × days`, exact: a UTC day is 270 epochs on PulseChain.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "active_validators",
                        "as_of_ts",
                        "day_from",
                        "day_to",
                        "epoch_from",
                        "epoch_to",
                        "epochs_captured",
                        "epochs_expected",
                        "queue_estimates",
                        "slashed_24h",
                        "slashed_basis",
                        "status_mix",
                        "window",
                        "window_epochs"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Beacon-chain totals: validator counts by status, participation, and the epoch they were read at",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/blocks": {
      "get": {
        "operationId": "getV2Blocks",
        "parameters": [
          {
            "description": "Keyset cursor: the last `number` returned. The next page is strictly BELOW it, so a page boundary is stable while the head advances.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=100. Default 25.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of the block list — the fields a home-page feed renders.",
                        "properties": {
                          "burnt_wei": {
                            "description": "Base fee burned in this block, wei. String.",
                            "type": "string"
                          },
                          "direct_payments_wei": {
                            "description": "Direct payments to the fee recipient, wei. String. Kept separate from tips — Data §2.4's \"never blended\" rule.",
                            "type": "string"
                          },
                          "extra_data": {
                            "description": "Block `extra_data`, raw hex, lowercase.\n\nThree states, all distinct: **null** — not recorded for this block (does not occur across the indexed range today); **`\"0x\"`** — recorded and empty, which a minority of blocks genuinely are; **`\"0x…\"`** — the bytes. Variable length.\n\nNOT decoded server-side and NOT text. It is arbitrary proposer-supplied bytes, frequently not valid UTF-8 — **escape it before rendering**.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fee_recipient": {
                            "type": "string"
                          },
                          "gas_limit": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "gas_used": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "gas_used_pct": {
                            "description": "Fullness, 0-100, two decimals. Precomputed because every consumer wants it and computing it from two integers is where off-by-a-factor bugs go.",
                            "format": "double",
                            "type": "number"
                          },
                          "graffiti": {
                            "description": "**THE PROPOSER'S GRAFFITI, from `beacon.blocks` — NOT `extra_data`.**\n\nThese are different facts and both are served: `extra_data` is what the EXECUTION client put in the block header, `graffiti` is what the CONSENSUS proposer signed into the beacon block. A reader expecting one and shown the other is the defect this field closes.\n\nRAW 32 bytes, hex, lowercase, 66 characters. **Never decoded** — it is arbitrary proposer-supplied bytes and frequently not valid UTF-8, so escape it before rendering. Null with a `graffiti_reason` whenever it cannot be served.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "graffiti_reason": {
                            "anyOf": [
                              {
                                "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                "oneOf": [
                                  {
                                    "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                    "enum": [
                                      "missing"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                    "enum": [
                                      "malformed"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                    "enum": [
                                      "unlinked"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Why `graffiti` is null. **`unlinked` is the ordinary case on this surface**, not an error: `beacon.blocks` begins at the CL slot walker's floor, so every pre-frontier execution block has no beacon row at all. Null only when `graffiti` is present."
                          },
                          "missed_slots_before": {
                            "description": "**MISSED SLOTS BETWEEN THIS BLOCK AND THE PREVIOUS ONE**, or null when nothing can be claimed.\n\n# WHY A SIBLING FIELD AND NOT AN INTERLEAVED ROW\n\nThis list is `core.chain_blocks`-keyed and **a missed slot has no execution block by construction** — it is absent from that table, and there is no number to key it on. Interleaving would mean inventing a row with a null `number`, breaking the keyset (which reads the last row's `number`) and the page count, and making every consumer branch on \"is this row a block\". The slot-keyed surfaces —`/v2/slots` and `/v2/slots/{slot}` — are where a missed slot IS a row, and they exist.\n\nSo this list carries the FACT rather than the rows: how many consensus slots produced nothing between this block's slot and its predecessor's. A page can render \"3 slots missed\" between two rows and link to the slot surface for the detail.\n\n# THE THREE-VALUED READING, and the ~2-epoch band\n\n* `0` — measured: consecutive slots, nothing missed. * `n > 0` — measured: `n` slots between them produced no block. * **`null` — NOTHING IS CLAIMED.** Either this block or its predecessor has no beacon row, so the gap is unknowable. **That is the ordinary state of the newest band**: the consensus producer trails the chain head by roughly two epochs, so the top ~64 slots of the list report null here and say nothing about missed-ness rather than reporting 0 and implying none.\n\nIt LIGHTS UP LATE by construction — the value is computed per request from whatever beacon rows exist at that moment, and this route's `Cache-Control` is the short at-head TTL, so nothing pins the null.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "proposer_index": {
                            "description": "The proposer's validator index, or null when unlinked or unattributed.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "slot": {
                            "description": "The consensus slot that produced this execution block, or null when there is no beacon row for it.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "tips_wei": {
                            "description": "Priority fees to the proposer, wei. String.",
                            "type": "string"
                          },
                          "ts": {
                            "description": "Unix seconds. The page derives \"age\" from this rather than the API baking in a relative string that is stale the moment it is cached.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "tx_count": {
                            "format": "int32",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "burnt_wei",
                          "direct_payments_wei",
                          "fee_recipient",
                          "gas_limit",
                          "gas_used",
                          "gas_used_pct",
                          "number",
                          "tips_wei",
                          "ts",
                          "tx_count"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Recent blocks, newest first",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/blocks/{num}/rewards": {
      "get": {
        "operationId": "getV2BlocksByNumRewards",
        "parameters": [
          {
            "in": "path",
            "name": "num",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "`/v2/blocks/{num}/rewards`.",
                      "properties": {
                        "base_fee_per_gas": {
                          "description": "Wei, STRING.",
                          "type": "string"
                        },
                        "block_number": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "cl": {
                          "description": "Null when there is no beacon linkage at all.",
                          "properties": {
                            "attestation_hit": {
                              "description": "Non-null exactly when `state` is `available`.",
                              "type": [
                                "boolean",
                                "null"
                              ]
                            },
                            "cl_reward_gwei": {
                              "description": "Gwei, as a string. Non-null exactly when `state` is `available`.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "epoch": {
                              "description": "Null only when `state` is `unlinked` — there is no beacon row, so there is no epoch.",
                              "format": "int64",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "state": {
                              "description": "**Replaces `retained: bool`.** One flag carried two opposite causes; this names which.",
                              "oneOf": [
                                {
                                  "description": "The row exists. `cl_reward_gwei` and `attestation_hit` are non-null.",
                                  "enum": [
                                    "available"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**NOT YET COMPUTED.** `epoch` is above the producer's cursor (`meta.consumer_progress['batch.epoch_summaries']`). At the head this is the permanent two-epoch `REWARDS_LAG` window and is entirely healthy; a stalled producer widens the window without changing its nature.",
                                  "enum": [
                                    "pending"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**RETENTION REMOVED IT.** `epoch` is below the oldest epoch any row survives at, so `retention::epoch_summaries` (`retention.rs:72-82`) has swept past it. **Unreachable for a house validator** — see `ClRewardAnomaly`.\n\n# WIRE MEANING CHANGE, for the FE ledger\n\n**A swept epoch that used to report `never_captured` now reports `aged_out`** whenever `beacon.epoch_totals` holds a row for it with `captured = true`. No new state, no schema change on the wire, and the FE's existing `aged_out` copy is the correct sentence for it — where the `never_captured` copy (\"No consensus reward was recorded for this epoch\", Web §107) was a false one about an epoch whose reward WAS recorded and then retired on schedule.\n\nIt reaches this state through `epoch_totals` rather than through surviving house rows because OPS-51 measured `is_house = 0 of 110,459`: the house-row witness has zero width on production and always will until the VaaS roster is populated.",
                                  "enum": [
                                    "aged_out"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**THE PRODUCER PASSED THIS EPOCH WITHOUT WRITING IT, AND NEVER WILL.**\n\nFound while implementing rather than assumed: `epochs.rs:320-333` has a permanent-skip path — when the beacon node answers 404 for an epoch *below* the live edge, the rewards are pruned upstream, so the producer logs *\"epoch skipped permanently\"*, **advances the cursor anyway**, and moves on.\n\nThat makes \"epoch ≤ cursor and no row\" ambiguous: it is aged out only when the epoch is below the retained range. Inside the retained range it is this — data that will never arrive. Reporting it as `AgedOut` would have reproduced the original defect one level down, which is why the four-arm design in `docs/beacon_aged_out_defect.md` §4 gained a fifth arm here.",
                                  "enum": [
                                    "unavailable"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**THE PRODUCER WAS NEVER RUNNING HERE.** Below the oldest epoch any row exists at, and there is no evidence retention swept that far.\n\n# Why this arm exists, and why it is the COMMON case rather than an edge\n\n`c310f4a` shipped without it and called this range `AgedOut`. That was wrong, and `docs/proposal_validator_dashboard.md` §0.3 is the measurement that shows why:\n\n* OPS-48 measured `min(epoch)` = **322,375**, `max(epoch)` = 325,603, head epoch 325,605 — a span of **3,228 epochs**. * PulseChain runs 320 s epochs (`rollup.rs:25-26`), so 3,228 epochs is **11.95 days**. * `beacon_epoch_detail_retention_days` is **90** (`0012:53`).\n\n**A twelve-day-old dataset cannot have aged out of a ninety-day window.** 322,375 is where the producer *started*, and `epochs.rs:14-30` says it must be: that producer **cannot backfill at all**, because `/eth/v1/beacon/rewards/attestations/{epoch}` needs a state the node prunes within ~2 epochs, so *\"a fresh cursor therefore starts at the head window, NOT at genesis\"*.\n\nWith the chain at 325,605 and the floor at 322,375, **essentially every historical block is in this range**. Calling it `aged_out` blamed retention for data retention never touched — the same class of error the enum was built to remove, one level down.",
                                  "enum": [
                                    "never_captured"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "No beacon row for this block at all, so there is no epoch and no proposer to ask about. Replaces the old `cl: null`.\n\n**This also covers a block the CL slot-walker has not reached yet**, and the two are not distinguished here. `docs/proposal_validator_dashboard.md` §0.4 records a possible gap between the walker's frontier and the summaries floor; a block inside it has no `beacon.blocks` row, so it arrives here rather than at the classifier. *\"We have no beacon linkage for this block\"* is true under both readings, which is why this arm's shape did not change with the fix above.",
                                  "enum": [
                                    "unlinked"
                                  ],
                                  "type": "string"
                                }
                              ]
                            }
                          },
                          "required": [
                            "state"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "exec": {
                          "description": "Execution-layer rewards for a block. Data §2.4's \"never blended\" rule: burnt, tips and direct payments stay separate, and `validator_exec_reward_wei` is the proposer's share (tips + direct payments), provided because it is the figure a validator page shows and computing it from two decimal strings client-side invites a float bug.",
                          "properties": {
                            "burnt_wei": {
                              "description": "Wei, STRING.",
                              "type": "string"
                            },
                            "direct_payments_wei": {
                              "type": "string"
                            },
                            "tips_wei": {
                              "type": "string"
                            },
                            "validator_exec_reward_wei": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "burnt_wei",
                            "direct_payments_wei",
                            "tips_wei",
                            "validator_exec_reward_wei"
                          ],
                          "type": "object"
                        },
                        "extra_data": {
                          "description": "Block `extra_data`, raw hex, lowercase — the same field `/v2/blocks` serves, from the same row, so a reader with a block number needs one call rather than a paged scan.\n\n`null` = not recorded (does not occur across the indexed range today); `\"0x\"` = recorded and empty, which a minority of blocks genuinely are; `\"0x…\"` = the bytes, variable length. NOT decoded and frequently not valid UTF-8 — **escape it before rendering**.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "fee_recipient": {
                          "type": "string"
                        },
                        "gas_limit": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "gas_used": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "graffiti": {
                          "description": "Proposer graffiti, raw hex, lowercase, exactly 66 characters when present (SSZ `Bytes32`).\n\n**Two states on this route**, because it is keyed by execution block. `\"0x…\"` with `missed: false` means a block exists and these are the bytes its proposer set — including `\"0x0000…\"`, 32 zero bytes, which is a VALUE and not an absence. `null` with `missed: null` means no beacon row is linked to this block, so nothing is known either way.\n\nThe missed-slot state (`graffiti: null`, `missed: true`) is served by `/v2/shadow/{slot}`, which joins on slot. §3o.7 measured `graffiti IS NULL` and `missed = true` to be the same set exactly — 241,538 of 10,334,340 slots, zero mismatches — but that whole set is unreachable through an execution-block join.\n\n`\"0x0000…\"` is NOT decidable as \"the proposer set nothing\": a proposer that deliberately writes 32 zero bytes is byte-identical to one that writes nothing at all, and the chain does not record the difference. Render it as empty; do not claim intent either way.\n\nNOT decoded server-side. This is **attacker-controlled input**: any proposer may put arbitrary bytes here, so escape it before rendering and never interpolate it into markup.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "graffiti_reason": {
                          "anyOf": [
                            {
                              "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                              "oneOf": [
                                {
                                  "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                  "enum": [
                                    "missing"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                  "enum": [
                                    "malformed"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                  "enum": [
                                    "unlinked"
                                  ],
                                  "type": "string"
                                }
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Why `graffiti` is null, when the null is not already explained by `missed`. Null when `graffiti` is present.\n\n`missing` — the block exists and no graffiti was stored: ps-core's body fetch returned nothing while the header resolved, so the value was never ingested. The graffiti this slot had is UNKNOWN, not absent. `malformed` — a value is stored and it is not 32 bytes, so serving it would break the published 66-character shape."
                        },
                        "hash": {
                          "description": "**THIS BLOCK'S OWN HASH**, raw hex, lowercase, 66 characters.\n\nNOT nullable and never absent: `core.chain_blocks.block_hash` is `BYTEA NOT NULL` (`0003:15`) with a UNIQUE index over it (`0003:31`), so a block this route can find is a block that has one. The route already 404s when the number is not indexed, which is the only \"absence\" there is.\n\nServed rather than derived because the FE asked upstream: a client deriving it would have to make a second call, and a client deriving the PARENT's identity from `block_number - 1` would be asserting a chain link this row already states.",
                          "type": "string"
                        },
                        "missed": {
                          "description": "Whether the slot that produced this block was a missed slot.\n\n**On this route it is only ever `false` or `null`, never `true`** — a missed slot produced no execution block, so its `exec_block_number` is NULL (0031 counted 240,821 such rows) and the join this route makes, `bb.exec_block_number = cb.block_number`, cannot reach one. `null` here means \"no beacon row is linked to this block\", not \"the slot was missed\". For the missed-slot state use the slot-keyed surface, `/v2/shadow/{slot}`.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "parent_hash": {
                          "description": "**THE PARENT'S HASH**, raw hex, lowercase, 66 characters.\n\nAlso NOT nullable (`0003:16`). **At the genesis edge it is 32 zero bytes** — `\"0x0000…0000\"` — which is a REAL VALUE the chain defines and not a null: block 0 has no parent, and the protocol spells that as the zero hash. A consumer walking backwards stops on that value rather than on an absent field.\n\n**This estate does not index from genesis.** ps-core starts at the fork block (`derive.start_block = 17_233_000`), so the oldest row here has a parent_hash naming a block that is NOT in `core.chain_blocks` — a real hash pointing outside the indexed range. That is a different condition from the zero hash and neither is an absence; both are what the chain says.",
                          "type": "string"
                        },
                        "proposer_index": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "slot": {
                          "description": "Null when this block has no beacon row — the same fact `cl.state == \"unlinked\"` reports, kept here because a client filtering on slot should not have to reach into `cl` to do it.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "ts": {
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "base_fee_per_gas",
                        "block_number",
                        "exec",
                        "fee_recipient",
                        "gas_limit",
                        "gas_used",
                        "hash",
                        "parent_hash",
                        "ts"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One block's fee recipient, gas use and burnt fees, with its consensus reward",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/blocks/{num}/txs": {
      "get": {
        "operationId": "getV2BlocksByNumTxs",
        "parameters": [
          {
            "in": "path",
            "name": "num",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor: the last `tx_index` returned. ASCENDING — the next page is above it, because a block's transactions are ordered by execution.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int32",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One transaction in a block's list.\n\nDeliberately NOT the same shape as `TxDetail`. A list row carries what a table renders — who, to whom, how much, did it work, what did it cost — and omits `confirmations` (identical for every row in a block, so repeating it per row implies rows can disagree), the fee breakdown (`TxFee` is four fields the table has no column for), and the transfer counts (two extra aggregate queries per row, which is the N+1 this route exists to remove).",
                        "properties": {
                          "burned_wei": {
                            "description": "Base fee burned by this transaction, wei. String. Kept separate from `tip_wei` — Data §2.4's \"never blended\" rule, the same split the block list makes.",
                            "type": "string"
                          },
                          "created_contract": {
                            "description": "Set only when this transaction deployed a contract.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "effective_gas_price": {
                            "description": "Price actually paid per gas, wei. String.",
                            "type": "string"
                          },
                          "from": {
                            "type": "string"
                          },
                          "gas_used": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "hash": {
                            "type": "string"
                          },
                          "method": {
                            "description": "*THE HUMAN LABEL** for `method_id`, or null. See `crate::method`.",
                            "properties": {
                              "label": {
                                "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                                "type": "string"
                              },
                              "signature": {
                                "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                                "type": "string"
                              },
                              "source": {
                                "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                                "type": "string"
                              },
                              "tier": {
                                "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                                "format": "uint8",
                                "maximum": 3.0,
                                "minimum": 1.0,
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "signature",
                              "source"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "method_id": {
                            "description": "First 4 calldata bytes as 0x-hex; null for a plain transfer.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "1 success, 0 reverted.",
                            "format": "int16",
                            "type": "integer"
                          },
                          "tip_wei": {
                            "description": "Priority fee to the proposer, wei. String.",
                            "type": "string"
                          },
                          "to": {
                            "description": "Null for contract creations.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tx_index": {
                            "description": "Position in the block. This IS execution order and IS the cursor.",
                            "format": "int32",
                            "type": "integer"
                          },
                          "tx_type": {
                            "description": "EIP-2718 type: 0 legacy, 2 dynamic-fee.",
                            "format": "int16",
                            "type": "integer"
                          },
                          "value_wei": {
                            "description": "Value transferred, wei. String.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "burned_wei",
                          "effective_gas_price",
                          "from",
                          "gas_used",
                          "hash",
                          "status",
                          "tip_wei",
                          "tx_index",
                          "tx_type",
                          "value_wei"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Transactions in one block",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/epochs": {
      "get": {
        "operationId": "getV2Epochs",
        "parameters": [
          {
            "description": "Keyset cursor: the last `epoch` returned. The next page is at or below it — see the row shape; the cursor is exclusive in effect because the handler subtracts one.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=100. Default 50 (§4.4).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One epoch. Every ratio ships with its numerator AND its denominator, and every absence is null rather than 0 — `0056` declares three of these columns nullable precisely so \"we have no record\" is expressible.",
                        "properties": {
                          "attestations_included": {
                            "description": "Null = unknown, never 0 (`0056`: absent-is-not-zero).",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "blocks_missed": {
                            "description": "The whole. `missed_attributed + missed_unattributable == blocks_missed` by construction — the producer computes all three from one scan partitioned by `missed` and `proposer_index IS NULL`, and `attributed` is served as the difference so the identity cannot fail to hold.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "blocks_proposed": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "captured": {
                            "description": "Detail rows existed for this epoch when it was rolled — the PER-EPOCH coverage flag.",
                            "type": "boolean"
                          },
                          "cl_reward_gwei": {
                            "description": "Signed string: CL rewards are legitimately negative under penalties.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "cl_state": {
                            "description": "From `classify_cl_reward`, the SAME classifier `/v2/blocks/{n}/rewards` uses. **Treat the set as open**: adding a variant is a visible schema change, and §4.8 says so.",
                            "oneOf": [
                              {
                                "description": "The row exists. `cl_reward_gwei` and `attestation_hit` are non-null.",
                                "enum": [
                                  "available"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "**NOT YET COMPUTED.** `epoch` is above the producer's cursor (`meta.consumer_progress['batch.epoch_summaries']`). At the head this is the permanent two-epoch `REWARDS_LAG` window and is entirely healthy; a stalled producer widens the window without changing its nature.",
                                "enum": [
                                  "pending"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "**RETENTION REMOVED IT.** `epoch` is below the oldest epoch any row survives at, so `retention::epoch_summaries` (`retention.rs:72-82`) has swept past it. **Unreachable for a house validator** — see `ClRewardAnomaly`.\n\n# WIRE MEANING CHANGE, for the FE ledger\n\n**A swept epoch that used to report `never_captured` now reports `aged_out`** whenever `beacon.epoch_totals` holds a row for it with `captured = true`. No new state, no schema change on the wire, and the FE's existing `aged_out` copy is the correct sentence for it — where the `never_captured` copy (\"No consensus reward was recorded for this epoch\", Web §107) was a false one about an epoch whose reward WAS recorded and then retired on schedule.\n\nIt reaches this state through `epoch_totals` rather than through surviving house rows because OPS-51 measured `is_house = 0 of 110,459`: the house-row witness has zero width on production and always will until the VaaS roster is populated.",
                                "enum": [
                                  "aged_out"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "**THE PRODUCER PASSED THIS EPOCH WITHOUT WRITING IT, AND NEVER WILL.**\n\nFound while implementing rather than assumed: `epochs.rs:320-333` has a permanent-skip path — when the beacon node answers 404 for an epoch *below* the live edge, the rewards are pruned upstream, so the producer logs *\"epoch skipped permanently\"*, **advances the cursor anyway**, and moves on.\n\nThat makes \"epoch ≤ cursor and no row\" ambiguous: it is aged out only when the epoch is below the retained range. Inside the retained range it is this — data that will never arrive. Reporting it as `AgedOut` would have reproduced the original defect one level down, which is why the four-arm design in `docs/beacon_aged_out_defect.md` §4 gained a fifth arm here.",
                                "enum": [
                                  "unavailable"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "**THE PRODUCER WAS NEVER RUNNING HERE.** Below the oldest epoch any row exists at, and there is no evidence retention swept that far.\n\n# Why this arm exists, and why it is the COMMON case rather than an edge\n\n`c310f4a` shipped without it and called this range `AgedOut`. That was wrong, and `docs/proposal_validator_dashboard.md` §0.3 is the measurement that shows why:\n\n* OPS-48 measured `min(epoch)` = **322,375**, `max(epoch)` = 325,603, head epoch 325,605 — a span of **3,228 epochs**. * PulseChain runs 320 s epochs (`rollup.rs:25-26`), so 3,228 epochs is **11.95 days**. * `beacon_epoch_detail_retention_days` is **90** (`0012:53`).\n\n**A twelve-day-old dataset cannot have aged out of a ninety-day window.** 322,375 is where the producer *started*, and `epochs.rs:14-30` says it must be: that producer **cannot backfill at all**, because `/eth/v1/beacon/rewards/attestations/{epoch}` needs a state the node prunes within ~2 epochs, so *\"a fresh cursor therefore starts at the head window, NOT at genesis\"*.\n\nWith the chain at 325,605 and the floor at 322,375, **essentially every historical block is in this range**. Calling it `aged_out` blamed retention for data retention never touched — the same class of error the enum was built to remove, one level down.",
                                "enum": [
                                  "never_captured"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "No beacon row for this block at all, so there is no epoch and no proposer to ask about. Replaces the old `cl: null`.\n\n**This also covers a block the CL slot-walker has not reached yet**, and the two are not distinguished here. `docs/proposal_validator_dashboard.md` §0.4 records a possible gap between the walker's frontier and the summaries floor; a block inside it has no `beacon.blocks` row, so it arrives here rather than at the classifier. *\"We have no beacon linkage for this block\"* is true under both readings, which is why this arm's shape did not change with the fix above.",
                                "enum": [
                                  "unlinked"
                                ],
                                "type": "string"
                              }
                            ]
                          },
                          "end_slot": {
                            "description": "`start_slot + 31`.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "epoch": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "exec_reward_wei": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "finalized": {
                            "description": "**Every slot of this epoch is finalized by the CL.** `epoch < meta.finalized_epoch`, strictly — the checkpoint at F finalizes the chain up to slot `F*32`, so F's own remaining 31 slots are not covered. Null when no checkpoint has been resolved.",
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "missed_attributed": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "missed_unattributable": {
                            "description": "Missed slots with no proposer recorded. Falls as the walk's attribution leg progresses; read it with `meta.backfill_frontier_epoch`.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "participation_pct": {
                            "description": "`attestations_included / validators_observed`. **Null when the denominator is 0 or either side is absent** — never 0, which would read as total failure rather than as no data.",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "slots_ingested": {
                            "description": "`blocks_proposed + blocks_missed` — how many of the epoch's 32 slots have a `beacon.blocks` row at all. **This is what tells an un-ingested epoch from an empty one**; both read 0 proposed.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "slots_not_yet_walked": {
                            "description": "`32 - slots_ingested`. Above 0 means the slot walker has not finished this epoch, so the counts beside it are partial.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "start_slot": {
                            "description": "`epoch × 32`, stored by `0056` rather than recomputed here.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "ts_end": {
                            "description": "`ts_start + 320`. The instant the epoch ENDS, which is also the next epoch's `ts_start`.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "ts_start": {
                            "description": "Unix seconds at which the epoch begins.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "validators_assigned": {
                            "description": "Validator-epochs that SHOULD have attested, from the activation/exit overlap. Null = the registry was empty when the row was written.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "validators_observed": {
                            "description": "Validator-epochs we have a RECORD for. **The denominator of `participation_pct`** (§12 decision 1) — dividing by `validators_assigned` instead would conflate the chain's behaviour with our ingestion coverage. NOT NULL by `0056`'s design: it counts OUR rows, so 0 is a true and complete answer.",
                            "format": "int64",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "blocks_missed",
                          "blocks_proposed",
                          "captured",
                          "cl_state",
                          "end_slot",
                          "epoch",
                          "missed_attributed",
                          "missed_unattributable",
                          "slots_ingested",
                          "slots_not_yet_walked",
                          "start_slot",
                          "ts_end",
                          "ts_start",
                          "validators_observed"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "backfill_frontier_epoch": {
                          "description": "`meta.consumer_progress['batch.epoch_backfill']` — how far the historical walk has got. **Null when it has never run.** It is what makes a `pending` `cl_state` unambiguous between \"closed a minute ago\" and \"the walk has not reached January 2025\".",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "epoch_secs": {
                          "description": "320. `slots_per_epoch × 10 s`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "epoch_to": {
                          "description": "`max(epoch)` in `beacon.epoch_totals` — the newest rolled epoch. Null when the producer has never rolled a day.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finality_as_of": {
                          "description": "Unix seconds at which that checkpoint was polled. **Read `finalized` with this**: finality is monotonic, so a stale checkpoint under-claims rather than over-claims.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finalized_epoch": {
                          "description": "The CL's finalized checkpoint epoch, from the head lane's poller. Null when none has been resolved.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "slots_per_epoch": {
                          "description": "32. Served so nothing downstream hardcodes it.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "epoch_secs",
                        "slots_per_epoch"
                      ],
                      "type": "object"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Recent beacon epochs and their participation",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/head/blocks": {
      "get": {
        "operationId": "getV2HeadBlocks",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The lane envelope. **`indexed_head` is echoed beside `as_of_ts` so the seam is a FACT OF ONE PAYLOAD rather than an inference across two responses.**\n\nTwo responses have two clocks; this has one. Without it a client cannot state the size of the truncated gap, because it would be differencing a value from this payload against one it fetched separately.",
                      "properties": {
                        "as_of_ts": {
                          "description": "Unix seconds at which the poller last refreshed. NOT the block time.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "blocks": {
                          "items": {
                            "description": "One provisional block.",
                            "properties": {
                              "base_fee_per_gas": {
                                "description": "Wei, STRING — the estate's u256 rule.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "confirmations": {
                                "description": "`node_head - number`. **THE HEAD BLOCK IS 0** — settled by measurement against the deployed API, and it is what the confirmed lane already does. Compare against `finality_confirmations`, never against a hardcoded 12.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "gas_limit": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "gas_used": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "graffiti": {
                                "description": "Proposer graffiti, RAW 32 bytes, hex, 66 characters. **Never decoded.**",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "graffiti_reason": {
                                "anyOf": [
                                  {
                                    "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                    "oneOf": [
                                      {
                                        "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                        "enum": [
                                          "missing"
                                        ],
                                        "type": "string"
                                      },
                                      {
                                        "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                        "enum": [
                                          "malformed"
                                        ],
                                        "type": "string"
                                      },
                                      {
                                        "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                        "enum": [
                                          "unlinked"
                                        ],
                                        "type": "string"
                                      }
                                    ]
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Why `graffiti` is null, on the same closed set every other carrier uses (§3o.7's one mapping). `unlinked` = the CL leg has not resolved this block, which on an unfinalized block is the ordinary transient state."
                              },
                              "hash": {
                                "description": "**NOT OPTIONAL.** Without it a same-height hash swap during a reorg is SILENT — the number is unchanged and the contents are not. Tombstone diffing is by hash precisely because height cannot see that case.",
                                "type": "string"
                              },
                              "miner": {
                                "type": "string"
                              },
                              "number": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "parent_hash": {
                                "description": "Also required: it is what [`repaint_needed`] verifies the chain with, and what lets a client detect a swap one block below the head.",
                                "type": "string"
                              },
                              "proposer_index": {
                                "description": "The proposer's validator index.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "slot": {
                                "description": "The consensus slot that produced this block.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "state": {
                                "description": "Why a lane row's validity rule differs from a confirmed row's.\n\nA closed set, declared the way `MarkStatus` (`marks.rs:14`) and `PriceSource` (`tokens.rs:314`) are: a consumer MUST branch on it. One value today; it exists so a second is a visible schema change.",
                                "oneOf": [
                                  {
                                    "description": "Read from the node, not from the index. May vanish or change hash.",
                                    "enum": [
                                      "provisional"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "ts": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "tx_count": {
                                "format": "int64",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "confirmations",
                              "gas_limit",
                              "gas_used",
                              "hash",
                              "miner",
                              "number",
                              "parent_hash",
                              "state",
                              "ts",
                              "tx_count"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "finality_as_of": {
                          "description": "Unix seconds at which the checkpoint above was polled. Null with the other two.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finality_confirmations": {
                          "description": "The dial, served so nobody hardcodes 12.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "finalized_epoch": {
                          "description": "The epoch of the CL's `finalized` checkpoint. Null = never successfully polled (no CL configured, or every poll so far has failed).",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "indexed_head": {
                          "description": "**The indexed head THIS PAYLOAD WAS COMPUTED AGAINST**, captured in the same tick as `node_head`. Not a fresh read.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "lane_available": {
                          "type": "boolean"
                        },
                        "lane_floor": {
                          "description": "`indexed_head + 1`, unless the gap exceeded [`HEAD_LANE_MAX_BLOCKS`], in which case it is `node_head - HEAD_LANE_MAX_BLOCKS + 1` and `truncated` is true.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "lane_unavailable_reason": {
                          "anyOf": [
                            {
                              "description": "Why the lane is not serving. `null` when it is.",
                              "oneOf": [
                                {
                                  "description": "No successful refresh inside [`HEAD_LANE_MAX_AGE_SECS`].",
                                  "enum": [
                                    "rpc_unreachable"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The node's head is at or below the indexed head. A lane below the confirmed frontier has nothing to add and would imply a rollback.",
                                  "enum": [
                                    "node_behind_index"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The node's head is implausibly far above the indexed head. The honest reading of a gap that size is \"these two disagree\", not \"here are ten thousand provisional blocks\".",
                                  "enum": [
                                    "node_divergent"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The poller has not completed a first refresh yet.",
                                  "enum": [
                                    "warming"
                                  ],
                                  "type": "string"
                                }
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "last_finalized_block": {
                          "description": "**The EXECUTION block number of that checkpoint's block.** Null when the checkpoint is unknown, or when our `beacon.blocks` cannot yet resolve it — see `finalized_block_of`, which refuses rather than guesses.\n\n**It UNDER-claims when stale and never over-claims.** Finality is monotonic, so a value from ten minutes ago names a block that is still finalized; it is merely not the newest such block. Read it with `finality_as_of`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "node_head": {
                          "description": "The node's head at `as_of_ts`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "truncated": {
                          "description": "True when blocks exist between `indexed_head` and `lane_floor` that are in NEITHER lane. Show the gap; do not paint continuity over it.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "blocks",
                        "finality_confirmations",
                        "indexed_head",
                        "lane_available",
                        "lane_floor",
                        "node_head",
                        "truncated"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Blocks from the head preview lane, ahead of the indexed head",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/head/blocks/{num}/txs": {
      "get": {
        "operationId": "getV2HeadBlocksByNumTxs",
        "parameters": [
          {
            "in": "path",
            "name": "num",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One provisional transaction. No raw logs and **no USD** — the lane serves raw chain facts only, and a price is a derived surface it may not reach.\n\nIt DOES serve the receipt summary and the decoded `Transfer` logs; the two arrived in that order and the sentence here used to deny both. What it still refuses is a raw log, a calldata payload, and any figure that came from PostgreSQL rather than from the node — see the module header.",
                        "properties": {
                          "block_hash": {
                            "description": "The block's hash, so a client can tie a tx to the exact block it was seen in rather than to a height that may be re-used.",
                            "type": "string"
                          },
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "confirmations": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "effective_gas_price": {
                            "description": "Wei, STRING — the price actually paid per gas after the 1559 split. **Not `gas_price`**, which is what the sender offered.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "from": {
                            "type": "string"
                          },
                          "gas": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "gas_price": {
                            "description": "Wei, STRING.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gas_used": {
                            "description": "Gas actually consumed. Null with the other two.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "hash": {
                            "type": "string"
                          },
                          "input_size": {
                            "description": "Calldata length in bytes. The calldata itself is not served.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "method": {
                            "description": "**THE HUMAN LABEL.** Null when the selector is unknown to the dictionary or is marked ambiguous there — never a guess. See `crate::method`.",
                            "properties": {
                              "label": {
                                "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                                "type": "string"
                              },
                              "signature": {
                                "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                                "type": "string"
                              },
                              "source": {
                                "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                                "type": "string"
                              },
                              "tier": {
                                "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                                "format": "uint8",
                                "maximum": 3.0,
                                "minimum": 1.0,
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "signature",
                              "source"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "method_id": {
                            "description": "The function selector, `0x` + 8 hex, or null for a plain value transfer. The same fact `core.chain_transactions.method_id` carries on the indexed twin (`0003:61`), so the two surfaces are comparable.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "nonce": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "receipts_state": {
                            "description": "Whether the receipts leg landed for this transaction's BLOCK. See [`ReceiptsState`], and read it before `transfers`.",
                            "oneOf": [
                              {
                                "description": "The receipts came back and were walked. An empty `transfers` therefore means the transaction emitted no `Transfer` log — a real answer.",
                                "enum": [
                                  "available"
                                ],
                                "type": "string"
                              },
                              {
                                "description": "The call failed, the node does not implement `eth_getBlockReceipts`, or it answered something that is not a receipts array. `transfers` is EMPTY for every transaction in this block and means NOTHING; the surface says \"transfers unknown\" rather than \"none\".",
                                "enum": [
                                  "unavailable"
                                ],
                                "type": "string"
                              }
                            ]
                          },
                          "state": {
                            "description": "Why a lane row's validity rule differs from a confirmed row's.\n\nA closed set, declared the way `MarkStatus` (`marks.rs:14`) and `PriceSource` (`tokens.rs:314`) are: a consumer MUST branch on it. One value today; it exists so a second is a visible schema change.",
                            "oneOf": [
                              {
                                "description": "Read from the node, not from the index. May vanish or change hash.",
                                "enum": [
                                  "provisional"
                                ],
                                "type": "string"
                              }
                            ]
                          },
                          "status": {
                            "description": "`true` = succeeded, `false` = REVERTED, `null` = no receipt yet.",
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "to": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "transfers": {
                            "description": "Every ERC-20/ERC-721 `Transfer` this transaction emitted, in log order.\n\n**EMPTY MEANS NOTHING WITHOUT `receipts_state`.** Read that field first: `available` + `[]` is \"this transaction moved no tokens\"; `unavailable` + `[]` is \"nobody could ask\". The frontend renders the second as *\"transfers unknown — receipts unavailable for block N\"*.",
                            "items": {
                              "description": "**ONE DECODED TRANSFER, ON THE WIRE.**\n\nThe lane's [`ProvisionalTransfer`] plus the two display fields the registry resolves, minus `tx_hash`/`tx_index` — the row it hangs off already names the transaction, and repeating the hash on every transfer of a 4,000-row block is bytes that say nothing.",
                              "properties": {
                                "amount": {
                                  "description": "ERC-20 only, and RAW — no `decimals` applied, because `decimals` may be null. u256 as a decimal STRING, the estate's rule. Null on an ERC-721.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "decimals": {
                                  "description": "Null with `symbol`, and for the same reason. **A guessed `decimals` is worse than none**: rendering a raw `1000000000000000000` against an assumed 18 when the token uses 6 is wrong by twelve orders of magnitude. The frontend's fallback is the RAW `amount`, which is the truth.",
                                  "format": "int16",
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "from": {
                                  "type": "string"
                                },
                                "kind": {
                                  "description": "**WHICH TOKEN STANDARD A DECODED `Transfer` CAME FROM.**\n\nA closed set rather than a string, so the two literals reach `docs/openapi.json` and a generated client can branch on them. The words are [`ps_common::transfer_log::Transfer::kind`]'s, and `the_transfer_wire_words_are_ps_commons_own` pins that they still are — the decoder and the wire may not drift apart.",
                                  "oneOf": [
                                    {
                                      "description": "`value` came from `data`: an `amount`, no `token_id`.",
                                      "enum": [
                                        "erc20"
                                      ],
                                      "type": "string"
                                    },
                                    {
                                      "description": "The third parameter was indexed: a `token_id`, no `amount`.",
                                      "enum": [
                                        "erc721"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                "log_index": {
                                  "description": "The log's index within the BLOCK, as the node reported it. **The dedupe key**: stable across a re-fetch of the same block in a way an array position is not.",
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "state": {
                                  "description": "Always `provisional`. Present as a field, not implied by the row it sits on, so a transfer copied out of one keeps its own warning.",
                                  "oneOf": [
                                    {
                                      "description": "Read from the node, not from the index. May vanish or change hash.",
                                      "enum": [
                                        "provisional"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                "symbol": {
                                  "description": "**NULL UNLESS `financial.token_registry` HAS THE TOKEN `resolved`.** The frontend renders the raw `token` address when it is null; a symbol guessed from an unresolved row would name a token nobody verified. See `crate::registry`.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "to": {
                                  "type": "string"
                                },
                                "token": {
                                  "description": "The token contract that emitted the log, lowercase `0x` hex. Not the transaction's `to`, which for a multicall is the router.",
                                  "type": "string"
                                },
                                "token_id": {
                                  "description": "ERC-721 only. Null on an ERC-20.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "from",
                                "kind",
                                "log_index",
                                "state",
                                "to",
                                "token"
                              ],
                              "type": "object"
                            },
                            "type": "array"
                          },
                          "transfers_omitted": {
                            "description": "Decoded transfers the block's [`TRANSFERS_PER_BLOCK_CAP`] discarded. **Block-wide, not per-transaction**: the cap is a bound on what the ring holds for a block, so the honest statement is that this block lost this many rows — attributing them to one transaction would be a number the lane never computed. 0 in every block OPS-87 measured.",
                            "format": "uint32",
                            "minimum": 0.0,
                            "type": "integer"
                          },
                          "tx_index": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "value": {
                            "description": "Wei, STRING.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "block_hash",
                          "block_number",
                          "confirmations",
                          "from",
                          "gas",
                          "hash",
                          "input_size",
                          "nonce",
                          "receipts_state",
                          "state",
                          "transfers",
                          "transfers_omitted",
                          "tx_index",
                          "value"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Transactions in one head-lane block, ahead of the indexed head",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/head/txs/{hash}": {
      "get": {
        "operationId": "getV2HeadTxsByHash",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "One provisional transaction. No raw logs and **no USD** — the lane serves raw chain facts only, and a price is a derived surface it may not reach.\n\nIt DOES serve the receipt summary and the decoded `Transfer` logs; the two arrived in that order and the sentence here used to deny both. What it still refuses is a raw log, a calldata payload, and any figure that came from PostgreSQL rather than from the node — see the module header.",
                      "properties": {
                        "block_hash": {
                          "description": "The block's hash, so a client can tie a tx to the exact block it was seen in rather than to a height that may be re-used.",
                          "type": "string"
                        },
                        "block_number": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "confirmations": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "effective_gas_price": {
                          "description": "Wei, STRING — the price actually paid per gas after the 1559 split. **Not `gas_price`**, which is what the sender offered.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "from": {
                          "type": "string"
                        },
                        "gas": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "gas_price": {
                          "description": "Wei, STRING.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "gas_used": {
                          "description": "Gas actually consumed. Null with the other two.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "hash": {
                          "type": "string"
                        },
                        "input_size": {
                          "description": "Calldata length in bytes. The calldata itself is not served.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "method": {
                          "description": "**THE HUMAN LABEL.** Null when the selector is unknown to the dictionary or is marked ambiguous there — never a guess. See `crate::method`.",
                          "properties": {
                            "label": {
                              "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                              "type": "string"
                            },
                            "signature": {
                              "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                              "type": "string"
                            },
                            "source": {
                              "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                              "type": "string"
                            },
                            "tier": {
                              "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                              "format": "uint8",
                              "maximum": 3.0,
                              "minimum": 1.0,
                              "type": [
                                "integer",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "label",
                            "signature",
                            "source"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "method_id": {
                          "description": "The function selector, `0x` + 8 hex, or null for a plain value transfer. The same fact `core.chain_transactions.method_id` carries on the indexed twin (`0003:61`), so the two surfaces are comparable.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "nonce": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "receipts_state": {
                          "description": "Whether the receipts leg landed for this transaction's BLOCK. See [`ReceiptsState`], and read it before `transfers`.",
                          "oneOf": [
                            {
                              "description": "The receipts came back and were walked. An empty `transfers` therefore means the transaction emitted no `Transfer` log — a real answer.",
                              "enum": [
                                "available"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "The call failed, the node does not implement `eth_getBlockReceipts`, or it answered something that is not a receipts array. `transfers` is EMPTY for every transaction in this block and means NOTHING; the surface says \"transfers unknown\" rather than \"none\".",
                              "enum": [
                                "unavailable"
                              ],
                              "type": "string"
                            }
                          ]
                        },
                        "state": {
                          "description": "Why a lane row's validity rule differs from a confirmed row's.\n\nA closed set, declared the way `MarkStatus` (`marks.rs:14`) and `PriceSource` (`tokens.rs:314`) are: a consumer MUST branch on it. One value today; it exists so a second is a visible schema change.",
                          "oneOf": [
                            {
                              "description": "Read from the node, not from the index. May vanish or change hash.",
                              "enum": [
                                "provisional"
                              ],
                              "type": "string"
                            }
                          ]
                        },
                        "status": {
                          "description": "`true` = succeeded, `false` = REVERTED, `null` = no receipt yet.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "to": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "transfers": {
                          "description": "Every ERC-20/ERC-721 `Transfer` this transaction emitted, in log order.\n\n**EMPTY MEANS NOTHING WITHOUT `receipts_state`.** Read that field first: `available` + `[]` is \"this transaction moved no tokens\"; `unavailable` + `[]` is \"nobody could ask\". The frontend renders the second as *\"transfers unknown — receipts unavailable for block N\"*.",
                          "items": {
                            "description": "**ONE DECODED TRANSFER, ON THE WIRE.**\n\nThe lane's [`ProvisionalTransfer`] plus the two display fields the registry resolves, minus `tx_hash`/`tx_index` — the row it hangs off already names the transaction, and repeating the hash on every transfer of a 4,000-row block is bytes that say nothing.",
                            "properties": {
                              "amount": {
                                "description": "ERC-20 only, and RAW — no `decimals` applied, because `decimals` may be null. u256 as a decimal STRING, the estate's rule. Null on an ERC-721.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "decimals": {
                                "description": "Null with `symbol`, and for the same reason. **A guessed `decimals` is worse than none**: rendering a raw `1000000000000000000` against an assumed 18 when the token uses 6 is wrong by twelve orders of magnitude. The frontend's fallback is the RAW `amount`, which is the truth.",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "from": {
                                "type": "string"
                              },
                              "kind": {
                                "description": "**WHICH TOKEN STANDARD A DECODED `Transfer` CAME FROM.**\n\nA closed set rather than a string, so the two literals reach `docs/openapi.json` and a generated client can branch on them. The words are [`ps_common::transfer_log::Transfer::kind`]'s, and `the_transfer_wire_words_are_ps_commons_own` pins that they still are — the decoder and the wire may not drift apart.",
                                "oneOf": [
                                  {
                                    "description": "`value` came from `data`: an `amount`, no `token_id`.",
                                    "enum": [
                                      "erc20"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "The third parameter was indexed: a `token_id`, no `amount`.",
                                    "enum": [
                                      "erc721"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "log_index": {
                                "description": "The log's index within the BLOCK, as the node reported it. **The dedupe key**: stable across a re-fetch of the same block in a way an array position is not.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "state": {
                                "description": "Always `provisional`. Present as a field, not implied by the row it sits on, so a transfer copied out of one keeps its own warning.",
                                "oneOf": [
                                  {
                                    "description": "Read from the node, not from the index. May vanish or change hash.",
                                    "enum": [
                                      "provisional"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "symbol": {
                                "description": "**NULL UNLESS `financial.token_registry` HAS THE TOKEN `resolved`.** The frontend renders the raw `token` address when it is null; a symbol guessed from an unresolved row would name a token nobody verified. See `crate::registry`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "to": {
                                "type": "string"
                              },
                              "token": {
                                "description": "The token contract that emitted the log, lowercase `0x` hex. Not the transaction's `to`, which for a multicall is the router.",
                                "type": "string"
                              },
                              "token_id": {
                                "description": "ERC-721 only. Null on an ERC-20.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "from",
                              "kind",
                              "log_index",
                              "state",
                              "to",
                              "token"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "transfers_omitted": {
                          "description": "Decoded transfers the block's [`TRANSFERS_PER_BLOCK_CAP`] discarded. **Block-wide, not per-transaction**: the cap is a bound on what the ring holds for a block, so the honest statement is that this block lost this many rows — attributing them to one transaction would be a number the lane never computed. 0 in every block OPS-87 measured.",
                          "format": "uint32",
                          "minimum": 0.0,
                          "type": "integer"
                        },
                        "tx_index": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "value": {
                          "description": "Wei, STRING.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "block_hash",
                        "block_number",
                        "confirmations",
                        "from",
                        "gas",
                        "hash",
                        "input_size",
                        "nonce",
                        "receipts_state",
                        "state",
                        "transfers",
                        "transfers_omitted",
                        "tx_index",
                        "value"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One transaction from the head preview lane, ahead of the indexed head",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/home/stats": {
      "get": {
        "operationId": "getV2HomeStats",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The landing-page aggregate.\n\nEvery field is `Option` because the underlying aggregates are null before the relevant consumer has produced anything — they serialise as `null`, never absent, so a consumer branches on the value rather than on presence.",
                      "properties": {
                        "as_of_block": {
                          "description": "Block the aggregate was computed as of.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "pls_burned_24h_wei": {
                          "description": "Wei burned in the window. **String** — wei is u256-scale and exceeds Number.MAX_SAFE_INTEGER (9.007e15) by orders of magnitude.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "pls_price_change_24h": {
                          "description": "Percentage change over the window, e.g. -5.89.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "pls_price_usd": {
                          "description": "PLS price in USD. **f64 by decision** — see `docs/api_typed_responses.md`: the oracle's price is a trimmed depth-weighted median of pool ratios and is approximate by construction, so a string would advertise precision the number does not have. f64 is also JS's native type, so transport is lossless.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "txs_24h": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "window_blocks": {
                          "description": "Width of the \"24h\" window in blocks, so a consumer can label the figure honestly rather than assuming wall-clock hours.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "window_blocks"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The front page's headline numbers: PLS price and its 24-hour change, PLS burned, transaction count, and the block they were computed at",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/plans": {
      "get": {
        "operationId": "getV2Plans",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "endpoint_groups": {
                          "items": {
                            "properties": {
                              "auth": {
                                "description": "The auth plane, for groups that are not on the tier plane (`siwe-session`, `open`, `hmac-ingest`). `null` when `min_tier` is set.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "cu_class": {
                                "description": "The CU classes charged in this group, distinct and sorted, joined with `\" | \"`. One name when the group is uniform.\n\n**The separator is `\" | \"` and not `\", \"`** because a class value is not always a bare name: the `/rpc` operations publish the sentence `\"RpcLight; RpcHeavy for eth_getBlockByNumber, eth_getBlockByHash, eth_getLogs\"`, which contains commas. Joining on `\", \"` produced a string no consumer could split back into the classes it was built from.",
                                "type": "string"
                              },
                              "cu_units": {
                                "description": "**WHAT THOSE CLASSES COST, IN COMPUTE UNITS**, ascending and deduplicated (web batch 6 follow-up).\n\nThe plans page must speak in units, not letters: `cu_class` said `H` and a reader had no way to learn that H is 3 against their `daily_call_units`. These come from [`crate::tiers::cu_class_table`] — the same `Class::weight` the limiter charges — via the document's own `x-cu-classes`, so the page, the document and the meter are one set of numbers.\n\nA group charging one class has one entry. `[0]` means the group is unmetered (`/health`, `/openapi.json`, `/v2/plans`, the `/v1` ingest routes), which is a statement, not an absence.",
                                "items": {
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "type": "array"
                              },
                              "group": {
                                "type": "string"
                              },
                              "max_tier": {
                                "description": "The HIGHEST rank any route in the group requires. Equal to `min_tier` in a uniform group; different where one route costs more than its neighbours, which a table showing only the minimum would hide.",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "max_tier_label": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "min_tier": {
                                "description": "The LOWEST rank that admits any route in the group — the cheapest way in. `null` when the group is not on the tier plane at all (`account` is SIWE-session, `meta` is open).",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "min_tier_label": {
                                "description": "[`min_tier`](Self::min_tier) as a plan name, never as `\"Free\"`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "min_tier_variants": {
                                "description": "The raw `x-min-tier` strings the OpenAPI document publishes for this group, distinct and sorted, so the two documents can be reconciled by a consumer or a test. A set for the same reason as on a plan: `Anon` and `Free` are one rank under two names and both occur.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "routes": {
                                "description": "Every path in the group, sorted and deduplicated.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              }
                            },
                            "required": [
                              "cu_class",
                              "cu_units",
                              "group",
                              "min_tier_variants",
                              "routes"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "plans": {
                          "items": {
                            "properties": {
                              "daily_call_units": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "features": {
                                "description": "The `features` JSONB verbatim (`ws_connections`, `trace`, `getlogs_range`)."
                              },
                              "min_tier_label": {
                                "description": "The plan name a route requiring this rank should be labelled with — for this row, its own name. Present so a consumer can join `endpoint_groups[].min_tier` to a plan without re-deriving the rule.",
                                "type": "string"
                              },
                              "min_tier_variants": {
                                "description": "The `x-min-tier` strings **the document actually uses** for this rank, sorted. Same derivation as `endpoint_groups[].min_tier_variants` — see `source.min_tier_variants` for why that matters.\n\n**A SET, not one name**: `Anon` and `Free` both mean rank 0 and the document uses both, so picking one would publish an arbitrary answer. **Empty means no route gates on this rank** — which is true of ranks 2 and 4 (no variant maps to them) AND of rank 3, whose `Advanced` variant exists in the enum but gates no published operation. `\"Free\"` here is the legacy label; see the route doc.",
                                "items": {
                                  "type": "string"
                                },
                                "type": "array"
                              },
                              "monthly_call_units": {
                                "description": "`daily_call_units * 30`. **Derived arithmetic, not an enforced bucket** — the limiter resets daily and the schema has no monthly column. Served because a comparison table shows monthly figures; see `source.monthly_call_units`.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "price_usd_month": {
                                "description": "**Always `null`.** No price is stored in this estate — see `source.price_source`.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "rps_burst": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "tier": {
                                "description": "Rank. Ordering key, and what `min_tier` on a group compares against.",
                                "format": "int16",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "daily_call_units",
                              "features",
                              "min_tier_label",
                              "min_tier_variants",
                              "monthly_call_units",
                              "name",
                              "rps_burst",
                              "tier"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "source": true
                      },
                      "required": [
                        "endpoint_groups",
                        "plans",
                        "source"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Plans, limits and the endpoint map the web builds its comparison table from",
        "tags": [
          "v2"
        ],
        "x-auth": "open",
        "x-cu-budget": "none",
        "x-cu-class": "none",
        "x-cu-units": 0,
        "x-min-tier": "None"
      }
    },
    "/v2/pools/new": {
      "get": {
        "operationId": "getV2PoolsNew",
        "parameters": [
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Restrict to one protocol by its registry slug, e.g. `pulsex_v2` (slugs use underscores). An unknown slug is a 400 naming it, not an empty page.",
            "in": "query",
            "name": "protocol",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of `/v2/pools/new`.",
                        "properties": {
                          "address": {
                            "type": "string"
                          },
                          "created_block": {
                            "description": "Null for pools discovered by enumeration rather than from a factory log.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "fee_tier": {
                            "description": "V3-style fee tier in hundredths of a bip; null for V2 pools.",
                            "format": "int32",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "pool_type": {
                            "type": "string"
                          },
                          "protocol": {
                            "type": "string"
                          },
                          "protocol_id": {
                            "format": "int16",
                            "type": "integer"
                          },
                          "token0": {
                            "type": "string"
                          },
                          "token0_display": {
                            "description": "**THE CURATED OVERRIDE** for `token0`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it: the contract's own `symbol()` stays what it is, and this is the display decision a human pinned to that ADDRESS (`0058`). Null on every token without an override, and null everywhere when `0058` has not been applied.\n\nOne in-process map lookup at serialization — no query, no join.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "token0_symbol": {
                            "description": "Null until the token's metadata resolves.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "token1": {
                            "type": "string"
                          },
                          "token1_display": {
                            "description": "**THE CURATED OVERRIDE** for `token1`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it: the contract's own `symbol()` stays what it is, and this is the display decision a human pinned to that ADDRESS (`0058`). Null on every token without an override, and null everywhere when `0058` has not been applied.\n\nOne in-process map lookup at serialization — no query, no join.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "token1_symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "address",
                          "pool_type",
                          "protocol",
                          "protocol_id",
                          "token0",
                          "token1"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Pools registered most recently",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/pools/{addr}/stats": {
      "get": {
        "operationId": "getV2PoolsByAddrStats",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "`/v2/pools/{addr}/stats`.\n\nEvery metric is `Option` because a pool exists in the registry before ps-batch has produced metrics for it — null means \"not computed yet\", which is a different claim from zero.",
                      "properties": {
                        "address": {
                          "type": "string"
                        },
                        "created_block": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "fee_apr": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "fee_tier": {
                          "format": "int32",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "metrics_updated_at": {
                          "description": "Unix seconds of the last ps-batch metrics pass for this pool.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "pool_type": {
                          "type": "string"
                        },
                        "protocol": {
                          "type": "string"
                        },
                        "protocol_id": {
                          "format": "int16",
                          "type": "integer"
                        },
                        "reserve0": {
                          "description": "Raw reserve, token0 units. **String** — u256-scale.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "reserve1": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "token0": {
                          "type": "string"
                        },
                        "token1": {
                          "type": "string"
                        },
                        "tvl_usd": {
                          "description": "f64 by decision — derived from oracle prices that are a trimmed depth-weighted median and approximate by construction. See docs/api_typed_responses.md.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "volume_24h_usd": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "volume_7d_usd": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "address",
                        "pool_type",
                        "protocol",
                        "protocol_id",
                        "token0",
                        "token1"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One pool's tokens, fee tier, reserves and recent volume",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/protocols": {
      "get": {
        "operationId": "getV2Protocols",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of `/v2/protocols`.",
                        "properties": {
                          "active": {
                            "type": "boolean"
                          },
                          "display_name": {
                            "type": "string"
                          },
                          "factory": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fee_tiers": {
                            "description": "Always an array, empty for V2-style protocols rather than null.",
                            "items": {
                              "format": "int32",
                              "type": "integer"
                            },
                            "type": "array"
                          },
                          "pool_count": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "position_manager": {
                            "description": "V3-style position manager; null for V2-style protocols.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "protocol_id": {
                            "format": "int16",
                            "type": "integer"
                          },
                          "protocol_type": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "active",
                          "display_name",
                          "fee_tiers",
                          "pool_count",
                          "protocol_id",
                          "protocol_type",
                          "slug"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Registered dex protocols and the factories they are discovered by",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/search": {
      "get": {
        "operationId": "getV2Search",
        "parameters": [
          {
            "description": "REQUIRED. The thing to resolve: a 0x tx hash, a 0x address, a bare block number, a 0x validator pubkey, or a token symbol/name prefix. Max 128 characters.\n\nIt being required and undeclared is why a generated client could not call this route at all.",
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "OPTIONAL. Comma-separated kinds to restrict the answer to: `tx,block,address,token,validator,slot,epoch,label`. Omitting it searches every kind, which is the default and is not a breaking change.\n\n**`validator` and `slot` are only reachable WITH this parameter.** A bare integer could be a block number, a validator index or a slot, and the API will not guess between them — so those two kinds are returned only when you ask for them by name.",
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "hits": {
                          "items": {
                            "properties": {
                              "detail": {
                                "description": "Secondary line: a token's name, a block's timestamp, otherwise null.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "display": {
                                "description": "**THE CURATED OVERRIDE**, on a `token` hit whose address carries one.\n\n`label`/`detail` above stay the REGISTRY's symbol and name — what the contract says — so a hit found by searching `dai` still shows `DAI` and carries `display.symbol = \"pDAI\"` beside it. Without this a registry hit and an override hit for the SAME token rendered differently depending on which word the user typed, which is the inconsistency this closes.\n\nNull on every non-token hit and on every token without an override.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "The canonical identifier for the target page: 0x-hash, 0x-address, or a decimal block number as a string. One field rather than a union so the consumer's routing is `/{kind}/{id}`.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "What kind of page this hit opens. A closed set, so a consumer can switch on it exhaustively rather than string-matching.",
                                "oneOf": [
                                  {
                                    "enum": [
                                      "tx",
                                      "block",
                                      "address",
                                      "token",
                                      "validator",
                                      "slot"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A consensus EPOCH, routing to the epochs surface.\n\n**Reachable only with `type=epoch`**, for the same reason `validator` and `slot` are: a bare integer is already a block number, and the epoch space (0..~325k today) sits ENTIRELY inside the block space (0..~27M), so every epoch a user could type is also a real block. Blocks are the commoner intent by a wide margin, and adding epoch to the unconditional set would put a second hit on EVERY block-number search — noise for every user, to serve one filter.\n\n`type=` is the mechanism this route already has for exactly that, and the frontend's Epochs filter IS a `type=`.",
                                    "enum": [
                                      "epoch"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Reachable only once global labels exist (migration pending). The kind is declared now so `type=label` parses, validates and returns an honestly empty list rather than a 400 — a caller can build against it today and see results appear without a contract change.",
                                    "enum": [
                                      "label"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "label": {
                                "description": "Human label where one exists — a token's symbol, otherwise null.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "unfinalized": {
                                "default": false,
                                "description": "**THE SUBJECT IS IN THE HEAD LANE AND NOT YET INDEXED.**\n\n`false` on every hit that came from the database, which is every hit this route used to be able to return. `true` means the block or transaction exists on the node but ps-core has not reached it — the page should open, and it should say so.\n\nA field rather than a separate kind: it is the SAME page, and a `head_tx` kind would make every consumer's routing switch grow an arm that resolves to the same destination.",
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "id",
                              "kind"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "query": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "hits",
                        "query"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Resolve a query to a transaction, block, address, token, validator, slot or epoch",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/slots": {
      "get": {
        "operationId": "getV2Slots",
        "parameters": [
          {
            "description": "Keyset cursor: the last `slot` returned. The next page is strictly BELOW it.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=100. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "**THE MISSED-SLOT BROWSE.** `true` = missed slots only, `false` = proposed only, absent = every slot (the default, and the existing behaviour).\n\n# Why a filter rather than a second route\n\nThe full Slots page needs a missed-only view, and a keyset over ALL slots cannot give one: §3o.7 measured 241,538 missed of 10,334,340 — **2.34 %** — so a client filtering client-side pages through roughly forty-two proposed rows for each missed one it wants to show.\n\n# Why no index is needed, and the arithmetic\n\nThe predicate rides the SAME backward primary-key scan the unfiltered list uses (`slot` is the PK, `0008:16`) with `missed` applied as a filter. At the measured 2.34 %, a full 50-row missed page reads about **2,140 index entries** — a trivial backward scan, and bounded by the same `LIMIT`. A partial index on `missed` would buy a few hundred microseconds and cost a migration, so it is named here and not built.",
            "in": "query",
            "name": "missed",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "boolean",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One slot — **including a missed one, which is the point of the route.**",
                        "properties": {
                          "direct_payments_wei": {
                            "description": "Direct payments to the fee recipient, wei, STRING. **Kept separate from tips — Data §2.4's never-blended rule.**",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "epoch": {
                            "description": "`slot / 32`. Served so a client never has to know the constant.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "exec_block_number": {
                            "description": "The execution block this slot produced. Null on a missed slot, and null on a produced slot whose execution linkage was not recorded.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "finalized": {
                            "description": "The CL has finalized this slot: `slot <= finalized_epoch × 32`. Null when no checkpoint has been resolved, never `false`.",
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "graffiti": {
                            "description": "RAW 32 bytes, hex, lowercase, 66 characters. **Never decoded**: graffiti is arbitrary proposer-supplied bytes and frequently not valid UTF-8 — escape it before rendering. Null on a missed slot (there was no proposer), and null with a `graffiti_reason` when a produced slot has none or has a wrong-length value.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "graffiti_reason": {
                            "anyOf": [
                              {
                                "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                "oneOf": [
                                  {
                                    "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                    "enum": [
                                      "missing"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                    "enum": [
                                      "malformed"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                    "enum": [
                                      "unlinked"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Why `graffiti` is null when `missed` does not already explain it."
                          },
                          "missed": {
                            "description": "**TWO-VALUED ON THIS ROUTE.** A keyset list returns only slots that have a `beacon.blocks` row, so §4.6's third value (`null` = the walker has not reached this slot) cannot occur here. An unreached slot is a GAP in the slot numbers instead; `meta.slot_to` is the frontier.",
                            "type": "boolean"
                          },
                          "proposer_index": {
                            "description": "**Null on a missed slot whose proposer the walk has not attributed.** `beacon.blocks.proposer_index` is nullable since `0013`, and a missed slot with a known proposer is a different fact from one without — `/v2/beacon/stats` counts the two separately as `missed_attributed` and `missed_unattributable`.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "slot": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "tips_wei": {
                            "description": "Priority fees to the proposer, wei, STRING. Null when there is no execution block or no `core.chain_blocks` row for it.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ts": {
                            "description": "Unix seconds, from `beacon.blocks.ts`.",
                            "format": "int64",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "epoch",
                          "missed",
                          "slot",
                          "ts"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "properties": {
                        "finality_as_of": {
                          "description": "Unix seconds at which the checkpoint was polled.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finalized_epoch": {
                          "description": "The CL's finalized checkpoint epoch. Null when none has been resolved.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "last_finalized_slot": {
                          "description": "`finalized_epoch × 32` — the highest slot the checkpoint covers, and the exact boundary every row's `finalized` is compared against.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "slot_to": {
                          "description": "`max(slot)` in `beacon.blocks` — **the slot walker's frontier**. Above it there are no rows and never were; a gap BELOW it is an unreached slot. Null when the table is empty.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "slots_per_epoch": {
                          "description": "32. Served so nothing downstream hardcodes it.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "slots_per_epoch"
                      ],
                      "type": "object"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Recent beacon slots, including the ones no block was proposed for",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/slots/{slot}": {
      "get": {
        "operationId": "getV2SlotsBySlot",
        "parameters": [
          {
            "in": "path",
            "name": "slot",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What we hold about one slot. **Everything the beacon row does not carry is null, and nothing here is derived from the absence of a row.**",
                      "properties": {
                        "epoch": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "exec_block_number": {
                          "description": "The execution block this slot produced. Null on a missed slot.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "finalized": {
                          "description": "The CL has finalized this slot: `slot <= finalized_epoch × 32`. Null when no checkpoint has been resolved, never `false`.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "graffiti": {
                          "description": "RAW 32 bytes, hex, 66 characters. Never decoded.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "graffiti_reason": {
                          "anyOf": [
                            {
                              "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                              "oneOf": [
                                {
                                  "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                  "enum": [
                                    "missing"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                  "enum": [
                                    "malformed"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                  "enum": [
                                    "unlinked"
                                  ],
                                  "type": "string"
                                }
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Why `graffiti` is null, on the estate's one closed set."
                        },
                        "missed": {
                          "description": "`true` = the slot produced no block. Never null on this route: an absent row leaves as a 404 with a code, not as a null field.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "proposer_index": {
                          "description": "The proposer's validator index. **Null on a missed slot the attribution leg has not reached** — `beacon.blocks.proposer_index` is nullable since `0013`, and `/v2/beacon/stats` counts those separately as `missed_unattributable`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "proposer_status": {
                          "description": "The proposer's registry status, e.g. `active_ongoing`. Null with the address, for the same reasons.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proposer_withdrawal_address": {
                          "description": "**THE PROPOSER'S WITHDRAWAL ADDRESS**, from `beacon.validators` (`0008:35`). Null when the proposer is unknown, when the registry has no row for it, and — legitimately — when the validator still has BLS (`0x00`) credentials, which contain no execution address at all (`ps_common::beacon::withdrawal_address`). Three different absences, one null; `proposer_index` beside it tells the first from the other two.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "slot": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "ts": {
                          "description": "Unix seconds, from `beacon.blocks.ts`.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "epoch",
                        "slot",
                        "ts"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One beacon slot: its proposer, block and status",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/swaps": {
      "get": {
        "operationId": "getV2Swaps",
        "parameters": [
          {
            "description": "Opaque cursor from the previous page's `next_cursor`. Pass it back unchanged to fetch the next page; omit it for the first page.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Page size, 1..=100. Default 25. Out of range is a 400 naming the bound.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "USD floor for the feed. Range 100–10000; values outside it are clamped to the nearest end. A non-finite value (NaN, ±inf) is rejected with 400.",
            "in": "query",
            "name": "min_usd",
            "required": false,
            "schema": {
              "default": null,
              "format": "double",
              "type": [
                "number",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The page of priced swaps, newest first.",
                      "items": {
                        "properties": {
                          "amount_in": {
                            "description": "Amount sent by the wallet, in the token's raw base units. STRING because these are token-scale integers that exceed f64's exact range.",
                            "type": "string"
                          },
                          "amount_out": {
                            "description": "Amount received by the wallet, in the token's raw base units. STRING because these are token-scale integers that exceed f64's exact range.",
                            "type": "string"
                          },
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "direction": {
                            "description": "Trade direction as classified by the netting pass — \"buy\" or \"sell\" from the wallet's point of view.",
                            "type": "string"
                          },
                          "token_in": {
                            "type": "string"
                          },
                          "token_in_display": {
                            "description": "**THE CURATED OVERRIDE** for `token_in`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it: the contract's own `symbol()` stays what it is, and this is the display decision a human pinned to that ADDRESS (`0058`). Null on every token without an override, and null everywhere when `0058` has not been applied.\n\nOne in-process map lookup at serialization — no query, no join.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "token_out": {
                            "type": "string"
                          },
                          "token_out_display": {
                            "description": "**THE CURATED OVERRIDE** for `token_out`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it: the contract's own `symbol()` stays what it is, and this is the display decision a human pinned to that ADDRESS (`0058`). Null on every token without an override, and null everywhere when `0058` has not been applied.\n\nOne in-process map lookup at serialization — no query, no join.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "ts": {
                            "description": "Block timestamp, unix seconds. Joined from core.chain_blocks over the page's rows only (<= 100), so it costs one PK lookup per row rather than a second round trip per row from the client — the age cell is unbuildable without it.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "tx_hash": {
                            "type": "string"
                          },
                          "usd_value": {
                            "description": "Always non-null on this route by construction: the feed is priced-only.",
                            "format": "double",
                            "type": "number"
                          },
                          "wallet": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "amount_in",
                          "amount_out",
                          "block_number",
                          "direction",
                          "token_in",
                          "token_out",
                          "ts",
                          "tx_hash",
                          "usd_value",
                          "wallet"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "disclosure": {
                      "description": "Why this feed omits rows. `usd_value_at_trade` is NULL on a large share of swaps, and a USD-filtered feed cannot rank what has no USD value, so unpriced swaps are excluded by construction rather than by choice.\n\nTwo absences are deliberate. There is no per-page count of what was skipped: `idx_wallet_trades_feed` is partial on `usd_value_at_trade >= 100`, an unpriced row compares UNKNOWN against that predicate and is not in the index at all, so a query riding it never visits one and cannot count them. And `unpriced_pct_at_head` is not recomputed per request for the same reason — hence `measured_at`, `measured_block` and `window_blocks`, which let a client judge the figure's age for itself.\n\n`note` is the one field here written for humans rather than clients: the frontend renders it, so it is one short sentence naming none of these fields. This description is the documentation; that string is the copy.",
                      "properties": {
                        "measured_at": {
                          "description": "Unix seconds when `unpriced_pct_at_head` was measured. The field exists so the number's age is visible: it is not recomputed per request, and cannot be, because no index on `analytics.wallet_trades` can serve a count of unpriced rows (the feed index is partial on `usd_value_at_trade >= 100`, which excludes exactly them).",
                          "format": "int64",
                          "type": "integer"
                        },
                        "measured_block": {
                          "description": "Indexed head at the time of the measurement — the age in blocks, which is the unit that actually matters for a figure about chain state.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "note": {
                          "type": "string"
                        },
                        "unpriced_excluded": {
                          "description": "Always true. Present as a field rather than prose so a client can assert on it.",
                          "type": "boolean"
                        },
                        "unpriced_pct_at_head": {
                          "description": "Share of swaps with no USD value, as a percentage. A POINT-IN-TIME measurement compiled into the build, not a live figure — read `measured_at` before relying on it.",
                          "format": "double",
                          "type": "number"
                        },
                        "window_blocks": {
                          "description": "Blocks covered by the measurement window.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "measured_at",
                        "measured_block",
                        "note",
                        "unpriced_excluded",
                        "unpriced_pct_at_head",
                        "window_blocks"
                      ],
                      "type": "object"
                    },
                    "min_usd": {
                      "description": "The USD floor actually applied, after clamping to 100..=10000.",
                      "format": "double",
                      "type": "number"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "disclosure",
                    "min_usd"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Recent dex swaps across every registered protocol",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Anon"
      }
    },
    "/v2/tokens/new": {
      "get": {
        "operationId": "getV2TokensNew",
        "parameters": [
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Only tokens whose tracked liquidity is at least this many USD. 0 or absent disables the filter.",
            "in": "query",
            "name": "min_liquidity",
            "required": false,
            "schema": {
              "default": null,
              "format": "double",
              "type": [
                "number",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of the scout feed: the registry fields plus the two metrics that decide whether a new token is worth opening.",
                        "properties": {
                          "address": {
                            "type": "string"
                          },
                          "decimals": {
                            "description": "NULL until metadata resolves. Do NOT assume 18 (Data §2.1).",
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "display": {
                            "description": "**THE CURATED OVERRIDE**, or null when there is none.\n\n`symbol`/`name` above are WHAT THE CONTRACT SAYS and are never overwritten — a user checking this page against the contract must find them agreeing. This is the display decision a human pinned to this ADDRESS (`0058`), and for the fork-origin tokens it is the difference between \"Dai Stablecoin\" and \"pDAI (fork copy), no backing and no peg\".\n\nNull on every token without an override, and null everywhere when `0058` has not been applied.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "first_seen_block": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "liquidity_usd": {
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "metadata_status": {
                            "type": "string"
                          },
                          "name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "price_usd": {
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "total_supply": {
                            "description": "u256-scale, therefore a STRING.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trust_tier": {
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "address",
                          "metadata_status"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Tokens seen most recently",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/tokens/{addr}": {
      "get": {
        "operationId": "getV2TokensByAddr",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The token page's header object: registry identity plus the 24h metrics and the pricing-anchor flags.",
                      "properties": {
                        "address": {
                          "type": "string"
                        },
                        "anchor_type": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "decimals": {
                          "description": "NULL until metadata resolves. Do NOT assume 18 (Data §2.1).",
                          "format": "int16",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "display": {
                          "description": "**THE CURATED OVERRIDE**, or null when there is none.\n\n`symbol`/`name` above are WHAT THE CONTRACT SAYS and are never overwritten — a user checking this page against the contract must find them agreeing. This is the display decision a human pinned to this ADDRESS (`0058`), and for the fork-origin tokens it is the difference between \"Dai Stablecoin\" and \"pDAI (fork copy), no backing and no peg\".\n\nNull on every token without an override, and null everywhere when `0058` has not been applied.",
                          "properties": {
                            "fork_copy": {
                              "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                              "type": "boolean"
                            },
                            "name": {
                              "description": "The curated name — `\"pDAI (fork copy)\"`.",
                              "type": "string"
                            },
                            "note": {
                              "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                              "type": "string"
                            },
                            "symbol": {
                              "description": "The curated symbol — `\"pDAI\"`.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "fork_copy",
                            "name",
                            "note",
                            "symbol"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "first_seen_block": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "holder_count": {
                          "format": "int32",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "holder_count_as_of": {
                          "description": "Unix seconds: when `holder_count` was computed. Null when it has never been computed, or when it was cleared as stale.\n\nSEPARATE FROM the metrics' own freshness, and that is why it exists (§4s, §75). Most tokens' holder counts are recomputed every two minutes; the native sentinel's and every LP pool token's are recomputed DAILY, because their holder sets are the whole balances table and a per-pair set respectively. Without this field both look equally fresh, since the same pass restamps the row's `updated_at` either way.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "is_pricing_anchor": {
                          "type": "boolean"
                        },
                        "liquidity_usd": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "metadata_status": {
                          "type": "string"
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "price_change_24h": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "price_usd": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "single_source": {
                          "description": "Priced from ONE pool — the price is real but undiversified. Not nullable: a token with no metrics row reads `false`, which is what the `json!` handler emitted via `unwrap_or(false)`.",
                          "type": "boolean"
                        },
                        "symbol": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "total_supply": {
                          "description": "u256-scale, therefore a STRING.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trust_tier": {
                          "format": "int16",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "tx_count_24h": {
                          "format": "int32",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "volume_24h_usd": {
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "address",
                        "is_pricing_anchor",
                        "metadata_status",
                        "single_source"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One token's metadata, supply and trust tier",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/tokens/{addr}/ohlc": {
      "get": {
        "operationId": "getV2TokensByAddrOhlc",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Human-facing alias for `cursor`: return candles starting BEFORE this unix-second bucket start. Ignored when `cursor` is present.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Keyset cursor: the `t` of the oldest candle on the previous page. Exclusive — the next page is strictly older.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Include the in-progress bucket, which is recomputed at read time and carries `closed: false`. Default true. Only ever returned on the newest page, so it is ignored when paging backwards.\n\n`false` excludes the current bucket in EVERY form: not just the one folded from live ticks, but also a partial bucket already stored for it. At `30m` and `12h` the stored partial is the ordinary case — a 12 h candle can hold two closed 4 h source rows with four hours still to run — and it used to come back regardless of this flag.",
            "in": "query",
            "name": "include_open",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "boolean",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 300. **Bounds CLOSED candles.**\n\nThe newest-window page appends the live open bucket (`closed: false`) on top, so it returns up to `limit + 1` rows; an anchored page — one with `cursor` or `before` — never reaches the open bucket and returns at most `limit`. Measured on the deployed binary before this was written down: a `1h` newest window with `limit=50` served 51 rows, 50 closed and 1 open, and the anchored form of the same request served 50.\n\nThis was undocumented and very nearly a defect: the open bucket used to consume a `limit` slot whenever a partial row happened to be stored for it — the ordinary case at `30m` and `12h` — so that page came back one closed candle short of every other page. The count is now the same wherever you are in the series.\n\n**On an anchored page, fewer than `limit` rows does NOT mean end-of-history.** Do not use a short page as a stop condition; page until a page comes back EMPTY, or until its oldest `t` stops moving.\n\nThe walk is bounded twice: by how many CLOSED candles it has emitted and by how many buckets it has VISITED, and the visit bound is `limit + 1` rather than unbounded. So a page containing an in-progress bucket spends a visit on it without spending a closed-candle slot, and the walk can hit the visit ceiling one candle early — measured: an anchored page with `limit=100` served 99 closed candles with plenty of history still below it. That is the co-bound doing its job, not the series ending.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Candle width. Default `1h`.",
            "in": "query",
            "name": "res",
            "required": false,
            "schema": {
              "enum": [
                "1m",
                "5m",
                "15m",
                "30m",
                "1h",
                "4h",
                "12h",
                "1d",
                null
              ],
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One candle. The single-letter names are the charting convention every client library already expects (lightweight-charts, TradingView), so they are kept rather than expanded — renaming them would be a breaking change that buys nothing.",
                        "properties": {
                          "anchor_lag_s": {
                            "description": "Seconds between this bucket and the anchor observation its price was derived from, or null when the anchor priced this bucket directly.\n\nOnly ever set on `synthetic` candles. The anchor's own series has gaps, and where it does the estimate uses the anchor's newest close AT OR BELOW the bucket instead — so the candle is still contiguous, and this says how far the input had to be carried. **The added error is whatever the anchor did in that interval, and it is unbounded in principle**; a client that cares can threshold on this number. `0` never appears — a direct hit reports null.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "c": {
                            "format": "double",
                            "type": "number"
                          },
                          "closed": {
                            "description": "False for the in-progress bucket, which is recomputed at read time and will change. A client must not cache an unclosed candle as final.",
                            "type": "boolean"
                          },
                          "h": {
                            "format": "double",
                            "type": "number"
                          },
                          "l": {
                            "format": "double",
                            "type": "number"
                          },
                          "n": {
                            "format": "int32",
                            "type": "integer"
                          },
                          "o": {
                            "format": "double",
                            "type": "number"
                          },
                          "provisional": {
                            "default": false,
                            "description": "True when ps-derive has not yet written any candle for this period, so a real candle is expected to replace this estimate.\n\n**Only ever set on the newest page.** A page reached with `cursor` or `before` is a walk backwards through settled history, which the writer passed long ago, so nothing on it is provisional.\n\nDetected without knowing the writer's cadence: the bucket sits above the ANCHOR's newest stored candle. The anchor trades constantly, so a bucket the anchor has not reached is a bucket the writer has not reached. A dormant token's right-hand tail is NOT provisional — the anchor has candles there and the token genuinely did not trade.\n\nA client should not cache a provisional candle as final even though `closed` is true: `closed` is a statement about the bucket's time window, this one is about the data.",
                            "type": "boolean"
                          },
                          "synthetic": {
                            "description": "True when the candle is derived rather than observed: the token did not trade in this bucket, so its price was recomputed from the anchor's move over the same period (for a T1 stable, it is $1.00 by definition). `v` and `n` are 0 — skip these when summing volume.\n\nThis includes the RIGHT-HAND TAIL: when a token has not traded recently, the buckets between its last trade and the current one are an anchor-ratio ESTIMATE, not observations. A client may render them as estimated — dashed, faded, however it chooses. Nothing is ever emitted before a token's first observation.",
                            "type": "boolean"
                          },
                          "t": {
                            "description": "Bucket start, unix seconds.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "v": {
                            "description": "Quote volume, or NULL when none has been computed for this bucket yet.\n\nVolume comes from the batch job's trade join, and the tick stream the open bucket is folded from does not carry it — so a bucket built only from ticks reports NULL rather than 0, which would be a lie rather than a default. At an aggregated width the in-progress bucket may already hold closed source rows, and then it DOES carry their volume: partial, and still growing.",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "c",
                          "closed",
                          "h",
                          "l",
                          "n",
                          "o",
                          "synthetic",
                          "t"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "description": "The chart envelope's `meta`, and everything `chart_quality` was computed against, so its numbers are checkable from ONE payload rather than by differencing this response against a second request.",
                      "properties": {
                        "chart_quality": {
                          "description": "**BUCKET COVERAGE OVER THE SERVED WINDOW.** Served on EVERY chart response, not only the suppressed ones — the numbers are the observability, and a flag that only appears when it fires cannot be calibrated.",
                          "properties": {
                            "buckets_observed": {
                              "description": "Buckets that are observations at all (`synthetic: false`), whether or not the swap join counted a trade in them. Always `>= buckets_traded`; the gap is the \"priced by a tick, no swap matched\" class, which `ohlc.rs:149`'s `COALESCE(v.cnt, 0)` makes reachable.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "buckets_returned": {
                              "description": "Candles actually in `data`. Below `buckets_total` means the page has HOLES — an anchor hole wider than a page is the documented case.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "buckets_total": {
                              "description": "Buckets the served window SPANS at the requested resolution: `(window_to - window_from) / res_secs + 1`. **The denominator.** 0 on an empty page.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "buckets_traded": {
                              "description": "Buckets with at least one REAL TRADE: an observation (`synthetic: false`) carrying `n > 0`. **The numerator.**",
                              "format": "int64",
                              "type": "integer"
                            },
                            "coverage": {
                              "description": "`buckets_traded / buckets_total`. **Null when `buckets_total` is 0** — 0/0 is not 0, and the estate's absent-is-not-zero rule applies to a ratio as much as to a count.",
                              "format": "double",
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "insufficient": {
                              "description": "`coverage < threshold`. **Always false while `threshold` is 0.0**, which is the shipped default — see [`ChartDials`]. An EMPTY page with an armed threshold is `true`: a chart with no buckets has no activity in it.",
                              "type": "boolean"
                            },
                            "threshold": {
                              "description": "The dial this decision was made against, echoed so a client and an operator can both see WHICH number produced the flag rather than inferring it. `0.0` = suppression is off.",
                              "format": "double",
                              "type": "number"
                            }
                          },
                          "required": [
                            "buckets_observed",
                            "buckets_returned",
                            "buckets_total",
                            "buckets_traded",
                            "insufficient",
                            "threshold"
                          ],
                          "type": "object"
                        },
                        "res_secs": {
                          "description": "The resolution the page was served at, in seconds. `30m` and `12h` are aggregated at read time from a stored width; this is the TARGET width.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "window_from": {
                          "description": "`t` of the OLDEST candle in `data`. Null on an empty page.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "window_to": {
                          "description": "`t` of the NEWEST candle in `data`. Null on an empty page.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "chart_quality",
                        "res_secs"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Open, high, low and close candles for one token",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/tokens/{addr}/pools": {
      "get": {
        "operationId": "getV2TokensByAddrPools",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "1..=500. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "`liquidity` (default) or `created`.",
            "in": "query",
            "name": "sort",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "description": "How a token's pools are ordered.\n\nA closed set, declared the way `Resolution` is: the allowed values are published in the schema rather than living in an error string, and an unknown one is rejected by the extractor (`util::params` -> `BadRequest` -> 400) instead of by a hand-rolled lookup.",
                  "oneOf": [
                    {
                      "description": "DEFAULT. Deepest first, in three tiers, with newest-first as the tiebreak inside each. Tier 1 is the pool's reserve on whichever side of the pair is a pricing anchor; tier 2, for pools with no anchor side, is the pool's reserve of the token you asked about; tier 3 is pools with no reserve data, which rank last and are never dropped. The tiers are separate because the two measures are in different units and are not comparable — nothing in tier 2 outranks anything in tier 1. Both are depth heuristics in raw base units, not USD valuations, and tier 2 is the weaker of the two: a pool holding a great deal of one token and almost nothing of the other scores high there and may be worth little.",
                      "enum": [
                        "liquidity"
                      ],
                      "type": "string"
                    },
                    {
                      "description": "Newest first. The ordering this endpoint had before, kept because clients exist that depend on it.",
                      "enum": [
                        "created"
                      ],
                      "type": "string"
                    }
                  ]
                },
                {
                  "type": "null"
                }
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One pool holding this token. Oriented around the REQUESTED token: `target_is_token0` says which side it sits on, and `counterparty_*` describes the other side — so a consumer never has to compare addresses to work out which half of the pair it asked about.",
                        "properties": {
                          "as_of_block": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "counterparty_address": {
                            "type": "string"
                          },
                          "counterparty_decimals": {
                            "description": "NULL until the counterparty's metadata resolves (Data §2.1).",
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "counterparty_display": {
                            "description": "**THE CURATED OVERRIDE** for the counterparty token, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it: the contract's own `symbol()` stays what it is, and this is the display decision a human pinned to that ADDRESS (`0058`). Null on every token without an override, and null everywhere when `0058` has not been applied.\n\nOne in-process map lookup at serialization — no query, no join.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "counterparty_symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_block": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "fee_tier": {
                            "format": "int32",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "pool_address": {
                            "type": "string"
                          },
                          "pool_type": {
                            "description": "`v2`, `v3`, … — whatever the registry recorded. **This endpoint does not filter by it**: a V3 pool holding the token is returned like any other. V3 pools carry `reserve0`/`reserve1`/`as_of_block` as `null`, because those come from V2 `Sync` events which V3 does not emit — and under `sort=liquidity` that null depth ranks them LAST. See the type note on the liquidity ordering; ranking V3 by its own depth measure is not built.",
                            "type": "string"
                          },
                          "protocol": {
                            "type": "string"
                          },
                          "rank_value_source": {
                            "description": "Which store produced the side `rank_value_usd` was computed from. `null` exactly when `rank_value_usd` is null.",
                            "enum": [
                              "oracle_pool_state",
                              "v3_pool_depth",
                              "lp_pool_state",
                              null
                            ],
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "rank_value_usd": {
                            "description": "**S3 pool value — an ORDERING KEY IN US DOLLARS. NOT A DISPLAYABLE FIGURE.** `null` when no side of the pool can be trusted to carry a price.\n\n# What the number is\n\n`2 × (the value of the highest-precedence PRICED side)` — never a sum of the two sides. See `POOLS_BY_LIQUIDITY`'s type note for the full rule and `docs/proposal_pool_value_ranking.md` §2 for why summing fails.\n\n# Why it must not be rendered\n\nIt is **deliberately conservative**: `2 ×` the trusted side UNDERSTATES a lopsided pool, and for a tie between two equally-trusted sides it takes the SMALLER. That is correct for an ordering — understating a real pool moves it a few rows, while overstating a junk pool puts it at the top of page 1 — and it is wrong for a figure, because a published understatement is an ASSERTED NUMBER that happens to be low. `0051`'s header states the estate's line here: an ordering key can be revised without revising anything anyone was shown; a displayed figure cannot.\n\n**It is not TVL and must never be labelled TVL.**\n\n# For the frontend\n\nThis is the one field a client needs to reproduce the server's `sort=liquidity` order client-side: rows sort by it DESCENDING with nulls last. It is emitted on BOTH sorts, so a client can rank by value while asking for `sort=created`. Units are **US dollars**; the type is `f64` because the value is computed rather than read from a NUMERIC column (`docs/api_typed_responses.md`'s rule), and a non-finite result is served as `null` rather than as a number JSON cannot carry.",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "reserve0": {
                            "description": "u256-scale, therefore STRINGS. Null when no state row is tracked yet. These stay token0/token1 in POOL order, not target/counterparty order — re-labelling them would silently swap the pair for half the rows.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reserve1": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "target_is_token0": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "counterparty_address",
                          "pool_address",
                          "pool_type",
                          "protocol",
                          "target_is_token0"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Every registered pool holding one token",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/tokens/{addr}/price": {
      "get": {
        "operationId": "getV2TokensByAddrPrice",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "A token's current USD price, with the provenance that produced it.\n\n**All eleven keys are always present.** The six oracle-only fields — `as_of_block`, `as_of_ts`, `source_pool`, `source_depth_usd`, `first_tick_block`, `first_tick_ts` — are `null` rather than absent when `source` is not `oracle`, so a client reads the same shape on every branch and branches on `source` alone.\n\n# `first_tick_*` — the disclosure pair (P0/B2)\n\n`as_of_block` is the NEWEST tick and `first_tick_block` is the OLDEST. Until B2 the oldest was served nowhere: `token_registry.first_seen_block` is the token's first SIGHTING, which for a token that traded for months before this deployment could price it is a different and much earlier block.\n\nHaving both is what lets a surface say *\"priced from <date> — no history before it\"* instead of drawing a gap. **Figures before `first_tick_block` are not missing data; they are PRE-COVERAGE**, and the distinction is the whole point: a gap invites \"when will you fix it\", pre-coverage answers it.\n\n`source` is `oracle` (priced from a pool observation), `t1_definition` (a T1 stable, $1.00 by definition) or `none` (no price is known — `price_usd` is null, never zero).",
                      "properties": {
                        "address": {
                          "type": "string"
                        },
                        "as_of_block": {
                          "description": "Null unless `source == oracle`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "as_of_ts": {
                          "description": "Null unless `source == oracle`. Unix seconds of the tick's block.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "first_tick_block": {
                          "description": "The FIRST block at which this token had a price. Null when it has never had one — §3.4's no-sentinel rule, so this is never 0 and never the coverage floor standing in for \"unknown\".\n\nNull is not one state but two, and `source` separates them: with `source = none` it means never priced; with `source = t1_definition` it means priced by definition, so there is no first tick to name.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "first_tick_ts": {
                          "description": "Unix SECONDS of `first_tick_block`'s block — the same epoch-seconds convention as `as_of_ts`, not milliseconds and not RFC-3339.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "price_usd": {
                          "description": "Exactly 1.0 for `t1_definition`, null for `none`.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "single_source": {
                          "description": "Priced from ONE pool. Null when there is no price at all.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "source": {
                          "description": "Where a price came from. A closed set so a consumer can switch on it exhaustively instead of string-matching, and so adding a source is a visible schema change.",
                          "oneOf": [
                            {
                              "description": "A T1 stable, $1.00 by definition (Data §4.6). No tick exists.",
                              "enum": [
                                "t1_definition"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "No tick has ever been recorded for this token.",
                              "enum": [
                                "none"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "A real tick from `analytics.price_ticks`.",
                              "enum": [
                                "oracle"
                              ],
                              "type": "string"
                            }
                          ]
                        },
                        "source_depth_usd": {
                          "description": "Null unless `source == oracle`. The tracked liquidity behind the tick.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "source_pool": {
                          "description": "Null unless `source == oracle`.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "stale": {
                          "description": "Held-and-marked-stale after 24h (Data §4.4). Null when there is no tick to age; false by definition for a T1 stable.",
                          "type": [
                            "boolean",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "address",
                        "source"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One token's current price, with the anchor it was priced against",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/tokens/{addr}/price/history": {
      "get": {
        "operationId": "getV2TokensByAddrPriceHistory",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`. Ascending.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Inclusive lower bound, BLOCK NUMBER (not a timestamp). Default 0.",
            "in": "query",
            "name": "from",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=5000. Default 1000.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Inclusive upper bound, BLOCK NUMBER. Default unbounded.",
            "in": "query",
            "name": "to",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One tick. Deliberately NOT the full `price_ticks` row: `log_index` is the cursor's second component, not something a chart consumes, and emitting it invites clients to build their own cursor out of it.",
                        "properties": {
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "price_usd": {
                            "format": "double",
                            "type": "number"
                          }
                        },
                        "required": [
                          "block_number",
                          "price_usd"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One token's price over time",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/tokens/{addr}/richlist": {
      "get": {
        "operationId": "getV2TokensByAddrRichlist",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "properties": {
                          "balance_raw": {
                            "description": "u256-scale, therefore a STRING.",
                            "type": "string"
                          },
                          "holder": {
                            "type": "string"
                          },
                          "rank": {
                            "description": "Dense and ascending — it is also this list's cursor.",
                            "format": "int32",
                            "type": "integer"
                          },
                          "share_basis": {
                            "description": "What `share_pct` divides by, so the number is never read as something else. Always `\"total_supply\"` today; the field exists because a second basis (circulating) is a real possibility and a silent switch would be invisible.",
                            "type": "string"
                          },
                          "share_pct": {
                            "description": "Percentage of **RAW `totalSupply()`**, 0-100.\n\n# THE DENOMINATOR IS DEFINED, AND IT IS NOT \"CIRCULATING\"\n\n`financial.token_registry.total_supply` is what the contract's `totalSupply()` returned — every token that exists, including any held at burn addresses. It is **not** circulating supply: subtracting burns needs a curated burn-address set this estate does not have, and every explorer that attempts it picks a different one. So this figure means \"fraction of the tokens that exist\", which is checkable against the contract, rather than a number whose definition the reader has to guess.\n\n# WHY IT IS NULL, and the four cases are different\n\nThe producer computes it as `CASE WHEN supply > 0 THEN balance/supply*100 END` (`ps-batch/src/richlist.rs`), so null means one of:\n\n* the token never resolved, so no supply was ever fetched; * it resolved but its `totalSupply()` call reverted — that read is best-effort in the resolver, and until `resolver`'s supply-refresh dial is armed nothing revisits it; * the supply is genuinely `0`, and a token with no tokens has no shares to apportion. Dividing by it would be an infinity, not a percentage.\n\n**A non-null share can still be STALE**: `total_supply` was written once at resolution, so a token that has minted or burned since carries a denominator from that block until the refresh dial is armed.",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "balance_raw",
                          "holder",
                          "rank",
                          "share_basis"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The largest holders of one token, ranked by balance",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/tokens/{addr}/transfers": {
      "get": {
        "operationId": "getV2TokensByAddrTransfers",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Cursor from the previous page's `next_cursor`. Pass it back unchanged to fetch the next page; omit it for the first page. Treat it as opaque — its format is not a contract and may change.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Page size, 1..=200. Default 50. Out of range is a 400 naming the bound.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One ERC-20 transfer of this token, newest first.",
                        "properties": {
                          "amount_raw": {
                            "description": "Raw base units, STRING — these are token-scale integers that exceed f64's exact range. Apply the token's `decimals` to display them.",
                            "type": "string"
                          },
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "from": {
                            "description": "Sender, or null when the log has NO SENDER LEG — a WPLS `Deposit`, whose only row is receiver-subject. Matches `/v2/txs/{hash}/transfers`, which derives the same field as `max(address) FILTER (WHERE is_sender)` with no fallback and therefore also serves null there.\n\nAn ordinary ERC-20 mint is NOT this case: `Transfer(0x0, to, amount)` has a sender leg, so `from` is the zero address, not null.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "log_index": {
                            "description": "Position of the `Transfer` log within its block. With `block_number` it forms this feed's page cursor, and the pair is unique per token.",
                            "format": "int32",
                            "type": "integer"
                          },
                          "to": {
                            "description": "Recipient, or null when the row's `counterparty` was not recorded.\n\nThe schema allows NULL and the current writer never emits one for an ERC-20 row, so this is null in practice only if that changes. A WPLS `Withdrawal` does NOT produce null here: its `to` is the WPLS contract, which is what the sibling route serves too.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ts": {
                            "description": "Block timestamp, unix seconds — null if `core.chain_blocks` has no row for this block. See the LEFT JOIN note in `list_inner`: a nullable `ts` is honest, a silently short page is not.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "tx_hash": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "amount_raw",
                          "block_number",
                          "log_index",
                          "tx_hash"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Transfers of one token, newest first",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/txs/{hash}": {
      "get": {
        "operationId": "getV2TxsByHash",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "block_number": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "confirmations": {
                          "description": "Blocks since inclusion, measured against the NODE HEAD — the chain tip the head lane holds in memory — on BOTH sources. An unindexed transaction and an indexed one are counted in the same frame, so the number does not jump when a transaction indexes.\n\n**NULL WHEN THE LANE HAS NO NODE HEAD** — the poller's cold start, or an outage of the node it polls. There is no fallback frame: a depth measured against anything else is not the number this field defines, and serving it would be wrong silently and only sometimes. Unknown is served as unknown.\n\nThis is a DEPTH, not a settlement claim. Whether the beacon chain has finalized the block is the separate `finality` field, from the CL checkpoint.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "created_contract": {
                          "description": "Set only when this transaction deployed a contract.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "erc20_transfer_count": {
                          "description": "Counts only. The rows themselves are NOT embedded — see the module header's note on `/transfers` and `/trace`. **ERC-20 ONLY.** `ui.address_erc20` — the table the indexed count reads — holds no ERC-721 row, so an ERC-721 `Transfer` is counted by NEITHER source. The lane sees them and drops them here for parity; `/v2/head/txs/{hash}` still serves both kinds.\n\n**NULL, NOT 0, WHEN THE LANE HAS NO RECEIPT** for this transaction: the count is decoded from `Transfer` logs and logs arrive with the receipt, so a 0 would claim the transaction moved no tokens. The indexed source always has a number here.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "fee": {
                          "description": "The fee breakdown — Data §2.4's \"never blended\" rule applied per transaction.\n\n`burned_wei` is the base fee destroyed (EIP-1559); `tip_wei` is the priority fee that reached the proposer. They are separate fields and must never be summed into a single \"fee\" by this API — the page shows both because on PulseChain the split is the interesting part. `total_wei` is provided because the sum is what a user recognises as \"what this cost me\", and computing it client-side from two decimal strings invites a float bug.",
                          "properties": {
                            "burned_wei": {
                              "description": "Base fee burned, wei. String — see the module header.\n\n**NULL, NOT \"0\", WHEN THE RECEIPT HAS NOT LANDED** on a lane-sourced answer. The fee is `gas_used * price` and a pending transaction has neither, so there is no split to compute; \"0\" would say the transaction cost nothing, which is a claim and a wrong one. Read `status` beside it — null there means the receipt has not landed. Every field of this object is null, or none of them is.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "effective_gas_price_wei": {
                              "description": "Effective gas price actually paid, wei. String. Null with the rest — see `burned_wei`.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "tip_wei": {
                              "description": "Priority fee to the proposer, wei. String. Null with the rest — see `burned_wei`.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "total_wei": {
                              "description": "burned + tip, wei. String. Convenience, not a new fact. Null with the rest — see `burned_wei`.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "type": "object"
                        },
                        "finality": {
                          "description": "CL-checkpoint finality — see [`Finality`]. **Not** \"did it come from the index\": an indexed transaction above the checkpoint is `unfinalized`.",
                          "enum": [
                            "finalized",
                            "unfinalized"
                          ],
                          "type": "string"
                        },
                        "from": {
                          "type": "string"
                        },
                        "gas_limit": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "gas_used": {
                          "description": "**NULL WHEN THE RECEIPT HAS NOT LANDED** on a lane-sourced answer — gas used is a receipt fact. `gas_limit` beside it comes from the transaction itself and is always known.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "gas_used_pct": {
                          "description": "Percentage of the tx's own gas limit consumed, 0-100. Null exactly when `gas_used` is.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "hash": {
                          "type": "string"
                        },
                        "internal_transfer_count": {
                          "description": "The `ui.address_internal` projection count — value-moving internal calls, root excluded — on both sources.\n\n**NULL WHILE THE TRACE IS UNAVAILABLE**, never 0: a 0 claims the transaction made no internal transfers, which is a different statement from \"nobody could ask\". Read `traces` beside it.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "method": {
                          "description": "**THE HUMAN LABEL** for `method_id`. Null when the selector is unknown to the dictionary or is marked ambiguous there — never a guess (`crate::method`). A map lookup, not a join: the selector is already on this row (`core.chain_transactions.method_id`, `0003:61`).\n\n**NULL FOR A CONTRACT CREATION** — no lookup is performed at all — and null for the EVM init-code prefixes (`0x60806040`, `0x60a06040`, `0x60c06040`) on ANY transaction, so a creation routed through a factory never acquires a junk name from a public signature set.",
                          "properties": {
                            "label": {
                              "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                              "type": "string"
                            },
                            "signature": {
                              "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                              "type": "string"
                            },
                            "source": {
                              "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                              "type": "string"
                            },
                            "tier": {
                              "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                              "format": "uint8",
                              "maximum": 3.0,
                              "minimum": 1.0,
                              "type": [
                                "integer",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "label",
                            "signature",
                            "source"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "method_id": {
                          "description": "First 4 bytes of calldata as 0x-hex, or null for a plain transfer.\n\n**NULL FOR A CONTRACT CREATION TOO** (`to` is null). A creation's calldata is INIT CODE and its first four bytes are opcodes — `PUSH1 0x80 PUSH1 0x40 …` — not a selector, so publishing them would be a value that means nothing and invites a lookup. Render \"Contract creation\" from `to == null` / `created_contract`, never from this field. The same rule applies on every list that carries it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "nonce": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "status": {
                          "description": "1 = success, 0 = reverted. Nullable for pre-Byzantium-style rows where the receipt carried no status; kept nullable rather than defaulted so a missing status is not rendered as a failure.\n\n**ON A LANE-SOURCED ANSWER, NULL ALSO MEANS \"THE RECEIPT HAS NOT LANDED\"** — the transaction is in a block the node has published but whose receipts the poller has not merged yet. That is the same state in which `gas_used`, `gas_used_pct`, every `fee` component and `erc20_transfer_count` are null: they are all receipt facts, and none of them is served as a zero. A null `status` beside a null `fee.total_wei` is \"not settled yet\", not \"cost nothing\".",
                          "format": "int16",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "to": {
                          "description": "None for contract creations.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "traces": {
                          "description": "Where the internal calls came from, and whether they came at all — see [`TracesSource`].",
                          "enum": [
                            "indexed",
                            "traced",
                            "unavailable"
                          ],
                          "type": "string"
                        },
                        "traces_reason": {
                          "description": "Why, when `traces` is `unavailable`. **A CLOSED SET** — the four literals of [`crate::ondemand_trace::TraceUnavailable`], or null. It was an open `string|null`, which a generated client could not assert set equality on (§140 L9).\n\nThe four: `trace_timeout` | `trace_too_large` | `trace_node_error` | `trace_undecodable`. Null otherwise.",
                          "enum": [
                            "trace_timeout",
                            "trace_too_large",
                            "trace_node_error",
                            "trace_undecodable",
                            null
                          ],
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "ts": {
                          "description": "Unix seconds of the containing block.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "tx_index": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "tx_type": {
                          "description": "EIP-2718 type: 0 legacy, 2 dynamic-fee, etc.",
                          "format": "int16",
                          "type": "integer"
                        },
                        "value_wei": {
                          "description": "Value transferred, wei. String.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "block_number",
                        "fee",
                        "finality",
                        "from",
                        "gas_limit",
                        "hash",
                        "nonce",
                        "traces",
                        "ts",
                        "tx_index",
                        "tx_type",
                        "value_wei"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One transaction: its status, value, gas and decoded action",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/txs/{hash}/internal": {
      "get": {
        "operationId": "getV2TxsByHashInternal",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor: the last `trace_address` returned. The next page is strictly above it in TEXT order — see `InternalCall::trace_address`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The rows of this page, in `trace_address` TEXT order — the array itself, not an object wrapping one. `total` beside it is the full count for the transaction and `next_cursor` pages through the rest.\n\nAn empty array is not by itself an answer — read `traces` beside it.",
                      "items": {
                        "description": "One entry of a transaction's call tree.",
                        "properties": {
                          "depth": {
                            "description": "Number of components in `trace_address`; the tree depth, served so a client does not have to parse the path to indent a row. The root call is depth 1.",
                            "format": "int32",
                            "type": "integer"
                          },
                          "error": {
                            "description": "The revert reason, or null on success. `0003:115` — NULL means the call succeeded.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "from": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "gas_used": {
                            "description": "Gas consumed by this call. Null when the node recorded none.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "method": {
                            "description": "**THE HUMAN LABEL** for `method_id`, from the shared dictionary. Null when the selector is unknown or ambiguous, and null everywhere until `0057` is applied — never a guess.",
                            "properties": {
                              "label": {
                                "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                                "type": "string"
                              },
                              "signature": {
                                "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                                "type": "string"
                              },
                              "source": {
                                "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                                "type": "string"
                              },
                              "tier": {
                                "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                                "format": "uint8",
                                "maximum": 3.0,
                                "minimum": 1.0,
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "signature",
                              "source"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "method_id": {
                            "description": "The callee's function selector, or null for a call with no calldata.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "to": {
                            "description": "The callee — or the CREATED ADDRESS for `create`/`create2`, and the refund target for `selfdestruct` (`0003:111`). Null when the node recorded none.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trace_address": {
                            "description": "Position in the call tree, dot-separated: `\"0\"`, `\"0.1\"`, `\"0.1.3\"`.\n\n# THE ORDERING CONTRACT, stated because it is not the obvious one\n\nRows come back in **TEXT order**, which is total and stable — the two properties a keyset cursor needs — and is **NOT execution order** once any component reaches two digits: `\"1.10\"` sorts before `\"1.2\"`. That is a `TEXT` column (`0003:106`) and re-sorting it numerically in SQL would cost a sort over the whole set and defeat the keyset.\n\n**A client that needs true execution order sorts by the path components as INTEGERS**, which is a total order on a tree and is what `depth` beside it is for. The panel most clients want — an indented tree — needs `depth` and the parent relation, both derivable from this string without re-ordering anything.",
                            "type": "string"
                          },
                          "trace_type": {
                            "description": "`call` | `delegatecall` | `staticcall` | `callcode` | `create` | `create2` | `selfdestruct` | `reward` — the `0003:107` closed set.",
                            "type": "string"
                          },
                          "value_wei": {
                            "description": "Wei, STRING. `\"0\"` is the ordinary case here and is a real value: most internal calls move nothing, which is exactly why they are absent from `/trace`.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "depth",
                          "trace_address",
                          "trace_type",
                          "value_wei"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.\n\nIt is a `trace_address` and the keyset walks it in TEXT order — see [`InternalCall::trace_address`] for why that is not execution order.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "total": {
                      "description": "The full count for this transaction. Null when `traces` is `unavailable` — a 0 would be a claim nobody measured.",
                      "format": "int64",
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "traces": {
                      "description": "**WHERE THE INTERNAL CALLS CAME FROM, AND WHETHER THEY CAME AT ALL.**\n\n`indexed` = read from `core.chain_traces`. `traced` = fetched on demand from the node for a transaction the index has not reached (`crate::ondemand_trace`). `unavailable` = nobody could ask — and it is **never rendered as an empty list**: an empty `data` with `traces: \"unavailable\"` means \"not yet available\", and the same empty `data` with `traces: \"traced\"` means \"this transaction made no internal calls\". Those are different facts and the frontend writes different words from them.",
                      "enum": [
                        "indexed",
                        "traced",
                        "unavailable"
                      ],
                      "type": "string"
                    },
                    "traces_reason": {
                      "description": "Why a trace could not be served. **Never an empty list** — the wire carries `traces: \"unavailable\"` and this reason, and the frontend writes \"traces not yet available\" from it.\n\n* `trace_timeout` — the node did not answer inside `trace_budget_ms`. * `trace_too_large` — the body exceeded [`MAX_TRACE_BYTES`]. * `trace_node_error` — transport, HTTP status, a JSON-RPC error object, or **the node returned no frames**: it does not know the hash or has not imported the block yet. A real transaction always has at least its root frame, so an empty result is not a trace (§140b LOW 7). * `trace_undecodable` — the answer was not a Parity-flat array this decoder understands.\n\n**A CLOSED SET ON THE WIRE** (§140 L9), like `TracesSource` and `Finality` beside it. It used to reach `docs/openapi.json` as an open `string|null`, so a generated client could not assert set equality and a fifth reason would have arrived unannounced.\n\nThe four descriptions are in THIS doc comment rather than on the variants deliberately: schemars renders a unit enum as a flat `enum` list when the variants carry no doc comments and as a `oneOf` of single-value schemas when they do. The flat list is what a client compares as a set.",
                      "enum": [
                        "trace_timeout",
                        "trace_too_large",
                        "trace_node_error",
                        "trace_undecodable",
                        null
                      ],
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "traces"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Internal value transfers made by one transaction",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/txs/{hash}/swaps": {
      "get": {
        "operationId": "getV2TxsByHashSwaps",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The transaction's swap legs, in on-chain order.\n\n# There is deliberately NO transaction-level USD total\n\nSumming `usd_volume` across legs DOUBLE-COUNTS a multi-hop path: hop 1's output IS hop 2's input, so the same value moving through a route is counted once per hop it passes. A total here would be **wrong**, not merely undisclosed, so the field does not exist and callers must not compute one.",
                      "properties": {
                        "available_after_indexing": {
                          "description": "**THE ONE SECTION THAT CANNOT BE 1:1 BEFORE THE FLIP** (item C).\n\n`true` on a LANE-sourced answer, where `legs` is always `[]`. Swap legs are `analytics.dex_swaps` rows, WRITTEN BY ps-derive from the indexed logs — they are a derivation, not a fact the node hands over, so there is nothing to decode from a block the indexer has not reached. The honest answer is an empty list that SAYS it is empty for a reason a reload will fix, rather than one that looks like \"this transaction swapped nothing\".\n\n`false` on the indexed answer, where `[]` means exactly that. The frontend renders \"swap details appear once this transaction is indexed\" from the `true` arm and nothing from the `false` one.",
                          "type": "boolean"
                        },
                        "block_number": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "legs": {
                          "items": {
                            "description": "One decoded swap leg of a transaction.\n\n# SHAPE DIVERGENCE FROM THE PROPOSAL — the FE type needs correcting\n\n`docs/proposal_swap_activity_surfaces.md` §3.1 sketched a leg with NESTED token objects — `token_in: {address, symbol, decimals}` — and the Web panel was typed from it (`TxSwapLegRow`, Web `994c3c1`, marked not-measured). **This ships FLAT instead**: `token_in`, `token_in_symbol`, `token_in_decimals`.\n\nThe reason is that the nested form is not the house pattern and the sketch was for surface (a), not this route. Every sibling is flat — `swaps::Swap` carries `token_in: String`/`token_out: String`, and `Erc20Transfer` carries `token_address: String` — so a nested object here would be the only one of its kind on the API and would have to be justified route by route forever.\n\n**What the FE must change:** `token_in.address` -> `token_in`, `token_in.symbol` -> `token_in_symbol`, `token_in.decimals` -> `token_in_decimals`, and the same for `token_out`. Two other differences, both in the FE's favour: `tx_hash` and `block_number` are on the ENVELOPE rather than repeated per leg (they are constant across a transaction), and there is no per-leg `ts` — the tx detail page this panel sits on already has the block timestamp from `/v2/txs/{hash}`.\n\n**`usd_volume` is nullable BY DESIGN.** It is NULL wherever the leg could not be valued at its block — the token had no usable price then. That is a state, not an error and not a zero: render it as \"no price\", never as `$0`.",
                            "properties": {
                              "amount_in": {
                                "description": "Raw units, string — these exceed f64 and JSON number precision.",
                                "type": "string"
                              },
                              "amount_out": {
                                "type": "string"
                              },
                              "log_index": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "pool": {
                                "description": "The pool the swap happened in.",
                                "type": "string"
                              },
                              "protocol": {
                                "description": "Registry slug of the pool's protocol, e.g. `ninemm_v3`.",
                                "type": "string"
                              },
                              "token_in": {
                                "description": "What the pool RECEIVED — the wallet side sent it.",
                                "type": "string"
                              },
                              "token_in_decimals": {
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token_in_display": {
                                "description": "**THE CURATED OVERRIDE** for `token_in`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "token_in_symbol": {
                                "description": "Symbol from `financial.token_registry`, absent when unresolved. A truncated address is the house fallback; a symbol is never invented.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_out": {
                                "description": "What the pool RELEASED.",
                                "type": "string"
                              },
                              "token_out_decimals": {
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token_out_display": {
                                "description": "**THE CURATED OVERRIDE** for `token_out`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "token_out_symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "usd_volume": {
                                "description": "USD value of this LEG, or null when it could not be valued at this block.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "amount_in",
                              "amount_out",
                              "log_index",
                              "pool",
                              "protocol",
                              "token_in",
                              "token_out"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "truncated": {
                          "description": "True when the transaction has more legs than `SWAP_LEGS_MAX` and the list was cut. False on every real transaction.",
                          "type": "boolean"
                        },
                        "tx_hash": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "available_after_indexing",
                        "block_number",
                        "legs",
                        "truncated",
                        "tx_hash"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Dex swaps decoded from one transaction",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/txs/{hash}/trace": {
      "get": {
        "operationId": "getV2TxsByHashTrace",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor: the last `trace_address` returned. A STRING, not a number — trace addresses are dot-separated paths and their TEXT order is what the keyset walks (\"1.10\" sorts before \"1.2\").",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The rows of this page, in `trace_address` TEXT order — the array itself, not an object wrapping one. `total` beside it is the full count for the transaction and `next_cursor` pages through the rest.\n\nAn empty array is not by itself an answer — read `traces` beside it.",
                      "items": {
                        "description": "One internal value transfer (a trace).",
                        "properties": {
                          "error": {
                            "description": "Revert reason when the sub-call failed, else null. A non-null here does NOT mean the transaction failed — an inner call can revert and be caught.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "from": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "to": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trace_address": {
                            "description": "Position in the call tree, dot-separated, e.g. \"1.0.6.0.1.5.0\".\n\nNOTE the ordering caveat: rows are returned in TEXT order, which is NOT true execution order once any component reaches two digits — \"1.10\" sorts before \"1.2\". Text order is used deliberately because it is consistent with the keyset cursor, so pagination never skips or repeats; but a client that needs true call-tree order must sort by the component-wise numeric value itself. Verified against real data 2026-08-17.",
                            "type": "string"
                          },
                          "trace_type": {
                            "description": "call / create / suicide, as decoded by ps-core.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "value_wei": {
                            "description": "Wei. **String** — see the module header.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "trace_address",
                          "value_wei"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.\n\nIt is a `trace_address` and the keyset walks it in TEXT order — see [`InternalCall::trace_address`] for why that is not execution order.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "total": {
                      "description": "The full count for this transaction. Null when `traces` is `unavailable` — a 0 would be a claim nobody measured.",
                      "format": "int64",
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "traces": {
                      "description": "**WHERE THE INTERNAL CALLS CAME FROM, AND WHETHER THEY CAME AT ALL.**\n\n`indexed` = read from `core.chain_traces`. `traced` = fetched on demand from the node for a transaction the index has not reached (`crate::ondemand_trace`). `unavailable` = nobody could ask — and it is **never rendered as an empty list**: an empty `data` with `traces: \"unavailable\"` means \"not yet available\", and the same empty `data` with `traces: \"traced\"` means \"this transaction made no internal calls\". Those are different facts and the frontend writes different words from them.",
                      "enum": [
                        "indexed",
                        "traced",
                        "unavailable"
                      ],
                      "type": "string"
                    },
                    "traces_reason": {
                      "description": "Why a trace could not be served. **Never an empty list** — the wire carries `traces: \"unavailable\"` and this reason, and the frontend writes \"traces not yet available\" from it.\n\n* `trace_timeout` — the node did not answer inside `trace_budget_ms`. * `trace_too_large` — the body exceeded [`MAX_TRACE_BYTES`]. * `trace_node_error` — transport, HTTP status, a JSON-RPC error object, or **the node returned no frames**: it does not know the hash or has not imported the block yet. A real transaction always has at least its root frame, so an empty result is not a trace (§140b LOW 7). * `trace_undecodable` — the answer was not a Parity-flat array this decoder understands.\n\n**A CLOSED SET ON THE WIRE** (§140 L9), like `TracesSource` and `Finality` beside it. It used to reach `docs/openapi.json` as an open `string|null`, so a generated client could not assert set equality and a fifth reason would have arrived unannounced.\n\nThe four descriptions are in THIS doc comment rather than on the variants deliberately: schemars renders a unit enum as a flat `enum` list when the variants carry no doc comments and as a `oneOf` of single-value schemas when they do. The flat list is what a client compares as a set.",
                      "enum": [
                        "trace_timeout",
                        "trace_too_large",
                        "trace_node_error",
                        "trace_undecodable",
                        null
                      ],
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "traces"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The call tree of one transaction",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/txs/{hash}/transfers": {
      "get": {
        "operationId": "getV2TxsByHashTransfers",
        "parameters": [
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor: the last `log_index` returned. Ascending — log order is emission order within the transaction.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": null,
              "format": "int32",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "properties": {
                          "amount_raw": {
                            "description": "Raw token units, NOT decimal-adjusted. **String** — an ERC-20 amount is u256 and exceeds Number.MAX_SAFE_INTEGER. Divide by the token's `decimals` (from /v2/tokens/{addr}) to display.",
                            "type": "string"
                          },
                          "display": {
                            "description": "**THE CURATED OVERRIDE** for the transferred token, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "from": {
                            "description": "The sender. **NOT null on a mint** — an ERC-20 mint is `Transfer(0x0, to, amount)` and this field is `\"0x0000000000000000000000000000000000000000\"`, on both sources. Render the mint chip from the value being the zero address, never from a null.\n\n**Null when the log has no sender leg**, which today is the WETH9 `Deposit` (wrap) leg: `ui.address_erc20` holds one receiver-subject row for it, so there is no `from` to report. Its `to` is the depositor.\n\nA `Transfer` whose party topics do not decode produces **no row at all** on either source and is absent from this list rather than appearing with a null side — the writer's `?` skips the whole log, so it can never write one leg without the other.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "log_index": {
                            "description": "Position within the block's logs — the stable identity of the transfer.",
                            "format": "int32",
                            "type": "integer"
                          },
                          "to": {
                            "description": "The receiver. **NOT null on a burn** — a burn is `Transfer(from, 0x0, amount)` and this field is the zero address, on both sources. Render the burn chip from the value, never from a null.\n\n**On a WETH9 `Withdrawal` (unwrap) leg it is the WPLS CONTRACT**: that row is sender-subject and its counterparty is the token itself, so `to` is the contract's own address, not a party and not null.\n\nIt stays nullable because it is derived from a COALESCE over per-subject rows. A null here means the row carried neither a counterparty nor a receiver leg, which **no current writer produces** — treat one as a data-quality signal, not a rendering case.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "token_address": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "amount_raw",
                          "log_index",
                          "token_address"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Token transfers emitted by one transaction",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/validators": {
      "get": {
        "operationId": "getV2Validators",
        "parameters": [
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Beacon status filter. One of the consensus spec's `ValidatorStatus` values, in snake_case — an unrecognised value is a 400 naming the parameter rather than an empty page.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "pending_initialized",
                "pending_queued",
                "active_ongoing",
                "active_exiting",
                "active_slashed",
                "exited_unslashed",
                "exited_slashed",
                "withdrawal_possible",
                "withdrawal_done",
                null
              ],
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of `/v2/validators`.",
                        "properties": {
                          "activation_epoch": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "balance_gwei": {
                            "description": "**Gwei, the validator's ACTUAL balance at the last registry refresh** (`0055`). Moves every epoch, so read it against the registry's own cadence rather than as a live figure.\n\n**Null means NOT YET REFRESHED by a build that writes it — never a zero balance.** A genuinely emptied validator reports `0`, and the two must not be rendered the same way.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "cl_reward_gwei_7d": {
                            "description": "Gwei, STRING. Null when no validator_daily rows in window.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "complete_7d": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "coverage_7d": {
                            "description": "captured/expected epochs, worst day in the window. Below 1 means the SUMS above understate. Null = unknown (rows predating migration 0032).",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "effective_balance_gwei": {
                            "description": "**Gwei, the capped and hysteresis-smoothed value the protocol weights this validator by.** Moves only at epoch boundaries and in whole increments, so THIS is the right input for a group stake total — a sum of `balance_gwei` would drift with every reward payment.\n\nNull on the same terms as `balance_gwei`: unknown, not zero.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "effectiveness_7d": {
                            "description": "hits / epochs over the window. A RATE, so it survives a partially ingested day — unlike the SUMS below. Null when no rows in window.",
                            "format": "double",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "exec_reward_wei_7d": {
                            "description": "Wei, STRING.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "exit_epoch": {
                            "description": "Null while the validator is still active.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "is_house": {
                            "type": "boolean"
                          },
                          "proposals_7d": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "validator_index": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "withdrawal_address": {
                            "description": "Null when the withdrawal credential is BLS (0x00 prefix) rather than an execution address.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "is_house",
                          "status",
                          "validator_index"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Validators in index order, oldest first, optionally narrowed to one status",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/validators/entities": {
      "get": {
        "operationId": "getV2ValidatorsEntities",
        "parameters": [
          {
            "description": "`withdrawal` (default) or `graffiti`.",
            "in": "query",
            "name": "by",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "How many rows. 1..=1000, default 200. **There is no cursor** — a top-entities module is a leaderboard, so \"view more\" is a larger limit rather than a deeper page.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "`1d` (default) | `7d` | `30d` | `90d`.",
            "in": "query",
            "name": "window",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "**THE ROW SHAPE IS PUBLISHED THROUGH `EntityRow`, NOT INFERRED.**\n\nThe field stays `serde_json::Value` because the handler folds two different aggregates into one list and picks between them at runtime; `schemars(with)` is what makes the DOCUMENT say which two, without changing a single served byte. Left inferred, `data.items` published as `true` — \"anything\" — so every key on either row, including the two this envelope gained, was absent from the contract.",
                      "items": {
                        "anyOf": [
                          {
                            "description": "One withdrawal-address entity. **Asymmetric with `GraffitiRow` on purpose** — see each row type's doc.",
                            "properties": {
                              "attestation_pct": {
                                "description": "Over OBSERVED, per §12 decision 1. Null when observed is 0.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "attestations_included": {
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "avg_block_reward_wei": {
                                "description": "Signed string. Null when `blocks_for_avg` is 0. Blended: includes direct payments. Prefer `avg_tips_wei`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "avg_tips_wei": {
                                "description": "Signed integer string, wei: `tips_wei` divided by `blocks_with_exec_row`. Null when that count is 0. This is the per-block reward figure to headline.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "blocks_for_avg": {
                                "description": "The denominator of `avg_block_reward_wei`, served so it is never guessed. For this grouping it is `proposals`.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "blocks_with_exec_row": {
                                "description": "`avg_tips_wei`'s denominator: the window's blocks for this entity that have an indexed execution row. Not `proposals` — a proposed block whose exec row is not indexed must not lower the average.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "cl_reward_gwei": {
                                "description": "Signed string — CL rewards go negative under penalties.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "direct_payments_wei": {
                                "description": "Signed integer string, wei. Σ value moved to the entity's fee recipient by successful call-family traces inside the entity's OWN blocks in the window. It counts EVERY inbound transfer, ordinary deposits included, not only builder payments — an entity whose fee recipient is its own busy wallet books its own deposits here. Shown separately for that reason.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "epochs_assigned": {
                                "description": "Validator-epochs that should have attested (§2's overlap arithmetic).",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "epochs_observed": {
                                "description": "Validator-epochs we have a record for — `attestation_pct`'s denominator.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "exec_reward_wei": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "median_tips_wei": {
                                "description": "Per-block lower median (percentile_disc 0.5) of tips_wei over the same blocks; null when there are none.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "missed_blocks": {
                                "description": "Missed proposals by this entity's validators inside the window.\n\n**A MEASURED ZERO, never unknown**: `beacon.blocks` holds one row per slot including missed ones, so an entity absent from the miss aggregate missed nothing. Attributed misses only — a missed slot whose proposer the CL could not name has no validator and therefore no entity, and lives in `beacon.epoch_totals.blocks_missed_unattributable` instead.\n\nThe per-validator breakdown is `/v2/validators/missed`.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "proposals": {
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "proposed_in_range": {
                                "description": "`top_graffiti_share`'s denominator: NOT-missed blocks this entity's validators proposed in the window's SLOT range, blocks with no graffiti included. A MEASURED ZERO when the entity proposed nothing.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "share_by_count": {
                                "description": "Share of all validators that HAVE a withdrawal address. Sums to ≤ 1 across the full list because the grouping is a partition.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "share_by_stake": {
                                "description": "Share of `effective_balance_gwei` across the same population. **Labelled separately from `share_by_count` because they answer different questions** — a hundred small validators and one large one are the same count share and very different stake shares. Null until `0055`'s columns are populated.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "slashed": {
                                "description": "This entity's validators whose `status` is `active_slashed` or `exited_slashed`, matched EXACTLY — `exited_unslashed` is a voluntary exit and is not counted. The same predicate `/v2/beacon/stats` and `/v2/validators/slashed` identify one by.\n\nCounted over validators that have an `activation_epoch`, which every slashed validator has: a validator that never activated cannot be slashed. **Not windowed** — WHEN a slashing happened is not stored (see `/v2/validators/slashed`' `exit_epoch`), so this is a lifetime count sitting beside windowed columns, and it does not move with `window`.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "stake_gwei": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "tips_wei": {
                                "description": "Signed integer string, wei: Σ tips over the window's blocks with an indexed execution row; null when there are none.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "top_graffiti": {
                                "description": "The most common graffiti among the blocks this entity's validators proposed in the window, as the graffiti table's own `0x` hex key (decode and sanitise it the way the graffiti table is rendered). Blocks with no graffiti do not compete but count toward `top_graffiti_share`'s denominator. Null when the entity proposed no block carrying graffiti in the window. Ties: the smaller graffiti bytes.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "top_graffiti_blocks": {
                                "description": "Blocks carrying `top_graffiti`. Null with it.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "top_graffiti_share": {
                                "description": "Decimal string, 4 places: `top_graffiti_blocks` over `proposed_in_range` (the entity's proposed blocks in the window's slot range — the same population as the tips/direct-payments fields, which may differ at the day/epoch edge from `proposals`). Null with `top_graffiti`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "validators_total": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "withdrawal_address": {
                                "description": "The withdrawal address, `0x`-prefixed hex.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "blocks_with_exec_row",
                              "missed_blocks",
                              "proposed_in_range",
                              "slashed",
                              "validators_total",
                              "withdrawal_address"
                            ],
                            "type": "object"
                          },
                          {
                            "description": "One graffiti group. **PROPOSAL-LINKED COLUMNS ONLY** — the asymmetry with `WithdrawalEntityRow` is the point, not an oversight.",
                            "properties": {
                              "avg_block_reward_wei": {
                                "description": "Blended: includes direct payments. Prefer `avg_tips_wei`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "avg_tips_wei": {
                                "description": "Signed integer string, wei: `tips_wei` divided by `blocks_for_avg`, which on this row already IS blocks-with-an-exec-row. Null when that count is 0. This is the per-block reward figure to headline.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "blocks_for_avg": {
                                "description": "Blocks whose exec row IS indexed. **NOT `proposed`** — see the module's statement docs.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "direct_payments_wei": {
                                "description": "Signed integer string, wei. Σ value moved to the entity's fee recipient by successful call-family traces inside the entity's OWN blocks in the window. It counts EVERY inbound transfer, ordinary deposits included, not only builder payments — an entity whose fee recipient is its own busy wallet books its own deposits here. Shown separately for that reason.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "exec_reward_wei": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "graffiti": {
                                "description": "The RAW 32 bytes, `0x`-prefixed hex, 66 characters. Never decoded. **Null means `beacon.blocks.graffiti` was NULL** — not recorded — which is a different statement from the all-zero graffiti, itself an ordinary row.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "median_tips_wei": {
                                "description": "Per-block lower median (percentile_disc 0.5) of tips_wei over the same blocks; null when there are none.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "proposed": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "share_of_blocks": {
                                "description": "`proposed / blocks_in_window`.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "tips_wei": {
                                "description": "Signed integer string, wei. Σ `tips_wei` over the window's blocks that have an indexed execution row.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "top_withdrawal_address": {
                                "description": "The withdrawal address behind most of this graffiti's blocks in the window (`0x` hex; the registry's CURRENT withdrawal address of the proposer). Blocks whose proposer has no withdrawal address count toward the denominator only. Null when none. Ties: the smaller address bytes.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "top_withdrawal_blocks": {
                                "description": "Blocks whose proposer's withdrawal address is `top_withdrawal_address`. Null with it.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "top_withdrawal_share": {
                                "description": "Decimal string, 4 places: `top_withdrawal_blocks` over `proposed`. Null with `top_withdrawal_address`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "blocks_for_avg",
                              "proposed"
                            ],
                            "type": "object"
                          }
                        ],
                        "description": "The two shapes `data` carries, one per `by`. **Untagged**, because the discriminator is already on the envelope: `meta.by` says which grouping produced the list, and a second tag on every row would be a second place for the same fact to be wrong."
                      },
                      "type": "array"
                    },
                    "meta": {
                      "description": "The window and the denominators.",
                      "properties": {
                        "as_of_ts": {
                          "description": "Unix seconds at which the window CLOSES — the end of `epoch_to`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "backfill_frontier_epoch": {
                          "description": "How far the historical walk has got. Null = it has never run.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "blocks_in_window": {
                          "description": "`by=graffiti` only: proposed blocks in the window — `share_of_blocks`' denominator.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "by": {
                          "description": "`\"withdrawal\"` or `\"graffiti\"`.",
                          "type": "string"
                        },
                        "daily_rows_through": {
                          "description": "**THE DIVERGENCE DISCLOSURE.** `max(day)` in `beacon.validator_daily`.\n\nWhen this is **below `day_to`**, the per-entity aggregate covers fewer days than the window states — `ROLL_DAY_SQL` emits no `validator_daily` row for a day with no detail and no attributable blocks, so a total-ingestion-outage day rolls 270 `epoch_totals` rows and none here. The stat bar (which reads `epoch_totals`) still covers that day; the entity rows cannot. **A client comparing the two must read this field**, and `entity_days_missing` gives the gap as a number.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "day_from": {
                          "description": "The FIRST UTC day of the window: `day_to - (days - 1)`. Exact, because a UTC day is exactly 270 epochs.",
                          "type": "string"
                        },
                        "day_to": {
                          "description": "The LAST UTC day of the window, `YYYY-MM-DD` — the day containing `epoch_to`. **Every day range on every surface is derived from this**, so the envelope and the entity rows cannot describe different windows.",
                          "type": "string"
                        },
                        "distinct_graffiti": {
                          "description": "`by=graffiti` only. **Equal to `entities_total` by construction** — both are the aggregate's group count, and a graffiti group IS a distinct graffiti value (with the NULL-graffiti group counted as one). Served under both names because the FE asked for `distinct_graffiti` as the denominator's companion and removing a field is a wire change.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "entities_in_registry": {
                          "description": "`by=withdrawal` only: distinct withdrawal addresses in the WHOLE registry, active in the window or not. **Not the list's N** — that is `entities_total`. This is the denominator for \"X % of all validators belong to an entity that appears here\".",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "entities_total": {
                          "description": "**How many rows the FULL AGGREGATE has** — `count(*) OVER ()` from the aggregate itself, so it counts exactly the groups this list is a truncation of. This is the N in a showing-`limit`-of-N label.\n\n**ITS MEANING CHANGED (FE ledger).** It previously served, for `by=withdrawal`, the count of distinct withdrawal addresses in the whole registry — which overstated by every address with no activity in the window; and for `by=graffiti`, `count(DISTINCT graffiti)`, which EXCLUDES NULL while the aggregate emits the NULL-graffiti group as a row, undercounting by one. Neither ever corrupted a share denominator (those are separate fields and were always correct) — but the label was wrong. The registry-wide count is still available as `entities_in_registry`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "entity_days_missing": {
                          "description": "`day_to − daily_rows_through` in days, or null when the disclosure does not apply. **0 is the healthy case**; above 0 is the outage shape above.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "epoch_from": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epoch_to": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_captured": {
                          "description": "How many of those epochs `beacon.epoch_totals` reports as `captured`. **Below `epochs_expected` means the reward sums are partial** — and for a RANKING, a coverage fraction understates the problem: order can differ, not just magnitude.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_expected": {
                          "description": "`epoch_to - epoch_from + 1`. Equal to `window_epochs` except where the window would run below genesis.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "stake_gwei_total": {
                          "description": "`by=withdrawal` only: the denominator of `share_by_stake`.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "validators_with_entity": {
                          "description": "`by=withdrawal` only: validators WITH a withdrawal address — the denominator of `share_by_count`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "validators_without_entity": {
                          "description": "`by=withdrawal` only: BLS-credential validators, excluded from the rows and counted here so the missing share is visible.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "window": {
                          "description": "`\"1d\" | \"7d\" | \"30d\" | \"90d\"`. **`\"1d\"` is YESTERDAY** — the last complete UTC day — not a rolling 24 hours. `epoch_to` and `as_of_ts` say so exactly.",
                          "type": "string"
                        },
                        "window_epochs": {
                          "description": "`270 × days`, exact: a UTC day is 270 epochs on PulseChain.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "by",
                        "day_from",
                        "day_to",
                        "epoch_from",
                        "epoch_to",
                        "epochs_captured",
                        "epochs_expected",
                        "window",
                        "window_epochs"
                      ],
                      "type": "object"
                    },
                    "next_cursor": {
                      "description": "Always null — see the type's doc.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Validators grouped by withdrawal address, or blocks grouped by the graffiti they carried",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/validators/missed": {
      "get": {
        "operationId": "getV2ValidatorsMissed",
        "parameters": [
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=200. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "`1d` | `7d` | `30d` | `90d`, defaulting to `1d`.\n\n**THE ESTATE SPELLS THE DAY WINDOW `1d`, NOT `24h`** — this is `v2::beacon::Window`, the same closed set `/v2/validators/entities` and `/v2/beacon/stats` parse, so a client that has a window in hand can reuse it across the three. A second spelling for the same window on a sibling route would be a trap, so `24h` is a 400 here exactly as it is there.",
            "in": "query",
            "name": "window",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "**THE ROW SHAPE IS PUBLISHED THROUGH `MissedRow`, NOT INFERRED.** The field stays `serde_json::Value` because the handler serialises rows as it maps them; `schemars(with)` is what makes the DOCUMENT say what they are, without changing a single served byte. Left inferred, `data.items` publishes as `true` - \"anything\" - and every key on the row is absent from the contract. The same rule the entities envelope follows.",
                      "items": {
                        "description": "One row of `/v2/validators/missed`.",
                        "properties": {
                          "graffiti_reason": {
                            "anyOf": [
                              {
                                "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                "oneOf": [
                                  {
                                    "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                    "enum": [
                                      "missing"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                    "enum": [
                                      "malformed"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                    "enum": [
                                      "unlinked"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "is_house": {
                            "type": "boolean"
                          },
                          "last_graffiti": {
                            "description": "RAW 32 bytes, hex, from this validator's newest PRODUCED block — not its newest slot, which may be one of the misses this row counts.\n\nNull with a `graffiti_reason`, by the one rule every carrier shares (`graffiti_with_reason`). Null with NO reason means the validator has produced no block at all in the table.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "last_proposal": {
                            "description": "The newest PRODUCED block, or null when there is none.",
                            "properties": {
                              "slot": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "ts": {
                                "description": "Unix seconds.",
                                "format": "int64",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "slot",
                              "ts"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "missed_blocks": {
                            "description": "Missed proposals attributed to this validator inside the window.\n\nFrom `beacon.blocks WHERE missed AND proposer_index = v`.\n\nA missed slot whose proposer the CL could not attribute has `proposer_index` NULL (0013 dropped the NOT NULL for exactly this) and is in NOBODY's count here — `beacon.epoch_totals`' `blocks_missed_unattributable` is where those live, and 0054's backfill attribution moves them out of it over time. Summing this column over a page will therefore not reach `/v2/beacon/stats`' `missed_slots`.",
                            "format": "int64",
                            "type": "integer"
                          },
                          "validator_index": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "withdrawal_address": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "is_house",
                          "missed_blocks",
                          "validator_index"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "meta": {
                      "description": "The block every windowed envelope carries (§1).",
                      "properties": {
                        "as_of_ts": {
                          "description": "Unix seconds at which the window CLOSES — the end of `epoch_to`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "backfill_frontier_epoch": {
                          "description": "How far the historical walk has got. Null = it has never run.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "daily_rows_through": {
                          "description": "**THE DIVERGENCE DISCLOSURE.** `max(day)` in `beacon.validator_daily`.\n\nWhen this is **below `day_to`**, the per-entity aggregate covers fewer days than the window states — `ROLL_DAY_SQL` emits no `validator_daily` row for a day with no detail and no attributable blocks, so a total-ingestion-outage day rolls 270 `epoch_totals` rows and none here. The stat bar (which reads `epoch_totals`) still covers that day; the entity rows cannot. **A client comparing the two must read this field**, and `entity_days_missing` gives the gap as a number.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "day_from": {
                          "description": "The FIRST UTC day of the window: `day_to - (days - 1)`. Exact, because a UTC day is exactly 270 epochs.",
                          "type": "string"
                        },
                        "day_to": {
                          "description": "The LAST UTC day of the window, `YYYY-MM-DD` — the day containing `epoch_to`. **Every day range on every surface is derived from this**, so the envelope and the entity rows cannot describe different windows.",
                          "type": "string"
                        },
                        "entity_days_missing": {
                          "description": "`day_to − daily_rows_through` in days, or null when the disclosure does not apply. **0 is the healthy case**; above 0 is the outage shape above.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "epoch_from": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epoch_to": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_captured": {
                          "description": "How many of those epochs `beacon.epoch_totals` reports as `captured`. **Below `epochs_expected` means the reward sums are partial** — and for a RANKING, a coverage fraction understates the problem: order can differ, not just magnitude.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "epochs_expected": {
                          "description": "`epoch_to - epoch_from + 1`. Equal to `window_epochs` except where the window would run below genesis.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "window": {
                          "description": "`\"1d\" | \"7d\" | \"30d\" | \"90d\"`. **`\"1d\"` is YESTERDAY** — the last complete UTC day — not a rolling 24 hours. `epoch_to` and `as_of_ts` say so exactly.",
                          "type": "string"
                        },
                        "window_epochs": {
                          "description": "`270 × days`, exact: a UTC day is 270 epochs on PulseChain.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "day_from",
                        "day_to",
                        "epoch_from",
                        "epoch_to",
                        "epochs_captured",
                        "epochs_expected",
                        "window",
                        "window_epochs"
                      ],
                      "type": "object"
                    },
                    "next_cursor": {
                      "description": "`missed_blocks:validator_index:epoch_to`. **The window travels with the key**, so a walk that spans a day roll stays inside the window it started in rather than mixing two.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Validators ranked by the proposals they missed inside a 1d/7d/30d/90d window",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/validators/slashed": {
      "get": {
        "operationId": "getV2ValidatorsSlashed",
        "parameters": [
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=200. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One row of `/v2/validators/slashed`.",
                        "properties": {
                          "exit_epoch": {
                            "description": "**NOT THE SLASHING EPOCH — the exit epoch.**\n\n`beacon.validators` stores `activation_epoch` and `exit_epoch` and nothing else temporal, so WHEN a validator was slashed cannot be served from this estate at all. A slashed validator's exit is FORCED and follows its slashing, so this is the nearest stored fact and the one this route orders by — but it is an exit, it is later than the slashing by a variable amount, and it is null for a validator whose exit epoch the CL has not yet published.\n\nThe same proxy, named the same way, backs `/v2/beacon/stats`' `slashed_24h` under its `slashed_basis` field.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "graffiti_reason": {
                            "anyOf": [
                              {
                                "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                "oneOf": [
                                  {
                                    "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                    "enum": [
                                      "missing"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                    "enum": [
                                      "malformed"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                    "enum": [
                                      "unlinked"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "is_house": {
                            "type": "boolean"
                          },
                          "last_graffiti": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "last_proposal": {
                            "description": "The `{slot, ts}` pair both routes carry.",
                            "properties": {
                              "slot": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "ts": {
                                "description": "Unix seconds.",
                                "format": "int64",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "slot",
                              "ts"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "status": {
                            "description": "The lighthouse status string as stored — `active_slashed` or `exited_slashed`. **This is how a slashing is identified**: slashed = `status` is `active_slashed` or `exited_slashed`, matched EXACTLY. There is no slashed flag and no slashed epoch in the schema.\n\n`exited_unslashed` is a VOLUNTARY exit and is NOT slashed — the two validators this route named before OPS-99 carried that status, and a substring match on `slashed` is what listed them.",
                            "type": "string"
                          },
                          "validator_index": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "withdrawal_address": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "is_house",
                          "status",
                          "validator_index"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Validators that have been slashed",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/validators/{idx}": {
      "get": {
        "operationId": "getV2ValidatorsByIdx",
        "parameters": [
          {
            "in": "path",
            "name": "idx",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "How many DAYS of reward history, not rows. 1..=400. Default 90.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "`/v2/validators/{idx}`.",
                      "properties": {
                        "activation_epoch": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "balance_gwei": {
                          "description": "**Gwei, the validator's ACTUAL balance at the last registry refresh** (`0055`). Moves every epoch, so read it against the registry's own cadence rather than as a live figure.\n\n**Null means NOT YET REFRESHED by a build that writes it — never a zero balance.** A genuinely emptied validator reports `0`, and the two must not be rendered the same way.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "daily": {
                          "description": "Newest first. Always an array, empty rather than null.",
                          "items": {
                            "description": "One day of a validator's history.",
                            "properties": {
                              "attestations_hit": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "cl_reward_gwei": {
                                "description": "Gwei, STRING.",
                                "type": "string"
                              },
                              "complete": {
                                "description": "The flag to branch on. Null = unknown; false = `cl_reward_gwei` is a PARTIAL sum and must not be charted as earnings.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "coverage": {
                                "description": "captured/expected. Null when unknown.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "day": {
                                "description": "ISO date.",
                                "type": "string"
                              },
                              "effectiveness": {
                                "description": "Null when `epochs` is 0 — not 0.0, which would read as total failure.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "epochs": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "epochs_captured": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "epochs_expected": {
                                "description": "Epochs the day contains. 0 means the row predates 0032 and coverage is unknown.",
                                "format": "int32",
                                "type": "integer"
                              },
                              "exec_reward_wei": {
                                "description": "Wei, STRING.",
                                "type": "string"
                              },
                              "proposals": {
                                "format": "int32",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "attestations_hit",
                              "cl_reward_gwei",
                              "day",
                              "epochs",
                              "epochs_captured",
                              "epochs_expected",
                              "exec_reward_wei",
                              "proposals"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "effective_balance_gwei": {
                          "description": "**Gwei, the capped and hysteresis-smoothed value the protocol weights this validator by.** Moves only at epoch boundaries and in whole increments, so THIS is the right input for a group stake total — a sum of `balance_gwei` would drift with every reward payment.\n\nNull on the same terms as `balance_gwei`: unknown, not zero.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "exit_epoch": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "is_house": {
                          "type": "boolean"
                        },
                        "pubkey": {
                          "type": "string"
                        },
                        "recent_proposals": {
                          "description": "Newest first, capped at 20.",
                          "items": {
                            "description": "One recent block proposal.",
                            "properties": {
                              "direct_payments_wei": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "exec_block_number": {
                                "description": "Null for a missed slot — there is no execution block.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "graffiti": {
                                "description": "Proposer graffiti, raw hex, lowercase, exactly 66 characters when present (SSZ `Bytes32`).\n\n**THIS is where the missed-slot state is reachable.** §68.8 #36: the block-keyed carrier `/v2/blocks/{num}/rewards` joins on `exec_block_number`, and a missed slot has none, so it can only ever answer `missed: false` or `missed: null`. This route reads `beacon.blocks` directly — one row per SLOT, missed ones included — so all four states occur here and `missed` is the discriminator:\n\n`missed: true` with `graffiti: null` — the slot produced no block, so there was no proposer to set anything. `missed: false` with `graffiti: \"0x0000…\"` — a block exists and its graffiti is 32 zero bytes. A VALUE, not an absence, and NOT decidable as \"the proposer set nothing\": deliberate zeros are byte-identical to none. `missed: false` with `graffiti: \"0x…\"` — a block exists and those are the bytes. `graffiti: null` with `missed: false` — the fifth state: the stored value is absent or not 32 bytes. §3o.7 measured zero such rows.\n\nNOT decoded server-side. **Attacker-controlled input** — any proposer may put arbitrary bytes here, so escape before rendering and never interpolate into markup.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "graffiti_reason": {
                                "anyOf": [
                                  {
                                    "description": "Why `graffiti` is null.\n\nNull itself when `graffiti` is PRESENT, and on a **missed** slot — there the `missed` field beside it already accounts for the absence, so a reason would be noise. Every other null carries one, including `unlinked` for a block with no beacon row at all.",
                                    "oneOf": [
                                      {
                                        "description": "The block exists and no graffiti was stored for it: the body fetch that would have carried it returned nothing. Ingest gap, not chain state — the graffiti this slot had is unknown, not absent.",
                                        "enum": [
                                          "missing"
                                        ],
                                        "type": "string"
                                      },
                                      {
                                        "description": "A value is stored and it is not 32 bytes, so it cannot be served without breaking the published 66-character shape. A ps-core ingest bug; §3o.7 measured zero of these.",
                                        "enum": [
                                          "malformed"
                                        ],
                                        "type": "string"
                                      },
                                      {
                                        "description": "**NO BEACON ROW FOR THIS BLOCK AT ALL**, so there is no proposer to ask about and no graffiti to have.\n\nAdded for the BLOCK surfaces, where it is the ordinary case rather than an edge: `beacon.blocks` starts at the CL slot walker's floor, so every pre-beacon-frontier execution block is here, as is any block the walker has not reached. Before this variant those blocks served `graffiti: null, graffiti_reason: null` — indistinguishable from a slot the walker HAS reached and found nothing for, which is a different fact.\n\n**It is unreachable on the slot surfaces.** `/v2/slots` and `/v2/validators/{idx}` pass `Some(missed)` from a `beacon.blocks` row they already hold, so `missed` is never `None` there; only a caller starting from `core.chain_blocks` can produce it.",
                                        "enum": [
                                          "unlinked"
                                        ],
                                        "type": "string"
                                      }
                                    ]
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Why `graffiti` is null, when the null is not already explained by `missed` — see `GraffitiReason`."
                              },
                              "missed": {
                                "type": "boolean"
                              },
                              "slot": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "tips_wei": {
                                "description": "Wei, STRING. Null when the exec block is not indexed (missed, or above the indexed frontier).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "missed",
                              "slot"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "status": {
                          "type": "string"
                        },
                        "validator_index": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "withdrawal_address": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "daily",
                        "is_house",
                        "pubkey",
                        "recent_proposals",
                        "status",
                        "validator_index"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One validator: its status, balance and activation window",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/wallets/{addr}/bridge": {
      "get": {
        "operationId": "getV2WalletsByAddrBridge",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Restrict to one bridge contract, 0x address.",
            "in": "query",
            "name": "bridge",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Restrict to inbound or outbound flows.",
            "in": "query",
            "name": "direction",
            "required": false,
            "schema": {
              "enum": [
                "in",
                "out",
                null
              ],
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One bridge flow. The two amounts are NOT interchangeable and the field names are the only thing saying so: `amount_raw` is the on-chain transfer on THIS chain and is the trustworthy figure; `src_amount_raw` is the source-chain amount lifted out of the calldata envelope — a different asset, at different decimals, display-only.",
                        "properties": {
                          "amount_raw": {
                            "description": "u256-scale on THIS chain, therefore a STRING. The trustworthy amount.",
                            "type": "string"
                          },
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "bridge_address": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "bridge_name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "bridge_slug": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "direction": {
                            "description": "`in` or `out` as the producer recorded it. Left a plain string rather than the `Direction` enum on purpose: this value comes from a table, not from a bool, so a closed set here would turn an unexpected producer value into a schema lie instead of visible data.",
                            "type": "string"
                          },
                          "display": {
                            "description": "**THE CURATED OVERRIDE** for the bridged token, or null when there is none. Beside the raw symbol, never merged into it; one map lookup.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "flow_kind": {
                            "type": "string"
                          },
                          "is_swap": {
                            "type": "boolean"
                          },
                          "message_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "src_amount_raw": {
                            "description": "SOURCE-chain denominated and u256-scale, therefore a STRING. Do not scale it by `token_decimals`; that is this chain's token.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "src_chain_id": {
                            "description": "Envelope enrichment. NULL when the calldata was unrecognised — never guessed.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "token": {
                            "description": "The zero address is the native-PLS sentinel (0015), not a missing token. Null only when the row records no token at all.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "token_decimals": {
                            "description": "NULL until metadata resolves (Data §2.1).",
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "token_symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ts": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "tx_hash": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "amount_raw",
                          "block_number",
                          "direction",
                          "flow_kind",
                          "is_swap",
                          "ts",
                          "tx_hash"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Bridge transfers made by one wallet",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/wallets/{addr}/holdings": {
      "get": {
        "operationId": "getV2WalletsByAddrHoldings",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "1..=500. Default 200. The ceiling is [`VALUATION_ITEM_CAP`], which is what bounds `load_marks` — one index descent per distinct token.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The Holdings tab's body.",
                      "properties": {
                        "as_of_block": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "as_of_ts": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "price_rule": {
                          "description": "The dials this page's prices were computed under — the same type `/positions` publishes, so the two pages state one rule.",
                          "properties": {
                            "depth_floor_usd": {
                              "description": "The oracle's `candidate_min_depth_usd` dial, read per request.",
                              "format": "double",
                              "type": "number"
                            },
                            "rule": {
                              "description": "`marks` — the valuation rule named in Justin's §3.0 ruling (`marks.rs`; the ruling calls it \"the /pnl rule\" after the route that first carried it, removed by OPS-107).",
                              "type": "string"
                            },
                            "staleness_secs": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "twap_window_secs": {
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "depth_floor_usd",
                            "rule",
                            "staleness_secs",
                            "twap_window_secs"
                          ],
                          "type": "object"
                        },
                        "priced_rows": {
                          "description": "Rows the wallet holds (up to the cap) that carry a price — the count `total_usd` is a sum over. Like it, independent of `limit`.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "rows": {
                          "items": {
                            "description": "One row of the Holdings tab.",
                            "properties": {
                              "amount": {
                                "description": "The decimal amount, or null when decimals are unknown. Null is not 0: an unresolved token's balance is a number whose SCALE nobody knows.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "amount_raw": {
                                "description": "Raw units, STRING — u256 does not fit a JSON number.",
                                "type": "string"
                              },
                              "decimals": {
                                "description": "Null unless `metadata_status = 'resolved'` — the estate reads decimals only from a resolved row (`0004`'s `resolved_has_decimals` comment).",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "display": {
                                "description": "The curated override, served BESIDE the raw identity as `items` does.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "is_native": {
                                "description": "True for the 20-zero-byte sentinel — native PLS, which is a ROW here and not a separate field (`0015` §3 seeds it as PLS / 18 / resolved).",
                                "type": "boolean"
                              },
                              "is_t1_stable": {
                                "description": "The token is a `t1_stable` pricing anchor, so its mark is $1 by definition (Data §4.6). **A FLAG, NOT A STATUS**: its `mark_status` is `ok`, because that is what the valuation returns for it, and folding \"why\" into \"whether\" would make the status set unclosed.",
                                "type": "boolean"
                              },
                              "mark_status": {
                                "description": "`ok | stale | shallow | unpriced`, the closed set `marks.rs` defines and `/holdings` already serves. A consumer MUST branch on it: `price_usd: null` alone does not say whether the price is missing, old or untrusted.",
                                "oneOf": [
                                  {
                                    "enum": [
                                      "ok"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Newest tick older than the staleness ceiling.",
                                    "enum": [
                                      "stale"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Liquidity below the candidate depth floor.",
                                    "enum": [
                                      "shallow"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "No tick history at all.",
                                    "enum": [
                                      "unpriced"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "price_usd": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "symbol": {
                                "description": "Registry symbol; null when the token is unresolved. A truncated address is the house fallback and a symbol is never invented.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_address": {
                                "type": "string"
                              },
                              "value_usd": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "amount_raw",
                              "is_native",
                              "is_t1_stable",
                              "mark_status",
                              "token_address"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "rows_omitted": {
                          "description": "Non-zero balances NOT in `rows`: `total − returned`. Non-zero either because the caller's `limit` cut them or because the wallet holds more than [`VALUATION_ITEM_CAP`] tokens.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "total_usd": {
                          "description": "**Σ `value_usd` OVER THE WALLET'S PRICED ROWS, UP TO [`VALUATION_ITEM_CAP`] — NOT over this page.** Unpriced rows contribute nothing and are counted separately rather than folded in as zero.\n\nIt does NOT vary with `limit`: `limit` chooses how many rows are SERVED, and this describes what the wallet holds. A page total under a wallet-total name is what audit §130 MED 1 found, and the FE's Current Holdings cell adds this figure to `v3_total_usd`.\n\nThe one bound that does apply is the fetch: a wallet holding more than [`VALUATION_ITEM_CAP`] tokens has a tail this sum never saw, and `rows_omitted` is how big that tail is.",
                          "type": "string"
                        },
                        "unpriced_rows": {
                          "description": "The rest of the fetched set: held, but with no usable mark or no scale.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "wallet": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "price_rule",
                        "priced_rows",
                        "rows",
                        "rows_omitted",
                        "total_usd",
                        "unpriced_rows",
                        "wallet"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Every token one wallet holds, with its current value",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/networth": {
      "get": {
        "operationId": "getV2WalletsByAddrNetworth",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "Net worth as last computed by the batch job. All three data fields are null together when no snapshot exists — the KEY SET IS THE SAME on both branches, which is already true of the handler and is now asserted by the schema rather than being a coincidence.",
                      "properties": {
                        "computed_block": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "networth_usd": {
                          "description": "f64 by the money-precision decision. Null when never computed — NOT zero, which would claim an empty wallet.",
                          "format": "double",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "updated_at": {
                          "description": "Unix seconds.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "wallet": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "wallet"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One wallet's current net worth",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/networth/history": {
      "get": {
        "operationId": "getV2WalletsByAddrNetworthHistory",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Human-facing alternative to `cursor`: points strictly before this unix SECOND. Ignored when `cursor` is present.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`. Carries epoch MICROseconds, because `ts` is a full-precision TIMESTAMPTZ and a whole-second cursor can skip or repeat same-second rows at a boundary.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=5000. Default 500.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One point on the net-worth curve.",
                        "properties": {
                          "computed_block": {
                            "description": "Block this point was computed at, so the chart is self-describing and a consumer needs no second per-wallet call to /networth just to learn it (~20 requests off a cold dashboard load).\n\nNULL for points written before migration 0034 — genuinely unknown, since networth_history stored only a timestamp and mapping one back to a block would be a guess dressed as data. Also NULL on every point until the ps-batch binary carrying the writer change is deployed. **Treat NULL as unknown, never as zero or as head.**",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "networth_usd": {
                            "format": "double",
                            "type": "number"
                          },
                          "ts": {
                            "description": "Unix seconds. The cursor uses MICROseconds internally; this is the human-scale value and is not cursor material.",
                            "format": "int64",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "networth_usd",
                          "ts"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One wallet's net worth over time",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/networth/replay": {
      "get": {
        "operationId": "getV2WalletsByAddrNetworthReplay",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "`24h` | `7d` | `30d`. **Absent or empty → `24h`** (the default). Any other value is a 400 (`bad_param`) rather than a silently different window.",
            "in": "query",
            "name": "window",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "as_of_block": {
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "as_of_ts": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "buckets": {
                          "items": {
                            "properties": {
                              "gaps": {
                                "description": "Drawn series — tokens, the native line and the position legs — holding a quantity in this bucket whose price was NOT a close of their own: carried forward from an earlier bucket, back-filled from the window's first close, or absent.\n\n**A BUCKET WITH `gaps > 0` STILL CARRIES A REAL `value_usd`, AND MUST NOT BE DRAWN AS A BREAK.** This counts how much of the bucket's price was inferred rather than observed — it is a confidence signal, not a hole. Rendering a gap as a discontinuity reintroduces exactly the dip this route was changed to remove: before Justin's ruling of 2026-09-03 a bucket without a close contributed nothing, so the line fell by that token's whole value and read as a sale (WPLS measured 179/180 closes in OPS-77, so nearly every chart dipped at least once).\n\n`absent` is the rare arm and it is NOT the leading-bucket case: leading buckets are back-filled from the first close, so a DRAWN TOKEN has a price in every bucket and its gaps are always carried ones. A price is absent only for the native line when there is no WPLS series at all, in which case native contributes nothing and every bucket it holds PLS in is a gap.\n\nPer-token, `tokens[].price_coverage` reports the same thing as a ratio, and stays the RAW closes-over-buckets figure.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "priced_tokens": {
                                "description": "**SERIES** that CONTRIBUTED A VALUE to this bucket, whether from a close of their own or a carried one.\n\n**\"SERIES\" MEANS TOKENS, THE NATIVE LINE *AND* THE POSITION LEGS**, and a leg is not always one series: a V3 position contributes TWO — one per pool token — because its value is the two sides summed. So this counter is not a count of holdings, and `positions_included.len()` is not the number it adds.\n\n**This is not the complement of `gaps`.** Since a bucket without its own close is priced from the last one published, a series can be counted here AND in `gaps` for the same bucket: it contributed, and the price it contributed at was carried.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "ts": {
                                "description": "The bucket's START, unix seconds, aligned to `resolution_secs`.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "value_usd": {
                                "description": "Total USD across the DRAWN tokens plus native. **Never null.**",
                                "type": "string"
                              }
                            },
                            "required": [
                              "gaps",
                              "priced_tokens",
                              "ts",
                              "value_usd"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "budget_ms": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "complete": {
                          "description": "Every top-N token drawn or listed unpriced (none dropped for time) AND native complete-or-skipped-for-code AND the budget kept.\n\n**WHEN `reason_code` IS `setup_timeout`, `is_contract` AND `price_rule` ARE DEFAULTS, NOT READINGS.** That arm is returned before either is read: `is_contract` is `false` because nothing probed `core.deployed_contracts`, and `price_rule.depth_floor_usd` is the compiled-in fallback because `meta.config` was never queried. This flag alone does not say so — its own sentence above is about tokens, native and the budget — so it is said here, and on `reason_code`.",
                          "type": "boolean"
                        },
                        "is_contract": {
                          "type": "boolean"
                        },
                        "native": {
                          "properties": {
                            "complete": {
                              "type": "boolean"
                            },
                            "reason": {
                              "anyOf": [
                                {
                                  "description": "**WHY THE NATIVE LEG IS INCOMPLETE — AN ENUM, SO THE COMPILER OWNS THE SET.**\n\nThis was a `String` drawn from a `NATIVE_REASONS` const, policed by a census that scanned the source for assignments. Audit §132.8 proved that census hollow twice over: it skipped the contract arm entirely (its `find` landed on `skipped_reason`) and it accepted any constant merely NAMED `NATIVE_*`, so a new `NATIVE_GAVE_UP = \"gave_up\"` passed. A census that resolves literals is still a census; a type is not.\n\nThe wire is unchanged: `rename_all = \"snake_case\"` serialises the one variant as `\"timed_out\"`, exactly as the string did, and `JsonSchema` now publishes the enumeration into `docs/openapi.json` instead of the doc-comment merely claiming it.",
                                  "oneOf": [
                                    {
                                      "description": "One native source exceeded the statement ceiling. Two of three sources is a line wrong by the third, so the leg is dropped whole.",
                                      "enum": [
                                        "timed_out"
                                      ],
                                      "type": "string"
                                    }
                                  ]
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Why the native leg is incomplete, or null when it is not. The variants of [`NativeReason`] are the whole set — a closed one, owned by the type rather than by a comment."
                            },
                            "rows_scanned": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "skipped_reason": {
                              "description": "`contract` when the address has code. Null otherwise.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "source": {
                              "description": "`native_deltas` (exact, inside the sliding window) or `address_tables` (the three aggregated sources), or null when there is no native line.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "complete",
                            "rows_scanned"
                          ],
                          "type": "object"
                        },
                        "omitted_now_usd": {
                          "type": "string"
                        },
                        "positions_included": {
                          "description": "The position legs ON the line. Their value is inside every `buckets[].value_usd`, and they count in `priced_tokens`/`gaps` exactly as token legs do — \"series\" there means tokens AND position legs, and a V3 leg is two of them.\n\n**EVERY LEG HERE HELD ONE CONSTANT QUANTITY ACROSS THE WHOLE WINDOW** (the pHEX accrual excepted, which is a known function of the day rather than a movement). A position whose quantity moved is in `positions_omitted` with `changed_in_window`: this route values positions, it does not replay their journals.",
                          "items": {
                            "description": "One position drawn on the line.",
                            "properties": {
                              "accrual": {
                                "description": "pHEX only. `capped` fires when BOTH of these hold, and `included` otherwise:\n\n1. the stake CAN accrue — `shares > 0`, `staked_days > 0` and `locked_day >= 0`, the sweeper's own three guards; and 2. the recorded daily history begins strictly AFTER the stake's own `locked_day` (or there is no recorded day at all), so the days between the two are missing from the prefix sum and the accrual in `now_value_usd` is a FLOOR rather than the whole of it (R3).\n\n**A STAKE THAT CANNOT ACCRUE IS `included`, NOT `capped`** — zero shares, a zero-day term or a negative `locked_day` make the accrual exactly zero by the sweeper's own guards, and no amount of extra history would change it. Labelling that `capped` claimed the estate was short of a number it was not short of (audit §133 LOW 5).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "id": {
                                "description": "`token_id` for v3, `stake_id` for phex, `farm_address:pid` for a farm.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "`v3` | `phex` | `farm`.",
                                "type": "string"
                              },
                              "now_value_usd": {
                                "description": "The leg's value NOW — the figure the cap ranked it by. For v3 it is the refresher's stored amounts at the live marks, the same number `/v2/wallets/{addr}/positions/items` serves; for phex it is `(principal + accrued) / 1e8` at the live mark; for a farm it is the staked quantity at the newest LP NAV.",
                                "type": "string"
                              },
                              "pool_or_token": {
                                "description": "The pool (v3, farm) or token (phex) this leg is denominated in.",
                                "type": "string"
                              },
                              "price_coverage": {
                                "description": "As `tokens[].price_coverage`: the RAW closes-over-buckets ratio of the series backing this leg, unaffected by the carry.\n\n**A V3 LEG IS BACKED BY TWO SERIES AND THIS IS THEIR CONJUNCTION** — a bucket counts as observed only when BOTH pool tokens published a close, because the position's amounts at that bucket are a function of the pair. A farm's NAV series counts a bucket as observed when the row backing it is a DIFFERENT row from the previous bucket's; the repeat is a carry, exactly as a missing OHLC close is.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "now_value_usd",
                              "pool_or_token",
                              "price_coverage"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "positions_omitted": {
                          "description": "The positions the line does NOT cover, each with the reason and its current value, so the size of the omission is visible.\n\nA `cap` or `changed_in_window` omission does NOT make the response incomplete — both are rules, not failures, and the omission is published with the value it is worth. `time_budget` does, through the top-level `reason_code`; `timed_out` confines itself to the one position.",
                          "items": {
                            "description": "One position NOT drawn, and why.",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string"
                              },
                              "now_value_usd": {
                                "type": "string"
                              },
                              "reason": {
                                "description": "**WHY A POSITION IS NOT ON THE LINE — an enum, so the compiler owns the set** and `JsonSchema` publishes it (pin 3 R6).",
                                "oneOf": [
                                  {
                                    "description": "The position's QUANTITY moved inside the window, so there is no single constant to value across it. The replay does not walk position journals; it asserts a constant quantity and refuses the position when that is false, rather than drawing a line it cannot support.",
                                    "enum": [
                                      "changed_in_window"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A token this position is denominated in has no OHLC series at the window's resolution, so no bucket could be priced. Never drawn flat.",
                                    "enum": [
                                      "unpriced"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Outside the top [`POSITION_CAP`] by current value. Named with its value, so the reader can see the size of what the line omits.\n\n**TIES ARE BROKEN BY `kind` THEN `id`**, so which leg survives a cap that falls between two equal values is a function of the positions themselves and not of the order a statement returned rows in. Without it, two calls could name different legs.",
                                    "enum": [
                                      "cap"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "A statement for this position hit the per-statement ceiling. The position is omitted whole; the rest of the response stands.",
                                    "enum": [
                                      "timed_out"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "The request budget ran out before this position was reached.",
                                    "enum": [
                                      "time_budget"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "now_value_usd",
                              "reason"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "positions_omitted_now_usd": {
                          "description": "Σ `now_value_usd` over `positions_omitted`.",
                          "type": "string"
                        },
                        "price_rule": {
                          "description": "The valuation rule, reused from the sibling routes so one reader sees one rule.",
                          "properties": {
                            "depth_floor_usd": {
                              "description": "The oracle's `candidate_min_depth_usd` dial, read per request.",
                              "format": "double",
                              "type": "number"
                            },
                            "rule": {
                              "description": "`marks` — the valuation rule named in Justin's §3.0 ruling (`marks.rs`; the ruling calls it \"the /pnl rule\" after the route that first carried it, removed by OPS-107).",
                              "type": "string"
                            },
                            "staleness_secs": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "twap_window_secs": {
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "depth_floor_usd",
                            "rule",
                            "staleness_secs",
                            "twap_window_secs"
                          ],
                          "type": "object"
                        },
                        "reason": {
                          "description": "**HUMAN PROSE.** Null when `complete`. Branch on `reason_code`, not on this — the wording is free to improve.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "reason_code": {
                          "anyOf": [
                            {
                              "description": "**WHY A REPLAY IS INCOMPLETE — AN ENUM, FOR THE REASON `NativeReason` IS.**\n\nThese were four `&str` consts and a test that built a list of THREE and asserted its own length, so deleting `setup_timeout` from the doc and the openapi together left the suite green while the handler still emitted it (audit §132.8 LOW 3). The set is the type's now; `JsonSchema` publishes it, and `ALL` is exhaustive, so a new variant cannot be added without every census here seeing it.\n\nThe wire words are unchanged.",
                              "oneOf": [
                                {
                                  "description": "A held token was not replayed inside the request budget — its walk timed out, or it was never reached. The tokens are named in `tokens_omitted`.",
                                  "enum": [
                                    "time_budget"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The native leg could not be drawn whole; see `native.reason`.",
                                  "enum": [
                                    "native_incomplete"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The request budget ran out.",
                                  "enum": [
                                    "budget_exhausted"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "A statement in the SETUP phase — boundaries, contract, balances, the depth dial or the marks — hit the per-statement ceiling, so nothing was replayed. Distinct from `time_budget`, which is about held TOKENS not being reached: this says the database was slow, not that the wallet was large.\n\n**On this arm `is_contract` and `price_rule` are DEFAULTS, not readings** — see `complete`.",
                                  "enum": [
                                    "setup_timeout"
                                  ],
                                  "type": "string"
                                }
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "**THE MACHINE LITERAL for `reason`**, null when complete. The variants of [`ReasonCode`] are the whole set, and each carries its own description into the document — the enumeration is NOT restated here, because a hand-kept copy beside the type is precisely what drifted: `setup_timeout` could be deleted from this list and the openapi together while the handler still emitted it (audit §132.8 LOW 3).\n\nAdded because neither `reason` carried a description or an enumeration into `docs/openapi.json`, so a client had no stable thing to branch on (audit §131 MED 4). The prose stays exactly as it was.\n\n**`setup_timeout` MAKES `is_contract` AND `price_rule` DEFAULTS, NOT READINGS.** Nothing was read on that arm, so `is_contract` is `false` because it was never probed and `price_rule` carries the compiled-in depth floor because `meta.config` was never queried. Neither is a statement about the address."
                        },
                        "resolution_secs": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "time_ms": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "tokens": {
                          "items": {
                            "properties": {
                              "now_value_usd": {
                                "type": "string"
                              },
                              "price_coverage": {
                                "description": "`buckets_with_close / buckets`, as a string. 1.000000 is a complete series; anything less is visible rather than inferred from the chart.",
                                "type": "string"
                              },
                              "rows_scanned": {
                                "description": "Aggregate rows returned by this token's walk — at most one per bucket.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_address": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "now_value_usd",
                              "price_coverage",
                              "rows_scanned",
                              "token_address"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "tokens_omitted": {
                          "items": {
                            "properties": {
                              "now_value_usd": {
                                "type": "string"
                              },
                              "reason": {
                                "description": "`top_n` — outside the top [`TOP_N`] by current value. `timed_out` — its walk exceeded [`STATEMENT_TIMEOUT_MS`]. `time_budget` — the request's budget ran out before it was reached.",
                                "type": "string"
                              },
                              "symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_address": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "now_value_usd",
                              "reason",
                              "token_address"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "unpriced_now_usd": {
                          "type": "string"
                        },
                        "unpriced_tokens": {
                          "items": {
                            "properties": {
                              "now_value_usd": {
                                "type": "string"
                              },
                              "reason": {
                                "description": "`no_ohlc_series` — held, priced NOW, but with no closed OHLC bucket at this resolution anywhere in the window. Drawing it flat at its current mark would claim its price never moved.",
                                "type": "string"
                              },
                              "symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_address": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "now_value_usd",
                              "reason",
                              "token_address"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "wallet": {
                          "type": "string"
                        },
                        "window": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "buckets",
                        "budget_ms",
                        "complete",
                        "is_contract",
                        "native",
                        "omitted_now_usd",
                        "positions_included",
                        "positions_omitted",
                        "positions_omitted_now_usd",
                        "price_rule",
                        "resolution_secs",
                        "time_ms",
                        "tokens",
                        "tokens_omitted",
                        "unpriced_now_usd",
                        "unpriced_tokens",
                        "wallet",
                        "window"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One wallet's net worth recomputed across a window, for charting",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/positions": {
      "get": {
        "operationId": "getV2WalletsByAddrPositions",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "`GET /v2/wallets/{addr}/positions` — what a wallet holds, by leg.",
                      "properties": {
                        "legs": {
                          "items": {
                            "description": "One leg of a wallet's position composition.\n\n§4r's shape, with one deliberate narrowing (decision B2, cycle-026): the legs carry COUNTS, not USD. The two missing networth terms — `farm` and `v3` — are gated by B3 behind readiness bars §4r sets out and neither is met: the farm reconciler's convergence is unproven and the V3 refresher's coverage clock has only just started. Pricing three legs here and omitting two would hand a client five rows of which three carry money and two do not, which is the shape §4r spends a paragraph rejecting. Counting all five invents nothing and answers the question the surface exists for — the reproduction wallet reads `networth_usd = $0.44` and this says, on the wire, that it also holds fifteen V3 positions nobody has priced.",
                            "properties": {
                              "as_of_block": {
                                "description": "The **OLDEST** block at which any row COUNTED IN THIS LEG for this wallet was written.\n\n> # ⚠ BREAKING SEMANTIC CHANGE, 2026-08-29 > > **This was `max(...)` and is now `min(...)`.** The field name, type > and nullability are unchanged, so a client reading it will not fail — > it will quietly read a different, older number. That is the most > dangerous kind of change and it is called out here rather than > discovered. > > **Why.** For a COUNT, the newest contributing block is defensible. > For a VALUE it is not: it asserts a freshness the leg as a whole does > not have. A leg holding one token refreshed at head and forty > refreshed a week ago is a week old, and `max()` would have reported > head. This is the same conservative choice `0051` made deliberately > for `analytics.v3_pool_depth.as_of_block` — *\"the OLDEST input, not > the newest and not the head\"* — applied to a surface that now carries > money.\n\n**Null means different things per leg, and for `v3` it does NOT mean \"no rows\".** The block comes from the rows that carry one:\n\n* `spot`, `phex`, `ptgc`, `farm` — null when the leg counts no rows for this wallet. * `v3` — null when the refresher has not yet reached ANY of this wallet's positions. `positions: 15, as_of_block: null` is an ordinary reading today, not a contradiction: the block is taken over `ui.v3_position_liquidity`, and an owner row with no liquidity row has never been read from chain. Compare it with `refreshed` in `detail`, which is the count of positions that DO have a block behind them.\n\n**Per leg, never per response** (§4r): the legs have genuinely different freshness, and one response-level block would be a claim about the freshest leg applied to the stalest.\n\n**It is a LOWER BOUND on freshness, not a consumer cursor.** For an `observed` leg it is the last block at which this wallet's rows CHANGED — a wallet that has not traded for a month reports a month-old block while being perfectly current. Do not read it as head-lag; read it with `source`. For `reconciled` and `refreshed` legs it is where the rotation last reached these rows, which is the freshness statement that matters.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "detail": {
                                "additionalProperties": {
                                  "format": "int64",
                                  "type": "integer"
                                },
                                "description": "Counts for this leg. Keys differ per leg, which is why this is a map rather than five optional fields.",
                                "type": "object"
                              },
                              "leg": {
                                "description": "`spot` | `phex` | `ptgc` | `farm` | `v3`.",
                                "type": "string"
                              },
                              "source": {
                                "description": "How the underlying rows are maintained. §4r: a value whose provenance differs must say so on the wire rather than be averaged into a total that implies one provenance.\n\n* `observed` — maintained event-exactly by a live consumer. * `reconciled` — an accumulator corrected against chain on a rotation, accurate to within one rotation period plus the reconciler's residual. * `refreshed` — read from chain by a rotating refresher, accurate as of `as_of_block`, which may be up to one coverage period behind head.",
                                "type": "string"
                              },
                              "value": {
                                "description": "**What this leg is worth, or null if this build does not value it.**\n\n`null` means \"not valued by this deployment\" — check `legs_valued` on the response, which names the set. It does NOT mean the leg is worth nothing; a leg that IS valued and found nothing priceable says so inside `LegValue` with `value_usd: null` and a reason breakdown.",
                                "properties": {
                                  "complete": {
                                    "description": "True iff every item in this leg was priced. **False means `value_usd` is a partial sum**, and the counts below say by how much it is partial.",
                                    "type": "boolean"
                                  },
                                  "priced_items": {
                                    "format": "int64",
                                    "type": "integer"
                                  },
                                  "unpriced_by_reason": {
                                    "additionalProperties": {
                                      "format": "int64",
                                      "type": "integer"
                                    },
                                    "description": "Why each excluded item was excluded, by count. Keys are the closed set `/holdings`'s `mark_status` publishes — `stale`, `shallow`, `unpriced` — plus `unresolved` (no decimals, so the quantity has no scale), `not_valued_truncated` (beyond this build's per-leg valuation cap) and `staking_token_unregistered` (the protocol row carries no token).\n\nSums to `unpriced_items`. Empty when `complete` is true.",
                                    "type": "object"
                                  },
                                  "unpriced_items": {
                                    "format": "int64",
                                    "type": "integer"
                                  },
                                  "value_usd": {
                                    "description": "USD. **Null is UNPRICED and is never 0**, never a guess, never a range and never a \">= $X\".\n\nThree cases, and the middle one is the one that matters:\n\n* some component priced → the sum of those, partial when `complete: false`; * **items present but NONE priced → `null`** — `0.0` would assert the holdings are worth nothing, when the truth is that their worth is unknown; * no items at all → `0.0`. Holding nothing IS worth nothing, and that is knowledge rather than absence.",
                                    "format": "double",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "complete",
                                  "priced_items",
                                  "unpriced_by_reason",
                                  "unpriced_items"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "detail",
                              "leg",
                              "source"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "legs_included": {
                          "description": "The legs this response counts. All five today; the field exists because the set is a property of the BUILD, not of the wallet, and a consumer comparing two responses across a deploy needs to see that it changed.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "legs_valued": {
                          "description": "The legs this build VALUES, as opposed to merely counts. Phase 1 of `docs/proposal_portfolio_surface.md` values the three that `networth_usd` already sums; `farm` and `v3` are counted and carry `value: null` until Phases 3 and 4.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "networth_usd_includes": {
                          "description": "The legs `ui.wallet_networth.networth_usd` actually sums today.\n\n**A15.** `legs_included` alone would let a reader assume the five legs counted here are the five legs the published net worth values. They are not: `farm` and `v3` are counted here and absent from `networth_usd`, which is exactly how the $0.44 reproduction reads as a pricing bug rather than as two missing terms. When B3 ships the legs this list grows to five and the discontinuity in `networth_history` is explainable rather than mysterious.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "total": {
                          "description": "The cross-leg total. **Absent — not null — while withheld**; see `total_withheld_reason`, which is present exactly when this is not.",
                          "properties": {
                            "complete": {
                              "type": "boolean"
                            },
                            "legs_omitted": {
                              "description": "Legs this build does not value, and which are therefore MISSING from the figure entirely — not zero in it.",
                              "items": {
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "legs_valued": {
                              "description": "Legs summed into `value_usd`.",
                              "items": {
                                "type": "string"
                              },
                              "type": "array"
                            },
                            "oldest_as_of_block": {
                              "description": "The OLDEST `as_of_block` across the summed legs. The total is no fresher than its stalest input.",
                              "format": "int64",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "priced_items": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "unpriced_by_reason": {
                              "additionalProperties": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "type": "object"
                            },
                            "unpriced_items": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "value_usd": {
                              "format": "double",
                              "type": [
                                "number",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "complete",
                            "legs_omitted",
                            "legs_valued",
                            "priced_items",
                            "unpriced_by_reason",
                            "unpriced_items"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "total_withheld_reason": {
                          "description": "Why `total` is absent. `pending_jump_disclosure` means the figure is built and tested but gated on the Gate C artifact (`docs/positions_scope_proposal.md` P0) existing first.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "valuation": {
                          "description": "The rule every figure in this response was computed under. Read it before comparing anything here with `/networth`.",
                          "properties": {
                            "depth_floor_usd": {
                              "description": "The oracle's `candidate_min_depth_usd` dial, read per request.",
                              "format": "double",
                              "type": "number"
                            },
                            "rule": {
                              "description": "`marks` — the valuation rule named in Justin's §3.0 ruling (`marks.rs`; the ruling calls it \"the /pnl rule\" after the route that first carried it, removed by OPS-107).",
                              "type": "string"
                            },
                            "staleness_secs": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "twap_window_secs": {
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "depth_floor_usd",
                            "rule",
                            "staleness_secs",
                            "twap_window_secs"
                          ],
                          "type": "object"
                        },
                        "wallet": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "legs",
                        "legs_included",
                        "legs_valued",
                        "networth_usd_includes",
                        "valuation",
                        "wallet"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One wallet's open liquidity positions",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/positions/items": {
      "get": {
        "operationId": "getV2WalletsByAddrPositionsItems",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "1..=500. Default 100. **PER LEG**, not across the response — the legs are independent reads and a shared budget would let a wallet's HEX stakes crowd out its V3 positions.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The legs, each its own array. **Sectioned rather than one heterogeneous list**: a V3 position, a HEX stake and a PTGC lock share no fields, and an untagged union of the three would force every client to sniff keys.",
                      "properties": {
                        "phex": {
                          "items": {
                            "description": "One HEX stake.",
                            "properties": {
                              "cost_usd": {
                                "description": "Principal at the stake-start day's oracle price. **`0` is a real value here and means \"the price predates our tick history\"** — a fork-inherited stake — rather than \"this stake cost nothing\" (`0019:87`).",
                                "format": "double",
                                "type": "number"
                              },
                              "last_updated_block": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "locked_day": {
                                "description": "HEX day index (day 0 = 2019-12-03T00:00:00Z, epoch 1575331200).",
                                "format": "int32",
                                "type": "integer"
                              },
                              "principal": {
                                "description": "`stakedHearts`, 8 decimals. String.",
                                "type": "string"
                              },
                              "shares": {
                                "description": "`stakeShares`. String.",
                                "type": "string"
                              },
                              "stake_id": {
                                "description": "`uint40` on chain, `NUMERIC` in the column — a STRING here.",
                                "type": "string"
                              },
                              "staked_days": {
                                "format": "int32",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "cost_usd",
                              "last_updated_block",
                              "locked_day",
                              "principal",
                              "shares",
                              "stake_id",
                              "staked_days"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "ptgc": {
                          "items": {
                            "description": "One PTGC lock.",
                            "properties": {
                              "amount": {
                                "description": "18 decimals. String.",
                                "type": "string"
                              },
                              "cost_usd": {
                                "format": "double",
                                "type": "number"
                              },
                              "end_time": {
                                "description": "Unix seconds. **`0` is the UNLOCKED row** (`0019:111`), not a lock that ended at the epoch.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "last_updated_block": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "lock_id": {
                                "format": "int32",
                                "type": "integer"
                              },
                              "reward_debt": {
                                "type": "string"
                              },
                              "start_time": {
                                "description": "Unix seconds.",
                                "format": "int64",
                                "type": "integer"
                              }
                            },
                            "required": [
                              "amount",
                              "cost_usd",
                              "end_time",
                              "last_updated_block",
                              "lock_id",
                              "reward_debt",
                              "start_time"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "v3": {
                          "items": {
                            "description": "One concentrated-liquidity position.\n\n**Every field outside `protocol`/`token_id`/`owner_updated_block` is nullable, and null NEVER means zero.** The owner row is the only fact guaranteed to exist; each of the other three tables is written by a different mechanism that can legitimately not have run yet.",
                            "properties": {
                              "amount0": {
                                "description": "DISPLAY-GRADE token amounts from the refresher's f64 liquidity maths — not exact, and not to be summed into a balance. Strings for scale.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "amount1": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "current_value_usd": {
                                "description": "`amount0 x price0 + amount1 x price1`, in USD, when **BOTH** sides are valued; null otherwise. See [`price_v3_item`] for what \"valued\" requires — it is more than a price.\n\n**NULL IS NOT ZERO.** A half-priced position has a real value that this route cannot state, and stating the priced half alone would understate it. `value_status` distinguishes the two cases.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "fee_tier": {
                                "description": "Fee tier in hundredths of a basis point, as the pool stores it.",
                                "format": "int32",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "fees_owed0": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "fees_owed1": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "fees_usd": {
                                "description": "USD value of the owed fees. Null when either token is unresolved or its price is past the staleness bound — **never guessed**.",
                                "format": "double",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "in_range": {
                                "description": "**THREE-VALUED.** `true`/`false` from the last refresh; **null when the refresher has not established the range**, which is neither in nor out (`0005:112` makes the column nullable for exactly this).",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "liquidity": {
                                "description": "EVENT-EXACT liquidity, summed from the NPM's own deltas. A STRING: `uint128` scale.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "liquidity_updated_block": {
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "mark0_status": {
                                "description": "Why `token0` is (or is not) priced — `ok` | `stale` | `shallow` | `unpriced`, the same closed set `/holdings` and `/positions` publish.",
                                "oneOf": [
                                  {
                                    "enum": [
                                      "ok"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Newest tick older than the staleness ceiling.",
                                    "enum": [
                                      "stale"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Liquidity below the candidate depth floor.",
                                    "enum": [
                                      "shallow"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "No tick history at all.",
                                    "enum": [
                                      "unpriced"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "mark1_status": {
                                "description": "Why a mark is (or isn't) servable.\n\nSerialised directly into `/v2/wallets/{addr}/holdings` and `/v2/wallets/{addr}/positions` as a closed set: a consumer MUST branch on it, because `mark_price_usd: null` alone does not say whether the price is missing, stale or untrustworthy, and those render differently. `rename_all` reproduces `as_str` exactly — the wire values are unchanged.",
                                "oneOf": [
                                  {
                                    "enum": [
                                      "ok"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Newest tick older than the staleness ceiling.",
                                    "enum": [
                                      "stale"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "Liquidity below the candidate depth floor.",
                                    "enum": [
                                      "shallow"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "No tick history at all.",
                                    "enum": [
                                      "unpriced"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "minted_block": {
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "owner_updated_block": {
                                "description": "Block at which ownership was last observed to change.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "pool_address": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "price0_usd": {
                                "description": "`token0`'s live mark, or null. **A STRING** for the same reason every other quantity here is one.\n\nNull whenever `mark0_status` is not `ok`: `mark_with_validity` (`marks.rs:92-104`) returns `(None, …)` on every other arm, so a `stale`/`shallow`/`unpriced` side has no price to serve. The status is the field that says WHY, which is why both ship.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "price1_usd": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "protocol": {
                                "description": "`financial.protocol_registry.slug` — `ninemm_v3` or `liberty_swap_v3` today. See `meta.v3_protocols_covered` for the set that can appear.",
                                "type": "string"
                              },
                              "protocol_id": {
                                "format": "int16",
                                "type": "integer"
                              },
                              "tick_lower": {
                                "description": "The position's range. **Ticks, not prices** — a client converts with `1.0001^tick`; serving a price here would need a decimals pair this row does not carry.",
                                "format": "int32",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "tick_upper": {
                                "format": "int32",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token0": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token0_decimals": {
                                "description": "**THE SCALE FOR `amount0`.** Null unless `metadata_status = 'resolved'` — the estate reads decimals only from a resolved row (`0004`'s `resolved_has_decimals` comment), so an unresolved token yields null and the raw amount must be shown unscaled rather than scaled wrongly.",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token0_display": {
                                "description": "**THE CURATED OVERRIDE** for `token0`, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "token0_name": {
                                "description": "`token0`'s registry name. Null when the token is unresolved.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token0_symbol": {
                                "description": "`token0`'s registry symbol. Null when the token is unresolved.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token1": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token1_decimals": {
                                "description": "*THE SCALE FOR `amount1`**, on the same terms as `token0_decimals`.",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token1_display": {
                                "description": "*THE CURATED OVERRIDE** for `token1`, or null when there is none.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "token1_name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token1_symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "token_id": {
                                "description": "The NFT's `tokenId`. **A STRING**: it is a `uint256` on chain and `NUMERIC` in the column, so it does not fit a JSON number.",
                                "type": "string"
                              },
                              "value_status": {
                                "description": "`priced` (both sides valued) | `partial` (exactly one) | `unpriced` (neither). On `partial` the priced side's `priceN_usd` is still served — the reader can see what IS known, just not a total.",
                                "type": "string"
                              },
                              "yield_updated_at": {
                                "description": "Unix seconds of the yield refresh this row came from.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "mark0_status",
                              "mark1_status",
                              "owner_updated_block",
                              "protocol",
                              "protocol_id",
                              "token_id",
                              "value_status"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "phex",
                        "ptgc",
                        "v3"
                      ],
                      "type": "object"
                    },
                    "meta": {
                      "properties": {
                        "limit": {
                          "description": "The per-leg row bound this response used.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "sources": {
                          "description": "**THE PROVENANCE STATEMENT.** Every leg of the portfolio, with whether this response itemises it and where to look if not. The FE renders its coverage note from this rather than from a hardcoded list, so the note cannot claim coverage the backend does not have.",
                          "items": {
                            "description": "What one leg contributed, and whether this response tells the whole story about it.",
                            "properties": {
                              "itemised": {
                                "description": "**Whether THIS response carries rows for it.** False for `spot` and `farm`, which are counted elsewhere and not itemised here.",
                                "type": "boolean"
                              },
                              "itemised_by": {
                                "description": "Where else to look for a leg this route does not itemise. Null when it does.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "items": {
                                "description": "Rows in this response for this leg. 0 on a leg that is not itemised.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "items_total": {
                                "description": "The wallet's EXACT count for this leg, whatever the limit did. Null on a leg this route does not read at all — absent, not zero.",
                                "format": "int64",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "source": {
                                "description": "`spot` | `phex` | `ptgc` | `farm` | `v3` — the same leg names the counts route uses, so the two surfaces describe one portfolio.",
                                "type": "string"
                              },
                              "truncated": {
                                "description": "`items_total > items`. A client must not read a short leg as complete.",
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "itemised",
                              "items",
                              "source",
                              "truncated"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "v3_partial_count": {
                          "description": "Items with exactly one side valued. Their value is real and unstated.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "v3_priced_count": {
                          "description": "Items with `value_status = \"priced\"` — exactly the ones summed above.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "v3_protocols_covered": {
                          "description": "The `dex_v3` protocols whose positions CAN appear, read from `financial.protocol_registry` (`active` + non-NULL `position_manager` — the same conditions the v3 consumer applies). A protocol outside this set has no rows anywhere to return.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "v3_total_truncated": {
                          "description": "**TRUE WHEN THE TOTAL ITSELF IS SHORT** — the wallet holds more than [`V3_ITEMS_SCAN_CAP`] V3 positions, so `v3_total_usd` is a sum over the first `V3_ITEMS_SCAN_CAP` and not over the wallet.\n\nFALSE on every response from a wallet inside the bound, which is every wallet this estate has seen — `sources[].truncated` is about the PAGE and says nothing about this figure, which is precisely the confusion OPS-85B was. A client must not render `v3_total_usd` as the holdings figure while this is true.",
                          "type": "boolean"
                        },
                        "v3_total_usd": {
                          "description": "**Σ `current_value_usd` OVER THE FULLY PRICED V3 ITEMS ONLY**, as a string. Partial and unpriced items contribute NOTHING — adding a half-priced position's known side would report a total the estate cannot stand behind, and the three counts below are what makes the omission visible rather than silent.\n\nThese four live in `meta` beside `sources`, which already carries this response's per-leg counts: they describe what this response says about the v3 leg, not the positions themselves.",
                          "type": "string"
                        },
                        "v3_unpriced_count": {
                          "description": "Items with neither side valued.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "limit",
                        "sources",
                        "v3_partial_count",
                        "v3_priced_count",
                        "v3_protocols_covered",
                        "v3_total_truncated",
                        "v3_total_usd",
                        "v3_unpriced_count"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "The individual items behind one wallet's liquidity positions",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "H",
        "x-cu-units": 3,
        "x-min-tier": "Paid"
      }
    },
    "/v2/wallets/{addr}/summary": {
      "get": {
        "operationId": "getV2WalletsByAddrSummary",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "properties": {
                        "activity_source": {
                          "type": "string"
                        },
                        "first_active": {
                          "description": "A block and its timestamp.",
                          "properties": {
                            "block": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "ts": {
                              "description": "Unix seconds, from `core.chain_blocks`.",
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "block",
                            "ts"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "funded_by": {
                          "description": "Who first sent this address value, and out of which feed.",
                          "properties": {
                            "address": {
                              "description": "The COUNTERPARTY of the inbound row — the sender.",
                              "type": "string"
                            },
                            "block": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "source": {
                              "description": "`address_txs` (a top-level transaction) or `address_internal` (a trace).",
                              "type": "string"
                            },
                            "ts": {
                              "description": "The funding block's timestamp. **NULL when `core.chain_blocks` has no row for that block** — which happens on a partially-backfilled range.\n\nIt used to be `unwrap_or(0)`, so a missing block row served `ts: 0` — 1 January 1970, rendered as a date, indistinguishable from a real one (audit §130 LOW 4). Absent is not a timestamp.",
                              "format": "int64",
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "tx_hash": {
                              "type": "string"
                            },
                            "value_wei": {
                              "description": "Wei, as a STRING: `uint256` does not fit a JSON number.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "address",
                            "block",
                            "source",
                            "tx_hash",
                            "value_wei"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "funded_by_reason": {
                          "description": "Why `funded_by` is null, or null when it is not. The two cases are different and a reader must be able to tell them apart: no history at all, versus no inbound transfer inside the bounded window.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "last_active": {
                          "description": "The last-seen point, plus how long ago that was.",
                          "properties": {
                            "block": {
                              "format": "int64",
                              "type": "integer"
                            },
                            "days_since": {
                              "description": "Whole days between `ts` and the request's clock. **Floored**, so an address seen 23 hours ago reads `0` — \"today\" — rather than rounding up to a day that has not passed.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "ts": {
                              "format": "int64",
                              "type": "integer"
                            }
                          },
                          "required": [
                            "block",
                            "days_since",
                            "ts"
                          ],
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "rx_count": {
                          "description": "Transactions RECEIVED by this address, from the same `wallet_stats` row and the same read as `tx_count`. **Null when there is no row and null when the estate is not counting receivers yet** — `rx_count_source` says which, and is the field to branch on.\n\n**NOT ADDABLE TO `tx_count` UNLESS `rx_count_source` IS `counted`.** The lane counts receivers FORWARD from `rx_from_block`, so for a wallet active below that block this number is a window, not a total.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "rx_count_caption": {
                          "description": "The exact sentence for `rx_count_source`, always present. Byte-stable, so a client may render it verbatim in a hover without restating this route's rules in its own words.",
                          "type": "string"
                        },
                        "rx_count_source": {
                          "description": "Which of the four states `rx_count` is in. A closed set, published as an enum: `counted`, `partial_from_block`, `not_yet_counted`, `no_row`.",
                          "oneOf": [
                            {
                              "description": "The row exists, the marker is set, and the wallet's first indexed activity is STRICTLY ABOVE it — so nothing of this wallet's history sits at or below the last block the lane did not count, and `rx_count` is its lifetime received total.",
                              "enum": [
                                "counted"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "The row exists and the marker is set, but this wallet's history reaches TO OR BELOW the marker (or its first activity is not known at all, which cannot be distinguished from it). `rx_count` covers blocks ABOVE `rx_from_block` only.",
                              "enum": [
                                "partial_from_block"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "`meta.config['wallet_stats.rx_from_block']` is absent: `0063` has not been applied, or the lane has not yet written a marker. The received count has no start block, so no figure is served at all.",
                              "enum": [
                                "not_yet_counted"
                              ],
                              "type": "string"
                            },
                            {
                              "description": "`analytics.wallet_stats` has no row for this wallet — the same absence `tx_count_reason` reports, and neither count is known.",
                              "enum": [
                                "no_row"
                              ],
                              "type": "string"
                            }
                          ]
                        },
                        "rx_from_block": {
                          "description": "The block `analytics.wallet_stats.rx_count` starts counting above — `meta.config['wallet_stats.rx_from_block']`, set once by `0063` from the lane's cursor at apply time. Carried on the wire so a client can say \"received since block N\" rather than implying a lifetime figure.\n\n**Null only when the marker itself is absent**, which is exactly `rx_count_source = not_yet_counted`. It is an estate-wide fact, not a per-wallet one, so it is served in the `no_row` case too.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "tx_count": {
                          "description": "Transactions SENT by this address. **Null when `analytics.wallet_stats` has no row**, which for a receive-only address is the normal case, not an error — see `tx_count_reason`.",
                          "format": "int64",
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "tx_count_reason": {
                          "description": "Why `tx_count` is null, or null when it is not.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "tx_count_source": {
                          "description": "Where `tx_count` came from and what it counts. Always present, so a reader never has to know this route's internals to caption the number.",
                          "type": "string"
                        },
                        "wallet": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "activity_source",
                        "rx_count_caption",
                        "rx_count_source",
                        "tx_count_source",
                        "wallet"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "One wallet's headline balances and activity",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/wallets/{addr}/trades": {
      "get": {
        "operationId": "getV2WalletsByAddrTrades",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "Restrict to trades touching this token on EITHER leg, 0x address.\n\nEither leg, not just `token_in`: a swap is one event, and a user filtering their PLSX history means every trade where PLSX moved, whichever side it was on. Matching one leg would silently return about half the answer — the same lie as filtering a paginated list in the client, which is what this parameter exists to stop.",
            "in": "query",
            "name": "token",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One swap, with the prices PINNED at execution time — not recomputed from today's oracle. That is the whole point of the row: a trade's USD value is a historical fact.",
                        "properties": {
                          "amount_in_raw": {
                            "description": "u256-scale, therefore STRINGS.",
                            "type": "string"
                          },
                          "amount_out_raw": {
                            "type": "string"
                          },
                          "anchor_leg": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "block_number": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "direction": {
                            "type": "string"
                          },
                          "exec_price_usd": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "pls_usd_at_trade": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "protocol_id": {
                            "format": "int16",
                            "type": "integer"
                          },
                          "token_in": {
                            "type": "string"
                          },
                          "token_in_decimals": {
                            "description": "NULL until metadata resolves (Data §2.1).",
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "token_in_display": {
                            "description": "**THE CURATED OVERRIDE** for the traded tokens, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "token_in_symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "token_out": {
                            "type": "string"
                          },
                          "token_out_decimals": {
                            "format": "int16",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "token_out_display": {
                            "description": "What a token surface shows INSTEAD of the contract's own strings — beside them, never in place of them.",
                            "properties": {
                              "fork_copy": {
                                "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                "type": "boolean"
                              },
                              "name": {
                                "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                "type": "string"
                              },
                              "note": {
                                "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                "type": "string"
                              },
                              "symbol": {
                                "description": "The curated symbol — `\"pDAI\"`.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "fork_copy",
                              "name",
                              "note",
                              "symbol"
                            ],
                            "type": [
                              "object",
                              "null"
                            ]
                          },
                          "token_out_symbol": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ts": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "tx_hash": {
                            "type": "string"
                          },
                          "usd_value_at_trade": {
                            "description": "STRINGS, not numbers — these come out of Postgres NUMERIC via `::text` and are emitted verbatim so no rounding happens in transit. NULL means UNPRICED and is never guessed (Data §3.2.6); it does not mean zero.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "amount_in_raw",
                          "amount_out_raw",
                          "block_number",
                          "direction",
                          "protocol_id",
                          "token_in",
                          "token_out",
                          "ts",
                          "tx_hash"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Dex trades made by one wallet",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Free"
      }
    },
    "/v2/wallets/{addr}/txs": {
      "get": {
        "operationId": "getV2WalletsByAddrTxs",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Restrict to value the wallet sent (`out`) or received (`in`).",
            "in": "query",
            "name": "direction",
            "required": false,
            "schema": {
              "enum": [
                "in",
                "out",
                null
              ],
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "`type=internal` ONLY.\n\n`ui.address_internal` records value-transfer ATTEMPTS: a frame that reverted carries its own error, and (pre_replay_audit §2 B3) a child poisoned by an ancestor revert carries `'ancestor reverted'`, because Parity-style traces mark only the failing frame and a NULL there would claim the value moved. So `true` keeps exactly what moved on chain and `false` keeps exactly what did not.\n\nABSENT KEEPS BOTH. The feed shows failed attempts on purpose and the default must not start hiding them.",
            "in": "query",
            "name": "effective",
            "required": false,
            "schema": {
              "default": null,
              "type": [
                "boolean",
                "null"
              ]
            }
          },
          {
            "description": "1..=1000. Default 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "description": "`type=erc20` ONLY. Restrict to one token contract, 0x address.",
            "in": "query",
            "name": "token",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "Which feed. Default `tx`. **Selects the response shape.**",
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "description": "Which feed `GET /v2/wallets/{addr}/txs` returns. Selects the response shape — see `WalletFeedRow`.",
                  "oneOf": [
                    {
                      "description": "Transactions the wallet sent or received.",
                      "enum": [
                        "tx"
                      ],
                      "type": "string"
                    },
                    {
                      "description": "Value-transfer attempts from the trace tree, failures included.",
                      "enum": [
                        "internal"
                      ],
                      "type": "string"
                    },
                    {
                      "description": "ERC-20 Transfer logs touching the wallet.",
                      "enum": [
                        "erc20"
                      ],
                      "type": "string"
                    }
                  ]
                },
                {
                  "type": "null"
                }
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "The page's rows, newest first.",
                      "items": {
                        "anyOf": [
                          {
                            "description": "`?type=tx` — one row per transaction the wallet sent or received.",
                            "properties": {
                              "block_number": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "counterparty": {
                                "description": "The other party. **For a successful contract creation this is the CREATED CONTRACT**, not null: ps-derive writes `to OR created_contract` into this column (`ps-derive/src/balances.rs`, the `recipient` binding). It is null only when there is neither — a failed creation, or an `Out` row whose receipt produced no address.\n\nSo a null here is NOT the creation signal. See `is_creation` on [`FEED_TX_SQL`] for the one that is — and `created_contract` below, which is that signal ON THE WIRE.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_contract": {
                                "description": "Set only when this transaction deployed a contract.\n\n**THE POSITIVE CREATION SIGNAL** (§141 M2). This feed had none: a creation was distinguishable only by `method`/`method_id` being null, which is exactly what a plain value transfer looks like, and `counterparty`'s own description pointed at `is_creation` — a SQL alias on `FEED_TX_SQL`, not a key any client can read.\n\nThe address is `core.chain_transactions.created_contract` (`0003:51`), the same column `/v2/txs/{hash}` and `/v2/blocks/{n}/txs` serve under this name — not a re-reading of `counterparty`, which holds `to OR created_contract` and cannot say which it is.\n\nNull on a failed creation, whose receipt produced no address, and on every non-creation.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "direction": {
                                "description": "Which way value moved relative to the wallet being viewed. Derived from a bool, so the set really is closed and an enum cannot misrepresent the data.",
                                "enum": [
                                  "in",
                                  "out"
                                ],
                                "type": "string"
                              },
                              "method": {
                                "description": "**THE HUMAN LABEL** for `method_id`, or null. The selector is already on `ui.address_txs` (`0005:19`), so this list needs no extra read.",
                                "properties": {
                                  "label": {
                                    "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                                    "type": "string"
                                  },
                                  "signature": {
                                    "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                                    "type": "string"
                                  },
                                  "source": {
                                    "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                                    "type": "string"
                                  },
                                  "tier": {
                                    "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                                    "format": "uint8",
                                    "maximum": 3.0,
                                    "minimum": 1.0,
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "label",
                                  "signature",
                                  "source"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "method_id": {
                                "description": "First four calldata bytes, 0x-prefixed. Null for a plain transfer.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "status": {
                                "description": "Receipt status: 1 success, 0 reverted.",
                                "format": "int16",
                                "type": "integer"
                              },
                              "ts": {
                                "description": "Unix seconds of the containing block.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "tx_hash": {
                                "type": "string"
                              },
                              "value_wei": {
                                "description": "wei-scale, therefore a STRING.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "block_number",
                              "direction",
                              "status",
                              "ts",
                              "tx_hash",
                              "value_wei"
                            ],
                            "type": "object"
                          },
                          {
                            "description": "`?type=internal` — value-transfer ATTEMPTS from the trace tree, including failed ones. See `parse_effective` for why failures are shown by default.",
                            "properties": {
                              "block_number": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "counterparty": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "direction": {
                                "description": "Which way value moved relative to the wallet being viewed. Derived from a bool, so the set really is closed and an enum cannot misrepresent the data.",
                                "enum": [
                                  "in",
                                  "out"
                                ],
                                "type": "string"
                              },
                              "error": {
                                "description": "NULL means the value actually moved. Non-null is either this frame's own revert or `'ancestor reverted'` — the latter because a Parity-style tracer marks only the failing frame, and a NULL there would claim value moved when it did not.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "trace_address": {
                                "description": "Dot-separated path in the trace tree. Text order is total and stable, which is what the cursor needs; it is NOT execution order (\"1.10\" sorts before \"1.2\").",
                                "type": "string"
                              },
                              "trace_type": {
                                "description": "`call`, `create`, `suicide`, … as the tracer reported it.",
                                "type": "string"
                              },
                              "ts": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "tx_hash": {
                                "type": "string"
                              },
                              "value_wei": {
                                "description": "wei-scale, therefore a STRING.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "block_number",
                              "direction",
                              "trace_address",
                              "trace_type",
                              "ts",
                              "tx_hash",
                              "value_wei"
                            ],
                            "type": "object"
                          },
                          {
                            "description": "`?type=erc20` — one row per Transfer log touching the wallet.",
                            "properties": {
                              "amount_raw": {
                                "description": "u256-scale, therefore a STRING. Undecimalised — divide by `token_decimals`, and only when that is non-null.",
                                "type": "string"
                              },
                              "block_number": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "counterparty": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "direction": {
                                "description": "Which way value moved relative to the wallet being viewed. Derived from a bool, so the set really is closed and an enum cannot misrepresent the data.",
                                "enum": [
                                  "in",
                                  "out"
                                ],
                                "type": "string"
                              },
                              "display": {
                                "description": "**THE CURATED OVERRIDE** for this token, or null when there is none.\n\nServed BESIDE the raw identity, never merged into it. One in-process map lookup at serialization — no query, no join — and null everywhere when `0058` has not been applied.",
                                "properties": {
                                  "fork_copy": {
                                    "description": "True for an Ethereum-state fork copy. A flag as well as the prose, so a client can branch without parsing a sentence.",
                                    "type": "boolean"
                                  },
                                  "name": {
                                    "description": "The curated name — `\"pDAI (fork copy)\"`.",
                                    "type": "string"
                                  },
                                  "note": {
                                    "description": "One sentence explaining WHY the override exists. Always present: an override with no explanation is just a second name.",
                                    "type": "string"
                                  },
                                  "symbol": {
                                    "description": "The curated symbol — `\"pDAI\"`.",
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "fork_copy",
                                  "name",
                                  "note",
                                  "symbol"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "token": {
                                "type": "string"
                              },
                              "token_decimals": {
                                "description": "NULL until the token's metadata resolves. Do NOT assume 18 (Data §2.1) — an amount shown against a guessed scale is wrong by orders of magnitude.",
                                "format": "int16",
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "token_symbol": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "ts": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "tx_hash": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "amount_raw",
                              "block_number",
                              "direction",
                              "token",
                              "ts",
                              "tx_hash"
                            ],
                            "type": "object"
                          }
                        ],
                        "description": "THE FEED IS POLYMORPHIC. `?type=tx|internal|erc20` selects which of three row shapes comes back, and the payload carries NO discriminator field — the caller already chose, so one was never emitted.\n\nSerialised `untagged`, which means this enum changes nothing on the wire: the bytes are exactly what the `json!` handler produced. What it changes is that the schema now SAYS there are three shapes instead of publishing an empty object and leaving a consumer to discover it by trying.\n\nA discriminator was deliberately NOT added. It would be a new key on a live route, and it would duplicate information the caller already holds — it sent the `type` parameter. A consumer narrows on the parameter it passed, not on the response."
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this is the last one. Pass it back as `?cursor=` — never construct one.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "unindexed": {
                      "description": "Present only on the FIRST page of `type=tx`. Null on cursor pages (the lane is a window at the HEAD, so it has nothing to say about a page walking backwards) and null for `type=internal` / `type=erc20` (**internal calls and token transfers are not in the lane** — it stores transactions, not traces or logs, so there is nothing to serve).",
                      "properties": {
                        "as_of_ts": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "gap_blocks": {
                          "description": "**THE RETIRED COUNT.** Blocks that left the live window before the index reached them: `lane_floor - indexed_head - 1` when the window is truncated, else 0. Their transactions are in NEITHER section, and this is the number that says so rather than letting them vanish silently.",
                          "format": "int64",
                          "type": "integer"
                        },
                        "indexed_head": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "lane_available": {
                          "description": "False when the lane is not serving; `rows` is then EMPTY and `lane_unavailable_reason` says why. An empty list with no reason would read as \"this wallet has nothing pending\", which is a different claim.",
                          "type": "boolean"
                        },
                        "lane_floor": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "lane_unavailable_reason": {
                          "anyOf": [
                            {
                              "description": "Why the lane is not serving. `null` when it is.",
                              "oneOf": [
                                {
                                  "description": "No successful refresh inside [`HEAD_LANE_MAX_AGE_SECS`].",
                                  "enum": [
                                    "rpc_unreachable"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The node's head is at or below the indexed head. A lane below the confirmed frontier has nothing to add and would imply a rollback.",
                                  "enum": [
                                    "node_behind_index"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The node's head is implausibly far above the indexed head. The honest reading of a gap that size is \"these two disagree\", not \"here are ten thousand provisional blocks\".",
                                  "enum": [
                                    "node_divergent"
                                  ],
                                  "type": "string"
                                },
                                {
                                  "description": "The poller has not completed a first refresh yet.",
                                  "enum": [
                                    "warming"
                                  ],
                                  "type": "string"
                                }
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "node_head": {
                          "format": "int64",
                          "type": "integer"
                        },
                        "rows": {
                          "items": {
                            "description": "One transaction the node has and the index has not.\n\nThe fields are `WalletTxRow`'s, minus what the lane cannot know, plus the two the provisional state requires. `status` is the one that changes TYPE: the indexed row has `i16`, this has `Option<bool>` — see the field.",
                            "properties": {
                              "block_number": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "confirmations": {
                                "description": "`node_head - block_number`. Compare against the lane's own `finality_confirmations`, never against a hard-coded depth.",
                                "format": "int64",
                                "type": "integer"
                              },
                              "counterparty": {
                                "description": "The OTHER side: `to` for an outbound tx, `from` for an inbound one, the CREATED address for a creation, and null when there is no other side (a self-send, or a creation whose receipt has not landed).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_contract": {
                                "description": "Set only when this transaction deployed a contract.\n\n**THE SAME KEY THE INDEXED ROW SERVES** (§141 M2). It is added here as well as on `WalletTxRow` deliberately: both rows appear in ONE response — the indexed page in `data`, this one in `unindexed` — so a key on only one of them would make the frontend's creation chip appear at the moment a transaction indexes, which is the flip every other field on this carrier is built to avoid.\n\nFrom the receipt (`contract_address`), which is the lane's only source for it and is already read here to decide `direction`. Null until the receipt lands, and on every non-creation.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "direction": {
                                "description": "Which side of an unindexed transaction the queried wallet is on.\n\nFOUR values where the indexed feed's `Direction` has two: the lane sees the receipt, so it can distinguish a self-send and a contract creation, and flattening either into in/out would be inventing a counterparty.",
                                "oneOf": [
                                  {
                                    "description": "The wallet is `to`.",
                                    "enum": [
                                      "in"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "The wallet is `from`.",
                                    "enum": [
                                      "out"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "`from == to == the wallet`.",
                                    "enum": [
                                      "self_send"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "The wallet IS the contract this transaction created (`to` is null and the receipt's `contractAddress` is the wallet).",
                                    "enum": [
                                      "creation"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "method": {
                                "description": "Resolved through the SAME in-process selector dictionary the head routes use, against the snapshot the rows came from.",
                                "properties": {
                                  "label": {
                                    "description": "The human label — `\"Transfer\"`, `\"Swap Exact Tokens For Tokens\"`.",
                                    "type": "string"
                                  },
                                  "signature": {
                                    "description": "The full canonical signature the label came from, so a client can show it on hover and an operator can tell WHICH `transfer` this was.",
                                    "type": "string"
                                  },
                                  "source": {
                                    "description": "`estate_abi` | `public_set` | `curated` | `openchain` | `4byte` — the five 0064's CHECK admits.\n\n**THE FRONTEND KEYS ITS \"public signature — may be wrong\" HOVER ON `source == \"4byte\"`, EXACTLY.** That tier is the 4byte directory and its mirror, which accept unverified submissions: the reviewed seed contains `0x60a06040` -> `rugPullAll((uint240),(bytes4),int88[],bytes4,int136)`, which is not a function at all — it is the tail of a constructor. The other four values are a curated ABI, our own contracts, a reviewed pick, or an openchain entry that was the only unfiltered candidate, and none of them carries that warning.\n\n**NOT an `Option`, and never empty**: `source` is `NOT NULL` on the table, so a row that reached this struct has one. A nullable provenance would give the frontend a third state to render for no reason.",
                                    "type": "string"
                                  },
                                  "tier": {
                                    "description": "`1` curated ABI, `2` openchain, `3` 4byte — **`null` for the 129 rows `0057`/`0059` wrote by hand**, which predate tiers. 0064 adds the column nullable precisely so those rows are not given a provenance nobody recorded, and this `Option` is that fact reaching the wire.\n\nIt is a *narrower* statement than `source` rather than a redundant one: a client that wants \"how was this decided\" reads the tier, and one that wants \"may this be wrong\" reads `source`, which is total.\n\n**1..=3, PUBLISHED AS SUCH.** `u8` alone would document `minimum: 0`, and 0 is not a tier — `0064`'s CHECK admits only 1, 2 and 3. A generated client that believed 0 was in range would accept a value the database cannot store (§139 LOW (g)).",
                                    "format": "uint8",
                                    "maximum": 3.0,
                                    "minimum": 1.0,
                                    "type": [
                                      "integer",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "label",
                                  "signature",
                                  "source"
                                ],
                                "type": [
                                  "object",
                                  "null"
                                ]
                              },
                              "method_id": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "receipts_state": {
                                "description": "Whether the receipts leg landed for this transaction's block.",
                                "oneOf": [
                                  {
                                    "description": "The receipts came back and were walked. An empty `transfers` therefore means the transaction emitted no `Transfer` log — a real answer.",
                                    "enum": [
                                      "available"
                                    ],
                                    "type": "string"
                                  },
                                  {
                                    "description": "The call failed, the node does not implement `eth_getBlockReceipts`, or it answered something that is not a receipts array. `transfers` is EMPTY for every transaction in this block and means NOTHING; the surface says \"transfers unknown\" rather than \"none\".",
                                    "enum": [
                                      "unavailable"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "state": {
                                "description": "Always `provisional`. Present as a field, not implied by the section, so a row copied out of it keeps its own warning.",
                                "oneOf": [
                                  {
                                    "description": "Read from the node, not from the index. May vanish or change hash.",
                                    "enum": [
                                      "provisional"
                                    ],
                                    "type": "string"
                                  }
                                ]
                              },
                              "status": {
                                "description": "**TRI-STATE, and that is the point.** `true` = succeeded, `false` = reverted, **`null` = the receipt has not landed yet**. The indexed twin is a non-null `i16` because a row only enters the index with its receipt; in the lane the receipt leg can trail the block by a tick, and rendering \"success\" for an unknown outcome is the one lie this surface must not tell.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "transfers": {
                                "description": "Every ERC-20/ERC-721 `Transfer` this transaction emitted. **Read `receipts_state` first** — see [`crate::v2::head::HeadTx::transfers`].",
                                "items": {
                                  "description": "**ONE DECODED TRANSFER, ON THE WIRE.**\n\nThe lane's [`ProvisionalTransfer`] plus the two display fields the registry resolves, minus `tx_hash`/`tx_index` — the row it hangs off already names the transaction, and repeating the hash on every transfer of a 4,000-row block is bytes that say nothing.",
                                  "properties": {
                                    "amount": {
                                      "description": "ERC-20 only, and RAW — no `decimals` applied, because `decimals` may be null. u256 as a decimal STRING, the estate's rule. Null on an ERC-721.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    },
                                    "decimals": {
                                      "description": "Null with `symbol`, and for the same reason. **A guessed `decimals` is worse than none**: rendering a raw `1000000000000000000` against an assumed 18 when the token uses 6 is wrong by twelve orders of magnitude. The frontend's fallback is the RAW `amount`, which is the truth.",
                                      "format": "int16",
                                      "type": [
                                        "integer",
                                        "null"
                                      ]
                                    },
                                    "from": {
                                      "type": "string"
                                    },
                                    "kind": {
                                      "description": "**WHICH TOKEN STANDARD A DECODED `Transfer` CAME FROM.**\n\nA closed set rather than a string, so the two literals reach `docs/openapi.json` and a generated client can branch on them. The words are [`ps_common::transfer_log::Transfer::kind`]'s, and `the_transfer_wire_words_are_ps_commons_own` pins that they still are — the decoder and the wire may not drift apart.",
                                      "oneOf": [
                                        {
                                          "description": "`value` came from `data`: an `amount`, no `token_id`.",
                                          "enum": [
                                            "erc20"
                                          ],
                                          "type": "string"
                                        },
                                        {
                                          "description": "The third parameter was indexed: a `token_id`, no `amount`.",
                                          "enum": [
                                            "erc721"
                                          ],
                                          "type": "string"
                                        }
                                      ]
                                    },
                                    "log_index": {
                                      "description": "The log's index within the BLOCK, as the node reported it. **The dedupe key**: stable across a re-fetch of the same block in a way an array position is not.",
                                      "format": "int64",
                                      "type": "integer"
                                    },
                                    "state": {
                                      "description": "Always `provisional`. Present as a field, not implied by the row it sits on, so a transfer copied out of one keeps its own warning.",
                                      "oneOf": [
                                        {
                                          "description": "Read from the node, not from the index. May vanish or change hash.",
                                          "enum": [
                                            "provisional"
                                          ],
                                          "type": "string"
                                        }
                                      ]
                                    },
                                    "symbol": {
                                      "description": "**NULL UNLESS `financial.token_registry` HAS THE TOKEN `resolved`.** The frontend renders the raw `token` address when it is null; a symbol guessed from an unresolved row would name a token nobody verified. See `crate::registry`.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    },
                                    "to": {
                                      "type": "string"
                                    },
                                    "token": {
                                      "description": "The token contract that emitted the log, lowercase `0x` hex. Not the transaction's `to`, which for a multicall is the router.",
                                      "type": "string"
                                    },
                                    "token_id": {
                                      "description": "ERC-721 only. Null on an ERC-20.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    }
                                  },
                                  "required": [
                                    "from",
                                    "kind",
                                    "log_index",
                                    "state",
                                    "to",
                                    "token"
                                  ],
                                  "type": "object"
                                },
                                "type": "array"
                              },
                              "transfers_omitted": {
                                "description": "Decoded transfers the block's cap discarded. Block-wide, not per-transaction.",
                                "format": "uint32",
                                "minimum": 0.0,
                                "type": "integer"
                              },
                              "ts": {
                                "format": "int64",
                                "type": "integer"
                              },
                              "tx_hash": {
                                "type": "string"
                              },
                              "value_wei": {
                                "description": "Wei, STRING — u256 does not fit a JSON number.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "block_number",
                              "confirmations",
                              "direction",
                              "receipts_state",
                              "state",
                              "transfers",
                              "transfers_omitted",
                              "ts",
                              "tx_hash",
                              "value_wei"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        },
                        "rows_omitted": {
                          "description": "**THE SECOND TRUNCATION, PUBLISHED LIKE THE FIRST.** Rows that matched in the window but were cut to fit the request's `limit`, newest kept. 0 when nothing was cut. `gap_blocks` says what fell out of the WINDOW; this says what fell out of the RESPONSE, and a section that silently dropped either would be a page pretending to be complete.",
                          "format": "int64",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "as_of_ts",
                        "gap_blocks",
                        "indexed_head",
                        "lane_available",
                        "lane_floor",
                        "node_head",
                        "rows",
                        "rows_omitted"
                      ],
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Transactions involving one wallet, newest first",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    },
    "/v2/wallets/{addr}/validators": {
      "get": {
        "operationId": "getV2WalletsByAddrValidators",
        "parameters": [
          {
            "in": "path",
            "name": "addr",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Keyset cursor from the previous page's `next_cursor`.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "description": "1..=500. Default 100.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": null,
              "format": "int64",
              "type": [
                "integer",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "description": "One validator connected to the address in the path.\n\nThe page unions TWO populations and `source` says which one put each row there — they are different sets and neither contains the other, so a client that ignores `source` will show a validator's past as its present:\n\n* **`credentials`** — the validator's withdrawal credentials decode to this address. This is where its withdrawals go; it may never have been paid yet. * **`observed`** — a withdrawal to this address was recorded for this validator, but its credentials point elsewhere NOW. That is what a credential change looks like from outside: the payments stay in history, the destination has moved. * **`both`** — the ordinary case.\n\n**BLS validators are absent, and that is correct.** `0x00` withdrawal credentials contain a hash of a BLS key and no execution address at all, so such a validator belongs to no address until it changes its credentials.\n\n**`0x01` and `0x02` are both included and are NOT distinguishable here.** Compounding credentials (`0x02`, Pectra) carry the address in the same last 20 bytes as `0x01`, and this indexer stores the decoded address without the prefix that produced it — so the API can say \"this validator withdraws to X\" but not \"via 0x01 or 0x02\". Surfacing the prefix needs a new column and a backfill; it is not inferable from what is stored.",
                        "properties": {
                          "activation_epoch": {
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "balance_gwei": {
                            "description": "**Gwei, actual balance at the last registry refresh** (`0055`). Null on two different terms here, and both mean UNKNOWN rather than zero: no `beacon.validators` row for this index at all (the same reason `status` is nullable on this row), or a row that predates the refresh which writes it.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "effective_balance_gwei": {
                            "description": "**Gwei, effective — the value the protocol weights this validator by.** This, not `balance_gwei`, is what a per-address stake total should sum: it moves only at epoch boundaries, where actual balances drift with every reward. Null on the same terms as above.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "exit_epoch": {
                            "description": "Null while the validator is still active, and also null when there is no registry row — see `status`.",
                            "format": "int64",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "is_house": {
                            "description": "Null when there is no registry row.",
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "source": {
                            "description": "Why this validator is on the page. Read it before reading anything else.\n\n`credentials` — its withdrawal credentials decode to this address, so this is where its withdrawals go; it may never have been paid yet. `observed` — a withdrawal to this address was recorded for it, but its credentials point elsewhere NOW, so the address is in this validator's PAST rather than its present. `both` — the ordinary case.",
                            "enum": [
                              "credentials",
                              "observed",
                              "both"
                            ],
                            "type": "string"
                          },
                          "status": {
                            "description": "Null when this indexer has no `beacon.validators` row for the index yet. Withdrawals are ingested per block and the registry is refreshed on its own cadence, so a very recent validator can be observed before it is registered. Null means \"not known yet\", never \"does not exist\".",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "validator_index": {
                            "format": "int64",
                            "type": "integer"
                          },
                          "withdrawal_address": {
                            "description": "The validator's CURRENT withdrawal address. For a `credentials` or `both` row this equals the address in the path; for an `observed` row it does not, and that difference is the point.\n\nNull when the credentials are BLS (`0x00`) — those carry no execution address at all.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "source",
                          "validator_index"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "next_cursor": {
                      "description": "Opaque cursor for the NEXT page, or null when this page is the last. Non-null means there are more rows.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "properties": {
                        "code": {
                          "enum": [
                            "bad_param",
                            "bad_request",
                            "unknown_param"
                          ],
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Refused. Branch on `error.code`, never on `error.message` — the codes are the contract and the messages are not."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "summary": "Validators whose withdrawal address is this wallet",
        "tags": [
          "v2"
        ],
        "x-cu-budget": "plan",
        "x-cu-class": "Lm",
        "x-cu-units": 1,
        "x-min-tier": "Anon"
      }
    }
  },
  "security": [
    {
      "apiKeyQuery": []
    },
    {
      "apiKeyHeader": []
    },
    {
      "internalToken": []
    }
  ],
  "x-cu-classes": {
    "H": 3,
    "Lm": 1,
    "RpcHeavy": 5,
    "RpcLight": 2,
    "Stream": 1,
    "Trace": 10
  },
  "x-cu-notes": {
    "batch": "`x-cu-units` is PER CALL. /rpc accepts a JSON-RPC batch of up to 10 calls (rpc::MAX_BATCH) and charges the SUM of the per-call weights, so one request can cost up to 50 CU. A call the endpoint refuses (-32601) adds nothing to that sum; a request whose calls are ALL refused sums to zero and is charged the 2-CU RpcLight minimum, not nothing.",
    "budget": "`x-cu-budget` says WHICH budget an operation's units are drawn from. `plan` = the key's `daily_call_units`, recorded in billing.usage_daily. `per-ip` = the anonymous per-IP allowance (`anon_daily_cu`), NOT a plan budget and never written to billing.usage_daily - the /v2/account family is admitted this way because it is how a key is obtained. `none` = unmetered.",
    "range": "/api's `logs.getlogs` is RANGE-PRICED: 1 CU for a block span under 2000, 3 at or above it. It is the only range-priced action in the estate."
  }
}
