# Get User Positions

List all DLMM position NFTs owned by a specific address, with optional filtering by trading pairs. This method helps track and manage your liquidity portfolio across multiple pools.

### Prerequisites

Before fetching positions:

* Set valid sender address in SDK
* Understand position NFT structure
* Know pair IDs for filtering (optional)

### Basic Usage

```typescript
// Set the address to query
sdk.senderAddress = "0x123...";

// Fetch all positions for the address
const positions = await sdk.Position.getLbPositions([]);

console.log(`Found ${positions.length} positions`);

// Display position details
positions.forEach(position => {
  console.log({
    positionId: position.id,
    pairId: position.pair_id,
    name: position.name,
    description: position.description
  });
});
```

### Method Signature

```typescript
async getLbPositions(pairIds: string[]): Promise<LBPosition[]>
```

#### Parameters

* `pairIds`: Array of pair addresses to filter by (empty array returns all)

#### Returns

Array of `LBPosition` objects:

```typescript
interface LBPosition {
  id: string;              // Position NFT address
  tokenXType: string;      // Token X type
  tokenYType: string;      // Token Y type
  pair_id: string;         // Associated pair address
  name: string;            // NFT name
  description: string;     // NFT description
  url: string;             // NFT image URL
  index: string;           // Position index
  version: string;         // Object version
}
```

### Filtering Positions

#### By Specific Pairs

```typescript
// Only get positions for specific pairs
const ethUsdcPair = "0xabc...";
const suiUsdcPair = "0xdef...";

const filteredPositions = await sdk.Position.getLbPositions([
  ethUsdcPair,
  suiUsdcPair
]);

console.log(`Positions in selected pairs: ${filteredPositions.length}`);
```

#### By Token Types

```typescript
// Get all positions first
const allPositions = await sdk.Position.getLbPositions([]);

// Filter by token type
const usdcPositions = allPositions.filter(pos => 
  pos.tokenXType.includes("USDC") || pos.tokenYType.includes("USDC")
);

// Group by pair
const positionsByPair = allPositions.reduce((acc, pos) => {
  if (!acc[pos.pair_id]) acc[pos.pair_id] = [];
  acc[pos.pair_id].push(pos);
  return acc;
}, {});
```

### Getting Position Details

```typescript
// First get positions list
const positions = await sdk.Position.getLbPositions([]);

// Then get detailed bin data for each
for (const position of positions) {
  // Get the pair
  const pair = await sdk.Pair.getPair(position.pair_id);
  
  // Get bins for this position
  const bins = await sdk.Position.getPositionBins(pair, position.id);
  
  console.log(`Position ${position.id} has ${bins.length} active bins`);
}
```

### Portfolio Analysis

```typescript
// Analyze entire portfolio
const positions = await sdk.Position.getLbPositions([]);

// Get unique pairs
const uniquePairs = [...new Set(positions.map(p => p.pair_id))];
console.log(`Active in ${uniquePairs.length} different pairs`);

// Count by token
const tokenCounts = {};
positions.forEach(pos => {
  tokenCounts[pos.tokenXType] = (tokenCounts[pos.tokenXType] || 0) + 1;
  tokenCounts[pos.tokenYType] = (tokenCounts[pos.tokenYType] || 0) + 1;
});

console.log("Token exposure:", tokenCounts);
```

### Check Position Status

```typescript
const positions = await sdk.Position.getLbPositions([]);

// Check which positions have liquidity
const positionsWithLiquidity = [];
const emptyPositions = [];

for (const position of positions) {
  const pair = await sdk.Pair.getPair(position.pair_id);
  const bins = await sdk.Position.getPositionBins(pair, position.id);
  
  if (bins.length > 0) {
    positionsWithLiquidity.push(position);
  } else {
    emptyPositions.push(position);
  }
}

console.log(`Active: ${positionsWithLiquidity.length}, Empty: ${emptyPositions.length}`);
```

### Common Use Cases

1. **Portfolio Dashboard**: Display all user positions
2. **Position Management**: Find positions to add/remove liquidity
3. **Fee Collection**: Identify positions with claimable fees
4. **Performance Tracking**: Monitor position returns across pairs

### Performance Notes

* Fetches all positions owned by the address
* Uses efficient pagination internally
* Filtered results are processed client-side
* Consider caching for frequent queries

### Error Handling

```typescript
try {
  // Must set sender address first
  sdk.senderAddress = userAddress;
  
  const positions = await sdk.Position.getLbPositions([]);
  
  if (positions.length === 0) {
    console.log("No positions found for this address");
  }
} catch (error) {
  if (error.message.includes("Invalid sender address")) {
    console.error("Please set a valid sender address");
  }
}
```

### Related Topics

* [Open Position](/integration/dlmm/typescript-sdk/position-management/open-position.md) - Create new position NFTs
* [Get Single Position](/integration/dlmm/typescript-sdk/position-management/get-single-position.md) - Detailed position data
* [Get Position Bins](/integration/dlmm/typescript-sdk/position-management/get-position-bins.md) - View liquidity distribution
* [Position Value](/integration/dlmm/typescript-sdk/fees-and-analytics/position-value.md) - Calculate portfolio value


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ferra.ag/integration/dlmm/typescript-sdk/position-management/get-user-positions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
