Wallet plugin: офлайн wallet-session и выбор homeserver\n\nСделано:\n- wallet plugin сохраняет PDA-профиль и остаётся офлайн до действия;\n- добавлен каркас выбора ключа подписи и homeserver-устройства;\n- добавлен ручной refresh trusted devices через ListSessions;\n- на регистрации показан первый сервер SHiNE и его адрес;\n- обновлены pending notes для ручной проверки.\n\nЕщё не проверено / не доделано:\n- end-to-end ручная проверка plugin после этих правок не завершена;\n- signaling запроса подписи и ответ подписи ещё не реализованы;\n- локальный browser plugin нужно отдельно reload в Chrome/Opera.

This commit is contained in:
AidarKC
2026-06-18 11:04:34 +04:00
parent f8a76bcd7f
commit 2225c2d173
10 changed files with 440 additions and 19 deletions
@@ -69,21 +69,32 @@ function parseServerFieldsFromUserPda(dataBytes) {
let isServer = false;
let serverAddress = '';
let accessServers = [];
let rootKey32 = null;
let deviceKey32 = null;
let blockchainKey32 = null;
let blockchainName = '';
let homeserverSessions = [];
for (let i = 0; i < blocksCount; i += 1) {
const blockType = readU8(bytes, cursorRef);
cursorRef.value += 1; // block_version
if (blockType === 1 || blockType === 2) {
cursorRef.value += 32;
const key32 = readBytes(bytes, cursorRef, 32);
if (blockType === 1) rootKey32 = key32;
if (blockType === 2) deviceKey32 = key32;
continue;
}
if (blockType === 3) {
const count = readU8(bytes, cursorRef);
for (let j = 0; j < count; j += 1) {
cursorRef.value += 1;
readStrU8(bytes, cursorRef);
cursorRef.value += 32;
const currentBlockchainName = readStrU8(bytes, cursorRef);
const currentBlockchainKey32 = readBytes(bytes, cursorRef, 32);
if (!blockchainKey32) {
blockchainKey32 = currentBlockchainKey32;
blockchainName = currentBlockchainName;
}
cursorRef.value += 8 + 8 + 4 + 32 + 64;
const arPresent = readU8(bytes, cursorRef);
if (arPresent === 1) readStrU8(bytes, cursorRef);
@@ -111,9 +122,19 @@ function parseServerFieldsFromUserPda(dataBytes) {
cursorRef.value += 1;
const sessionsCount = readU8(bytes, cursorRef);
for (let j = 0; j < sessionsCount; j += 1) {
cursorRef.value += 1 + 1;
readStrU8(bytes, cursorRef);
cursorRef.value += 32;
const sessionType = readU8(bytes, cursorRef);
const sessionVersion = readU8(bytes, cursorRef);
const sessionName = readStrU8(bytes, cursorRef);
const sessionPubKey32 = readBytes(bytes, cursorRef, 32);
if (sessionType === 100) {
homeserverSessions.push({
sessionType,
sessionVersion,
sessionName,
sessionPubKeyBase58: new PublicKey(sessionPubKey32).toBase58(),
sessionPubKeyB64: `ed25519/${btoa(String.fromCharCode(...sessionPubKey32))}`,
});
}
}
continue;
}
@@ -128,6 +149,13 @@ function parseServerFieldsFromUserPda(dataBytes) {
isServer,
serverAddress: normalizeHostLike(serverAddress),
accessServers: accessServers.map((value) => normalizeServerLogin(value)).filter(Boolean),
publicKeys: {
rootKeyBase58: rootKey32 ? new PublicKey(rootKey32).toBase58() : '',
deviceKeyBase58: deviceKey32 ? new PublicKey(deviceKey32).toBase58() : '',
blockchainKeyBase58: blockchainKey32 ? new PublicKey(blockchainKey32).toBase58() : '',
blockchainName,
},
homeserverSessions,
};
}
@@ -176,6 +204,17 @@ export async function resolveShineServerByServerLogin(serverLogin, solanaEndpoin
};
}
export async function readWalletProfileByLogin(login, solanaEndpoint = SOLANA_ENDPOINT_DEFAULT) {
const cleanLogin = normalizeServerLogin(login);
const parsed = await fetchUserPda(cleanLogin, solanaEndpoint);
return {
login: cleanLogin,
accessServers: parsed.accessServers,
publicKeys: parsed.publicKeys,
homeserverSessions: parsed.homeserverSessions,
};
}
export {
DEFAULT_SHINE_SERVER_ADDRESS,
DEFAULT_SHINE_SERVER_LOGIN,