> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powfi.alephium.org/llms.txt
> Use this file to discover all available pages before exploring further.

# 流动性与池工具

> 用于头寸数学的 ClmmLiquidityUtils，以及用于头寸 ID 和离线兑换模拟的 PoolUtils。

export const VersionBanner = ({network = 'mainnet', products = [], lang = 'en'}) => {
  const SDK_VERSION = '1.0.2';
  const ADDRESSES = {
    mainnet: {
      cpmm: {
        Router: 'ze15rnAwTyVCPnDhN7J8An3SvNeWBsZHAVMeBx1ehXeP',
        TokenPairFactory: '24CXRLvj1QiDH6riwr1EPERG7BcduHKZtktygbq97MfYb'
      },
      clmm: {
        PoolFactory: '24gqd4DMQXVzjm5QDAGxUtYupx3WM2PSu3vZUseuBCV9h',
        PositionManager: 'vFyKSqnJHS9MicrojBcLgztyRFqhS4hB349Ci3LJCELw'
      },
      staking: {
        XAlphToken: '225WevmFp5ZgzPsyVJTvyp2v2uyKrvp329HfrVmzffnWj',
        RewardFeeCollector: '22CE7vG6u64zjjsLZLxeJqQuPDydjPvbP9iG1d861j2G7'
      }
    },
    testnet: {
      cpmm: {
        Router: 'xaueT8kPMvpnaFJEfHv6CJLgqsSPpoNmHjF1QgTxoF9R',
        TokenPairFactory: '29hdd9b9Gp7oXuamwHKfUqBaRXP487HoeTcutS3RhZJEj'
      },
      clmm: {
        PoolFactory: 'z2QFT7qBQrfm8UwAYG3VHWoHs7B56ZDFNdSCcDu5j53m',
        PositionManager: '21p6egW8d6FEyVVuH17WqvHCARsCsD61GcBmeCr75XdGT'
      },
      staking: {
        XAlphToken: '23psDicimC5VdpM56wrgqgCzQzcyXWGCkQGSYWbtZAPRq',
        RewardFeeCollector: '29qQ1LPJ5uqawRviXLVDMeo19JUygRrNNTQy5RUBh817D'
      }
    }
  };
  const EXPLORERS = {
    mainnet: 'https://explorer.alephium.org/addresses/',
    testnet: 'https://testnet.alephium.org/addresses/'
  };
  const LABELS = {
    en: {
      sdk: 'SDK',
      network: 'Network',
      contracts: 'Contracts',
      all: 'All addresses',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: 'Local deployment (addresses vary per devnet)'
    },
    zh: {
      sdk: 'SDK 版本',
      network: '网络',
      contracts: '合约',
      all: '全部地址',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: '本地部署（每个 devnet 的地址不同）'
    },
    fr: {
      sdk: 'SDK',
      network: 'Réseau',
      contracts: 'Contrats',
      all: 'Toutes les adresses',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: 'Déploiement local (adresses propres à chaque devnet)'
    }
  };
  const t = LABELS[lang] ?? LABELS.en;
  const contractsPage = lang === 'en' ? '/reference/contracts' : `/${lang}/reference/contracts`;
  const short = a => `${a.slice(0, 6)}…${a.slice(-4)}`;
  const entries = [];
  const addrs = ADDRESSES[network];
  if (addrs) {
    for (const p of products) {
      for (const [name, address] of Object.entries(addrs[p] ?? ({}))) entries.push({
        name,
        address
      });
    }
  }
  let contractsCell;
  if (network === 'devnet' && products.length > 0) {
    contractsCell = <span>{t.devnet}</span>;
  } else if (entries.length > 0) {
    contractsCell = entries.map(({name, address}, i) => <span key={name}>
        {i > 0 && <span className="mx-1 opacity-50">·</span>}
        {name}{' '}
        <a href={EXPLORERS[network] + address} target="_blank" rel="noreferrer" title={address}>
          <code>{short(address)}</code>
        </a>
      </span>);
  }
  const row = (label, value) => <div className="flex flex-wrap gap-x-2">
      <span className="font-semibold min-w-[5.5rem]">{label}</span>
      <span className="flex-1 min-w-0 break-words">{value}</span>
    </div>;
  return <div className="not-prose mb-6 rounded-xl border border-zinc-950/10 dark:border-white/10 bg-zinc-50 dark:bg-white/5 px-4 py-3 text-sm leading-6 text-zinc-700 dark:text-zinc-300">
      {row(t.sdk, <code>@alephium/powfi-sdk@{SDK_VERSION}</code>)}
      {row(t.network, network === 'all' ? t.allNetworks : network)}
      {contractsCell && row(t.contracts, <span>
            {contractsCell}
            <span className="mx-1 opacity-50">·</span>
            <a href={contractsPage}>{t.all} →</a>
          </span>)}
    </div>;
};

<VersionBanner network="mainnet" products={[]} lang="zh" />

```ts theme={null}
import { ClmmLiquidityUtils, PoolUtils } from '@alephium/powfi-sdk'
```

这些是链上数学的无状态移植，使用 Alephium 的取整方式（`MathUtil.alphDiv`），因此结果与合约精确到最小单位一致。

## ClmmLiquidityUtils

约定：`sqrtRatioX96` 是当前价格。`sqrtRatioAX96` 和 `sqrtRatioBX96` 是区间边界（`getSqrtRatioAtTick(tickLower/Upper)`）。数量按排序后的 token0/token1 顺序。

### `getLiquidityFromAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1)`

给定数量所能铸造的最大流动性：

* 价格等于或低于区间下界 → 只计算 `amount0`
* 价格在区间内 → `min(amount0 对应的 L, amount1 对应的 L)`
* 价格高于区间 → 只计算 `amount1`

### `getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity)`

有符号流动性变化量对应的 `[amount0, amount1]`。合约约定：传入 `-liquidity` 得到**添加**流动性所需的数量（取负），传入 `+liquidity` 得到移除时收到的数量。

### `getAmountsAndLiquidityAtSqrtPrice(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1)`

返回 `[amount0Used, amount1Used, liquidity]`：针对期望的 `amount0` 和 `amount1`，实际存入的平衡数量。这是展示"你将存入"预览时通常使用的函数。

### `getAmountsAndLiquidityAtPrice(price, token0, token1, lowerTick, upperTick, amount0, amount1)`

与上面相同，但接收人类可读价格和 `TokenInfo`。

### `getPositionAmountsFromPrice(props)`

面向界面的版本，以基础/报价的方式工作，tick 顺序任意：

```ts theme={null}
const { newAmountBase, newAmountQuote, liquidity } = ClmmLiquidityUtils.getPositionAmountsFromPrice({
  sqrtRatioX96: state.sqrtPriceX96,
  tokenBaseId: alph,
  tokenQuoteId: usdt,
  lowerTick,
  upperTick,
  amountBase: 100n * 10n ** 18n,
  amountQuote: UNLIMITED_AMOUNT // let the base amount decide
})
```

任一输入数量为 `0n` 时返回零。要按一侧确定头寸大小，请给另一侧传入 `UNLIMITED_AMOUNT`（`2^128 − 1`）。

### 底层函数

| 方法 | 说明 |
| - | - |
| `getLiquidityFromToken0(sqrtA, sqrtB, amount0)` | 仅由 token0 计算 L |
| `getLiquidityFromToken1(sqrtA, sqrtB, amount1)` | 仅由 token1 计算 L |
| `getToken0Delta(sqrtA, sqrtB, liquidity)` | 两个价格之间的 Δtoken0 |
| `getToken1Delta(sqrtA, sqrtB, liquidity)` | 两个价格之间的 Δtoken1 |
| `getAmountDelta(sqrtA, sqrtB, liquidity, zeroForOne)` | 根据方向分派到上面两个函数 |

## PoolUtils

### `getPositionId(poolAddress, owner, tickLower, tickUpper)`

根据池**地址**推导头寸合约 ID。与 `clmm.getPositionId` 不同，它会自动规范化无分组的 `owner` 地址。

### `offlineSwap`

```ts theme={null}
static offlineSwap(liqDist: ClmmSimulateSwapQuote, amountSpecified: bigint, sqrtPriceX96: bigint): bigint
```

在 [`clmm.simulateSwap`](/zh/modules/clmm) 返回的流动性曲线上本地重放一次兑换，并以**有符号**值返回另一侧的数量：

* **精确输入**（`amountSpecified > 0`）：输出以**负数**返回（你收到的是 `-offlineSwap(...)`）
* **精确输出**（`amountSpecified < 0`）：返回所需的输入（取绝对值）

```ts theme={null}
const quote = await powfi.clmm.simulateSwap({ configIndex, token0, token1, zeroForOne: true, amount: amountIn })
const out = -PoolUtils.offlineSwap(quote, amountIn, quote.sqrtPriceX96)
```

集成测试验证了它与池在链上的 `simulateSwap` 返回值完全一致。

### `computeSwapStep(sqrtPriceX96, sqrtPriceTargetX96, liquidity, amount, feePips)`

在一个流动性区间内的单步兑换。返回 `[sqrtPriceNextX96, amountIn, amountOut, feeAmount]`。`offlineSwap` 对每一行调用一次。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.