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

# Demos de código AMM v4

> Exemplos em TypeScript para fazer swap contra e fornecer liquidez a um pool AMM v4 existente. A criação de novos pools está fora do escopo — use CPMM em seu lugar.

<Info>
  **Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.**

  [Ver versão em inglês →](/products/amm-v4/code-demos)
</Info>

<Info>
  **Banner de versão.** Todos os demos visam `@raydium-io/raydium-sdk-v2@0.2.42-alpha` contra Solana mainnet-beta, verificado em 2026-04. ID do programa: `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` (veja [`reference/program-addresses`](/pt/reference/program-addresses)).
</Info>

<Info>
  **Criação de novo pool não é mostrada aqui.** A interface do Raydium não oferece mais criação de pool AMM v4 — novos pares usam [CPMM](/pt/products/cpmm/code-demos) por padrão. O próprio programa AMM v4 ainda aceita `Initialize2` on-chain; apenas não é o caminho recomendado. Os demos abaixo cobrem as operações de pool ativo que todo integrador ainda precisa: swap, depósito, saque.
</Info>

## Configuração

```ts theme={null}
import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import fs from "node:fs";

const connection = new Connection(process.env.RPC_URL ?? clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(
  new Uint8Array(JSON.parse(fs.readFileSync(process.env.KEYPAIR!, "utf8"))),
);
const raydium = await Raydium.load({ owner, connection, cluster: "mainnet" });
```

## Buscar um pool por ID

```ts theme={null}
import { PublicKey } from "@solana/web3.js";

const poolId = new PublicKey("<AMM_V4_POOL_ID>");

// Obtenha o objeto pool normalizado pelo SDK. Para AMM v4 isso inclui as contas
// OpenBook que os construtores de instruções precisarão.
const data = await raydium.liquidity.getPoolInfoFromRpc({ poolId });
const { poolInfo, poolKeys, poolRpcData } = data;

console.log("Par:", poolInfo.mintA.symbol, "/", poolInfo.mintB.symbol);
console.log("Versão:", poolInfo.version);       // 4 para AMM v4
console.log("Mercado:", poolKeys.marketId.toBase58());
```

`poolKeys` é a struct que os construtores de instruções consomem. Ela carrega todas as contas AMM v4 e OpenBook na ordem que o programa espera.

## Swap (base-in)

```ts theme={null}
import BN from "bn.js";

const amountIn = new BN(1_000_000);            // 1 USDC (quote de 6 decimais)
const inputMint = new PublicKey(poolInfo.mintB.address);  // USDC
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountOut({
  poolInfo,
  amountIn,
  mintIn: inputMint,
  mintOut: new PublicKey(poolInfo.mintA.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn,
  amountOut: computed.minAmountOut,
  fixedSide: "in",
  inputMint,
  txVersion: TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Tx de swap:", txId);
```

O SDK roteia swaps AMM v4 através dos pontos de entrada V2, que não carregam as contas OpenBook. (Após a atualização de 2026-07, as contas de mercado não são mais validadas nem mesmo no caminho legado v1.)

## Swap (base-out)

```ts theme={null}
const amountOut = new BN(1_000_000_000);       // 1 SOL (base de 9 decimais)
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountIn({
  poolInfo,
  amountOut,
  mintOut: new PublicKey(poolInfo.mintA.address),
  mintIn: new PublicKey(poolInfo.mintB.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn: computed.maxAmountIn,
  amountOut,
  fixedSide: "out",
  inputMint: new PublicKey(poolInfo.mintB.address),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

## Adicionar liquidez

```ts theme={null}
const amountA = new BN(100_000_000);           // 0.1 SOL

const { anotherAmount, maxAnotherAmount } = raydium.liquidity.computePairAmount({
  poolInfo,
  amount: amountA,
  baseIn: true,
  slippage: 0.01,
});

const { execute } = await raydium.liquidity.addLiquidity({
  poolInfo,
  poolKeys,
  amountInA: amountA,
  amountInB: maxAnotherAmount,
  fixedSide: "a",
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

`fixedSide: "a"` diz ao SDK que você forneceu o `amountInA` exato e que `amountInB` deve ser no máximo `maxAnotherAmount`. A liquidez on-book do pool é liquidada antes da matemática pro-rata, então a proporção de depósito corresponde às reservas mais recentes.

## Remover liquidez

```ts theme={null}
const lpAmount = new BN(50_000);               // LP a queimar

const { execute } = await raydium.liquidity.removeLiquidity({
  poolInfo,
  poolKeys,
  lpAmount,
  baseAmountMin: new BN(0),
  quoteAmountMin: new BN(0),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

Os mínimos de slippage protegem contra o estado do pool mudar entre sua pré-cotação e o tempo de execução.

## Ajuste de unidade de computação / taxa de prioridade

Swaps AMM v4 são pesados em computação porque cada instrução valida o estado completo do OpenBook. Um swap típico usa 180k–250k CU dependendo de quantas ordens abertas precisam ser liquidadas no caminho. Sempre passe um limite de unidade de computação:

```ts theme={null}
import { ComputeBudgetProgram } from "@solana/web3.js";

const { execute, innerTransactions } = await raydium.liquidity.swap({
  /* ...params... */
  computeBudgetConfig: {
    units: 400_000,
    microLamports: 50_000,       // taxa de prioridade
  },
});
```

Se você omitir `computeBudgetConfig`, o SDK ainda pode usar seu próprio padrão; inspecione `innerTransactions` para confirmar. Veja [`integration-guides/priority-fee-tuning`](/pt/integration-guides/priority-fee-tuning).

## CPI Rust direto

Se você deve fazer CPI para AMM v4 a partir de seu próprio programa Anchor, você precisará modelar a lista de contas de `SwapBaseIn` verbatim. Um esboço mínimo:

```rust theme={null}
use anchor_lang::prelude::*;
use anchor_lang::solana_program::program::invoke_signed;
use anchor_lang::solana_program::instruction::Instruction;

const AMM_V4_PROGRAM_ID: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8");

#[derive(Accounts)]
pub struct ProxyAmmV4Swap<'info> {
    /// CHECK:
    pub token_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm:          UncheckedAccount<'info>,
    /// CHECK:
    pub amm_authority: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_open_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_target_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_coin_token_account: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_pc_token_account: UncheckedAccount<'info>,
    /// CHECK:
    pub market_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_bids: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_asks: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_event_queue: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_coin_vault: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_pc_vault: UncheckedAccount<'info>,
    /// CHECK:
    pub market_vault_signer: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_source: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_dest: UncheckedAccount<'info>,
    pub user_owner: Signer<'info>,
}

pub fn proxy_swap(
    ctx: Context<ProxyAmmV4Swap>,
    amount_in: u64,
    minimum_amount_out: u64,
) -> Result<()> {
    // O discriminador de instrução para SwapBaseIn é 9 em AMM v4.
    let mut data = vec![9u8];
    data.extend_from_slice(&amount_in.to_le_bytes());
    data.extend_from_slice(&minimum_amount_out.to_le_bytes());

    let ix = Instruction {
        program_id: AMM_V4_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new_readonly(ctx.accounts.token_program.key(), false),
            AccountMeta::new(ctx.accounts.amm.key(), false),
            AccountMeta::new_readonly(ctx.accounts.amm_authority.key(), false),
            AccountMeta::new(ctx.accounts.amm_open_orders.key(), false),
            AccountMeta::new(ctx.accounts.amm_target_orders.key(), false),
            AccountMeta::new(ctx.accounts.pool_coin_token_account.key(), false),
            AccountMeta::new(ctx.accounts.pool_pc_token_account.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_program.key(), false),
            AccountMeta::new(ctx.accounts.market.key(), false),
            AccountMeta::new(ctx.accounts.market_bids.key(), false),
            AccountMeta::new(ctx.accounts.market_asks.key(), false),
            AccountMeta::new(ctx.accounts.market_event_queue.key(), false),
            AccountMeta::new(ctx.accounts.market_coin_vault.key(), false),
            AccountMeta::new(ctx.accounts.market_pc_vault.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_vault_signer.key(), false),
            AccountMeta::new(ctx.accounts.user_source.key(), false),
            AccountMeta::new(ctx.accounts.user_dest.key(), false),
            AccountMeta::new_readonly(ctx.accounts.user_owner.key(), true),
        ],
        data,
    };
    invoke_signed(&ix, &ctx.accounts.to_account_infos(), &[])?;
    Ok(())
}
```

AMM v4 não fornece uma crate Anchor para CPI. O esboço acima usa uma `Instruction` construída manualmente.

<Note>
  O esboço de CPI acima usa o **layout legado v1 `SwapBaseIn`** (tag 9, 17 contas) para ler/reproduzir transações existentes. Desde a atualização de 2026-07, as contas de mercado são aceitas mas ignoradas. **Para novo código, prefira `SwapBaseInV2` / `SwapBaseOutV2`** (tags 16 / 17), que eliminam as contas de mercado (e `amm_open_orders`) inteiramente — passe apenas 8 contas: `token_program`, `amm`, `amm_authority`, os dois vaults do pool, as duas contas de token do usuário, e `user_owner`.
</Note>

## Armadilhas

* **Contagem de contas errada em swaps v1.** O `SwapBaseIn` / `SwapBaseOut` legado ainda requer a lista completa de 17 contas (ou 18 contas) — uma *contagem* incompatível reverte com `WrongAccountsNumber`. O *conteúdo* das contas de mercado não é mais validado, mas você ainda deve ocupar seus slots. Prefira os pontos de entrada V2 para evitar isso.
* **Leitura de saldos brutos de vault.** As reservas agora são apenas vault; subtraia PnL acumulado (`need_take_pnl_*`). A cotação do SDK ou `api-v3.raydium.io/pools/info/ids` faz isso para você.
* **Chamada de instruções removidas.** `MonitorStep`, `MigrateToOpenBook`, `WithdrawSrm`, `SimulateInfo`, `AdminCancelOrders`, e `Initialize` / `PreInitialize` legado agora revertam. Use `Initialize2` para criação de pool; não há crank para chamar.
* **Mints Token-2022.** Não suportado. Um pool AMM v4 não pode ser criado contra um mint Token-2022; qualquer par Token-2022 deve estar em CPMM ou CLMM.

## Próximos passos

* [`products/amm-v4/instructions`](/pt/products/amm-v4/instructions) — a superfície em nível de instrução por trás desses demos.
* [`user-flows/migrate-amm-v4-to-cpmm`](/pt/user-flows/migrate-amm-v4-to-cpmm) — se você é um LP considerando migração.
* [`integration-guides/priority-fee-tuning`](/pt/integration-guides/priority-fee-tuning) — dimensionamento de taxa de prioridade para swaps AMM v4 pesados.

Fontes:

* [Raydium SDK v2](https://github.com/raydium-io/raydium-sdk-V2)
* [Programa Raydium AMM](https://github.com/raydium-io/raydium-amm)
