14 KiB
Формат взаимодействия внешнего кошелька и ESP32
Этот документ фиксирует актуальный формат взаимодействия между внешним браузерным wallet-расширением SHiNE и устройством ESP32-S3-Touch-AMOLED-2.16.
Документ описывает:
- как расширение получает текущий активный публичный ключ кошелька с ESP32;
- как расширение отправляет на ESP32 запрос подписи транзакции;
- что именно считается активным кошельком на ESP32;
- какие проверки и UI-реакции ожидаются в браузерном расширении и на устройстве;
- какие ограничения действуют в текущей версии протокола.
1. Общая идея
Устройство ESP32 хранит master secret пользователя и локально умеет выводить несколько кошельков из одного секрета.
На устройстве в UI пользователь выбирает текущий активный кошелёк:
client.keyroot.keycustom
Для 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:
- смотрит, какой кошелёк сейчас выбран в локальном UI;
- вычисляет или берёт уже подготовленный публичный ключ именно этого активного кошелька;
- возвращает тип кошелька и его
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.keyroot.keycustom
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 расширение должно:
- показать пользователю тип кошелька;
- показать полный
publicKeyBase58; - дать кнопку копирования ключа в буфер;
- сохранить этот ключ как текущий ключ устройства для следующей операции подписи.
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:
- показать пользователю подтверждение подключения;
- показать, какой именно кошелёк будет подключён;
- после подтверждения пользователя завершить подключение;
- если пользователь отказался, не подключать кошелёк к сайту.
9. Запрос подписи транзакции
9.1. Назначение
Операция нужна, чтобы браузерное расширение могло запросить у ESP32 подпись Solana-транзакции текущим активным кошельком.
Расширение передаёт:
- публичный ключ, которым ожидается подпись;
- сериализованную транзакцию;
- комментарий, который должен быть показан на экране ESP32.
ESP32:
- показывает пользователю запрос подтверждения;
- показывает комментарий к подписи;
- после нажатия
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:
- сравнивает
publicKeyBase58с публичным ключом текущего активного выбранного кошелька; - если ключ не совпадает, сразу возвращает ошибку
wallet_mismatch; - если ключ совпадает, показывает отдельный экран подтверждения подписи;
- на экране показывает:
- каким кошельком будет выполнена подпись;
- комментарий
comment; - кнопки
APPROVEиREJECT;
- если пользователь подтверждает подпись, ESP32 подписывает транзакцию и возвращает результат;
- если пользователь отклоняет, 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_userwallet_unavailablewallet_mismatchtransaction_base64_invalidtransaction_sign_failedbad_request
11. Подключение кошелька с сайта
При вызове сайта connect wallet расширение должно вести себя как обычный wallet extension:
- запросить подтверждение у пользователя в браузере;
- получить текущий публичный ключ с ESP32;
- вернуть сайту
publicKeyтекущего активного кошелька.
Для signTransaction расширение:
- получает транзакцию от сайта;
- пересылает её на ESP32 через
sign_transaction; - ждёт решение пользователя на устройстве;
- возвращает браузеру уже подписанную транзакцию.
12. Ограничения текущей версии
- запрос возвращает только текущий активный кошелёк, а не список всех кошельков;
- выбор типа кошелька делается только на самом ESP32;
- отдельная цифровая подпись ответа пока не используется;
- отдельное E2E-шифрование wallet RPC пока не используется;
custom-кошельки пока не сверяются с PDA.