Fetching Positions
This section demonstrates how to fetch liquidity positions on the Storyhunt V3 protocol.
Introduction
This section demonstrates how to fetch liquidity positions on the Storyhunt V3 protocol. Using the NonfungiblePositionManager
contract, you can retrieve all positions associated with an address and fetch detailed data for each position.
Connecting to the NonfungiblePositionManager
Contract
NonfungiblePositionManager
ContractTo interact with the NonfungiblePositionManager
contract, create an ethers.js contract instance:
import { ethers } from 'ethers';
import INONFUNGIBLE_POSITION_MANAGER from '@storyhunt/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json';
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const nfpmContract = new ethers.Contract(
NONFUNGIBLE_POSITION_MANAGER_CONTRACT_ADDRESS,
INONFUNGIBLE_POSITION_MANAGER.abi,
provider
);
Fetching Position IDs
Retrieve all position IDs for a specific address. Start by fetching the number of positions:
const numPositions = await nfpmContract.balanceOf(address);
Iterate through the positions and fetch the IDs:
const calls = [];
for (let i = 0; i < numPositions; i++) {
calls.push(
nfpmContract.tokenOfOwnerByIndex(address, i)
);
}
const positionIds = await Promise.all(calls);
Fetching Position Info
Once you have the position IDs, fetch detailed information for each position using the positions
function:
function positions(
uint256 tokenId
) external view returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
For this example, focus on values needed to interact with positions. Define an interface:
interface PositionInfo {
tickLower: number;
tickUpper: number;
liquidity: JSBI;
feeGrowthInside0LastX128: JSBI;
feeGrowthInside1LastX128: JSBI;
tokensOwed0: JSBI;
tokensOwed1: JSBI;
}
Fetch the position data:
const positionCalls = [];
for (let id of positionIds) {
positionCalls.push(
nfpmContract.positions(id)
);
}
const callResponses = await Promise.all(positionCalls);
Map the RPC response to the PositionInfo
interface:
const positionInfos = callResponses.map((position) => {
return {
tickLower: position.tickLower,
tickUpper: position.tickUpper,
liquidity: JSBI.BigInt(position.liquidity),
feeGrowthInside0LastX128: JSBI.BigInt(position.feeGrowthInside0LastX128),
feeGrowthInside1LastX128: JSBI.BigInt(position.feeGrowthInside1LastX128),
tokensOwed0: JSBI.BigInt(position.tokensOwed0),
tokensOwed1: JSBI.BigInt(position.tokensOwed1),
};
});
You now have an array of PositionInfo
objects containing detailed data for all positions associated with the specified address.