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

# PDA'lar ve CPI'lar

> Program-türetilmiş adresler ve çapraz program çağırma — Raydium'un durumu belirleyici bir şekilde yönetmesini ve diğer programlarla bileşim yapmasını sağlayan iki ilkel. Tohumlar, bump'lar, invoke vs invoke_signed ve Raydium kodunun izlediği desenler.

<Info>
  **Bu sayfa yapay zekâ tarafından otomatik olarak çevrilmiştir. İngilizce sürüm esas alınır.**

  [İngilizce sürümü görüntüle →](/solana-fundamentals/pdas-and-cpis)
</Info>

<Info>
  **PDA'lar** (program-türetilmiş adresler) ve **CPI'lar** (çapraz program çağırma) Raydium'u mümkün kılan iki ilkeldir. PDA'lar bir programın özel anahtarlar olmadan belirleyici adresler "sahip olmasını" sağlar — havuz yetkilendirmeleri ve kasaları bu şekilde çalışır. CPI'lar bir programın başka bir programı çağırmasını sağlar — Raydium'un SPL Token programı aracılığıyla token'ları değiştirmesi ve entegratörlerin Raydium'u kendi akışlarına bileşim yapması bu şekilde gerçekleşir. Raydium kaynak kodunu okumadan önce her ikisini anlamak değerlidir.
</Info>

## PDA'lar: anahtarsız adresler

**Program-Türetilmiş Adres** şu özelliklere sahip bir genel anahtardır:

* ed25519 eğrisi üzerinde değildir (bunun için özel anahtar yoktur).
* Bir program kimliği ve bir tohum seti ile belirleyici bir şekilde türetilir.
* Yalnızca türetme programı tarafından `invoke_signed` aracılığıyla imzalanabilir.

Her Raydium havuz yetkilendirmesi, her havuz durum hesabı, her kasa, her farm durumu — hepsi PDA'dır.

### Türetme

Bir PDA, program kimliğinin tohumlarla birlikte hash'lenmesi ve sonucu eğri dışına zorlayan bir "bump" baytı bulunması ile hesaplanır. Eğri dışı bir adres üreten ilk bump (tipik olarak 255'ten başlayıp azalan) kazanır; bu **kanonik bump**'tır.

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

const [poolAuthority, bump] = PublicKey.findProgramAddressSync(
  [Buffer.from("authority"), poolId.toBuffer()],
  CPMM_PROGRAM_ID,
);
```

Tohumlar herhangi bir şey olabilir — dizeler, diğer genel anahtarlar, `u64` değerleri küçük-endian baytlar olarak. Raydium'un kuralı insan tarafından okunabilir bir ön ek ve ardından benzersiz tanımlayıcılar kullanmaktır.

### Raydium PDA desenleri

Raydium programlarında yaygın PDA'lar:

| PDA | Tohumlar | Program |
| - | - | - |
| AMM yetkilendirmesi (AMM v4) | `[b"amm authority"]` + bump | AMM v4 |
| Havuz durumu (CPMM) | `[b"pool", amm_config, mint_a, mint_b]` | CPMM |
| Havuz kasası (CPMM) | `[b"pool_vault", pool, mint]` | CPMM |
| Yetkilendirme (CPMM) | `[b"vault_and_lp_mint_auth_seed"]` | CPMM |
| Havuz durumu (CLMM) | `[b"pool", amm_config, mint_0, mint_1]` | CLMM |
| Tick dizisi (CLMM) | `[b"tick_array", pool, start_tick_index]` | CLMM |
| Gözlem (CLMM) | `[b"observation", pool]` | CLMM |
| Kişisel pozisyon (CLMM) | `[b"position", position_nft_mint]` | CLMM |
| Farm durumu (Farm v6) | `[b"pool_farm_state", farm_id]` | Farm v6 |
| Kullanıcı defteri (Farm v6) | `[b"user_ledger", farm, user]` | Farm v6 |

Kullanıcılar ve entegratörler herhangi bir şey getirmeden bu adresler hesaplayabilir — genel girdiler (havuz kimliği, farm kimliği, kullanıcı anahtarı) verildiğinde, PDA belirleyicidir.

### Kanonik bump

Prensipte eğri dışı adresler üreten birden fazla bump olabilse de, Raydium programları her zaman **kanonik bump**'ı (255'ten azaltarak bulunur) kullanır. Bu, PDA'nın hesap verilerinde saklanır, böylece sonraki işlemler bunu iletebilir ve (pahalı) türetme döngüsünü atlayabilir:

```rust theme={null}
// CPMM'nin gerçek alanı, AccountLoader aracılığıyla yüklenen sıfır-kopya PoolState'te:
#[account(zero_copy(unsafe))]
#[repr(C, packed)]
pub struct PoolState {
    pub auth_bump: u8,
    // ... havuz durumunun geri kalanı
}
```

(CLMM'nin `PoolState`'i bunun yerine `bump: [u8; 1]` depolar, bu nedenle bir şekil varsaymak yerine belirli programın yapısını kontrol edin.)

Sonraki işlemlerde, bump havuz durumundan okunur ve yeniden hesaplanmaz.

## CPI'lar: diğer programları çağırma

**Çapraz Program Çağırma** bir programın başka bir programın talimatlarını tek bir işlem içinde satır içi çağırmasını sağlar. Raydium, CPI'ları kapsamlı bir şekilde kullanır:

* Swap talimatları token'ları taşımak için SPL Token programını çağırır.
* CLMM, pozisyon NFT'sini basmak için Metaplex'i çağırır.
* Havuz oluşturma, hesapları tahsis etmek için Sistem Programını çağırır.
* Farm v6, ödülleri aktarmak için SPL Token'ı çağırır.

Entegratörler ayrıca Raydium'a *çağrı yapmak* için CPI'ları kullanır — kasa stratejileri, kaldıraçlı LP protokolleri ve otomatik bileşim yapıcılar bu şekilde çalışır. Bkz. [`integration-guides/cpi-integration`](/tr/integration-guides/cpi-integration).

### invoke vs invoke\_signed

Solana çalışma zamanı iki CPI ilkeli sunar:

* **`invoke`**: başka bir programı çağırın; çağrılan program dış işlemin imzalayanlarını devralır.
* **`invoke_signed`**: başka bir programı *bir PDA adına* çağırın; çalışma zamanı PDA'nın tohumlarını doğrular ve imzayı yetkilendirir.

`invoke_signed`, programların özel anahtarları yönetmeden hesaplar üzerinde yetki tutmasını sağlayan sihirdir.

### Örnek: Raydium havuz kasasından aktarım yapma

Bir havuz kasası, yetkilendirmesi havuz programının bir PDA'sı olan bir Token Hesabıdır. Bir swap sırasında token'ları dışarı aktarmak için, havuz programı bu PDA olarak imzalamalıdır:

```rust theme={null}
// Havuz yetkilendirmesi için tohumlar
let authority_seeds: &[&[u8]] = &[
    b"vault_and_lp_mint_auth_seed",
    &[authority_bump],
];
let signer_seeds: &[&[&[u8]]] = &[authority_seeds];

// CPI bağlamını oluştur
let cpi_accounts = Transfer {
    from:      input_vault.to_account_info(),
    to:        user_ata.to_account_info(),
    authority: pool_authority.to_account_info(),
};
// Anchor 1.0 burada programın Pubkey'ini alır; AccountInfo formu yalnızca 0.3x'tir.
let cpi_ctx = CpiContext::new_with_signer(token_program.key(), cpi_accounts, signer_seeds);

// Yürüt
token::transfer(cpi_ctx, amount)?;
```

Çalışma zamanı `invoke_signed`'ın CPMM programı tarafından çağrıldığını görür, `vault_and_lp_mint_auth_seed + bump`'ın CPMM program kimliği ile hash'lendiğinde `pool_authority`'nin adresine türetildiğini doğrular ve token aktarımında yetkilendirme imzasına izin verir. Özel anahtar söz konusu değildir.

### Örnek: entegratör Raydium CPMM'yi çağırma

Bir entegratör programı (örn. emanet) Raydium'un `swap_base_input`'ını CPI aracılığıyla çağırabilir:

```rust theme={null}
// Crate `raydium-cp-swap`'tır; lib adı — ve bu nedenle `use` yolu —
// `raydium_cp_swap`'tır. `raydium_cpmm` yoktur.
use raydium_cp_swap::cpi::{self, accounts::Swap};

let cpi_accounts = Swap {
    payer:                order.to_account_info(),      // PDA, imzalayacak
    authority:            pool_authority_info,
    amm_config:           amm_config_info,
    pool_state:           pool_info,
    input_token_account:  order_input_ata,
    output_token_account: order_output_ata,
    input_vault:          input_vault_info,
    output_vault:         output_vault_info,
    input_token_program:  input_token_program_info,
    output_token_program: output_token_program_info,
    input_token_mint:     input_mint_info,
    output_token_mint:    output_mint_info,
    observation_state:    observation_info,
};

let seeds = &[b"order", user.key.as_ref(), &[order.bump]];
let cpi_ctx = CpiContext::new_with_signer(
    cpmm_program.key(),     // Anchor 1.0: AccountInfo değil, bir Pubkey
    cpi_accounts,
    &[seeds],
);

cpi::swap_base_input(cpi_ctx, amount_in, min_out)?;
```

Bu kanonik entegrasyon desenidir — tam emanet örneği için [`integration-guides/cpi-integration`](/tr/integration-guides/cpi-integration) bölümüne bakın.

## CPI derinlik sınırı

Solana, CPI derinliğini **4 seviye** ile sınırlandırır. Bir işlemin üst düzey talimatı derinlik 0 olarak sayılır; her CPI çağırması derinliği artırır.

Pratik sonuç: Raydium'un kendi swap'ı zaten 1-2 seviye CPI kullanır (Raydium → SPL Token). Raydium'u çağıran bir entegratör 2 kullanır. Eğer bu entegratör başka bir entegratör tarafından çağrılırsa, 3'tür. 4. seviye sınırdır.

Çoğu bileşim bunu kolayca aşmaz, ancak derin iç içe geçme (toplayıcı → yönlendirici → Raydium → kanca) buna çarpabilir. Derin yerine düz tasarım yapın.

## Kalan hesaplar

Bir Raydium talimatı değişken sayıda hesaba ihtiyaç duyduğunda (örn. bilinmeyen sayıda tick dizisini geçen CLMM swap), ekstra hesaplar **kalan hesaplar** olarak iletilir — sabit hesap listesine eklenir, konuma göre yorumlanır.

CPMM'nin `SwapV2`'si transfer-hook programlarının ekstra gerekli hesapları için kalan hesapları kullanır. İstemciler gerekli hesapları getirir ve ekler:

```ts theme={null}
const swapIx = await raydium.cpmm.swap({
  /* ... */
  // SDK kalan hesapları otomatik olarak işler
});
```

CPI seviyesinde, entegratörler kalan hesapları kendi talimatları aracılığıyla iletmelidir:

```rust theme={null}
pub struct Swap<'info> {
    // ... sabit hesaplar
    // Artı ctx.remaining_accounts aracılığıyla iletilen Kalan hesaplar
}

// Kalan_hesapları CPI'ya ilet
cpi::swap_base_input(
    cpi_ctx.with_remaining_accounts(ctx.remaining_accounts.to_vec()),
    amount_in,
    min_out,
)?;
```

## PDA tuzakları

### Yanlış tohumlar → yanlış adres

Tohumların yanlış sırada, yanlış kodlamada veya ekstra bir bayt içermesi/hariç tutması sessizce farklı bir PDA üretir. İşlem belirsiz bir şekilde başarısız olur (program var olmayan bir hesabı okumaya çalışır). Tohum türetmesini her zaman bilinen altın değerlere karşı birim testleyin.

### Bump'ı depolamama

Her işlemde bump'ı yeniden türetirseniz, türetme döngüsü için hesaplama ödersiniz. Kanonik bump'ı PDA'nın verilerinde depolayın ve oradan okuyun.

### Kanonik vs kanonik olmayan bump'ı karıştırma

Kanonik olmayan bump'lar (eğer biri eğri dışı üreten bulursa) `invoke_signed` tarafından izin verilir ancak Raydium programları tarafından `assert_eq!(bump, canonical_bump)` aracılığıyla reddedilir. Biri kanonik olmayan bump ile bir PDA talep etmeye çalışırsa, tx başarısız olur.

### Sahip program olmadığınız halde bir PDA'yı imzalayan olarak iletme

Yalnızca PDA'nın türetmesinde kimliği olan program `invoke_signed`'ı tohumlarıyla çağırabilir. Çalışırsanız, çalışma zamanı reddeder.

## CPI tuzakları

### `remaining_accounts`'ı iletmeyi unutma

Eğer dış talimatınız transfer-hook hesaplarını `remaining_accounts`'ta iletirse ancak Raydium'a CPI bunu iletmezse, Raydium hook hesaplarını bulamadığı için başarısız olur. Her zaman ihtiyaç duyan CPI'lara `with_remaining_accounts` ekleyin.

### Yazılabilir bayrakları uyuşmazlığı

Dış talimatın yazılabilir olarak işaretlediği bir hesap, çağrılan program bunu yazmayı amaçlıyorsa CPI çağrısında da yazılabilir olmalıdır. Uyuşmazlık → çalışma zamanı reddi.

### Kirayı hesaba katmama

Bir hesap oluşturan bir programa CPI (örn. ATA oluşturma) ödeyenin kira için yeterli SOL'a sahip olmasını gerektirir. Başarısız kira kontrolleri belirsiz hatalar olarak görünür.

## Çalışılmış örnek: Raydium CPMM PDA'larını hesaplama

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

const CPMM_PROGRAM_ID = new PublicKey("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C");

function computeCpmmPdas(ammConfig, mintA, mintB) {
  const [poolState, poolBump] = PublicKey.findProgramAddressSync(
    [
      Buffer.from("pool"),
      ammConfig.toBuffer(),
      mintA.toBuffer(),
      mintB.toBuffer(),
    ],
    CPMM_PROGRAM_ID,
  );

  const [authority] = PublicKey.findProgramAddressSync(
    [Buffer.from("vault_and_lp_mint_auth_seed")],
    CPMM_PROGRAM_ID,
  );

  const [vaultA] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), mintA.toBuffer()],
    CPMM_PROGRAM_ID,
  );

  const [vaultB] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), mintB.toBuffer()],
    CPMM_PROGRAM_ID,
  );

  const [observation] = PublicKey.findProgramAddressSync(
    [Buffer.from("observation"), poolState.toBuffer()],
    CPMM_PROGRAM_ID,
  );

  return { poolState, authority, vaultA, vaultB, observation, poolBump };
}
```

Bu, `getPoolInfoFromRpc({ poolId })` çağırdığınızda Raydium SDK'sının perde arkasında yaptığı şeydir — gidiş-dönüş olmadan ilişkili PDA'ları türetir.

## İşaretçiler

* [`solana-fundamentals/account-model`](/tr/solana-fundamentals/account-model) — PDA'ların hesap modelinde nasıl uyduğu.
* [`solana-fundamentals/programs-and-anchor`](/tr/solana-fundamentals/programs-and-anchor) — PDA'ları bildirmek için Anchor'ın yardımcıları.
* [`integration-guides/cpi-integration`](/tr/integration-guides/cpi-integration) — Raydium'a CPI yapan entegrasyonlar oluşturma.
* [`sdk-api/rust-cpi`](/tr/sdk-api/rust-cpi) — Raydium'un Rust CPI türleri.

Kaynaklar:

* [Solana PDA belgeleri](https://solana.com/docs/core/pda).
* [Solana CPI belgeleri](https://solana.com/docs/core/cpi).
* [Anchor PDA belgeleri](https://www.anchor-lang.com/docs/basics/pda) ve [Anchor CPI belgeleri](https://www.anchor-lang.com/docs/basics/cpi) — Anchor'ın birleşik bir sayfası yoktur.


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