{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/getchord-xyz/json-schema/getchord-xyz-positions-answer-schema.json",
  "title": "PositionsAnswer",
  "description": "What each held token cost and what each exit made, on every chain in scope.",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/getchord-xyz-portfolio-api-openapi.yml#/components/schemas/PositionsAnswer",
  "type": "object",
  "properties": {
    "wallet": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "EVM address, lower-case."
    },
    "sol": {
      "type": [
        "string",
        "null"
      ],
      "pattern": "^[1-9A-HJ-NP-Za-km-z]{32,44}$",
      "description": "The Solana address as given, or null."
    },
    "asOf": {
      "type": "integer",
      "description": "Unix time, milliseconds. When this answer was computed. A cached answer keeps its own `asOf`."
    },
    "open": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/OpenCost"
      },
      "description": "Every held token that is not a stablecoin, on a chain whose history was read, largest value first (unpriced last)."
    },
    "closed": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/ClosedTrade"
      },
      "description": "Every token that is not a stablecoin sold in part or in full, newest last sale first, at most 100."
    },
    "totals": {
      "type": "object",
      "properties": {
        "openPnlUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "Sum of the open rows' pnlUsd. Null when a chain in scope could not be read (its holdings, or their history while it holds a priced token)."
        },
        "closedPnlUsd": {
          "type": "number",
          "description": "Sum of realizedUsd over every exit, the ones past the first 100 included."
        },
        "investedUsd": {
          "type": "number",
          "description": "Sum of the open rows' investedUsd."
        },
        "won": {
          "type": "integer",
          "description": "Exits with realizedUsd above zero."
        },
        "lost": {
          "type": "integer",
          "description": "Exits with realizedUsd below zero."
        }
      }
    },
    "chains": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/PositionsChain"
      },
      "description": "In registry order, Solana last."
    }
  },
  "$defs": {
    "ClosedTrade": {
      "type": "object",
      "properties": {
        "chain": {
          "type": [
            "integer",
            "string"
          ],
          "description": "EVM chain id, or `solana`."
        },
        "address": {
          "type": [
            "string",
            "null"
          ],
          "description": "EVM token, lower-case. Null for the chain's native coin (its wrapped twin is the same asset)."
        },
        "symbol": {
          "type": "string",
          "description": ""
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "description": ""
        },
        "logo": {
          "type": [
            "string",
            "null"
          ],
          "description": ""
        },
        "soldAll": {
          "type": "boolean",
          "description": "Nothing held now, or less than $1 of it."
        },
        "soldQty": {
          "type": "number",
          "description": ""
        },
        "boughtQty": {
          "type": "number",
          "description": ""
        },
        "unmatchedSoldQty": {
          "type": "number",
          "description": "Sold out of the part with no cost known, or beyond what was held on record at the time (a sale before the first buy): no profit is counted on it."
        },
        "avgBuyUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "Cost per token of what the sales took from the parts with a cost; (soldQty − unmatchedSoldQty) × avgBuyUsd is the cost `realizedPct` is a percent of."
        },
        "avgSellUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": ""
        },
        "realizedUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "Per sale, its proceeds on the part with a cost minus that part's cost, summed. Null = no sale took from a part with a cost."
        },
        "realizedPct": {
          "type": [
            "number",
            "null"
          ],
          "description": "realizedUsd over (soldQty − unmatchedSoldQty) × avgBuyUsd, a percent."
        },
        "firstBuyTs": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Unix time, milliseconds."
        },
        "lastSellTs": {
          "type": "integer",
          "description": "Unix time, milliseconds."
        }
      },
      "description": "What one exit made: a token sold in part or in full."
    },
    "OpenCost": {
      "type": "object",
      "properties": {
        "chain": {
          "type": [
            "integer",
            "string"
          ],
          "description": "EVM chain id, or `solana`."
        },
        "address": {
          "type": [
            "string",
            "null"
          ],
          "description": "EVM token, lower-case. Null for the chain's native coin."
        },
        "symbol": {
          "type": "string",
          "description": ""
        },
        "logo": {
          "type": [
            "string",
            "null"
          ],
          "description": ""
        },
        "amount": {
          "type": "string",
          "description": "Balance in whole tokens, decimal string (the portfolio's)."
        },
        "priceUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": ""
        },
        "valueUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": ""
        },
        "avgBuyUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "investedUsd / (heldBoughtQty + arrivedQty): the cost per token of the part of the holding that has one. Null = no part has a cost."
        },
        "investedUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "What the held part with a cost cost: the bought part at what was paid, the arrived part at its price on arrival. Null = none."
        },
        "pnlUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "(heldBoughtQty + arrivedQty) × priceUsd − investedUsd. Null = no cost behind the holding, or no price."
        },
        "pnlPct": {
          "type": [
            "number",
            "null"
          ],
          "description": "pnlUsd over investedUsd, a percent."
        },
        "heldBoughtQty": {
          "type": "number",
          "description": "The part of the holding bought by swap, after what later sales and transfers out took from it."
        },
        "arrivedQty": {
          "type": "number",
          "description": "The part that arrived by token transfer with a price on record at the hour it arrived; that price is its cost."
        },
        "arrivedUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "The cost of `arrivedQty` (quantity × price at arrival, after what later left). Null when arrivedQty is 0."
        },
        "lastArrivalTs": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Unix time, milliseconds. The newest priced arrival. Null when arrivedQty is 0."
        },
        "receivedQty": {
          "type": "number",
          "description": "The part with no cost known: arrived with no price on record, held before the history read, or a native coin received (no log). In no PnL. heldBoughtQty + arrivedQty + receivedQty = the holding."
        },
        "realizedUsd": {
          "type": [
            "number",
            "null"
          ],
          "description": "Profit on what was sold, by the closed rule. Null = nothing sold, or no sale took from a part with a cost."
        },
        "boughtQty": {
          "type": "number",
          "description": "Swap totals (transfers are not buys or sells)."
        },
        "boughtUsd": {
          "type": "number",
          "description": ""
        },
        "soldQty": {
          "type": "number",
          "description": ""
        },
        "soldUsd": {
          "type": "number",
          "description": ""
        },
        "buys": {
          "type": "integer",
          "description": ""
        },
        "sells": {
          "type": "integer",
          "description": ""
        },
        "firstBuyTs": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Unix time, milliseconds."
        },
        "lastTradeTs": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Unix time, milliseconds."
        }
      },
      "description": "What one held token cost."
    },
    "PositionsChain": {
      "type": "object",
      "properties": {
        "chain": {
          "type": [
            "integer",
            "string"
          ],
          "description": "EVM chain id, or `solana`."
        },
        "status": {
          "type": "string",
          "enum": [
            "ok",
            "partial",
            "unavailable"
          ],
          "description": "`ok` = every swap Chord's index holds for the wallet on this chain, and its token transfers, were read. `partial` = some were cut, and `reason` says which (for example `Transfers not read.` or `Transfers partial.`: the numbers stand on the swaps and the transfers that were read). `unavailable` = nothing read: no open or closed rows for this chain (Solana: not yet)."
        },
        "reason": {
          "type": "string",
          "description": "Present unless `ok`. One plain sentence for a person."
        },
        "fromTs": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Unix time, milliseconds. Swaps from here on are in the index for this chain: a buy before it reads as received. Null = no swap history read."
        }
      },
      "description": "One chain of a positions answer.",
      "required": [
        "chain",
        "status",
        "fromTs"
      ]
    }
  }
}