SHiNE-server/Dev_Docs/Протоколы/Формат_взаимодействия_внешнего_кошелька_и_ESP32.md

14 KiB
Raw Blame History

Формат взаимодействия внешнего кошелька и ESP32

Этот документ фиксирует актуальный формат взаимодействия между внешним браузерным wallet-расширением SHiNE и устройством ESP32-S3-Touch-AMOLED-2.16.

Документ описывает:

  • как расширение получает текущий активный публичный ключ кошелька с ESP32;
  • как расширение отправляет на ESP32 запрос подписи транзакции;
  • что именно считается активным кошельком на ESP32;
  • какие проверки и UI-реакции ожидаются в браузерном расширении и на устройстве;
  • какие ограничения действуют в текущей версии протокола.

1. Общая идея

Устройство ESP32 хранит master secret пользователя и локально умеет выводить несколько кошельков из одного секрета.

На устройстве в UI пользователь выбирает текущий активный кошелёк:

  • client.key
  • root.key
  • custom

Для custom используется derivation:

sha256(base64(secret32) + "|wallet." + customName)

Браузерное расширение не указывает ESP32, какой кошелёк нужно вернуть в первом запросе. Оно просто спрашивает:

какой кошелёк сейчас активен на устройстве

ESP32 возвращает:

  • тип текущего активного кошелька;
  • его публичный ключ Base58.

2. Транспорт и маршрут

Текущий формат использует уже существующую wallet-session браузерного расширения.

Схема маршрута:

browser extension -> SHiNE server -> homeserver session on ESP32 -> SHiNE server -> browser extension

В текущем формате:

  • отдельная цифровая подпись payload не добавляется;
  • отдельное E2E-шифрование для wallet RPC не добавляется;
  • используется существующая авторизованная wallet-session, транспорт WSS и server-side маршрут через уже существующую операцию CallSignalToSession.

3. Запрос текущего публичного ключа кошелька

3.1. Назначение

Операция нужна, чтобы браузерное расширение могло узнать, какой кошелёк сейчас выбран на ESP32, и показать его пользователю перед дальнейшими действиями.

3.2. Формат запроса

{
  "v": 1,
  "operation": "get_wallet_public_key",
  "requestId": "1718998123456-482193",
  "timeMs": 1718998123456
}

3.3. Поля запроса

  • v — версия формата wallet RPC. Для текущего варианта: 1.
  • operation — строка операции. Для текущего запроса: get_wallet_public_key.
  • requestId — идентификатор запроса, уникальный в пределах сеанса расширения. Рекомендуемый формат: timeMs-random.
  • timeMs — локальное время отправителя в миллисекундах.

3.4. Поведение ESP32

При получении такого запроса ESP32:

  1. смотрит, какой кошелёк сейчас выбран в локальном UI;
  2. вычисляет или берёт уже подготовленный публичный ключ именно этого активного кошелька;
  3. возвращает тип кошелька и его publicKeyBase58.

Запрос не содержит:

  • walletSelector;
  • customName;
  • targetSessionName.

Они намеренно не входят в текущий формат этого запроса.

4. Формат ответа

{
  "v": 1,
  "op": "get_wallet_public_key_result",
  "requestId": "1718998123456-482193",
  "ok": true,
  "wallet": {
    "type": "custom",
    "publicKeyBase58": "...."
  },
  "timeMs": 1718998123999
}

5. Поля ответа

  • v — версия формата ответа. Сейчас 1.
  • op — строка результата операции. Сейчас get_wallet_public_key_result.
  • requestId — должен совпадать с requestId исходного запроса.
  • ok — признак успешного результата.
  • wallet.type — тип активного кошелька:
    • client.key
    • root.key
    • custom
  • wallet.publicKeyBase58 — публичный ключ активного кошелька в Base58.
  • timeMs — время формирования ответа на стороне ESP32 в миллисекундах.

6. Ошибки текущего формата

Минимальный формат ошибки допускается таким:

{
  "v": 1,
  "op": "get_wallet_public_key_result",
  "requestId": "1718998123456-482193",
  "ok": false,
  "error": "wallet_unavailable",
  "timeMs": 1718998123999
}

Рекомендуемые коды ошибок:

  • wallet_unavailable — на устройстве нельзя получить текущий кошелёк;
  • secret_not_configured — на устройстве ещё нет корректно сохранённого секрета;
  • wallet_type_unknown — выбранный локальный тип кошелька не распознан;
  • internal_error — прочая локальная ошибка устройства.

7. Правила для браузерного расширения

После ответа ok=true расширение должно:

  1. показать пользователю тип кошелька;
  2. показать полный publicKeyBase58;
  3. дать кнопку копирования ключа в буфер;
  4. сохранить этот ключ как текущий ключ устройства для следующей операции подписи.

7.1. Проверка через PDA Solana

Расширение уже знает публичные ключи пользователя из Solana PDA. Поэтому оно может дополнительно проверить ответ ESP32:

  • если wallet.type = client.key, то publicKeyBase58 должен совпасть с clientKey, прочитанным из PDA;
  • если wallet.type = root.key, то publicKeyBase58 должен совпасть с rootKey, прочитанным из PDA;
  • если wallet.type = custom, такой проверки по PDA пока нет.

При несовпадении для client.key или root.key расширение должно показать пользователю предупреждение, что возвращённый ключ не совпал с ожидаемым ключом из PDA.

8. Ожидаемое поведение UI расширения

8.1. Общий вид popup

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

8.2. Состояние без подключения

Если wallet-session ещё не подключена:

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

8.3. Состояние после подключения

Если wallet-session уже подключена:

  • показывается статус Подключено;
  • остаётся выбор homeserver;
  • появляется кнопка запроса текущего кошелька;
  • появляется кнопка Отключить.

8.4. Подключение кошелька с сайта

Когда сайт просит подключить кошелёк через расширение, расширение должно вести себя как обычный wallet extension:

  1. показать пользователю подтверждение подключения;
  2. показать, какой именно кошелёк будет подключён;
  3. после подтверждения пользователя завершить подключение;
  4. если пользователь отказался, не подключать кошелёк к сайту.

9. Запрос подписи транзакции

9.1. Назначение

Операция нужна, чтобы браузерное расширение могло запросить у ESP32 подпись Solana-транзакции текущим активным кошельком.

Расширение передаёт:

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

ESP32:

  1. показывает пользователю запрос подтверждения;
  2. показывает комментарий к подписи;
  3. после нажатия APPROVE или REJECT возвращает ответ в расширение.

9.2. Формат запроса

{
  "v": 1,
  "operation": "sign_transaction",
  "requestId": "1718998123456-482193",
  "timeMs": 1718998123456,
  "publicKeyBase58": "....",
  "transactionBase64": "....",
  "comment": "Site https://example.com requested transaction signature"
}

9.3. Поля запроса

  • v — версия wallet RPC. Сейчас 1.
  • operation — строка операции: sign_transaction.
  • requestId — идентификатор запроса.
  • timeMs — время отправки на стороне расширения.
  • publicKeyBase58 — публичный ключ, от которого ожидается подпись.
  • transactionBase64 — сериализованная Solana transaction в base64.
  • comment — короткое текстовое описание, которое ESP32 показывает пользователю при запросе подписи.

9.4. Поведение ESP32

При получении такого запроса ESP32:

  1. сравнивает publicKeyBase58 с публичным ключом текущего активного выбранного кошелька;
  2. если ключ не совпадает, сразу возвращает ошибку wallet_mismatch;
  3. если ключ совпадает, показывает отдельный экран подтверждения подписи;
  4. на экране показывает:
    • каким кошельком будет выполнена подпись;
    • комментарий comment;
    • кнопки APPROVE и REJECT;
  5. если пользователь подтверждает подпись, ESP32 подписывает транзакцию и возвращает результат;
  6. если пользователь отклоняет, ESP32 возвращает rejected_by_user.

10. Формат ответа на подпись

{
  "v": 1,
  "op": "sign_transaction_result",
  "requestId": "1718998123456-482193",
  "ok": true,
  "publicKeyBase58": "....",
  "signatureBase58": "....",
  "signedTransactionBase64": "....",
  "timeMs": 1718998123999
}

Если пользователь отклонил запрос:

{
  "v": 1,
  "op": "sign_transaction_result",
  "requestId": "1718998123456-482193",
  "ok": false,
  "error": "rejected_by_user",
  "timeMs": 1718998123999
}

Рекомендуемые ошибки для sign_transaction:

  • rejected_by_user
  • wallet_unavailable
  • wallet_mismatch
  • transaction_base64_invalid
  • transaction_sign_failed
  • bad_request

11. Подключение кошелька с сайта

При вызове сайта connect wallet расширение должно вести себя как обычный wallet extension:

  1. запросить подтверждение у пользователя в браузере;
  2. получить текущий публичный ключ с ESP32;
  3. вернуть сайту publicKey текущего активного кошелька.

Для signTransaction расширение:

  1. получает транзакцию от сайта;
  2. пересылает её на ESP32 через sign_transaction;
  3. ждёт решение пользователя на устройстве;
  4. возвращает браузеру уже подписанную транзакцию.

12. Ограничения текущей версии

  • запрос возвращает только текущий активный кошелёк, а не список всех кошельков;
  • выбор типа кошелька делается только на самом ESP32;
  • отдельная цифровая подпись ответа пока не используется;
  • отдельное E2E-шифрование wallet RPC пока не используется;
  • custom-кошельки пока не сверяются с PDA.