Liquidity Positions
This section introduces liquidity positions in Storyhunt V3
Introduction
This section introduces liquidity positions in Storyhunt V3 and provides an overview of the SDK classes and contracts used to interact with the protocol. The focus is on the Position
and NonfungiblePositionManager
classes, as well as the NonfungiblePositionManager
contract.
At the end, you will understand the core classes for interacting with liquidity positions and learn how to fetch positions from the NonfungiblePositionManager
contract.
Prerequisites
To understand liquidity positions, itโs essential to grasp the concept of concentrated liquidity, ticks, and how they influence liquidity provisioning in Storyhunt V3.
Concentrated Liquidity
Storyhunt V3 pools use concentrated liquidity, allowing liquidity providers to focus their liquidity in specific price ranges. This approach increases capital efficiency compared to traditional models by enabling larger trades with less price impact. Liquidity providers can specify the price range for their liquidity.
Ticks
Ticks define the boundaries of discrete price ranges. Each tick represents a price change of 0.01% from the previous tick. Pools have a tickSpacing
value that determines which ticks are usable, based on the poolโs fee tier. Higher fees result in larger tick spacings.
or %
For example, a pool with a 1% fee and a tickSpacing
of 200 means the price difference between initializable ticks is approximately 2.02%.
Liquidity Positions
When liquidity is added to a pool, a liquidity position is created. This position includes the amount of liquidity and the start and end ticks (price range) of the position. Positions outside the poolโs current price range result in single-sided liquidity, where only one token is added to the pool.
Position Class
The Position
class is used to create local representations of on-chain positions and to generate calldata for on-chain transactions such as minting or modifying a position.
Constructing a Position
Using the Constructor:
import { Pool, Position } from '@storyhunt/v3-sdk';
import JSBI from 'jsbi';
const pool = new Pool(...);
const tickLower = -100;
const tickUpper = 200;
const liquidity = JSBI.BigInt('1000000000000000000');
const position = new Position({
pool,
liquidity,
tickLower,
tickUpper,
});
Using fromAmounts()
:
import { BigIntish } from '@storyhunt/sdk-core';
const amount0 = '1000000000000000000';
const amount1 = JSBI.BigInt('1000000000000000000');
const useFullPrecision = true;
const position = Position.fromAmounts({
pool,
tickLower,
tickUpper,
amount0,
amount1,
useFullPrecision,
});
Using fromAmount0()
or fromAmount1()
:
const amount0 = '1000000000000000000';
const singleSidePositionToken0 = Position.fromAmount0({
pool,
tickLower,
tickUpper,
amount0,
useFullPrecision,
});
const amount1 = 100000000;
const singleSidePositionToken1 = Position.fromAmount1({
pool,
tickLower,
tickUpper,
amount1,
useFullPrecision,
});
The tick values must match the poolโs initializable ticks, and the wallet must hold sufficient tokens to cover the position.
NonfungiblePositionManager
The NonfungiblePositionManager
class is primarily used to create calldata for functions on the NonfungiblePositionManager
contract.
Creating a Position
To create a position in a pool, use the mint
function on the contract. The SDK class provides the addCallParameters
method to generate the necessary calldata:
import { MintOptions, NonfungiblePositionManager } from '@storyhunt/v3-sdk';
const mintOptions: MintOptions = {
recipient: address,
deadline: Math.floor(Date.now() / 1000) + 60 * 20,
slippageTolerance: new Percent(50, 10_000),
};
const { calldata, value } = NonfungiblePositionManager.addCallParameters(
positionToMint,
mintOptions
);
Modifying a Position
To adjust a position, use the removeCallParameters
for decreasing liquidity or addCallParameters
for increasing liquidity:
const { calldata, value } = NonfungiblePositionManager.removeCallParameters(
currentPosition,
removeLiquidityOptions
);
Collecting Fees
To collect fees accrued by a position, use the collectCallParameters
method:
const { calldata, value } =
NonfungiblePositionManager.collectCallParameters(collectOptions);
Next Steps
Now that you understand the key classes and contracts for managing liquidity positions, you can proceed to explore advanced functionality such as minting new positions or modifying existing ones.