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

// 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

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

Parameters

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

Returns

Array of LBPosition objects:

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

// 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

// 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

// 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

// 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

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

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");
  }
}

Last updated