# Position Module

### Data Structures

#### Position

The main NFT struct representing position ownership:

```rust
struct Position has key, store {
    id: UID,                    // Unique identifier
    pool: ID,                   // Associated pool ID
    index: u64,                 // Position index number
    coin_type_a: TypeName,      // First token type
    coin_type_b: TypeName,      // Second token type
    name: String,               // Display name
    description: String,        // Description
    url: String,                // Icon URL
    tick_lower_index: I32,      // Lower tick bound
    tick_upper_index: I32,      // Upper tick bound
    liquidity: u128,            // Current liquidity amount
    lock_until: u64,            // Lock expiration timestamp
}
```

#### PositionInfo

The computational data for position calculations:

```rust
struct PositionInfo has copy, drop, store {
    position_id: ID,            // Corresponding Position NFT ID
    liquidity: u128,            // Active liquidity
    tick_lower_index: I32,      // Lower tick
    tick_upper_index: I32,      // Upper tick
    fee_growth_inside_a: u128,  // Fee growth for token A
    fee_growth_inside_b: u128,  // Fee growth for token B
    fee_owned_a: u64,          // Accumulated fees for token A
    fee_owned_b: u64,          // Accumulated fees for token B
    points_owned: u128,         // Accumulated points
    points_growth_inside: u128, // Points growth tracker
    rewards: vector<PositionReward>, // Multi-token rewards
}
```

#### PositionManager

Central registry managing all positions:

```rust
struct PositionManager has store {
    tick_spacing: u32,              // Tick spacing for the pool
    position_index: u64,            // Next position index
    positions: LinkedTable<ID, PositionInfo>, // Position data storage
}
```

#### PositionReward

Individual reward token tracking:

```rust
struct PositionReward has copy, drop, store {
    growth_inside: u128,    // Growth rate inside position range
    amount_owned: u64,      // Accumulated reward amount
}
```

### Core Functions

#### Position Creation

**`open_position<CoinTypeA, CoinTypeB>`**

Creates a new liquidity position NFT.

**Parameters:**

* `manager`: Mutable reference to PositionManager
* `pool_id`: ID of the target pool
* `pool_index`: Pool's index number
* `icon_url`: URL for position icon
* `tick_lower_index`: Lower bound of liquidity range
* `tick_upper_index`: Upper bound of liquidity range
* `lock_until`: Timestamp until position is locked
* `ctx`: Transaction context

**Returns:** New Position NFT

**Example:**

```rust
let position = position::open_position<USDC, ETH>(
    &mut manager,
    pool_id,
    1,
    string::utf8(b"https://example.com/icon.png"),
    i32::from(-1000),  // Lower tick
    i32::from(1000),   // Upper tick
    0,                 // No lock
    ctx
);
```

#### Liquidity Management

**`increase_liquidity`**

Adds liquidity to an existing position.

**Parameters:**

* `manager`: Mutable reference to PositionManager
* `position`: Mutable reference to Position NFT
* `delta_liquidity`: Amount of liquidity to add
* `fee_growth_inside_a`: Current fee growth for token A
* `fee_growth_inside_b`: Current fee growth for token B
* `points_growth_inside`: Current points growth
* `rewards_growth_inside`: Vector of current reward growth rates

**Returns:** New total liquidity amount

**`decrease_liquidity`**

Removes liquidity from a position.

**Parameters:** Similar to `increase_liquidity` but removes instead of adds **Additional Checks:**

* Validates position is not locked
* Ensures sufficient liquidity exists

#### Fee Management

**`update_fee`**

Updates accumulated fees for a position.

```rust
public(friend) fun update_fee(
    manager: &mut PositionManager,
    position_id: ID,
    fee_growth_a: u128,
    fee_growth_b: u128,
): (u64, u64)
```

**`reset_fee`**

Collects accumulated fees and resets counters.

```rust
public(friend) fun reset_fee(
    manager: &mut PositionManager,
    position_id: ID,
): (u64, u64)
```

### Position Lifecycle

#### 1. Creation

```rust
// Create new position
let position = open_position<TokenA, TokenB>(
    &mut manager, pool_id, pool_index, icon_url, 
    lower_tick, upper_tick, lock_until, ctx
);
```

#### 2. Liquidity Addition

```rust
// Add liquidity
let new_liquidity = increase_liquidity(
    &mut manager, &mut position, liquidity_amount,
    fee_growth_a, fee_growth_b, points_growth, rewards_growth
);
```

#### 3. Fee Collection

```rust
// Collect fees
let (fee_a, fee_b) = update_and_reset_fee(
    &mut manager, position_id, fee_growth_a, fee_growth_b
);
```

#### 4. Liquidity Removal

```rust
// Remove liquidity
let remaining_liquidity = decrease_liquidity(
    &mut manager, &mut position, liquidity_to_remove,
    fee_growth_a, fee_growth_b, points_growth, rewards_growth, clock
);
```

#### 5. Position Closure

```rust
// Close empty position
if (is_empty(&position_info)) {
    close_position(&mut manager, position);
}
```

### Fee and Reward Management

#### Fee Calculation

Fees are calculated using the formula:

```rust
delta_fee = liquidity × (current_growth - last_growth) / 2^64
```

The system tracks fee growth both globally and per position to calculate accumulated fees accurately.

#### Multi-token Rewards

The rewards system supports multiple reward tokens simultaneously:

```rust
// Each position can have multiple rewards
struct PositionReward {
    growth_inside: u128,    // Growth rate inside position's range
    amount_owned: u64,      // Accumulated reward amount
}
```

#### Reward Distribution

Rewards are distributed proportionally based on:

* Position liquidity amount
* Time in range
* Growth rates specific to the position's tick range

### Position Locking

#### Lock Mechanism

Positions can be locked until a specific timestamp to prevent premature liquidity removal:

```rust
// Lock position until timestamp
lock_position(&mut position, lock_until_timestamp);

// Check lock status
let lock_time = get_lock_until(&position);
```

#### Lock Validation

When decreasing liquidity, the system validates:

```rust
let current_time = clock::timestamp_ms(clock);
assert!(position.lock_until <= current_time, 11);
```

### API Reference

#### Query Functions

**Position Information**

* `liquidity(position: &Position): u128` - Get position liquidity
* `tick_range(position: &Position): (I32, I32)` - Get tick range
* `pool_id(position: &Position): ID` - Get associated pool ID
* `index(position: &Position): u64` - Get position index

**Position Info Queries**

* `info_liquidity(info: &PositionInfo): u128` - Get liquidity from info
* `info_fee_owned(info: &PositionInfo): (u64, u64)` - Get accumulated fees
* `info_points_owned(info: &PositionInfo): u128` - Get accumulated points
* `info_rewards(info: &PositionInfo): &vector<PositionReward>` - Get rewards

**Manager Queries**

* `is_position_exist(manager: &PositionManager, id: ID): bool` - Check if position exists
* `fetch_positions(manager: &PositionManager, start: vector<ID>, limit: u64): vector<PositionInfo>` - Get multiple positions

#### Validation Functions

**`check_position_tick_range`**

Validates tick range parameters:

* `tick_lower < tick_upper`
* Ticks within valid bounds
* Ticks align with tick spacing

**`is_empty`**

Checks if position can be closed:

* Zero liquidity
* No accumulated fees
* No pending rewards

### Examples

#### Complete Position Lifecycle Example

```rust
// 1. Create position manager
let manager = position::new(10, ctx); // 10 tick spacing

// 2. Open new position
let position = position::open_position<USDC, ETH>(
    &mut manager,
    pool_id,
    1,
    string::utf8(b"https://example.com/icon.png"),
    i32::from(-100),   // Lower tick
    i32::from(100),    // Upper tick
    0,                 // No lock
    ctx
);

// 3. Add liquidity
let liquidity_added = position::increase_liquidity(
    &mut manager,
    &mut position,
    1000000, // 1M liquidity units
    fee_growth_a,
    fee_growth_b,
    points_growth,
    rewards_growth
);

// 4. Later: collect fees
let (fee_a, fee_b) = position::update_and_reset_fee(
    &mut manager,
    object::id(&position),
    new_fee_growth_a,
    new_fee_growth_b
);

// 5. Remove some liquidity
let remaining = position::decrease_liquidity(
    &mut manager,
    &mut position,
    500000, // Remove 500K liquidity
    fee_growth_a,
    fee_growth_b,
    points_growth,
    rewards_growth,
    clock
);

// 6. Check if position can be closed
let position_info = position::borrow_position_info(
    &manager, 
    object::id(&position)
);
if (position::is_empty(position_info)) {
    position::close_position(&mut manager, position);
}
```

#### Batch Position Query Example

```rust
// Query multiple positions
let positions = position::fetch_positions(
    &manager,
    vector::empty<ID>(), // Start from beginning
    10                   // Limit to 10 positions
);

// Process each position
let i = 0;
while (i < vector::length(&positions)) {
    let pos_info = vector::borrow(&positions, i);
    let liquidity = position::info_liquidity(pos_info);
    let (fee_a, fee_b) = position::info_fee_owned(pos_info);
    // Process position data...
    i = i + 1;
}
```

### Best Practices

#### Position Management

1. **Always validate tick ranges** before creating positions
2. **Check lock status** before attempting to decrease liquidity
3. **Update fees and rewards** before liquidity changes
4. **Use batch queries** for efficient data retrieval

#### Error Handling

The module uses various assertion codes:

* `1`: Fee overflow in token A/B
* `2`: Reward overflow
* `3`: Points overflow
* `5`: Invalid tick range
* `6`: Position not found
* `7`: Cannot close non-empty position
* `8`: Liquidity addition overflow
* `9`: Insufficient liquidity to remove
* `10`: Invalid reward index
* `11`: Position is locked

#### Gas Optimization

* Use `fetch_positions` for batch operations
* Combine fee updates with liquidity changes
* Close empty positions to free storage

### Security Considerations

1. **Position Ownership**: Only the NFT holder can modify the position
2. **Tick Validation**: All tick ranges are validated for correctness
3. **Overflow Protection**: All arithmetic operations include overflow checks
4. **Lock Enforcement**: Locked positions cannot have liquidity decreased
5. **Access Control**: Critical functions are `friend`-only

This documentation provides a comprehensive guide to the Ferra CLMM Position Management system. For additional technical details, refer to the source code and inline comments.
