> For the complete documentation index, see [llms.txt](https://docs.lagoon.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lagoon.finance/developer-hub/integration/get-a-user-position.md).

# Get a user position

There are two independent ways to read a user position. Pick one:

* **On-chain** — call the vault contract directly over RPC. Always up to date, no dependency on Lagoon infrastructure.
* **Lagoon API (GraphQL)** — one query returns the user's positions in every vault on a chain, with USD values.

{% tabs %}
{% tab title="On-chain" %}
Lagoon vaults are based on [ERC7540](https://eips.ethereum.org/EIPS/eip-7540) ; the standard for asynchronous deposits and redemptions in a vault.

7540 is an extension of 4626 that add functions around requests and tweak others like `max` functions and deposit/mint/withdraw/redeem functions.

A user total share balance is the addition of the return of three functions:

* `vault.balanceOf(userAddress);` → ERC20 function
* `vault.maxMint(userAddress);` → shares ready to be claimed (to not be confused with the ERC4626 maxMint function)
* `vault.pendingRedeemRequest(0, userAddress);` → user shares waiting to be redeemed. [Why 0 ?](https://eips.ethereum.org/EIPS/eip-7540#request-ids)
  {% endtab %}

{% tab title="Lagoon API (GraphQL)" %}
Send this query to `https://api.lagoon.finance/query`. It returns every vault position the user holds on the given chain:

```graphql
query GetUserPositions($address: Address!, $chainId: Int!) {
  userByAddress(address: $address, chainId: $chainId) {
    vaultPositions {
      vault { address name symbol }
      state {
        shares
        assets
        usd
        balance
        claimableDeposit { shares }
        pendingRedeem { shares }
      }
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20GetUserPositions%28%24address%3A%20Address%21%2C%20%24chainId%3A%20Int%21%29%20%7B%0A%20%20userByAddress%28address%3A%20%24address%2C%20chainId%3A%20%24chainId%29%20%7B%0A%20%20%20%20vaultPositions%20%7B%0A%20%20%20%20%20%20vault%20%7B%20address%20name%20symbol%20%7D%0A%20%20%20%20%20%20state%20%7B%0A%20%20%20%20%20%20%20%20shares%0A%20%20%20%20%20%20%20%20assets%0A%20%20%20%20%20%20%20%20usd%0A%20%20%20%20%20%20%20%20balance%0A%20%20%20%20%20%20%20%20claimableDeposit%20%7B%20shares%20%7D%0A%20%20%20%20%20%20%20%20pendingRedeem%20%7B%20shares%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query GetUserPositions($address: Address!, $chainId: Int!) { userByAddress(address: $address, chainId: $chainId) { vaultPositions { vault { address name symbol } state { shares assets usd balance claimableDeposit { shares } pendingRedeem { shares } } } } }",
    "variables": { "address": "0xUSER", "chainId": 1 }
  }'
```

For a single vault, pick the entry whose `vault.address` matches.

| Field                       | Meaning                                                  | On-chain equivalent             |
| --------------------------- | -------------------------------------------------------- | ------------------------------- |
| `balance`                   | Shares held in the wallet                                | `balanceOf(user)`               |
| `claimableDeposit.shares`   | Shares ready to be claimed                               | `maxMint(user)`                 |
| `pendingRedeem.shares`      | Shares waiting to be redeemed                            | `pendingRedeemRequest(0, user)` |
| `shares` / `assets` / `usd` | Whole position, including pending and claimable requests | —                               |

More fields (pending deposits, claimable redeems, cancelability) are listed in [Common queries](/developer-hub/lagoon-api/common-queries.md#get-a-users-positions-across-vaults).
{% endtab %}
{% endtabs %}

## Balances without a Transfer to the user

A position rebuilt from Transfer events alone under-reports. These states never emit an ERC-20 Transfer to the user's address:

| State                                | Where the funds sit                                                                                      | How to read the user's amount                                                                                                                                                     |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pending deposit                      | pendingSilo                                                                                              | `pendingDepositRequest(0, user)`                                                                                                                                                  |
| Pending redemption                   | pendingSilo                                                                                              | `pendingRedeemRequest(0, user)`                                                                                                                                                   |
| Settled, shares unclaimed            | Vault                                                                                                    | `maxMint(user)` for the shares; `claimableDepositRequest(0, user)` gives the deposited assets                                                                                     |
| Settled, assets unclaimed            | Vault                                                                                                    | `maxWithdraw(user)` for the assets, net of the exit fee; `claimableRedeemRequest(0, user)` gives the redeemed shares                                                              |
| Pending deposit paid in native value | [pendingSilo](/developer-hub/integration/async-deposit-flow.md#contracts-involved), as the wrapped token | `pendingDepositRequest(0, user)`. No Transfer from the user records it either: only the wrapped token's `Deposit` event to the pendingSilo and the vault's `DepositRequest` event |
