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

# liquidityLocksV2

> Returns locked liquidity for a pair or token, read from current on-chain state. Vesting is matured at read time, so an expired lock stops counting.

<div data-generated>
  ## GraphQL

  ```
  type Query {
    # Requires a Growth or Enterprise plan.
    liquidityLocksV2(
      pairAddress: String
      tokenAddress: String
      networkId: Int!
      cursor: String
    ): LiquidityLockV2Connection
  }

  enum LiquidityLockProtocol {
    BASECAMP_V1
    UNCX_V2
    UNCX_V3
    BURN
    BITBOND
    METEORA_DAMM_V2
    DOPPLER
    O1_EXCHANGE
    MINARA
    PONS_V2
    METAPLEX_GENESIS
    PINKSALE
    TEAM_FINANCE
    LAUNCH_FAIR
    BAGS
    RAYDIUM_LOCK
    LETSCASH
    PAIR
    LAUNCH_HOOK
    LUNCH_FUN
    LAUNCH_TAX_HOOK
    PEACH
    FOCI
    LIFT
    LONG_SUPPLY
    TOLLY
  }

  type PairLockHolder {
    entityId: String
    displayName: String
    lockProtocol: LiquidityLockProtocol
    amount: String!
    permanent: Boolean!
    unlockAt: String
    shared: Boolean
  }

  type PairLockSummary {
    pairAddress: String!
    networkId: Int!
    liquidityProtocol: String!
    liquidity: String!
    locked: String!
    lockedPercent: Float
    permanentLocked: String!
    vestedLocked: String!
    unlocked: String!
    holders: [PairLockHolder!]!
    nextReleasePoint: String
    updatedAt: Int!
    current: Boolean!
  }

  type LiquidityLockV2Connection {
    items: [PairLockSummary!]!
    cursor: String
  }
  ```
</div>

### Example

<a href="/explore" target="_blank" rel="noopener noreferrer">Test this query in the Explorer →</a>

```graphql theme={null}
{
  liquidityLocksV2(
    pairAddress: "8WwcNqdZjCY5Pt7AkhupAFknV2txca9sq6YBkGzLbvdt"
    networkId: 1399811149
  ) {
    items {
      pairAddress
      networkId
      liquidityProtocol
      liquidity
      locked
      lockedPercent
      permanentLocked
      vestedLocked
      unlocked
      nextReleasePoint
      updatedAt
      current
      holders {
        entityId
        displayName
        lockProtocol
        amount
        permanent
        unlockAt
        shared
      }
    }
    cursor
  }
}
```

### Usage Guidelines

* Query by `pairAddress` for one pool, or by `tokenAddress` for every pool containing that token. `networkId` is required.
* Every result is a read of current on-chain state (the locker's own registry, the launch hook's position, the protocol's lock accounts), not a replay of past lock events. A lock created before Codex indexed a protocol reads the same as one created today.
* `lockedPercent` is 0–100 and is `locked / liquidity` from the same read, so it can never exceed 100. Note that `lockedLiquidityPercentage` on [`liquidityMetadataByToken`](/api-reference/queries/liquiditymetadatabytoken) is 0–1.
* `locked` is `permanentLocked` plus `vestedLocked`. `permanentLocked` is burned LP or a lock with no withdraw path; `vestedLocked` sits behind an unlock date. `unlocked` is everything else, including expired locks.
* Vesting is matured at read time. Once a lock's `unlockAt` passes it moves from `vestedLocked` to `unlocked`, whether or not the LP has been withdrawn from the locker. `nextReleasePoint` is when the next vested tranche matures, in the pool's own clock units (block, slot or seconds depending on the lock). Use `holders[].unlockAt` (unix seconds) for dates.
* `holders` attributes locked liquidity to whoever custodies it. `lockProtocol` is null for custodians the [`LiquidityLockProtocol`](/api-reference/enums/liquiditylockprotocol) enum cannot name, so use `displayName` or `entityId` to identify them. When `shared` is true, several holders name the same liquidity; count it once.
* `updatedAt` is when the state read was taken. Pools are re-read whenever liquidity is added or removed, and reconciled on a six-hour sweep. `current: false` means vesting could not be matured to now and the figures are as of that last refresh.
* Use `cursor` to page through token-level results.

### Coverage

Codex reports a lock only when it can prove it on chain. When a lock cannot be proven, none is reported, so a pool locked through an unverified mechanism shows its liquidity as unlocked rather than unknown. These are the mechanisms read today, across all major EVM networks and Solana:

| Mechanism | How the lock is proven | Where it is read |
| - | - | - |
| Burned LP | LP tokens destroyed or sent to a dead address. Permanent by construction. | Uniswap V2 and every fork (PancakeSwap, Solidly, ...), Pump.fun graduated pools (PumpSwap), Raydium V4 |
| Locker vault | A locker custodies the LP and publishes an unlock date per deposit. Read from the locker's own entries, not its wallet balance, so an expired deposit stops counting even if it is still held. | UNCX (V2 LP and V3 position NFTs), PinkSale, Team Finance, Raydium's lock program (CPMM) |
| Launch-hook custody | The launchpad's Uniswap V4 hook owns the pool position and exposes no way to withdraw it. Each hook is verified against its code and full liquidity history before it is registered. | Doppler, o1 Exchange, Pons, letscash.fun, PAIR, LaunchHook, lunch.fun, LaunchTaxHook, Bags, LaunchFair on Robinhood Chain and Base |
| Position-state lock | The protocol records the lock on the position account itself. Locked positions are summed against every position in the pool, in range or not, so an out-of-range position cannot inflate the share. | Meteora DAMM v2, Orca Whirlpools, Raydium CLMM |
| Vesting buckets | Launch allocations holding LP with an on-chain release schedule. | Metaplex Genesis |

Known gaps: Meteora's original DAMM (v1) lock escrows, and Uniswap V3 positions held by burned or third-party NFTs outside a supported locker. If a launchpad or locker you rely on is missing, [let us know](mailto:hello@codex.io?subject=Liquidity%20Lock%20Coverage) with a pool address and a graduation transaction hash.

### Troubleshooting Tips

<AccordionGroup>
  <Accordion title="How is liquidityLocksV2 different from liquidityLocks?">
    [`liquidityLocks`](/api-reference/queries/liquiditylocks) (deprecated) is event-derived: a lock existed in the data only if Codex decoded the transaction that created it, and nothing was re-checked afterwards, so expired or withdrawn locks kept reporting as locked. `liquidityLocksV2` reads what is locked right now, matures vesting at read time, and returns the locked share directly. Migrate to V2; V1 is retiring with the legacy lock pipeline.
  </Accordion>

  <Accordion title="The locked percentage doesn't match the locker's website.">
    Almost always an expired lock. Lockers show a deposit until it is withdrawn; Codex stops counting it the moment its `unlockAt` passes, because from then on the liquidity can leave at any time. The Codex figure answers "can this liquidity be pulled right now".
  </Accordion>

  <Accordion title="This token is locked but lockedPercent is 0.">
    Either the pool's custodian is one Codex has not verified (an unregistered launchpad hook, a team multisig, an upgradeable lock contract), or the "lock" is a token burn rather than a liquidity lock. A burned token supply is not locked liquidity, and a bonding-curve token has no pool before graduation, so it correctly shows no lock. If the custodian is a launchpad or locker we do not cover yet, [contact us](mailto:hello@codex.io?subject=Liquidity%20Lock%20Coverage) with the pool address; verifying and adding a new custodian is routine.
  </Accordion>

  <Accordion title="Why does a concentrated-liquidity pool show less than 100%?">
    On Uniswap V3/V4, Orca and Raydium CLMM, several providers can hold positions in the same pool. If a launchpad locks its own position and outside providers add theirs, the locked share is genuinely below 100%. The figure is the locked portion of everything currently in the pool, and it is re-read whenever liquidity is added, so a lock measured at launch is diluted as the pool grows.
  </Accordion>

  <Accordion title="Why is lockProtocol null on a holder?">
    `LiquidityLockProtocol` only names some custodians. Others, including several Robinhood Chain launch hooks and burn addresses, are attributed through the registry instead: `entityId` (for example `burn:0x...`) and `displayName` identify them, and `permanent` still tells you whether the lock can ever be withdrawn. For position-state locks such as Orca and Raydium CLMM, `entityId` is null because the position holds itself.
  </Accordion>

  <Accordion title="Are Robinhood Chain launchpad tokens covered?">
    Yes. Robinhood launchpads run on Uniswap V4 hooks, and the verified hooks (Doppler, Pons, o1 Exchange, letscash.fun, PAIR, LaunchHook, lunch.fun, LaunchTaxHook, Bags, LaunchFair) hold the pool position with no withdraw path, so their pools report as permanently locked from graduation onward. Pre-graduation bonding-curve tokens show no lock because there is no pool yet.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.