> For the complete documentation index, see [llms.txt](https://docs.ferra.ag/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ferra.ag/integration/damm/typescript-sdk/pool.md).

# Pool

### Table of Contents

* Get Pools
* Fetch Ticks
* Pool Transaction History
* Create Pool

***

### Get Pools

Retrieve pool information from the Ferra DAMM protocol.

#### Overview

The SDK provides multiple methods to fetch pool data, from basic immutable info to complete pool state with real-time data.

#### Quick Start

```typescript
import { dammMainnet, initFerraSDK } from '@ferra-labs/damm'

// Initialize SDK
const sdk = initFerraSDK({
  network: 'beta',
  fullNodeUrl: 'https://...',
  wallet: '0x...'
})

// Get a single pool
const pool = await sdk.Pool.getPool('0x...')

// Get multiple pools
const pools = await sdk.Pool.getPools()
```

#### Get Single Pool

Fetch complete pool data with current state:

```typescript
const poolId = '0x...'
const pool = await sdk.Pool.getPool(poolId)

console.log({
  address: pool.poolAddress,
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB,
  currentPrice: pool.currentSqrtPrice,
  currentTick: pool.currentTickIndex,
  liquidity: pool.liquidity,
  feeRate: pool.feeRate,
  tvlA: pool.coinAmountA,
  tvlB: pool.coinAmountB
})
```

#### Get Multiple Pools

**Basic Usage**

```typescript
// Get first 10 pools
const pools = await sdk.Pool.getPools([], 0, 10)

// Get specific pools
const poolIds = ['0x...', '0x...']
const pools = await sdk.Pool.getPools(poolIds)
```

**With Pagination**

```typescript
// Advanced pagination
const result = await sdk.Pool.getPoolsWithPage(
  [],           // Pool IDs (empty = all)
  {             // Pagination args
    limit: 20,
    cursor: nextCursor
  }
)
```

#### Get Pool Immutables

Lightweight method for basic pool info:

```typescript
// Get pool addresses and coin types only
const poolInfos = await sdk.Pool.getPoolImmutables()

poolInfos.forEach(info => {
  console.log({
    pool: info.poolAddress,
    coinA: info.coinTypeA,
    coinB: info.coinTypeB,
    tickSpacing: info.tickSpacing
  })
})
```

#### Pool Data Structure

```typescript
type Pool = {
  // Pool identity
  poolType: string
  poolAddress: string
  coinTypeA: string
  coinTypeB: string
  tickSpacing: string

  // Current state
  currentSqrtPrice: bigint
  currentTickIndex: number
  liquidity: number
  isQuoteY: boolean
  collectFeeMode: number

  // TVL
  coinAmountA: bigint
  coinAmountB: bigint

  // Fee config
  feeRate: number
  feeGrowthGlobalA: number
  feeGrowthGlobalB: number
  feeProtocolCoinA: number
  feeProtocolCoinB: number

  // Parameters
  parameters: {
    currentSqrtPrice: bigint
    currentTickIndex: number
    tickLowerIndex: number
    tickUpperIndex: number
    activationTimestamp: bigint
    feeRate: number
    tickSpacing: number
    enabledDynamicFee: boolean
    enabledFeeScheduler: boolean
    // ... more dynamic fee params
  }

  // Rewarders
  rewarderInfos: Rewarder[]
  rewarderLastUpdatedTime: string

  // Internal handles
  ticksHandle: string
  positionManager: {
    positionsHandle: string
    size: number
  }

  // Other
  index: number
  isPause: boolean
  uri: string
  name: string
}
```

#### Filtering Pools

**By Coin Types**

```typescript
// Get all pools
const allPools = await sdk.Pool.getPools()

// Filter by coin pair
const suiUsdcPools = allPools.filter(pool =>
  (pool.coinTypeA.includes('sui') && pool.coinTypeB.includes('usdc')) ||
  (pool.coinTypeA.includes('usdc') && pool.coinTypeB.includes('sui'))
)
```

#### Real-time Updates

```typescript
// Force refresh for latest data
const pool = await sdk.Pool.getPool(poolId, true)

// Auto-refresh example
setInterval(async () => {
  const freshPool = await sdk.Pool.getPool(poolId, true)
  updateUI(freshPool)
}, 5000) // Every 5 seconds
```

#### Error Handling (Get Pools)

```typescript
try {
  const pool = await sdk.Pool.getPool(poolId)
} catch (error) {
  if (error.code === 'InvalidPoolObject') {
    console.error('Pool not found')
  }
}
```

***

### Fetch Ticks

Retrieve tick data from a pool. Two methods available:

#### fetchTicksByRpc (Recommended)

Fetches active ticks directly from the pool's tick manager. Faster and recommended for most use cases:

```typescript
const pool = await sdk.Pool.getPool(poolId)

const ticks = await sdk.Pool.fetchTicksByRpc(pool.ticksHandle)

ticks.forEach(tick => {
  console.log({
    index: tick.index,
    liquidityGross: tick.liquidityGross.toString(),
    liquidityNet: tick.liquidityNet.toString()
  })
})
```

#### fetchTicks (Event-based)

Fetches ticks from on-chain events. More comprehensive but slower:

```typescript
const ticks = await sdk.Pool.fetchTicks({
  pool_id: poolId,
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB
})
```

#### When to Use Which

| Method            | Speed  | Data                 | Use Case                        |
| ----------------- | ------ | -------------------- | ------------------------------- |
| `fetchTicksByRpc` | Fast   | Active ticks only    | Swap calculations, price impact |
| `fetchTicks`      | Slower | All historical ticks | Full tick analysis              |

***

### Pool Transaction History

Get transaction history for a pool (swaps, liquidity changes, fee collections):

```typescript
const history = await sdk.Pool.getPoolTransactionList({
  poolId: '0x...',
  paginationArgs: { limit: 20 },
  order: 'descending'   // 'ascending' | 'descending'
})

history.data.forEach(tx => {
  console.log({
    type: tx.type,        // 'swap' | 'addLiquidity' | 'removeLiquidity' | ...
    timestamp: tx.timestamp,
    digest: tx.digest
  })
})

// Pagination
if (history.hasNextPage) {
  const nextPage = await sdk.Pool.getPoolTransactionList({
    poolId: '0x...',
    paginationArgs: { limit: 20, cursor: history.nextCursor }
  })
}
```

#### Custom RPC URL

Use a different RPC for history queries (useful for archive nodes):

```typescript
const history = await sdk.Pool.getPoolTransactionList({
  poolId: '0x...',
  paginationArgs: { limit: 50 },
  fullRpcUrl: 'https://archive-rpc.example.com'
})
```

***

### Create Pool

Create a new DAMM pool with initial liquidity in a single transaction. The SDK automatically handles coin type ordering according to protocol requirements.

#### Prerequisites

* Valid sender address configured in SDK
* Sufficient balance of both tokens
* Token metadata (required)

#### Quick Start

```typescript
import { initFerraSDK, TickMath, DammPoolUtil, d } from '@ferra-labs/damm'
import BN from 'bn.js'

// Initialize SDK
const sdk = initFerraSDK({
  network: 'beta',
  fullNodeUrl: 'https://...',
  wallet: '0x...'
})

sdk.senderAddress = keypair.toSuiAddress()

const coin_type_a = '0x...::usdc::USDC'
const coin_type_b = '0x2::sui::SUI'
const tick_spacing = 2

// Calculate initial sqrt price (e.g., 1.2 price)
const initialize_sqrt_price = TickMath.priceToSqrtPriceX64(d(1.2), 6, 6).toString()
const current_tick_index = TickMath.sqrtPriceX64ToTickIndex(new BN(initialize_sqrt_price))

// Build tick range
const tick_lower = TickMath.getPrevInitializableTickIndex(
  new BN(current_tick_index).toNumber(),
  new BN(tick_spacing).toNumber()
)
const tick_upper = TickMath.getNextInitializableTickIndex(
  new BN(current_tick_index).toNumber(),
  new BN(tick_spacing).toNumber()
)

// Input token amount
const fix_coin_amount = new BN(200)
const fix_amount_a = true
const slippage = 0.05
const cur_sqrt_price = new BN(initialize_sqrt_price)

// Estimate liquidity and token amounts
const liquidityInput = DammPoolUtil.estLiquidityAndcoinAmountFromOneAmounts(
  tick_lower,
  tick_upper,
  fix_coin_amount,
  fix_amount_a,
  true,
  slippage,
  cur_sqrt_price
)

const amount_a = fix_amount_a ? fix_coin_amount.toNumber() : liquidityInput.tokenMaxA.toNumber()
const amount_b = fix_amount_a ? liquidityInput.tokenMaxB.toNumber() : fix_coin_amount.toNumber()

// Get coin metadata (required)
const coinMetadataA = (await sdk.fullClient.getCoinMetadata({ coinType: coin_type_a }))!
const coinMetadataB = (await sdk.fullClient.getCoinMetadata({ coinType: coin_type_b }))!

// Create pool with initial liquidity
const tx = await sdk.Pool.createPoolTransactionPayload({
  tick_spacing: tick_spacing,
  initialize_sqrt_price: cur_sqrt_price.toString(),
  uri: '',
  fix_amount_a: fix_amount_a,
  amount_a: amount_a,
  amount_b: amount_b,
  coinTypeA: coin_type_a,
  coinTypeB: coin_type_b,
  slippage: slippage,
  metadata_a: coinMetadataA.id!,
  metadata_b: coinMetadataB.id!,
  tick_lower: tick_lower,
  tick_upper: tick_upper,
  // Advanced options
  activation_timestamp: Date.now() + 10000,  // Optional: delayed activation
  collect_fee_mode: 0,
  enable_dynamic_fee: true,
  enable_fee_scheduler: true,
  fee_scheduler_mode: 0,
  is_quote_y: false,
})

const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: await tx.build({ client: sdk.fullClient }),
  signer: keypair
})

console.log('Pool created:', result)
```

#### Parameters

| Parameter               | Type             | Required | Description                            |
| ----------------------- | ---------------- | -------- | -------------------------------------- |
| coinTypeA               | string           | ✓        | Type of coin A                         |
| coinTypeB               | string           | ✓        | Type of coin B                         |
| tick\_spacing           | number           | ✓        | Tick spacing (determines fee tier)     |
| initialize\_sqrt\_price | string           | ✓        | Initial sqrt price                     |
| uri                     | string           | ✓        | Pool URI (metadata)                    |
| amount\_a               | number \| string | ✓        | Amount of token A                      |
| amount\_b               | number \| string | ✓        | Amount of token B                      |
| fix\_amount\_a          | boolean          | ✓        | Whether to fix token A amount          |
| slippage                | number           | ✓        | Slippage tolerance (0.05 = 5%)         |
| collect\_fee\_mode      | number           | ✓        | Fee collection mode                    |
| is\_quote\_y            | boolean          | ✓        | Whether coin Y is the quote currency   |
| fee\_scheduler\_mode    | number           | ✓        | Fee scheduler mode                     |
| enable\_fee\_scheduler  | boolean          | ✓        | Enable fee scheduler                   |
| enable\_dynamic\_fee    | boolean          | ✓        | Enable dynamic fee                     |
| activation\_timestamp   | number           | ✓        | Timestamp for pool activation          |
| tick\_lower             | number           |          | Lower tick boundary (default: -443636) |
| tick\_upper             | number           |          | Upper tick boundary (default: 443636)  |
| metadata\_a             | string           |          | Coin metadata ID for coin A            |
| metadata\_b             | string           |          | Coin metadata ID for coin B            |

#### Get Available Fee Tiers

```typescript
// Get all available fee tiers
const feeTiers = await sdk.Pool.getBaseFeesAvailable()

feeTiers.forEach(tier => {
  console.log(`Tick spacing: ${tier.tick_spacing}`)
  console.log(`Fee rate: ${tier.fee_rate / 10000000}%`)
  console.log(`Dynamic fee enabled: ${tier.dynamic_fee !== null}`)
  console.log(`Fee scheduler:`, tier.fee_scheduler)
})
```

#### Price Calculation

Calculate initial sqrt price:

```typescript
import { TickMath, d } from '@ferra-labs/damm'
import BN from 'bn.js'

// Convert price to sqrt price
const price = 1.5 // 1 tokenA = 1.5 tokenB
const decimalsA = 9
const decimalsB = 6

const sqrtPrice = TickMath.priceToSqrtPriceX64(d(price), decimalsA, decimalsB)
console.log('Sqrt price:', sqrtPrice.toString())

// Get tick index from sqrt price
const tickIndex = TickMath.sqrtPriceX64ToTickIndex(new BN(sqrtPrice.toString()))
console.log('Tick index:', tickIndex)
```

#### Tick Spacing Guide

| Tick Spacing | Fee Tier | Use Case                 |
| ------------ | -------- | ------------------------ |
| 1            | \~0.01%  | Stable pairs (USDC/USDT) |
| 2            | \~0.02%  | Low volatility pairs     |
| 10           | \~0.05%  | Correlated pairs         |
| 60           | \~0.30%  | Most pairs               |
| 200          | \~1.00%  | Exotic/volatile pairs    |

#### Error Handling (Create Pool)

```typescript
try {
  const tx = await sdk.Pool.createPoolTransactionPayload(params)
  // Execute transaction
} catch (error) {
  if (error.code === 'InvalidSendAddress') {
    // Set sender address
    sdk.senderAddress = '0x...'
  }
  // Other error codes: InvalidConfig, InvalidPoolObject
}
```

#### Important Notes

* Coin types are automatically sorted according to protocol rules
* The SDK handles coin selection from your wallet
* Remaining coins are automatically returned to sender
* Pool creation includes initial liquidity position (NFT)
