Перейти к содержимому

Bundle-кошельки

Bundle — набор кошельков под управлением протокола (PDA), которые выполняют дополнительные покупки одновременно с initial buy. Bundle распределяет давление покупки по многим кошелькам в одной атомарной связке, а затем позволяет заёмщику свернуть позиции при закрытии займа.

Bundle настраивается per пресет запуска и переиспользуется между лончами.

Каждый bundle-кошелёк — Program Derived Address (PDA), производный от:

  • сида "bundle"
  • адреса пресета
  • индекса кошелька (0, 1, 2, …)

Поскольку адреса детерминированы, протокол подписывает за них в CPI без хранения приватных ключей. Отдельных кошельков, которыми вы управляете, нет — управляет протокол. Ваша задача — задать количество кошельков, прогреть их один раз, потом переиспользовать между лончами и слить (drain) при retirement пресета.

Количество bundle-кошельков задаётся в Bundle Addresses Count в пресете (верхняя граница ограничена программой). Сами адреса хранятся в персональной для пресета Address Lookup Table (Bundle ALT), чтобы транзакция запуска уложилась в лимиты Solana по аккаунтам.

  • Распределённый initial fill — вместо одного кошелька, который покупает всё, давление покупки расходится по N кошелькам в одной атомарной связке. Полезно, когда важно сразу иметь много холдеров после запуска.
  • Анти-снайп — в связке с curve-checkpoint и поддержкой Jito bundle-покупки дают плотную атомарную последовательность, в которую снайперам сложно встроиться.
  • Сворачивание одним действием — bundle-доли продаются через bundle_sell_all_market_0 (chunks до 20 кошельков на tx), остаток SOL сметается через bundle_drain_0.

Если эти свойства не нужны, можно запускать с bundle_addresses_count = 0 (или вообще без пресета), и bundle-слой пропускается.

Жизненный цикл: warmup один раз, reuse, drain при retirement

Заголовок раздела «Жизненный цикл: warmup один раз, reuse, drain при retirement»
initialize_launch_preset ← создание пресета
bundle_warmup_0 × chunks ← ОДНОРАЗОВАЯ настройка bundle-кошельков
═══ reuse между многими лончами ═══
launch_0 → migrate → complete → bundle_buy × chunks → user_buy → … → repay/liquidate
launch_0 → migrate → complete → bundle_buy × chunks → user_buy → … → repay/liquidate
═══ retire ═══
bundle_drain_0 × chunks ← закрывает всё, сметает SOL вам
delete_launch_preset ← опциональная финальная чистка

Паттерн warmup–reuse–drain — серьёзное изменение относительно прошлой версии, где setup делался per-launch. Теперь setup-расходы оплачиваются один раз и амортизируются на все лончи с этого пресета.

На странице пресета (или при создании) задайте Bundle Addresses Count и нажмите Recreate ALT. Приложение выведет все PDA bundle-кошельков и запишет их в новую Address Lookup Table, владельцем которой будет ваш кошелёк. Адрес ALT попадает в пресет.

При смене количества bundle-кошельков сделайте Recreate ALT (или Amend ALT, чтобы дополнить без полной пересборки) — иначе ALT разойдётся с тем, что ожидает программа.

До первого лонча с этого пресета запустите bundle_warmup_0 — одноразовую инициализацию per-protocol состояния каждого bundle-кошелька:

  • WSOL ATA на bundle-кошельке (чтобы он мог держать quote-токены)
  • pump.fun user_volume_accumulator (UVA)
  • PumpSwap user_volume_accumulator

Warmup обязателен для любого пресета, у которого bundle-чанки будут ≥4 кошельков на пост-грэд ветке — без warmup такие чанки упрутся в Solana-лимит 64 инструкций на tx. Для пресетов с ≤3 кошельками на чанк и только pre-grad warmup опционален (он всё равно экономит compute units, но не обязателен).

Warmup идемпотентен per wallet — повторный запуск на уже прогретых кошельках безопасен. Размер чанка — до ~6 кошельков на tx (ATA Create — тяжёлая суб-CPI).

Warmup заблокирован при открытом займе: active_loan пресета должен быть default pubkey. Сначала закройте открытый займ.

Каждому bundle-кошельку также нужен нативный SOL для:

  • Покрытия комиссий за транзакции bundle sell / collect
  • Небольшого буфера на любые дополнительные ATA, создаваемые во время торговли

На странице пресета есть таблица Bundle Wallets с индексом, адресом, ATA, volume accumulator и балансом SOL для каждого. Кнопка Fund Wallets пополняет их до рекомендованного уровня. Кошельки ниже порога подсвечены.

Финансирование — отдельная транзакция; SOL уходит с вашего основного кошелька.

При запуске из пресета слайдер Initial Buy Amount делит сумму займа между initial buy и bundle pot. Bundle pot распределяется по всем кошелькам согласно Bundle Distribution Type (сейчас только Equal). Каждый чанк bundle-покупок идёт одной транзакцией bundle_buy_universal_0; приложение само режет на чанки по MAX_BUNDLE_CHUNK_SIZE = 20.

Bundle-доли base-токенов учитываются в loan.bundled_base_amount отдельно от залога initial buy. Один и тот же пресет годится для многих последовательных лончей — после закрытия каждого займа (repay или liquidate) active_loan освобождается, и следующий лонч разрешён.

При repay протокол автоматически сметает base-токены bundle-кошельков на ваш основной кошелёк — отдельное действие не нужно.

При liquidate программа требует bundled_base_amount == 0. Используйте один из вариантов:

  • Sell & Liquidate (страница займа) — один клик; продаёт все bundle base через bundle_sell_all_market_0, затем ликвидирует займ в том же потоке
  • Sell Selected (пресет → Bundle Wallets) — явный выбор per-wallet; полезно, если хотите растянуть продажи по нескольким tx

Действия sell/collect принимают произвольные подмножества индексов (wallet_indexes: Vec<u16>), так что операцию можно разбить на несколько tx. Практический лимит — ~20 кошельков на чанк для sell.

После repay/liquidate на bundle-кошельках остаётся накопленный нативный SOL (неизрасходованное финансирование + rent-буфер ATA). Он возвращается при retirement пресета.

Когда пресет вам больше не нужен, запустите bundle_drain_0, который:

  1. Закроет WSOL ATA на каждом bundle-кошельке (rent → bundle-кошелёк, любой WSOL-баланс разворачивается в нативный SOL)
  2. Закроет pump.fun UVA (rent → bundle-кошелёк)
  3. Закроет PumpSwap UVA (rent → bundle-кошелёк)
  4. System-transfer всех lamports с bundle-кошелька на recipient (ваш основной кошелёк)

Drain заблокирован при открытом займе, как и warmup. Размер чанка — до ~6 кошельков на tx.

Так возвращается rent, оплаченный при warmup, плюс остаток финансирования.

Таблица Bundle Wallets может показывать баланс SPL по любому mint (по умолчанию — base-mint запуска). Кнопка SPL token над таблицей переключает отображаемый mint — полезно при проверке предзапускового финансирования или балансов другого токена после запуска.

Если вы возвращаетесь к пресету позже без активной ссылки на займ, но на bundle-кошельках всё ещё лежат токены, нажмите Try to Find Loan — приложение найдёт недавний займ, использовавший этот пресет, и подставит его адрес для маршрутизации sell/collect.

ТипПоведение
Equal (0)Протокол делит bundle-долю суммы займа на N равных частей, по одной на bundle-кошелёк

В будущем могут появиться другие типы распределения.

Bundle-покупки и продажи идут через bundle_buy_exact_quote_in_market_universal_0 и bundle_sell_all_market_0. Эти инструкции universal — они читают флаг complete у bonding curve в момент исполнения и сами роутят на pump.fun или PumpSwap. Bundle ALT содержит адреса обеих ветвей, поэтому одна и та же ALT работает и до, и после грэдуации.

Отдельная ALT или отдельный workflow при грэдуации посреди займа не нужны.

  • Прогрейте один раз на пресет — не пропускайте этот шаг; setup-расходы амортизируются на все будущие лончи
  • Recreate ALT после изменения количества — ALT должна содержать ровно те PDA bundle-кошельков, которые ожидает программа
  • Пополняйте финансирование перед каждым лончем — фонды переживают лончи, но расходуются на комиссии sell/collect
  • Используйте Jito для атомарности — без Jito чанки bundle могут попасть в разные слоты; с Jito вся entry-связка приземляется вместе
  • Drain только при retirement — rent возвращается; если планируете ещё лончи с этого пресета, оставьте его в warm-состоянии