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

# Rust SDK 모범 사례

> Helius Rust SDK를 사용하는 AI 에이전트를 위한 권장 패턴입니다. 트랜잭션 기록, 트랜잭션 전송, 일괄 처리, 웹훅, 페이지네이션, 점진적 패치, 일반적인 실수 및 오류 처리를 다룹니다.

[Helius Rust SDK](https://github.com/helius-labs/helius-rust-sdk)를 사용하는 에이전트를 위한 모범 사례 및 권장 패턴입니다. 설치 및 시작하기에 대한 내용은 [개요](/docs/ko/agents/rust-sdk)를 참조하세요.

## 에이전트에 대한 권장 사항

### 두 단계 조회 대신 `get_transactions_for_address` 사용

`get_transactions_for_address`는 서명 조회와 트랜잭션 가져오기를 서버 측 필터링과 함께 단일 호출로 결합합니다.

```rust theme={"system"}
// GOOD: Single call, server-side filtering
let txs = helius.rpc().get_transactions_for_address(
    "address".to_string(),
    GetTransactionsForAddressOptions {
        transaction_details: Some(TransactionDetails::Full),
        limit: Some(100),
        filters: Some(GetTransactionsFilters {
            token_accounts: Some(TokenAccountsFilter::BalanceChanged),
            ..Default::default()
        }),
        ..Default::default()
    },
).await?;

// BAD: Two calls, client-side filtering
let sigs = helius.connection().get_signatures_for_address(&address)?;
```

### 표준 전송에 `send_smart_transaction` 사용

자동으로 시뮬레이션하고, 컴퓨팅 단위를 추정하며, 우선 수수료를 가져오고 확인합니다. `ComputeBudget` 명령어를 수동으로 작성하지 마세요. SDK가 자동으로 추가합니다.

```rust theme={"system"}
let sig = helius.send_smart_transaction(SmartTransactionConfig {
    create_config: CreateSmartTransactionConfig {
        instructions: vec![your_instruction],
        signers: vec![wallet_signer],
        priority_fee_cap: Some(100_000),
        cu_buffer_multiplier: Some(1.1),
        ..Default::default()
    },
    ..Default::default()
}).await?;
```

### 초저지연에 Helius Sender 사용

시간이 민감한 트랜잭션(차익 거래, 스나이핑, 청산)을 위해 `send_smart_transaction_with_sender`를 사용하세요. 이는 Helius의 다중 지역 인프라와 Jito를 통해 라우팅됩니다.

```rust theme={"system"}
let sig = helius.send_smart_transaction_with_sender(
    SmartTransactionConfig {
        create_config: CreateSmartTransactionConfig {
            instructions: vec![your_instruction],
            signers: vec![wallet_signer],
            ..Default::default()
        },
        ..Default::default()
    },
    SenderSendOptions {
        region: "US_EAST".to_string(),    // Default, US_SLC, US_EAST, EU_WEST, EU_CENTRAL, EU_NORTH, AP_SINGAPORE, AP_TOKYO
        swqos_only: false,                // true = SWQOS only (lower tip), false = Dual (SWQOS + Jito)
        poll_timeout_ms: 60_000,
        poll_interval_ms: 2_000,
    },
).await?;
```

### 여러 자산에 `get_asset_batch` 사용

하나 이상의 자산을 가져올 때는 배치하세요. 루프에서 `get_asset`를 호출하지 마세요.

```rust theme={"system"}
// GOOD: Single request
let assets = helius.rpc().get_asset_batch(GetAssetBatch {
    ids: vec!["mint1".to_string(), "mint2".to_string(), "mint3".to_string()],
    ..Default::default()
}).await?;

// BAD: N requests
for id in mints {
    let asset = helius.rpc().get_asset(GetAsset { id, ..Default::default() }).await?;
}
```

### 폴링 대신 웹훅 사용

루프에서 `get_transactions_for_address`를 폴링하지 마세요. 서버 간 알림을 위해 웹훅을 사용하세요.

```rust theme={"system"}
let webhook = helius.create_webhook(CreateWebhookRequest {
    webhook_url: "https://your-server.com/webhook".to_string(),
    webhook_type: WebhookType::Enhanced,
    transaction_types: vec![TransactionType::Transfer, TransactionType::NftSale, TransactionType::Swap],
    account_addresses: vec!["address_to_monitor".to_string()],
    auth_header: Some("Bearer your-secret".to_string()),
    ..Default::default()
}).await?;
```

## 페이지네이션

### 토큰/커서 기반 (RPC V2 메소드)

```rust theme={"system"}
// get_transactions_for_address uses pagination_token
let mut pagination_token: Option<String> = None;
let mut all_txs = Vec::new();
loop {
    let result = helius.rpc().get_transactions_for_address(
        "address".to_string(),
        GetTransactionsForAddressOptions {
            limit: Some(100),
            pagination_token: pagination_token.clone(),
            ..Default::default()
        },
    ).await?;
    all_txs.extend(result.data);
    pagination_token = result.pagination_token;
    if pagination_token.is_none() { break; }
}

// Or use auto-paginating variants:
let all_accounts = helius.rpc().get_all_program_accounts(
    program_id.to_string(),
    GetProgramAccountsV2Config::default(),
).await?;
```

### 페이지 기반 (DAS API)

```rust theme={"system"}
let mut page = 1;
let mut all_assets = Vec::new();
loop {
    let result = helius.rpc().get_assets_by_owner(GetAssetsByOwner {
        owner_address: "...".to_string(),
        page,
        limit: Some(1000),
        ..Default::default()
    }).await?;
    let count = result.items.len();
    all_assets.extend(result.items);
    if count < 1000 { break; }
    page += 1;
}
```

## `token_accounts` 필터

`get_transactions_for_address`를 쿼리할 때, `token_accounts` 필터는 토큰 계정 활동이 포함되는지를 제어합니다:

| 값                | 동작                  | 사용 시기                                   |
| ---------------- | ------------------- | --------------------------------------- |
| `None`           | 주소에 직접적으로 관련된 트랜잭션만 | SOL 전송 및 프로그램 호출에만 관심이 있을 때             |
| `BalanceChanged` | 잔액을 변경한 토큰 트랜잭션도 포함 | **대부분의 에이전트에 권장** — 노이즈 없이 토큰 전송/수신을 표시 |
| `All`            | 모든 토큰 계정 트랜잭션 포함    | 전체 토큰 활동이 필요할 때 (많은 결과를 반환할 수 있음)       |

## `changed_since_slot` — 점진적 계정 가져오기

`changed_since_slot`는 주어진 슬롯 이후에 수정된 계정만 반환합니다. 동기화 또는 인덱싱 워크플로에 유용합니다. `get_program_accounts_v2`, `get_token_accounts_by_owner_v2`, `get_account_info`, `get_multiple_accounts`, `get_program_accounts` 및 `get_token_accounts_by_owner`에 의해 지원됩니다.

```rust theme={"system"}
// First fetch: get all accounts
let baseline = helius.rpc().get_program_accounts_v2(
    program_id.to_string(),
    GetProgramAccountsV2Config { limit: Some(10_000), ..Default::default() },
).await?;
let last_slot = current_slot;

// Later: only get accounts that changed since your last fetch
let updates = helius.rpc().get_program_accounts_v2(
    program_id.to_string(),
    GetProgramAccountsV2Config {
        limit: Some(10_000),
        changed_since_slot: Some(last_slot),
        ..Default::default()
    },
).await?;
```

## 일반적인 실수

1. **`transaction_details: Some(TransactionDetails::Full)`는 기본값이 아닙니다** — 기본적으로 `get_transactions_for_address`는 서명만 반환합니다. 전체 트랜잭션 데이터를 받으려면 `TransactionDetails::Full`를 설정하세요.

2. **`send_smart_transaction`와 함께 ComputeBudget 명령어를 추가하지 마세요** — SDK가 자동으로 추가합니다. 수동으로 추가하면 `HeliusError::InvalidInput` 오류가 발생합니다.

3. **우선 수수료는 마이크로램포트 단위** — 램포트가 아닙니다. `get_priority_fee_estimate`의 값은 이미 올바른 단위입니다.

4. **DAS 페이지네이션은 1-인덱스입니다** — `page: 1`가 첫 번째 페이지입니다, `page: 0`가 아닙니다.

5. **`async_connection()`는 `new_async` 또는 `HeliusBuilder`를 요구합니다** — `Helius::new()`로 생성된 클라이언트에서 `helius.async_connection()`를 호출하면 `Err(HeliusError::ClientNotInitialized)`가 반환됩니다.

6. **`get_asset`는 `Option<Asset>`를 반환합니다** — 성공적인 응답이 자산이 존재하지 않는 경우에도 `None`일 수 있습니다. `Option`를 명확히 처리하세요.

7. **Sender 팁은 필수입니다** — `send_smart_transaction_with_sender`는 팁을 자동으로 결정하고 추가합니다. 최소 0.0002 SOL (이중 모드) 또는 0.000005 SOL (SWQOS 전용).

8. **TLS 기능 플래그** — 크레이트는 기본적으로 `native-tls`입니다. 오픈SSL이 없을 때는 `features = ["rustls"]` (및 `default-features = false`)를 사용하세요.

## 오류 처리 및 재시도

SDK는 `HeliusError` 열거형을 통해 타입화된 오류 변수를 제공하여 이를 직접 매칭할 수 있습니다:

```rust theme={"system"}
use helius::error::{HeliusError, Result};

match helius.rpc().get_asset(request).await {
    Ok(asset) => { /* success */ }
    Err(HeliusError::Unauthorized { .. }) => { /* 401: invalid or missing API key */ }
    Err(HeliusError::RateLimitExceeded { .. }) => { /* 429: too many requests or out of credits */ }
    Err(HeliusError::InternalError { .. }) => { /* 5xx: server error, retry with backoff */ }
    Err(HeliusError::NotFound { .. }) => { /* 404: resource not found */ }
    Err(HeliusError::BadRequest { .. }) => { /* 400: malformed request */ }
    Err(HeliusError::Timeout { .. }) => { /* transaction confirmation timed out */ }
    Err(e) => { /* other errors: Network, SerdeJson, etc. */ }
}
```

### 재시도 전략

`RateLimitExceeded` 및 `InternalError`에서 지수 백오프로 재시도하세요:

```rust theme={"system"}
async fn with_retry<T, F, Fut>(f: F, max_retries: u32) -> Result<T>
where
    F: Fn() -> Fut,
    Fut: std::future::Future<Output = Result<T>>,
{
    for attempt in 0..=max_retries {
        match f().await {
            Ok(val) => return Ok(val),
            Err(HeliusError::RateLimitExceeded { .. })
            | Err(HeliusError::InternalError { .. }) if attempt < max_retries => {
                tokio::time::sleep(std::time::Duration::from_millis(1000 * 2u64.pow(attempt))).await;
            }
            Err(e) => return Err(e),
        }
    }
    unreachable!()
}
```

| 오류 변수               | HTTP 상태 | 조치             |
| ------------------- | ------- | -------------- |
| `Unauthorized`      | 401     | API 키 확인       |
| `RateLimitExceeded` | 429     | 백오프 후 재시도      |
| `InternalError`     | 5xx     | 지수 백오프로 재시도    |
| `BadRequest`        | 400     | 요청 매개변수 수정     |
| `NotFound`          | 404     | 리소스 존재 여부 확인   |
| `Timeout`           | —       | 타임아웃 증가 또는 재시도 |
