> ## Documentation Index
> Fetch the complete documentation index at: https://docs.windrose.market/llms.txt
> Use this file to discover all available pages before exploring further.

# Holders

> The holder table: current launch token balances per address, derived from Transfer events, for holder lists and wallet portfolios.

`holder` keeps the current balance of every address that holds a launch token. It is maintained from `LaunchToken.Transfer` events, and rows are deleted when a balance drops to zero, so the row count per launch is the holder count.

## Fields

| Field       | Type   | Unit         | Meaning                                              |
| ----------- | ------ | ------------ | ---------------------------------------------------- |
| `launch`    | hex    | address      | Launch token address. Part of the primary key.       |
| `address`   | hex    | address      | Holder. Part of the primary key.                     |
| `balance`   | bigint | 18 decimals  | Current balance. Always greater than zero.           |
| `updatedAt` | bigint | unix seconds | Time of the last transfer that touched this balance. |

Indexes: the primary key `(launch, address)`, `(launch, balance)` for "largest holders", and `address` for "one wallet across launches".

Protocol-owned balances are not holders: the bonding curve (which holds the unsold supply and the LP reserve until graduation), the Uniswap v4 `PoolManager` (which holds the pool's tokens after graduation) and the burn address `0x…dead` are excluded, as is the zero address.

## Examples

Largest holders of a launch:

```graphql theme={"system"}
query Holders($token: String!) {
  holders(where: { launch: $token }, orderBy: "balance", orderDirection: "desc", limit: 100) {
    items { address balance updatedAt }
    totalCount
  }
}
```

`totalCount` here equals `launch.holderCount`.

One wallet's holdings across launches, with enough launch data to value them:

```graphql theme={"system"}
query Portfolio($owner: String!) {
  holders(where: { address: $owner }, orderBy: "balance", orderDirection: "desc", limit: 200) {
    items {
      launch balance
      launchInfo { symbol name currency quoteDecimals lastPriceQuote lastPriceUsd graduated }
    }
  }
}
```

Value of each position in the launch currency is `balance * lastPriceQuote / 1e36`; in USD use `lastPriceUsd`.

Does this wallet hold this token:

```graphql theme={"system"}
{ holder(launch: "0x...", address: "0x...") { balance updatedAt } }
```

`null` means no position.

Holders above a threshold (the value is a string in 18 decimals; this is 1,000,000 tokens):

```graphql theme={"system"}
{
  holders(where: { launch: "0x...", balance_gte: "1000000000000000000000000" }, orderBy: "balance", orderDirection: "desc") {
    items { address balance }
    totalCount
  }
}
```

Share of supply for the top holders, computed client side against the fixed supply of `1e27`:

```javascript theme={"system"}
const SUPPLY = 10n ** 27n;
for (const h of data.holders.items) {
  const bps = (BigInt(h.balance) * 10_000n) / SUPPLY;
  console.log(h.address, `${Number(bps) / 100}%`);
}
```

Nested from the launch:

```graphql theme={"system"}
{
  launch(token: "0x...") {
    symbol holderCount
    holders(orderBy: "balance", orderDirection: "desc", limit: 10) { items { address balance } }
  }
}
```

With `curl`:

```bash theme={"system"}
curl -s https://api.windrose.market/graphql \
  -H 'content-type: application/json' \
  -d '{"query":"query($t:String!){ holders(where:{launch:$t}, orderBy:\"balance\", orderDirection:\"desc\", limit:10){ items { address balance } totalCount } }","variables":{"t":"0x..."}}'
```

## Notes

* Addresses are lowercase in both the rows and the filters. Lowercase a wallet address before querying by it.
* Balances come from `Transfer` events only, so they are exact for the launch tokens. The table does not track Windrose currency (wINR and friends) or dollar balances; read those from the ERC-20 contracts.
* Because rows are deleted at zero, a wallet that sold out disappears from the table rather than showing `0`.
* A launch's `holderCount` is adjusted in the same handler that writes the `holder` row, so the two never drift.
