> For the complete documentation index, see [llms.txt](https://docs.termina.technology/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.termina.technology/documentation/developer-docs-ru/obzor/ustanovka/spravochnik-po-rust.md).

# Справочник по Rust

## Справочник по Rust

Крейты `simulator-client` и `simulator-api` дают нативный Rust-интерфейс к симулятору Termina. Они подходят командам, которые хотят встроить бэктестинг прямо в свой Rust-код, а не использовать `sim` CLI.

* **`simulator-client`** — высокоуровневый асинхронный клиент. Он оборачивает WebSocket-протокол и предоставляет удобные билдеры для типовых сценариев: создания сессий, продвижения слотов, внедрения транзакций и чтения состояния аккаунтов.
* **`simulator-api`** определяет низкоуровневые типы протокола (структуры запросов и ответов, варианты ошибок, параметры сессии). Он нужен, если требуется прямой доступ к формату передачи данных или собственная реализация клиента.

Полный набор сквозных примеров — в [репозитории](https://github.com/nitro-svm/examples) со стартовым кодом.

#### Установка

```toml
[dependencies]
simulator-client = "0.23"
simulator-api = "0.23" # Только если нужны типы протокола (например, для собственного клиента)
```

#### Примеры

**Доступные слоты**

Перед созданием сессии убедитесь, что нужный диапазон слотов доступен для бэктеста.

```rust
use simulator_client::BacktestClient;

let client = BacktestClient::builder()
    .url("wss://simulator.termina.technology/backtest")
    .api_key(api_key)
    .build();

let ranges = client.available_ranges().await?;
for r in &ranges {
    println!(
        "slots {} – {}",
        r.bundle_start_slot,
        r.max_bundle_end_slot.unwrap_or(0)
    );
}
```

**Инициализация сессии**

Задайте диапазон слотов и нужные необязательные поля в параметрах создания сессии, затем создайте сессию:

* `signer_filter`: пропускать исторические транзакции, подписанные указанными адресами
* `actions`: выполнять заранее заданное действие в каждом слоте или при срабатывании на определенные транзакции
* `extra_compute_units`: повысить лимит вычислительных единиц, чтобы транзакции не падали

Остальные поля — в [полном справочнике](https://docs.rs/simulator-api/0.23.0/simulator_api/struct.CreateSessionParams.html).

```rust
use simulator_client::{Continue, CreateSession, ManagedBacktestSession, ManagedEvent};

let request = CreateSession::builder()
    .start_slot(300_000_000)
    .slot_count(100)
    .build();
```

```rust
// Используйте управляемый клиент вместо «сырого» `BacktestClient`:
// он автоматически переподключается при обрыве соединения
let mut session = ManagedBacktestSession::start(
    "wss://simulator.termina.technology/backtest".to_string(),
    api_key,
    request,
).await?;

loop {
    // Сервер сначала отправляет `slotNotification` для `startSlot`,
    // а затем `readyForContinue`, когда сессия готова
    match session.next_event().await? {
        ManagedEvent::ReadyForContinue => {
            session.send_continue(Continue::builder().build().into_params()).await?;
        }
        ManagedEvent::Completed { .. } => break,
        _ => {}
    }
}
session.shutdown().await;
```

**Чтение и запись**

Каждая сессия поддерживает стандартные методы и подписки Solana JSON-RPC по адресу `/backtest/<session_id>`, в том числе:

* `getAccountInfo`, `getBalance`, `getMultipleAccounts`
* `accountSubscribe`, `programSubscribe`, `signatureSubscribe`

> Полный список поддерживаемых методов подписки Solana — в [справочнике API](https://claude.ai/documentation/overview/installation/api-reference.md#api-table).

RPC-клиент сессии используется для отправки транзакций и чтения аккаунтов.

```rust
use std::str::FromStr;
use solana_sdk::pubkey::Pubkey;

// Соберите транзакцию любыми инструментами Solana SDK
let tx: solana_sdk::transaction::VersionedTransaction = /* ... */;

session
    .continue_until_ready(
        Continue::builder()
            .advance_count(1)
            .build()
            .push_transaction(&tx)?,
        Some(Duration::from_secs(30)),
        |_| {},
    )
    .await?;

let pubkey = Pubkey::from_str("SomePubkey11111111111111111111111111111111")?;
let account = session.rpc().get_account(&pubkey).await?;
println!("lamports: {}", account.lamports);
```

Также можно открыть WebSocket-соединение и использовать стандартные методы подписки.

```rust
use solana_commitment_config::CommitmentConfig;

let _handle = session
    .subscribe_program_logs(
        "YourProgramId111111111111111111111111111111",
        CommitmentConfig::confirmed(),
        |notification| async move {
            println!("logs: {:?}", notification.value.logs);
        },
    )
    .await?;

let _handle = session
    .subscribe_account_diffs(
        "SomePubkey11111111111111111111111111111111",
        |diff| async move {
            println!("account changed: {:?}", diff);
        },
    )
    .await?;

// Чтобы отписаться, достаточно удалить handle
```

**Замена программы**

Чтобы протестировать новую логику программы, скомпилируйте новый бинарник и подмените им существующий.

```rust
let elf = std::fs::read("your_program.so")?;

// Выводит корректную структуру аккаунта ProgramData через RPC-эндпоинт сессии
let modifications = session
    .modify_program("YourProgramId111111111111111111111111111111", &elf)
    .await?;

// Изменения применяются при следующем `Continue`
session
    .continue_until_ready(
        Continue::builder()
            .advance_count(1)
            .modify_accounts(modifications)
            .build(),
        None,
        |_| {},
    )
    .await?;
```

**Перенаправление потока ордеров**

Исторические свопы можно перенаправить через Jupiter Metis и посмотреть, как изменение параметров повлияло бы на поток, который получил бы пул.

```rust
use simulator_client::{AccountModifications, CreateSession};

// При необходимости внедрите пул, которого еще нет ончейн, чтобы протестировать котирование на новом рынке
// (проще всего скопировать и доработать существующий пул той же программы)
let accounts = AccountModifications(BTreeMap::from([
    (pool, AccountData {
        data: EncodedBinary::new(pool_data_b64, BinaryEncoding::Base64),
        owner: pool_program,
        lamports: pool_lamports,
        executable: false,
        space: pool_data_len,
    }),
    (vault_a, /* SPL-токен-аккаунт с инвентарем */),
    (vault_b, /* SPL-токен-аккаунт с инвентарем */),
]));
```

{% hint style="warning" %} При внедрении нового пула, если программа проверяет связи между аккаунтами (например, vault, производные от пула и mint), эти связи нужно сохранить, иначе свопы через новый пул будут падать. {% endhint %}

Чтобы включить перенаправление, обновите параметры создания сессии.

```rust
use simulator_api::{RerouteAggregators, SwapAggregator};

let all_aggregators = RerouteAggregators::new([
    SwapAggregator::Jupiter,
    SwapAggregator::Okx,
    SwapAggregator::Dflow,
    SwapAggregator::Titan,
]);

let request = CreateSession::builder()
    .start_slot(START_SLOT)
    .end_slot(END_SLOT)
    .reroute_order_flow(true)               // Перенаправлять исторические свопы через Jupiter Metis
    .reroute_aggregators(all_aggregators)   // Свопы каких агрегаторов перенаправлять
    .reroute_extra_markets([pool].into())   // Сообщить роутеру о пуле
    .build()
    .add_override(START_SLOT, accounts)     // Пул существует с первого слота
    .into_request()?;
```

**Сводка и метрики**

Чтобы получить сводку по перенаправлениям, подпишитесь на уведомления `replacementSubscribe`. Для каждого перенаправленного свопа доступны:

* маршрут, выбранный роутером, по шагам, с адресом каждого использованного пула
* входящие и исходящие объемы на каждом шаге
* исходный маршрут и исполнение ончейн для сравнения

```rust
use simulator_client::reroute_report::{self, Target};

// Площадку можно определить по метке роутера, ID программы или по обоим
let target = Target::new(None, Some(pool_program));
let report = reroute_report::from_notifications(target, &notifications)?;
println!("{}", report.render(None));
```

Сводка сессии также показывает, сколько свопов было обнаружено, перенаправлено, симулировано и успешно исполнено.
