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

# Swapper sur CLMM

> Choisir un palier de frais, simuler le swap, calculer la sortie hors ligne et exécuter avec une limite de prix.

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={['clmm']} lang="fr" />

## 1. Choisir le pool

Une paire peut avoir un pool par palier de frais. Utilisez le plus profond :

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

const powfi = Powfi.load({ networkId: 'mainnet', signer })

const configIndex = await powfi.clmm.findBestRoute(tokenIn, tokenOut)
const poolId = powfi.clmm.getPoolId(tokenIn, tokenOut, configIndex)
const state = await powfi.clmm.getPoolState(poolId)
```

## 2. Déterminer la direction

La direction se définit sur la paire **triée** : vendre `token0` correspond à `zeroForOne = true`.

```ts theme={null}
const [token0, token1] = sortTokens(tokenIn, tokenOut)
const zeroForOne = tokenIn === token0
```

## 3. Simuler et coter

<Tabs>
  <Tab title="Entrée exacte">
    ```ts theme={null}
    const amountIn = 10n * 10n ** 18n

    const sim = await powfi.clmm.simulateSwap({ configIndex, token0, token1, zeroForOne, amount: amountIn })
    const amountOut = -PoolUtils.offlineSwap(sim, amountIn, sim.sqrtPriceX96)
    ```
  </Tab>

  <Tab title="Sortie exacte">
    ```ts theme={null}
    const wantOut = 500n * 10n ** 6n
    const amount = -wantOut // negative = exact-out

    const sim = await powfi.clmm.simulateSwap({ configIndex, token0, token1, zeroForOne, amount })
    const raw = PoolUtils.offlineSwap(sim, amount, sim.sqrtPriceX96)
    const estimatedIn = raw < 0n ? -raw : raw
    ```
  </Tab>
</Tabs>

`simulateSwap` fait un seul appel au nœud et renvoie la courbe de liquidité tick par tick. `offlineSwap` la rejoue localement : vous pouvez donc recoter des montants proches sans nouvel aller-retour, tant que le montant ne dépasse pas la dernière ligne simulée.

Prix avant et après :

```ts theme={null}
const d0 = state.token0Info.decimals, d1 = state.token1Info.decimals
const priceBefore = TickUtils.sqrtPriceX96ToPrice(state.sqrtPriceX96, d0, d1) // token1 per token0
```

## 4. Exécuter

Dans `ClmmSwapRequest`, `token0` / `token1` signifient **entrée / sortie**, et non l'ordre trié.

<Tabs>
  <Tab title="Entrée exacte">
    ```ts theme={null}
    const result = await powfi.clmm.swap({
      token0: tokenIn,
      token1: tokenOut,
      amount: amountIn,   // positive
      amountIn,           // attach exactly this much
      slippage: 50n,      // 0.5% price movement allowed
      routePlan: [configIndex]
    })
    ```
  </Tab>

  <Tab title="Sortie exacte">
    ```ts theme={null}
    const slippage = 50n
    const result = await powfi.clmm.swap({
      token0: tokenIn,
      token1: tokenOut,
      amount: -wantOut,                                     // negative
      amountIn: estimatedIn + (estimatedIn * slippage) / 10_000n, // max input to attach
      slippage,
      routePlan: [configIndex]
    })
    ```
  </Tab>
</Tabs>

Le slippage devient un `sqrtPriceLimitX96` : le swap échoue si l'exécution du montant complet devait faire bouger le prix au-delà de la tolérance. Voir [CLMM : slippage sur le prix](/fr/concepts/amounts-and-slippage).

<Warning>
  `clmm.swap()` exige une exécution complète. Si la limite de prix est atteinte avant que tout le `amount` soit échangé, la transaction échoue avec l'erreur de contrat `501` et aucun token ne bouge. Réessayez avec un `slippage` plus élevé ou un montant plus petit. (`swapTo()` est différent : il s'arrête au prix cible et peut être exécuté partiellement, par conception.)
</Warning>

## Cotations multi-sauts

Pour coter `A → B → C` sur deux pools du même palier de frais, enchaînez les simulations. La sortie du premier saut devient le montant en entrée exacte du second :

```ts theme={null}
const q1 = await powfi.clmm.simulateSwap({ configIndex, token0: A, token1: B, zeroForOne: A < B, amount })
const out1 = -PoolUtils.offlineSwap(q1, amount, q1.sqrtPriceX96)

const q2 = await powfi.clmm.simulateSwap({ configIndex, token0: B, token1: C, zeroForOne: B < C, amount: out1 })
const out2 = -PoolUtils.offlineSwap(q2, out1, q2.sqrtPriceX96)
```

Pour simuler tout le chemin en un seul appel, passez `data: powfi.clmm.buildSwapPath(C, configIndex)` et l'adresse du second pool dans `interestedContracts`. `clmm.swap()` n'exécute que des swaps sur un seul pool. Pour exécuter un swap multi-sauts, appelez le script `SwapWithoutAccount` de `ClmmScripts` avec le même `data`.

## Swapper jusqu'à un prix cible

```ts theme={null}
const target = TickUtils.priceToSqrtPriceX96(0.051, d0, d1)
await powfi.clmm.swapTo({ tokenIn, tokenOut, configIndex, targetSqrtPriceX96: target, amountInMax })
```

La cible doit être du bon côté : vendre du token0 fait baisser le prix, vendre du token1 le fait monter.


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