# LP wallets

`GET https://api.getchord.xyz/v1/chains/solana/lp/top`

Source: https://getchord.xyz/docs/api-reference/operations/sollptop/

Wallets ranked over the LP positions active in the window: `fees` (claimed, default), `deposits` or `pnl` (realized). Many leaders are vaults and rebalancing bots; a short window is not a track record. Cached 60 seconds.

The board is **fee-checked**: a wallet whose realized profit is positive while the fees it claimed are under a tenth of that profit earned on the token's price (in practice one-sided liquidity on a token it launched) and is left out; `hidden` counts them. A launchpad account (500 or more positions with a pool of its own for at least every second one: the liquidity of what a launchpad launched) is left out with them; `operators` counts those. `all=1` keeps both in.

Liquidity on Solana from Chord's own tape: adds, removes, fee claims, position opens and closes, decoded from the same blocks as the swaps. No key needed.

- **Venues.** Meteora DLMM, Meteora DAMM v2, Raydium CLMM and PumpSwap. Orca Whirlpools, Raydium CPMM / v4 and Meteora dynamic pools are not read yet.
- **Since.** `since` is when LP decoding started (2026-10-06 15:53 UTC); windows never start before it. A position opened earlier is `partial: true` and carries no PnL.
- **Fees are claimed fees.** An LP's fees appear when it claims them, so a window's fees understate what the pool earned, and one claim can hold days of fees.
- **Positions.** One row per position account (DLMM / DAMM v2 position, Raydium CLMM position NFT, PumpSwap LP token account), rebuilt from all its events. `lower` / `upper` are DLMM bin ids or Raydium CLMM ticks; null = full range. Realized PnL = withdrawn + fees claimed − deposited, only for a position seen from its open to its close with every amount priced. An open position's current value is not in the events: none is given.
- **Amounts** are whole tokens in the pool's own order (`mintA` / `mintB`); USD is valued when the event happened. Each add / remove / claim is checked against the pool vaults' balance changes in the same transaction (`verified`).
- **Addresses** are base58 and case-sensitive, as on the other Solana routes.

## Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `sort` | query | no | `fees` · `deposits` · `pnl` · `win_rate` · `ev` · `positions` · `avg_age` · `last_activity` (default `fees`) |  |
| `unit` | query | no | `usd` · `native` (default `usd`) | `native` = the money fields of the answer in SOL: every deposit, withdrawal and claimed fee converted at the SOL price of its own minute, so a wallet that put SOL in and took the same SOL out reads flat whatever SOL did in dollars (win rate and expected value follow the unit). The fields keep their `…Usd` names; `unit` and `unitSymbol` in the answer say what they carry. `503 UNIT_NOT_READY` while positions are being folded again; another value is `400 BAD_UNIT`. |
| `limit` | query | no | integer (default `50`) |  |
| `hours` | query | no | integer (default `24`) | Window in hours, never before `since`. |
| `all` | query | no | `0` · `1` | 1 = keep the wallets the fee check and the launchpad rule leave out. |

## Response 200

Example (captured from the live API):

```json
{
  "chain": "solana",
  "sort": "fees",
  "windowHours": 24,
  "since": 1791750117,
  "feeChecked": true,
  "hidden": 235,
  "operators": 2,
  "rows": [
    {
      "wallet": "6sWm5C5E25mZD98z7RAZZCqetT3rjWuLXRZsmimg6KEK",
      "positions": 1,
      "open": 1,
      "pools": 1,
      "depositedUsd": 0,
      "withdrawnUsd": 0,
      "feesClaimedUsd": 225969.36547100003,
      "realizedPnlUsd": null,
      "realizedPositions": 0,
      "winRate": null,
      "evUsd": null,
      "avgAgeHours": 74.6913888888889,
      "avgDepositUsd": null,
      "firstTs": 1791567628,
      "lastTs": 1791818882
    },
    {
      "wallet": "9SgR9w7ii7ZofZ5kgyb7hUwRVAkqRApdTZWcx4gsssCb",
      "positions": 2,
      "open": 2,
      "pools": 1,
      "depositedUsd": 0,
      "withdrawnUsd": 0,
      "feesClaimedUsd": 94307.16837727133,
      "realizedPnlUsd": null,
      "realizedPositions": 0,
      "winRate": null,
      "evUsd": null,
      "avgAgeHours": null,
      "avgDepositUsd": null,
      "firstTs": 1791429320,
      "lastTs": 1791791319
    }
  ],
  "updatedAt": 1791836517
}
```

- **400**: `BAD_LIMIT` / `BAD_HOURS` / `BAD_SORT` / `BAD_ALL`, or `UNSUPPORTED_CHAIN` (Solana is not public on this deployment and the request has no `X-API-Key`).
- **429**: Over the per-minute limit (`RATE_LIMIT_EXCEEDED`). Read `X-RateLimit-Reset` and back off.
- **503**: `CHAIN_DATA_UNAVAILABLE` (the Solana store did not answer in time) or `CHAIN_NOT_ENABLED` (the lane is off on this deployment). Retry later; do not treat it as an empty answer.
