# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ferra.ag/integration/damm/typescript-sdk/pool.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
