Skip to main content
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
CPI (cross-program invocation) — это механизм, благодаря которому одна программа Solana вызывает другую. Программы Raydium на Anchor поставляются с CPI wrapper крейтами, которые превращают место вызова в типизированный вызов функции — структуры аккаунтов с проверенными именами полей и cpi::<ix>() вспомогательные функции. На этой странице описан общий паттерн; специфичные для продукта примеры кода смотрите на странице code-demos каждого раздела продукта.

Зависимости Cargo

Флаг функции cpi заставляет крейты компилироваться только в поверхность CPI (структуры аккаунтов + invoker’ы) вместо полной программы, так что ваш бинарный файл остаётся небольшим. Для рабочих примеров CPI, которые подключают структуры аккаунтов от начала до конца, смотрите raydium-io/raydium-cpi-example (охватывает AMM v4, CPMM и CLMM).

Построение списка аккаунтов

Каждый CPI Raydium требует структуры Accounts в вызывающей программе. Поля совпадают с порядком аккаунтов инструкции программы один в один, с валидаторами на уровне поля:
Большинство аккаунтов со стороны Raydium — это UncheckedAccount, потому что вызываемая программа (Raydium) отвечает за их проверку. Ваша вызывающая программа строго проверяет только аккаунты, которыми вы владеете — пользовательские ATA, собственные PDA. Комментарий /// CHECK: подавляет предупреждение Anchor о недостающих проверках.

Построение вызова CPI

Anchor генерирует по одному вспомогательному методу для каждой инструкции:
cpi::swap_base_input генерируется из IDL; его список аргументов зеркально отражает список аргументов инструкции Anchor.

Сids подписантов (CPI подписанный PDA)

Когда ваша программа подписывает CPI от имени PDA (обычно для хранилищ, условных сделок и т.д.), используйте CpiContext::new_with_signer:
Сids подписантов должны совпадать с производной PDA. Для любого аккаунта, переданного как authority (или другая роль подписанта), рантайм Solana проверяет, что PDA подписывает через эти seeds.

Оставшиеся аккаунты

Некоторые инструкции Raydium принимают оставшиеся аккаунты — список переменной длины, добавленный после фиксированных аккаунтов. Канонические примеры:
  • CLMM SwapV2: добавляет 1–8 аккаунтов TickArrayState, соответствующих tick массивам, которые может пересечь swap.
  • Farm v6 Deposit: добавляет пары (reward_vault, user_reward_ata) для каждого активного потока вознаграждений.
CPI helpers Anchor не проверяют типы оставшихся аккаунтов. Передавайте их через .with_remaining_accounts(...):
Порядок имеет значение: получающая программа перебирает оставшиеся аккаунты в порядке, в котором вы их передаёте. Для CLMM tick массивы должны быть упорядочены по направлению (первый массив в направлении swap идёт первым). Для farm v6 слоты вознаграждений идут в порядке индекса слота.

Распространение ошибок

Программы Raydium возвращают собственные перечисления ошибок. Anchor их оборачивает; ваша вызывающая программа видит их как Err(ProgramError::Custom(code)). Для обработки конкретных ошибок:
Номер кода ошибки стабилен в соответствии с политикой IDL (sdk-api/anchor-idl). Вы можете тестировать конкретные коды, сравнивая с числовым значением.

Бюджет вычислений в составных CPI

Каждый фрейм CPI имеет накладные расходы (~1,500 CU для самого вызова), и собственное потребление CU вызываемого программой складывается с вашим. Транзакция, которая вызывает CPMM swap изнутри вашей программы, расходует:
Для маршрутизации с несколькими уровнями (ваша программа → агрегатор → CPMM + CLMM + farm harvest), бюджет ≥500k CU. Всегда устанавливайте явную инструкцию ComputeBudgetProgram::set_compute_unit_limit(...) в транзакции — лимит по умолчанию 200k CU молча исчерпается.

AMM v4 — ручное построение Instruction

AMM v4 не имеет крейта Anchor. Постройте Instruction вручную:
Полный список аккаунтов смотрите в products/amm-v4/code-demos.

Farm v6 — оставшиеся аккаунты пар вознаграждений

Farm v6’s Deposit / Withdraw / Harvest использует паттерн пары (reward_vault_i, user_reward_ata_i) в оставшихся аккаунтах. Точная последовательность:
Одна пара на активный (работающий или закончившийся, но неполученный) слот вознаграждений. Пропускайте неиспользуемые слоты; программа диспетчеризует по farm_state.reward_infos[i].reward_state.

Тестирование потока CPI

Локальная разработка требует наличия программ Raydium в вашем тестовом валидаторе. Варианты:
  1. anchor test с клонированием программы — в Anchor.toml:
    Это подтягивает развёрнутый байткод из мейннета в ваш локальный валидатор.
  2. Devnet — Raydium развёртывает все программы на devnet с теми же program ID, что и мейннет. Запустите anchor test --provider.cluster devnet для обращения к живому коду.
  3. Локальное развёртывание — клонируйте репозитории Raydium и выполните anchor deploy на локальный валидатор. Добавляет накладные расходы цикла тестирования, но позволяет изменить вызываемую программу для отладки.

Ссылки

Источники: