> ## Documentation Index
> Fetch the complete documentation index at: https://build.flashnet.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating Locks

> Set or extend a lock

Call `lockPosition` on the `FlashnetClient` with a pool ID, a `lockUntilTimestamp` string, and, for V3 positions, the tick range.

## Signature

```typescript theme={null}
await client.lockPosition(
  poolId: string,
  lockUntilTimestamp: string,     // Unix seconds; "0" = indefinite
  opts?: {
    tickLower?: number;           // V3 only
    tickUpper?: number;           // V3 only
  }
): Promise<LockPositionResponse>;
```

The timestamp must parse as a non-negative integer at or below `"4102444800"` (2100-01-01 UTC). Pass `"0"` for an indefinite lock.

## Create a bounded lock

### V2

```typescript theme={null}
// Lock a V2 LP position for 30 days
const thirtyDays = Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60;

const response = await client.lockPosition(
  poolId,
  String(thirtyDays)
);

console.log("Accepted:", response.accepted);
console.log("Expires at:", response.lockUntilTimestamp);
console.log("Indefinite:", response.isIndefinite);   // false
```

Omit `tickLower` and `tickUpper` for V2 positions. The server scopes the lock to the entire LP share owned by the caller's public key in that pool.

### V3

```typescript theme={null}
// Lock a V3 position at a specific tick range
const response = await client.lockPosition(
  poolId,
  "1793836800",   // 2026-11-04 UTC
  { tickLower: -69080, tickUpper: -66850 }
);
```

Both `tickLower` and `tickUpper` are required together for V3. The tick pair must match an existing position owned by the caller. Supplying only one of the two is rejected.

## Create an indefinite lock

```typescript theme={null}
// V2
await client.lockPosition(poolId, "0");

// V3
await client.lockPosition(poolId, "0", { tickLower, tickUpper });
```

An indefinite lock cannot be converted to a bounded duration. Use `"0"` only when the hold has no planned release.

## Extend an existing lock

Call `lockPosition` again with a later timestamp (or `"0"`). The server updates the record in place.

```typescript theme={null}
const now = Math.floor(Date.now() / 1000);

// Initial lock: 30 days
await client.lockPosition(poolId, String(now + 30 * 86400));

// Later: extend to 90 days
await client.lockPosition(poolId, String(now + 90 * 86400));
```

## Rules on modification

* A new bounded timestamp must be greater than or equal to the existing one.
* A bounded lock can be converted to indefinite by passing `"0"`.
* An indefinite lock (`"0"`) cannot be converted back to bounded.
* Any request that would shorten the lock is rejected without state changes.

## Error handling

The SDK throws when the server rejects a request. Common rejections:

* **Position not found.** The `(poolId, owner, tickLower, tickUpper)` tuple does not match a live position owned by the caller.
* **Shortening attempted.** The requested timestamp is earlier than the existing lock.
* **Invalid timestamp.** The string does not parse as a non-negative integer at or below `4102444800`.

```typescript theme={null}
import { isFlashnetError } from "@flashnet/sdk";

try {
  await client.lockPosition(poolId, "1793836800", { tickLower, tickUpper });
} catch (error) {
  if (isFlashnetError(error)) {
    console.error(error.errorCode, error.userMessage);
  }
  throw error;
}
```

## Next steps

* [Read lock state](/products/flashnet-amm/lock-query)
* [Position locks overview](/products/flashnet-amm/lock-overview)
