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

# Ledger в Tonhub

В Tonhub можно использовать аппаратный кошелек **Ledger** для хранения ключей и подписи транзакций в сети TON. Ниже описано, как работает эта интеграция: подключение, выбор аккаунта, подписание операций, ограничения и типичные ошибки.

# Назначение и возможности

**Ledger** — это аппаратное устройство, холодный кошелек, такой как Nano S, Nano X, Nano S Plus и другие, на котором установлено приложение **TON** через Ledger Live. Ключи никогда не покидают устройство, а подтверждение переводов и подписей происходит непосредственно на Ledger.\
В Tonhub Ledger используется как отдельный тип кошелька: пользователь подключает устройство по USB, то есть HID, на Android или по Bluetooth, то есть BLE, на iOS и Android, выбирает один из аккаунтов с индексами 0-9 и после этого может просматривать баланс, отправлять TON и токены, стейкать, пользоваться Holders и подключать dApp через TON Connect. Подписание транзакций и данных всегда выполняется на Ledger. Подключать можно неограниченное количество холодных кошельков.\
Минимальная версия приложения TON на Ledger — 2.4.1. Если установлена более старая версия, приложение покажет сообщение с просьбой обновить TON-приложение через Ledger Live.

# Подключение Ledger

## Добавление устройства

1. Пользователь на приветственном экране выбирает **"Import Wallet"** или аналогичный пункт и на экране выбора метода импорта нажимает **"Connect Ledger"**.
2. Открывается **Ledger Onboarding**, то есть `LedgerOnboardingFragment`: краткое описание и кнопка "Continue". По ссылке можно перейти к инструкции по установке TON-приложения: [https://tonwhales.com/ledger](https://tonwhales.com/ledger)
3. Пользователь принимает условия и политику, то есть `LegalCreate` с параметром `ledger: true`, после чего попадает на экран создания кошелька с настройкой **PIN-кода**, то есть `WalletSecurePasscodeComponent` с флагом `ledger`. Этот PIN нужен для доступа к приложению, а не к ключам на Ledger.
4. После настройки PIN пользователь переходит на экран подключения устройства, то есть `HardwareWalletFragment`, который в навигации отображается как "Ledger".

## Экран подключения (`HardwareWalletFragment`)

**Android:** доступны два способа:

* **USB (HID):** кнопка "Connect via USB". Устройство подключается кабелем, приложение создает HID transport и переходит к выбору аккаунта, то есть `LedgerSelectAccount`, либо сразу возвращает пользователя в приложение, если аккаунт уже был выбран.
* **Bluetooth:** кнопка "Connect via Bluetooth". Запускается поиск BLE-устройств; при необходимости приложение запрашивает разрешения, например доступ к геолокации на Android для BLE.

**iOS:** доступен только **Bluetooth**. Кнопка "Connect" запускает поиск Ledger через BLE; требуются Bluetooth-разрешения.

* На экране также показываются краткие инструкции и ссылка на **руководство по установке TON-приложения** на Ledger по адресу `tonwhales.com/ledger`.

## Выбор BLE-устройства (`LedgerDeviceSelectionFragment`)

После запуска поиска BLE отображается список найденных устройств. Пользователь выбирает свой Ledger.\
Приложение подключается к выбранному устройству через `TransportBLE.open(device.id)` и сохраняет соединение в контексте `TransportContext`. Если выбранный аккаунт еще не задан, пользователь переходит на экран **выбора аккаунта**, то есть `LedgerSelectAccount`.\
При ошибке доступа, например если на Android не выданы разрешения на геолокацию, показывается сообщение с кнопкой "Grant Permissions"; при необходимости открываются настройки приложения.

## Выбор аккаунта (`LedgerSelectAccountFragment`)

* Ledger поддерживает несколько TON-аккаунтов, индексы 0-9; в коде используется `pathFromAccountNumber(i, isTestnet)`. Приложение запрашивает адреса для каждого индекса, максимум до 10, и показывает список с балансами.
* Пользователь должен разблокировать Ledger и открыть на устройстве приложение TON. Пока TON-приложение закрыто или устройство заблокировано, экран показывает подсказки вроде "Unlock Ledger" или "Open TON application".
* Проверка готовности выполняется через `isLedgerTonAppReady(tonTransport)`: приложение опрашивает состояние "app open" и при необходимости запрашивает адрес для индекса 0, включая обход особенностей Ledger S.
* Пользователь выбирает аккаунт из списка. Выбранный аккаунт сохраняется в контексте и хранилище через `setLedgerSelected(addr.address)`; список Ledger-кошельков `ledgerWallets` обновляется, после чего происходит переход в основное Ledger-приложение, то есть `LedgerApp`.

## Повторное подключение и переключение кошельков

На главном экране, то есть `HomeFragment`, по нажатию на карточку кошелька или через меню открывается выбор аккаунта, то есть `AccountSelectorFragment`. В списке отображаются и обычные кошельки, и ранее добавленные аккаунты Ledger из `ledgerContext.wallets`.\
Если Ledger уже подключен, то есть есть `tonTransport`, при выборе "Ledger" открывается экран выбора аккаунта `LedgerSelectAccount` с текущим выбранным адресом.\
Если Ledger не подключен, выбор "Ledger" вызывает `ledgerContext.reset()` и открывает экран подключения `HardwareWalletFragment`. После BLE-подключения пользователь снова переходит к выбору аккаунта; после HID-подключения — к выбору аккаунта или обратно, если аккаунт уже был выбран.

# Основной интерфейс Ledger

После выбора аккаунта пользователь попадает в `LedgerApp` — полноэкранный режим с нижними вкладками:

* **Home (`LedgerHome`)** — карточка кошелька, баланс, продукты, такие как переводы, получение, стейкинг, обмены, Holders и другие, а также переключатель режимов Holders и Wallet, то есть `AppModeToggle`.
* **History (`LedgerTransactions`)** — список транзакций. Режим зависит от типа аккаунта: для обычного кошелька это `TransactionsFragment`, а для Holders — `HoldersTransactionsFragment`.
* **Settings (`LedgerSettings`)** — для обычного кошелька открывается `SettingsFragment`, а в режиме Holders — `HoldersSettings`.

Состояние выбранного Ledger-аккаунта хранится в приложении через `ledgerSelected` в `appState`. При следующем запуске, если выбран Ledger, onboarding сразу переводит пользователя в состояние `LedgerApp`, и он попадает туда без повторного выбора, если в `ledgerContext.wallets` уже есть сохраненный аккаунт и восстановлен `ledgerContext.addr`.

# Подписание транзакций

Когда пользователь отправляет TON или токены с Ledger-кошелька, приложение формирует order операции, то есть `LedgerOrder`, и открывает экран подписи `LedgerSignTransfer`. Пользователь видит сводку: получатель, сумма, комиссия и при необходимости данные токена.\
Подписание выполняется через `tonTransport`, то есть `TonTransport` из `@ton-community/ton-ledger`: строится сообщение и вызывается метод подписи на устройстве через путь аккаунта `pathFromAccountNumber(addr.acc, isTestnet)`.\
**Важно:** на Ledger должно быть открыто TON-приложение, а само устройство должно быть разблокировано. Иначе подпись завершится ошибкой.

## Обработка ошибок подписи

* **LockedDeviceError:** показывается сообщение "Unlock Ledger".
* **Нет соединения**, то есть `!tonTransport`: приложение возвращает пользователя назад и показывает диалог "Ledger connection error" с кнопками "Connect" и "Cancel".
* **TON-приложение не открыто:** после проверки `isLedgerTonAppReady` показывается сообщение с просьбой открыть TON-приложение на Ledger.
* **Версия TON-приложения ниже 2.4.1:** проверяется через `checkLedgerTonAppVersion`; пользователь получает сообщение о необходимости обновить TON-приложение в Ledger Live.
* **"Небезопасная" транзакция при отключенном Blind Signing:** если операция помечена как unsafe и в настройках Ledger отключена подпись неподтвержденных данных, показывается сообщение наподобие "Enable unconfirmed data signing in TON app settings on Ledger".
* **Пользователь отменил операцию на Ledger**, код `0x6985`: показывается сообщение о том, что подпись была отменена.

Во всех остальных случаях отображается общее сообщение "Transaction rejected" и кнопка "Back".

# Подписание данных

Для dApp и TON Connect-сценариев может потребоваться подпись произвольных данных, например для аутентификации. Экран `LedgerSignData` позволяет ввести данные, в том числе в Base64, домен и extension, если это нужно, а затем подписать их на Ledger через `tonTransport.signData` с типом `app-data`.\
Используется текущий путь аккаунта; результат, то есть подпись, cell и timestamp, показывается на экране. Требования те же: устройство должно быть разблокировано, а TON-приложение открыто.

# Потеря соединения и повторное подключение

При потере соединения, например при отключении USB, выключении Bluetooth или самого Ledger, вызывается обработчик `onDisconnect`. Приложение пытается переподключиться ограниченное число раз: для HID — один раз, для BLE — два раза. Во время попыток может показываться состояние переподключения `isReconnectLedger`.\
Если переподключение не удалось, BLE-состояние сбрасывается в ошибку и вызывается `reset()`: соединение и выбранный адрес очищаются из контекста, а пользователю нужно снова подключить Ledger и, при необходимости, заново выбрать аккаунт.\
При явном выходе из Ledger-кошелька показывается диалог подтверждения; после согласия выбранный Ledger-аккаунт удаляется из списка кошельков, выбор очищается через `clearLedgerSelected`. Если это был последний Ledger-кошелек, контекст полностью сбрасывается.

# Ограничения и отличия от обычного кошелька

**DeDust:** если выбран Ledger-кошелек, в разделе "Exchanges", то есть `SelectExchangeFragment`, элемент DeDust.io не показывается, то есть `!isLedger`. Доступен только Changelly. Причина в том, что интеграция DeDust через WebView и TON Connect в текущем виде не поддерживает Ledger.

# Хранение данных

* **Список Ledger-кошельков** `ledgerWallets`: массив объектов вида `{ acc, address, deviceId?, publicKey }`, который хранится в storage по ключу `ledgerWalletsKey`. При выборе аккаунта он добавляется в список, если еще не был добавлен.
* **Выбранный Ledger-аккаунт:** адрес сохраняется через `setLedgerSelected(addr.address)` в `appState`. При следующем входе в `LedgerApp` этот адрес восстанавливается.
* **Включенная поддержка Ledger в приложении:** флаг `app_ledger_enabled` в storage; он используется для отображения или скрытия опции Ledger в списке кошельков, например в настройках или при первом выборе способа входа.
* Ключи и seed-фраза **не хранятся** в приложении; они остаются только на Ledger.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.