---
description: This section introduces liquidity positions in Storyhunt V3
---

# Liquidity Positions

### **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.

$$1.0001^{200} = 1.0202$$ or $$2.02$$%



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:**

```typescript
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()`:**

```typescript
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()`:**

```typescript
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:

```typescript
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:

```typescript
const { calldata, value } = NonfungiblePositionManager.removeCallParameters(
  currentPosition,
  removeLiquidityOptions
);
```

### **Collecting Fees**

To collect fees accrued by a position, use the `collectCallParameters` method:

```typescript
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](minting-a-position) or modifying existing ones.
