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

# gRPC İstemcisi (Yellowstone)

> Otomatik yeniden bağlanma, ping/pong canlılık denetimi ve YAML yapılandırması ile Yellowstone Geyser akışı.

## Kurulum

```bash theme={null}
cargo add orbitflare-sdk --features grpc
```

## İstemciyi oluşturma

Tüm seçeneklerin ayarlı olduğu bir istemci:

```rust theme={null}
use orbitflare_sdk::{GeyserClientBuilder, RetryPolicy, Result};
use std::time::Duration;

let client = GeyserClientBuilder::new()
    .url("http://ny.rpc.orbitflare.com:10000")
    .fallback_url("http://fra.rpc.orbitflare.com:10000")
    .retry(RetryPolicy {
        initial_delay: Duration::from_millis(100),
        max_delay: Duration::from_secs(30),
        multiplier: 2.0,
        max_attempts: 0,
    })
    .timeout_secs(30)
    .keepalive_secs(60)
    .ping_interval_secs(10)
    .max_missed_pongs(3)
    .channel_capacity(4096)
    .build()?;
```

Minimal kurulum:

```rust theme={null}
let client = GeyserClientBuilder::new()
    .url("http://ny.rpc.orbitflare.com:10000")
    .build()?;
```

### Builder yöntemleri

**`.url(url)`** — Birincil gRPC uç noktası. `ORBITFLARE_GRPC_URL` ortam değişkenine düşer.

```rust theme={null}
.url("http://ny.rpc.orbitflare.com:10000")
```

**`.urls(&[...])`** — Tek çağrıda birincil + yedekler. İlk eleman birincildir.

```rust theme={null}
.urls(&["http://ny.rpc.orbitflare.com:10000", "http://fra.rpc.orbitflare.com:10000"])
```

**`.fallback_url(url)` / `.fallback_urls(&[...])`** — Yedek uç noktalar ekler. Bağlantı hatasında SDK aralarında döner.

```rust theme={null}
.fallback_url("http://fra.rpc.orbitflare.com:10000")
```

**`.retry(policy)`** — Yeniden bağlanma geri çekilmesini denetler. Bağlantı koptuğunda SDK önce `initial_delay` bekler, sonra her denemede gecikmeyi iki katına çıkarır (`max_delay` ile sınırlı). `max_attempts` değerini 0 yaparak sonsuz yeniden deneme ayarlayın. Varsayılan: 100 ms başlangıç, 30 sn üst sınır, 2x çarpan, sonsuz.

```rust theme={null}
.retry(RetryPolicy {
    initial_delay: Duration::from_millis(200),
    max_delay: Duration::from_secs(15),
    multiplier: 2.0,
    max_attempts: 0,
})
```

**`.timeout_secs(n)`** — İstek başına gRPC zaman aşımı. Varsayılan: 30.

```rust theme={null}
.timeout_secs(15)
```

**`.keepalive_secs(n)`** — TCP keepalive aralığı. İşletim sistemi bu aralıkta ölü bağlantıları TCP düzeyinde tespit etmek için probe gönderir. Varsayılan: 60.

```rust theme={null}
.keepalive_secs(30)
```

**`.ping_interval_secs(n)`** — SDK’nın sunucuya proto düzeyinde `Ping` gönderme sıklığı. Sunucunun `Pong` ile yanıt vermesi beklenir. Varsayılan: 10.

```rust theme={null}
.ping_interval_secs(15)
```

**`.max_missed_pongs(n)`** — SDK’nın bağlantıyı ölü sayıp yeniden bağlanmadan önce ardışık kaç ping’in yanıtsız kalabileceği. Varsayılan: 3. Varsayılanlarla ölü bağlantı yaklaşık 30 saniye içinde tespit edilir.

```rust theme={null}
.max_missed_pongs(5)
```

**`.channel_capacity(n)`** — Arka plan görevi ile kodunuz arasındaki sınırlı kanal. Olayları tüketmek yavaşsa ve bu dolarsa arka plan görevi sınırsız bellek yemek yerine bloklanır. Varsayılan: 4096.

```rust theme={null}
.channel_capacity(8192)
```

## YAML yapılandırması yazma

İstediğiniz filtrelerle bir YAML dosyası oluşturun:

```yaml theme={null}
# grpc.yml
transactions:
  pumpfun:
    vote: false
    failed: false
    account_include:
      - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
  jupiter:
    vote: false
    failed: false
    account_include:
      - "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"

accounts:
  usdc_mint:
    account:
      - "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
  token_program:
    owner:
      - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"

slots:
  all:
    filter_by_commitment: true

commitment: confirmed
```

### YAML filtre referansı

**`transactions`** — her giriş adlı bir filtredir. Bir işlem `account_include` adreslerinden herhangi birini içeriyorsa eşleşir. `account_exclude` eşleşmeleri çıkarır. `account_required` listelenen tüm adreslerin bulunmasını gerektirir. `vote` ve `failed` işlem tipine göre filtreler.

**`accounts`** — adresle belirli hesapları izleyin veya `owner` ile bir programa ait tüm hesapları izleyin.

**`slots`** — slot güncellemelerine abone olun. `filter_by_commitment` yalnızca taahhüt düzeminizdeki güncellemeleri gönderir.

**`commitment`** — `"processed"`, `"confirmed"` veya `"finalized"`. Varsayılan: `"confirmed"`.

YAML `${ENV_VAR}` genişletmesini destekler:

```yaml theme={null}
transactions:
  target:
    account_include:
      - "${TARGET_PROGRAM}"
```

## Olaylara abone olma ve okuma

### YAML’dan

```rust theme={null}
let mut stream = client.subscribe_yaml("grpc.yml")?;
```

### Programatik olarak

Çalışma zamanında oluşturulan dinamik filtreler için:

```rust theme={null}
use std::collections::HashMap;
use orbitflare_sdk::proto::geyser::*;

let mut filters = HashMap::new();
filters.insert("target".into(), SubscribeRequestFilterTransactions {
    vote: Some(false),
    failed: Some(false),
    signature: None,
    account_include: vec![some_address.to_string()],
    account_exclude: vec![],
    account_required: vec![],
});

let request = SubscribeRequest {
    transactions: filters,
    commitment: Some(1),
    ping: Some(SubscribeRequestPing { id: 1 }),
    ..Default::default()
};

let mut stream = client.subscribe(request);
```

### Akışı okuma

Hem `subscribe_yaml` hem `subscribe` bir `GeyserStream` döndürür. Sonraki olay için `.next()` çağırın:

```rust theme={null}
use orbitflare_sdk::proto::geyser::subscribe_update::UpdateOneof;

while let Some(update) = stream.next().await {
    let update = update?;
    match update.update_oneof {
        Some(UpdateOneof::Transaction(tx)) => {
            // tx.slot - the slot this transaction was in
            // tx.transaction - the transaction info (signature, accounts, instructions, meta)
        }
        Some(UpdateOneof::Account(acct)) => {
            // acct.slot - the slot
            // acct.account - account info (pubkey, lamports, owner, data)
            // acct.is_startup - true during initial account snapshot
        }
        Some(UpdateOneof::Slot(slot)) => {
            // slot.slot - the slot number
            // slot.status - processed, confirmed, finalized, etc.
        }
        Some(UpdateOneof::BlockMeta(meta)) => {
            // meta.slot, meta.blockhash, meta.parent_slot
            // meta.executed_transaction_count
        }
        _ => {}
    }
}
```

`stream.next()` bir olay gelene kadar bloklar. Akış kapandığında `None` döner. Her olay bir `Result`tır — `Err`, tüm yeniden denemeler tükendi ve bağlantı kalıcı olarak gitti anlamına gelir.

Pong iletileri dahili tüketilir ve akışınızda asla görünmez.

### Kapatma

```rust theme={null}
stream.close();
```

Arka plan görevini anında durdurur. Ya da akışı düşürün.

## Birden çok akış

Tek istemci aynı anda birçok akış çalıştırabilir. Her biri kendi arka plan bağlantısını alır:

```rust theme={null}
let mut pumpfun = client.subscribe_yaml("config/pumpfun.yml")?;
let mut raydium = client.subscribe_yaml("config/raydium.yml")?;
let mut slots = client.subscribe_yaml("config/slots.yml")?;
```

Uç nokta sağlık durumunu paylaşırlar — bir akış başarısız bir uç noktayı karantinaya alırsa diğerleri bir sonraki yeniden bağlanmada onu atlar. Ancak bağlantıları ve yaşam döngüleri tamamen bağımsızdır.

Mevcut bir akıştan gelen veriye dayalı olarak da dahil olmak üzere istediğiniz zaman yeni akışlar başlatabilirsiniz.

## Tam örnek

pump.fun işlemlerini izleyen, imzayı çözen ve her biri için bir özet yazdıran bir akış.

```rust theme={null}
use orbitflare_sdk::{GeyserClientBuilder, Result};
use orbitflare_sdk::proto::geyser::subscribe_update::UpdateOneof;

#[tokio::main]
async fn main() -> Result<()> {
    let client = GeyserClientBuilder::new()
        .url("http://ny.rpc.orbitflare.com:10000")
        .fallback_url("http://fra.rpc.orbitflare.com:10000")
        .build()?;

    let mut stream = client.subscribe_yaml("grpc.yml")?;
    let mut tx_count: u64 = 0;

    println!("streaming...");

    while let Some(update) = stream.next().await {
        let update = update?;

        match update.update_oneof {
            Some(UpdateOneof::Transaction(tx)) => {
                tx_count += 1;
                if let Some(info) = &tx.transaction {
                    let sig = bs58::encode(&info.signature).into_string();
                    let fee = info.meta.as_ref().map(|m| m.fee).unwrap_or(0);
                    let ix_count = info.transaction
                        .as_ref()
                        .and_then(|t| t.message.as_ref())
                        .map(|m| m.instructions.len())
                        .unwrap_or(0);

                    println!(
                        "#{tx_count} slot={} sig={}... fee={fee} instructions={ix_count}",
                        tx.slot,
                        &sig[..16],
                    );
                }
            }
            Some(UpdateOneof::Slot(slot)) => {
                println!("slot {} ({:?})", slot.slot, slot.status);
            }
            _ => {}
        }
    }

    Ok(())
}
```

Bu `grpc.yml` ile:

```yaml theme={null}
transactions:
  pumpfun:
    vote: false
    failed: false
    account_include:
      - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"

slots:
  all:
    filter_by_commitment: true

commitment: confirmed
```
