diff --git a/Dev_Docs/API/02_Authentication_API.md b/Dev_Docs/API/02_Authentication_API.md index 6d11fdb..65f4024 100644 --- a/Dev_Docs/API/02_Authentication_API.md +++ b/Dev_Docs/API/02_Authentication_API.md @@ -303,13 +303,14 @@ SESSION_LOGIN:{sessionId}:{timeMs}:{nonce} Новые `op`, относящиеся к этому сценарию: -- `UpsertEspPairingSettings` -- `StartEspPairing` -- `ListEspPairingRequests` -- `ApproveEspPairing` -- `RejectEspPairing` -- `CancelEspPairing` -- `GetEspPairingStatus` +- `GetTrustedDeviceLoginSettings` +- `UpsertTrustedDeviceLoginSettings` +- `StartTrustedDeviceLogin` +- `ListTrustedDeviceLoginRequests` +- `ApproveTrustedDeviceLogin` +- `RejectTrustedDeviceLogin` +- `CancelTrustedDeviceLogin` +- `GetTrustedDeviceLoginStatus` В этом потоке: diff --git a/Dev_Docs/API/03_Session_Management_API.md b/Dev_Docs/API/03_Session_Management_API.md index 213752e..e5941e0 100644 --- a/Dev_Docs/API/03_Session_Management_API.md +++ b/Dev_Docs/API/03_Session_Management_API.md @@ -9,16 +9,17 @@ Дополнительно в этом же слое управления сессиями появился сценарий pairing через доверенную уже авторизованную сессию пользователя: -- `UpsertEspPairingSettings` -- `ListEspPairingRequests` -- `ApproveEspPairing` -- `RejectEspPairing` -- `CancelEspPairing` +- `GetTrustedDeviceLoginSettings` +- `UpsertTrustedDeviceLoginSettings` +- `ListTrustedDeviceLoginRequests` +- `ApproveTrustedDeviceLogin` +- `RejectTrustedDeviceLogin` +- `CancelTrustedDeviceLogin` Анонимное новое устройство работает с двумя связанными операциями: -- `StartEspPairing` -- `GetEspPairingStatus` +- `StartTrustedDeviceLogin` +- `GetTrustedDeviceLoginStatus` Логика раздела такая: @@ -167,11 +168,11 @@ K9v3nQ4u8jYk0a2p7cD4mLx1zR0sT5wV6bN8eH3fQ1M --- -## 5. ESP pairing через доверенную сессию +## 5. TrustedDeviceLogin через доверенную сессию Этот блок относится к сценарию добавления новой сессии через доверенное устройство пользователя. -### 5.1. `UpsertEspPairingSettings` +### 5.1. `GetTrustedDeviceLoginSettings` Доступно для любой уже авторизованной доверенной сессии пользователя. @@ -179,17 +180,57 @@ K9v3nQ4u8jYk0a2p7cD4mLx1zR0sT5wV6bN8eH3fQ1M ```json { - "op": "UpsertEspPairingSettings", - "requestId": "esp-set-001", + "op": "GetTrustedDeviceLoginSettings", + "requestId": "trusted-login-get-001", "payload": { - "enabled": true, - "passwordHash": "sha256$0123abcd...", - "ttlSeconds": 180 } } ``` -Если pairing должен работать **без доп. пароля**, клиент может включить его с пустым `passwordHash`. +### Успешный ответ + +```json +{ + "op": "GetTrustedDeviceLoginSettings", + "requestId": "trusted-login-get-001", + "status": 200, + "ok": true, + "payload": { + "enabled": true, + "hasPassword": false + } +} +``` + +Если отдельной записи настроек на сервере ещё нет, сервер считает состояние по умолчанию таким: + +- `enabled = true` +- `hasPassword = false` + +### Ошибки + +- `463 / PAIRING_REQUIRES_AUTH_SESSION` — операция вызвана без уже авторизованной доверенной сессии пользователя. + +### 5.2. `UpsertTrustedDeviceLoginSettings` + +Доступно для любой уже авторизованной доверенной сессии пользователя. + +### Запрос + +```json +{ + "op": "UpsertTrustedDeviceLoginSettings", + "requestId": "esp-set-001", + "payload": { + "enabled": true, + "passwordHash": "sha256$0123abcd..." + } +} +``` + +Если вход через доверенное устройство должен работать **без доп. пароля**, клиент включает его с пустым `passwordHash`. + +Если `enabled = false`, сервер автоматически удаляет пароль и запрещает вход через другое устройство. Формат непустого `passwordHash`: @@ -201,13 +242,13 @@ sha256$ ```json { - "op": "UpsertEspPairingSettings", + "op": "UpsertTrustedDeviceLoginSettings", "requestId": "esp-set-001", "status": 200, "ok": true, "payload": { "enabled": true, - "ttlSeconds": 180 + "hasPassword": true } } ``` @@ -216,7 +257,7 @@ sha256$ - `463 / PAIRING_REQUIRES_AUTH_SESSION` — операция вызвана без уже авторизованной доверенной сессии пользователя. -### 5.2. `StartEspPairing` +### 5.3. `StartTrustedDeviceLogin` Эта операция доступна без уже существующей пользовательской сессии. @@ -224,7 +265,7 @@ sha256$ ```json { - "op": "StartEspPairing", + "op": "StartTrustedDeviceLogin", "requestId": "esp-start-001", "payload": { "login": "alice", @@ -237,15 +278,17 @@ sha256$ } ``` -Если на доверённом устройстве pairing включён **без доп. пароля**, новое устройство может отправить пустой `passwordHash`. +Если на доверённом устройстве вход включён **без доп. пароля**, новое устройство может отправить пустой `passwordHash`. Поле `trustedSessionOnline` показывает, что у пользователя сейчас есть хотя бы одна онлайн доверенная сессия, способная принять pairing-заявку. +TTL заявки фиксирован на сервере и сейчас всегда равен `300` секундам. + ### Успешный ответ ```json { - "op": "StartEspPairing", + "op": "StartTrustedDeviceLogin", "requestId": "esp-start-001", "status": 200, "ok": true, @@ -272,7 +315,7 @@ sha256$ - `422 / PAIRING_NO_TRUSTED_SESSION_ONLINE` — сейчас нет ни одной онлайн доверённой сессии пользователя, поэтому код не создаётся. - `429 / PAIRING_RATE_LIMITED` -### 5.3. `ListEspPairingRequests` +### 5.4. `ListTrustedDeviceLoginRequests` Доступно для любой уже авторизованной доверенной сессии пользователя. Возвращает только реально активные pending-заявки со `state = created`. Уже `approved` и `rejected` заявки в этот список больше не попадают. @@ -281,7 +324,7 @@ sha256$ ```json { - "op": "ListEspPairingRequests", + "op": "ListTrustedDeviceLoginRequests", "requestId": "esp-list-001", "status": 200, "ok": true, @@ -309,7 +352,7 @@ sha256$ - `463 / PAIRING_REQUIRES_AUTH_SESSION` -### 5.4. `ApproveEspPairing` +### 5.5. `ApproveTrustedDeviceLogin` Доступно для любой уже авторизованной доверенной сессии пользователя. @@ -317,7 +360,7 @@ sha256$ ```json { - "op": "ApproveEspPairing", + "op": "ApproveTrustedDeviceLogin", "requestId": "esp-approve-001", "payload": { "pairingId": "base64url", @@ -330,7 +373,7 @@ sha256$ ```json { - "op": "ApproveEspPairing", + "op": "ApproveTrustedDeviceLogin", "requestId": "esp-approve-001", "status": 200, "ok": true, @@ -351,11 +394,11 @@ sha256$ - `422 / PAIRING_EXPIRED` - `463 / PAIRING_REQUIRES_AUTH_SESSION` -### 5.5. `RejectEspPairing` +### 5.6. `RejectTrustedDeviceLogin` Доступно для любой уже авторизованной доверенной сессии пользователя. Похоже на approve, но переводит заявку в `state=rejected`. -### 5.6. `GetEspPairingStatus` +### 5.7. `GetTrustedDeviceLoginStatus` Операция для нового устройства. @@ -363,7 +406,7 @@ sha256$ ```json { - "op": "GetEspPairingStatus", + "op": "GetTrustedDeviceLoginStatus", "requestId": "esp-status-001", "payload": { "pairingId": "base64url" @@ -375,7 +418,7 @@ sha256$ ```json { - "op": "GetEspPairingStatus", + "op": "GetTrustedDeviceLoginStatus", "requestId": "esp-status-001", "status": 200, "ok": true, @@ -399,7 +442,7 @@ sha256$ - `canceled` - `expired` -### 5.7. `CancelEspPairing` +### 5.8. `CancelTrustedDeviceLogin` Операция для нового устройства, которое уже создало pairing-заявку и хочет принудительно снять ожидание до истечения TTL. @@ -407,7 +450,7 @@ sha256$ ```json { - "op": "CancelEspPairing", + "op": "CancelTrustedDeviceLogin", "requestId": "esp-cancel-001", "payload": { "pairingId": "base64url", @@ -420,7 +463,7 @@ sha256$ ```json { - "op": "CancelEspPairing", + "op": "CancelTrustedDeviceLogin", "requestId": "esp-cancel-001", "status": 200, "ok": true, diff --git a/Dev_Docs/API/09_Operations_Index.md b/Dev_Docs/API/09_Operations_Index.md index 5e13779..95fa4d7 100644 --- a/Dev_Docs/API/09_Operations_Index.md +++ b/Dev_Docs/API/09_Operations_Index.md @@ -19,13 +19,14 @@ | `CreateAuthSession` | `02_Authentication_API.md` | создание новой авторизованной сессии | | `SessionChallenge` | `02_Authentication_API.md` | challenge для входа в существующую сессию | | `SessionLogin` | `02_Authentication_API.md` | вход в существующую сессию | -| `UpsertEspPairingSettings` | `03_Session_Management_API.md` | включение/обновление pairing-настроек доверенной сессией | -| `StartEspPairing` | `03_Session_Management_API.md` | создание pairing-заявки для нового устройства | -| `ListEspPairingRequests` | `03_Session_Management_API.md` | список активных pairing-заявок для доверенной сессии | -| `ApproveEspPairing` | `03_Session_Management_API.md` | подтверждение pairing-заявки доверенной сессией | -| `RejectEspPairing` | `03_Session_Management_API.md` | отклонение pairing-заявки доверенной сессией | -| `CancelEspPairing` | `03_Session_Management_API.md` | отмена pairing-заявки со стороны нового ожидающего устройства | -| `GetEspPairingStatus` | `03_Session_Management_API.md` | чтение статуса и результата pairing-заявки | +| `GetTrustedDeviceLoginSettings` | `03_Session_Management_API.md` | чтение текущего режима входа через доверенное устройство | +| `UpsertTrustedDeviceLoginSettings` | `03_Session_Management_API.md` | включение/обновление pairing-настроек доверенной сессией | +| `StartTrustedDeviceLogin` | `03_Session_Management_API.md` | создание pairing-заявки для нового устройства | +| `ListTrustedDeviceLoginRequests` | `03_Session_Management_API.md` | список активных pairing-заявок для доверенной сессии | +| `ApproveTrustedDeviceLogin` | `03_Session_Management_API.md` | подтверждение pairing-заявки доверенной сессией | +| `RejectTrustedDeviceLogin` | `03_Session_Management_API.md` | отклонение pairing-заявки доверенной сессией | +| `CancelTrustedDeviceLogin` | `03_Session_Management_API.md` | отмена pairing-заявки со стороны нового ожидающего устройства | +| `GetTrustedDeviceLoginStatus` | `03_Session_Management_API.md` | чтение статуса и результата pairing-заявки | | `ListSessions` | `03_Session_Management_API.md` | список активных сессий | | `CloseActiveSession` | `03_Session_Management_API.md` | закрытие активной сессии | | `AddBlock` | `04_Add_Block_to_Blockchain_API.md` | добавление блока в блокчейн | diff --git a/Dev_Docs/Pending_Features/2026-06-16_1410_wallet_pda_keys_и_homeserver_выбор.md b/Dev_Docs/Pending_Features/2026-06-16_1410_wallet_pda_keys_и_homeserver_выбор.md index cc8d29a..67aa04b 100644 --- a/Dev_Docs/Pending_Features/2026-06-16_1410_wallet_pda_keys_и_homeserver_выбор.md +++ b/Dev_Docs/Pending_Features/2026-06-16_1410_wallet_pda_keys_и_homeserver_выбор.md @@ -4,10 +4,11 @@ `SHiNE-browser-plugin-wallet` после session-only подключения сохраняет `login`, публичные `root/device/blockchain` ключи из PDA и список опубликованных `homeserver`-сессий. Постоянное подключение не удерживается: plugin остаётся офлайн, а список trusted devices обновляет по запросу. - что проверять: + 0. На стартовом экране plugin для подключения запрашивается только логин пользователя; серверный логин вручную не вводится, а показывается как информационная строка после чтения PDA. 1. После успешного pairing plugin показывает сохранённую wallet-session без автоматического постоянного подключения. 2. В карточке wallet-session виден сокращённый `deviceKey`. 3. Кнопка `Обновить устройства` подтягивает homeserver-сессии из PDA и показывает их список со статусом `online/offline/unknown`. - 4. В селекте ключа подписи доступен `deviceKey (ed25519, ...)`. + 4. В селекте ключа подписи доступны `rootKey (ed25519, ...)` и `deviceKey (ed25519, ...)`. 5. Кнопка `Запросить подпись` не падает и честно сообщает, что signaling подписи ещё не доделан. - ожидаемый результат: diff --git a/Dev_Docs/Pending_Features/2026-06-18_0942_trusted_device_login_settings.md b/Dev_Docs/Pending_Features/2026-06-18_0942_trusted_device_login_settings.md new file mode 100644 index 0000000..feb7111 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-06-18_0942_trusted_device_login_settings.md @@ -0,0 +1,24 @@ +# TrustedDeviceLogin settings и новый режим по умолчанию + +- краткое описание: + серверный API сценария входа через доверенное устройство переименован в `TrustedDeviceLogin`, добавлен `GetTrustedDeviceLoginSettings`, а отсутствие серверной записи настроек теперь трактуется как `enabled = true` и `hasPassword = false`. В UI вынесен отдельный экран настроек входа через доверенное устройство. + +- что проверять: + 1. Для логина без записи в `esp_pairing_settings` `StartTrustedDeviceLogin` работает без предварительного ручного включения. + 2. Экран `Подключить по коду` показывает один из трёх статусов: + - вход запрещён; + - вход разрешён без пароля; + - вход разрешён только с паролем. + 3. Кнопка `Изменить настройки входа` открывает отдельный экран. + 4. На отдельном экране: + - можно запретить вход; + - можно разрешить вход; + - можно задать новый пароль; + - можно сделать вход без пароля. + 5. `Войти через другое устройство` в основном UI и в browser wallet работает через новые `TrustedDeviceLogin`-операции. + +- ожидаемый результат: + вход через доверенное устройство по умолчанию доступен без лишнего ручного включения, а текущий режим и пароль управляются с отдельного экрана настроек. + +- статус: + pending diff --git a/SHiNE-browser-plugin-wallet/README.md b/SHiNE-browser-plugin-wallet/README.md index f1e387c..312a042 100644 --- a/SHiNE-browser-plugin-wallet/README.md +++ b/SHiNE-browser-plugin-wallet/README.md @@ -4,7 +4,7 @@ Chrome-compatible Manifest V3 plugin for SHiNE wallet-session login. ## Что уже умеет -- создать `wallet-session` через `StartEspPairing`; +- создать `wallet-session` через `StartTrustedDeviceLogin`; - показать код подключения; - дождаться подтверждения на доверенном устройстве; - принять `session-only` payload без передачи `deviceKey/rootKey/blockchainKey`; diff --git a/SHiNE-browser-plugin-wallet/background.js b/SHiNE-browser-plugin-wallet/background.js index e5ddc71..31d8006 100644 --- a/SHiNE-browser-plugin-wallet/background.js +++ b/SHiNE-browser-plugin-wallet/background.js @@ -4,9 +4,8 @@ import { ShineApiClient } from './js/lib/shine-api.js'; import { DEFAULT_SHINE_SERVER_LOGIN, buildHttpBase, - normalizeServerLogin, readWalletProfileByLogin, - resolveShineServerByServerLogin, + resolveShineServerByUserLogin, } from './js/lib/shine-server-resolver.js'; const state = { @@ -65,23 +64,10 @@ function ensureApi(serverUrl = state.settings.serverUrl) { return state.api; } -async function resolveSettingsServer(nextSettings = {}) { - const serverLogin = normalizeServerLogin(nextSettings?.serverLogin || state.settings.serverLogin || DEFAULT_SHINE_SERVER_LOGIN) - || DEFAULT_SHINE_SERVER_LOGIN; - const resolved = await resolveShineServerByServerLogin(serverLogin); - return { - serverLogin: resolved.serverLogin, - serverHttp: resolved.serverHttp, - serverUrl: resolved.serverUrl, - }; -} - async function loadStateFromStorage() { const settings = await loadPluginSettings(); - const storedServerLogin = normalizeServerLogin(settings?.serverLogin || state.settings.serverLogin || DEFAULT_SHINE_SERVER_LOGIN) - || DEFAULT_SHINE_SERVER_LOGIN; state.settings = { - serverLogin: storedServerLogin, + serverLogin: String(settings?.serverLogin || state.settings.serverLogin || DEFAULT_SHINE_SERVER_LOGIN).trim(), serverHttp: String(settings?.serverHttp || state.settings.serverHttp || buildHttpBase('shineup.me')).trim() || buildHttpBase('shineup.me'), serverUrl: String(settings?.serverUrl || state.settings.serverUrl || 'wss://shineup.me/ws').trim() || 'wss://shineup.me/ws', login: String(settings?.login || '').trim(), @@ -96,16 +82,38 @@ async function loadStateFromStorage() { } async function persistSettings(nextSettings = {}) { - const resolved = await resolveSettingsServer(nextSettings); state.settings = { ...state.settings, ...nextSettings, - ...resolved, }; await savePluginSettings(state.settings); return state.settings; } +async function resolveServerForLogin(login) { + const cleanLogin = String(login || state.settings.login || '').trim(); + if (!cleanLogin) { + state.settings = { + ...state.settings, + login: '', + serverLogin: '', + }; + await savePluginSettings(state.settings); + return { ok: true, resolved: false }; + } + + const resolved = await resolveShineServerByUserLogin(cleanLogin); + state.settings = { + ...state.settings, + login: cleanLogin, + serverLogin: resolved.serverLogin, + serverHttp: resolved.serverHttp, + serverUrl: resolved.serverUrl, + }; + await savePluginSettings(state.settings); + return { ok: true, resolved: true, ...resolved }; +} + async function saveActiveSessionRecord() { if (!state.activeSession) return; const nextRecord = { @@ -124,15 +132,47 @@ function shortKey(value = '', size = 10) { return raw ? raw.slice(0, size) : ''; } +function extractErrorCode(message = '') { + const match = String(message || '').match(/\(([A-Z0-9_]+)\)\s*$/i); + return match ? String(match[1]).toUpperCase() : ''; +} + +function toWalletErrorMessage(error, fallback = 'Не удалось выполнить операцию кошелька.') { + const raw = String(error?.message || '').trim(); + const code = String(error?.code || extractErrorCode(raw) || '').toUpperCase(); + if (code === 'PAIRING_NOT_AVAILABLE') { + return 'Для этого логина ещё не включено подключение по коду. На доверенном устройстве откройте «Подключить по коду» и нажмите «Включить подключение по коду» или задайте дополнительный пароль.'; + } + if (code === 'PAIRING_NO_TRUSTED_SESSION_ONLINE') { + return 'Сейчас нет ни одной онлайн доверенной сессии этого пользователя. Откройте SHiNE на другом уже подключённом устройстве и держите его в сети.'; + } + if (code === 'PAIRING_PASSWORD_INVALID') { + return 'Дополнительный пароль подключения не подходит.'; + } + return raw || fallback; +} + function buildSigningKeyOptions(walletProfile) { + const rootKey = String(walletProfile?.publicKeys?.rootKeyBase58 || '').trim(); const deviceKey = String(walletProfile?.publicKeys?.deviceKeyBase58 || '').trim(); - if (!deviceKey) return []; - return [{ - id: 'device', - label: `deviceKey (ed25519, ${shortKey(deviceKey)})`, - keyType: 'ed25519', - publicKeyBase58: deviceKey, - }]; + const options = []; + if (rootKey) { + options.push({ + id: 'root', + label: `rootKey (ed25519, ${shortKey(rootKey)})`, + keyType: 'ed25519', + publicKeyBase58: rootKey, + }); + } + if (deviceKey) { + options.push({ + id: 'device', + label: `deviceKey (ed25519, ${shortKey(deviceKey)})`, + keyType: 'ed25519', + publicKeyBase58: deviceKey, + }); + } + return options; } function mergeHomeserverStatuses(publishedHomeservers = [], serverSessions = []) { @@ -248,6 +288,8 @@ async function attachApprovedSession(payload) { await saveActiveSessionRecord(); await persistSettings({ login: sessionRecord.login, + serverLogin: sessionRecord.serverLogin, + serverHttp: sessionRecord.serverHttp, serverUrl: sessionRecord.serverUrl, }); state.connectionOnline = false; @@ -256,7 +298,7 @@ async function attachApprovedSession(payload) { async function pollPairingStatus() { if (!state.pairingId || !state.requesterMaterial) return; try { - const payload = await ensureApi().getEspPairingStatus(state.pairingId); + const payload = await ensureApi().getTrustedDeviceLoginStatus(state.pairingId); const stateValue = String(payload?.state || ''); if (stateValue === 'created') { state.pollTimer = setTimeout(() => { @@ -290,16 +332,14 @@ async function pollPairingStatus() { } } -async function startPairing({ login, usePassword, password, serverLogin }) { +async function startPairing({ login, usePassword, password }) { const cleanLogin = String(login || '').trim(); if (!cleanLogin) { throw new Error('Введите логин.'); } - await persistSettings({ - serverLogin: String(serverLogin || state.settings.serverLogin || DEFAULT_SHINE_SERVER_LOGIN).trim(), - login: cleanLogin, - }); + await persistSettings({ login: cleanLogin }); + await resolveServerForLogin(cleanLogin); clearPairingState(); setStatus('Проверяем пользователя и создаём wallet-session заявку...', 'info'); @@ -313,7 +353,7 @@ async function startPairing({ login, usePassword, password, serverLogin }) { const passwordHash = usePassword ? await deriveEspPairingPasswordHash(cleanLogin, String(password || '')) : ''; - const payload = await api.startEspPairing({ + const payload = await api.startTrustedDeviceLogin({ login: cleanLogin, passwordHash, requesterSessionKey: state.requesterMaterial.sessionKey, @@ -346,7 +386,7 @@ async function cancelPairing() { clearPairingState(); return { ok: true }; } - await ensureApi().cancelEspPairing(state.pairingId, state.requesterMaterial.sessionKey); + await ensureApi().cancelTrustedDeviceLogin(state.pairingId, state.requesterMaterial.sessionKey); clearPairingState(); setStatus('Ожидание подключения отменено.', 'info'); return { ok: true }; @@ -468,6 +508,11 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { sendResponse({ ok: true, state: snapshot() }); return; } + if (type === 'wallet:resolveServerInfo') { + const result = await resolveServerForLogin(String(message?.payload?.login || '').trim()); + sendResponse({ ok: true, result, state: snapshot() }); + return; + } if (type === 'wallet:startPairing') { const result = await startPairing(message?.payload || {}); sendResponse({ ok: true, result, state: snapshot() }); @@ -505,8 +550,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { } sendResponse({ ok: false, error: 'UNKNOWN_MESSAGE' }); })().catch((error) => { - setStatus(error?.message || 'Unknown error', 'error'); - sendResponse({ ok: false, error: error?.message || 'Unknown error', state: snapshot() }); + const message = toWalletErrorMessage(error, 'Unknown error'); + setStatus(message, 'error'); + sendResponse({ ok: false, error: message, state: snapshot() }); }); return true; }); diff --git a/SHiNE-browser-plugin-wallet/js/lib/shine-api.js b/SHiNE-browser-plugin-wallet/js/lib/shine-api.js index 5b51bc5..e665425 100644 --- a/SHiNE-browser-plugin-wallet/js/lib/shine-api.js +++ b/SHiNE-browser-plugin-wallet/js/lib/shine-api.js @@ -39,8 +39,8 @@ export class ShineApiClient { return response.payload || {}; } - async startEspPairing({ login, passwordHash, requesterSessionKey, payloadType = 1 }) { - const response = await this.ws.request('StartEspPairing', { + async startTrustedDeviceLogin({ login, passwordHash, requesterSessionKey, payloadType = 1 }) { + const response = await this.ws.request('StartTrustedDeviceLogin', { login: String(login || '').trim(), passwordHash: String(passwordHash || '').trim(), requesterSessionKey: String(requesterSessionKey || '').trim(), @@ -48,24 +48,24 @@ export class ShineApiClient { requesterClientPlatform: 'Chrome Extension Wallet', payloadType: Number(payloadType) || 1, }); - if (response.status !== 200) throw opError('StartEspPairing', response); + if (response.status !== 200) throw opError('StartTrustedDeviceLogin', response); return response.payload || {}; } - async getEspPairingStatus(pairingId) { - const response = await this.ws.request('GetEspPairingStatus', { + async getTrustedDeviceLoginStatus(pairingId) { + const response = await this.ws.request('GetTrustedDeviceLoginStatus', { pairingId: String(pairingId || '').trim(), }); - if (response.status !== 200) throw opError('GetEspPairingStatus', response); + if (response.status !== 200) throw opError('GetTrustedDeviceLoginStatus', response); return response.payload || {}; } - async cancelEspPairing(pairingId, requesterSessionKey) { - const response = await this.ws.request('CancelEspPairing', { + async cancelTrustedDeviceLogin(pairingId, requesterSessionKey) { + const response = await this.ws.request('CancelTrustedDeviceLogin', { pairingId: String(pairingId || '').trim(), requesterSessionKey: String(requesterSessionKey || '').trim(), }); - if (response.status !== 200) throw opError('CancelEspPairing', response); + if (response.status !== 200) throw opError('CancelTrustedDeviceLogin', response); return response.payload || {}; } diff --git a/SHiNE-browser-plugin-wallet/js/lib/shine-server-resolver.js b/SHiNE-browser-plugin-wallet/js/lib/shine-server-resolver.js index 2c50327..e6fda2e 100644 --- a/SHiNE-browser-plugin-wallet/js/lib/shine-server-resolver.js +++ b/SHiNE-browser-plugin-wallet/js/lib/shine-server-resolver.js @@ -204,6 +204,25 @@ export async function resolveShineServerByServerLogin(serverLogin, solanaEndpoin }; } +export async function resolveShineServerByUserLogin(login, solanaEndpoint = SOLANA_ENDPOINT_DEFAULT) { + const cleanLogin = normalizeServerLogin(login); + if (!cleanLogin) throw new Error('Не указан логин пользователя.'); + const parsed = await fetchUserPda(cleanLogin, solanaEndpoint); + const serverLogin = normalizeServerLogin(parsed.accessServers?.[0] || ''); + if (!serverLogin) { + throw new Error(`У пользователя @${cleanLogin} в PDA не найден первый сервер доступа.`); + } + const resolved = await resolveShineServerByServerLogin(serverLogin, solanaEndpoint); + return { + login: cleanLogin, + accessServers: parsed.accessServers, + serverLogin: resolved.serverLogin, + serverAddress: resolved.serverAddress, + serverHttp: resolved.serverHttp, + serverUrl: resolved.serverUrl, + }; +} + export async function readWalletProfileByLogin(login, solanaEndpoint = SOLANA_ENDPOINT_DEFAULT) { const cleanLogin = normalizeServerLogin(login); const parsed = await fetchUserPda(cleanLogin, solanaEndpoint); diff --git a/SHiNE-browser-plugin-wallet/popup.html b/SHiNE-browser-plugin-wallet/popup.html index 948143c..5467e40 100644 --- a/SHiNE-browser-plugin-wallet/popup.html +++ b/SHiNE-browser-plugin-wallet/popup.html @@ -17,11 +17,8 @@ offline - -

Текущий адрес: https://shineup.me

+

Сервер SHiNE: —

+

Адрес: —