SHA256
Синхронизировать регистр логинов и доработать UI каналов
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
const SNAPSHOT_STORAGE_KEY = 'shine-ui-blockchain-snapshot-v1';
|
||||
|
||||
function normalizeLogin(login) {
|
||||
return String(login || '').trim().toLowerCase();
|
||||
}
|
||||
|
||||
function storageBucketKey(login) {
|
||||
return normalizeLogin(login) || 'anonymous';
|
||||
}
|
||||
|
||||
function decodeBase64ToBytes(base64) {
|
||||
const raw = String(base64 || '').trim();
|
||||
if (!raw) return new Uint8Array();
|
||||
const bin = atob(raw);
|
||||
const out = new Uint8Array(bin.length);
|
||||
for (let i = 0; i < bin.length; i += 1) out[i] = bin.charCodeAt(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
function readStorageMap() {
|
||||
try {
|
||||
const raw = localStorage.getItem(SNAPSHOT_STORAGE_KEY);
|
||||
const parsed = raw ? JSON.parse(raw) : {};
|
||||
return parsed && typeof parsed === 'object' ? parsed : {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function writeStorageMap(value) {
|
||||
try {
|
||||
localStorage.setItem(SNAPSHOT_STORAGE_KEY, JSON.stringify(value || {}));
|
||||
} catch {
|
||||
// ignore localStorage errors
|
||||
}
|
||||
}
|
||||
|
||||
export function readStoredBlockchainSnapshot(login) {
|
||||
const key = storageBucketKey(login);
|
||||
const map = readStorageMap();
|
||||
const value = map?.[key];
|
||||
return value && typeof value === 'object' ? value : null;
|
||||
}
|
||||
|
||||
export function saveStoredBlockchainSnapshot(login, snapshot) {
|
||||
const key = storageBucketKey(login);
|
||||
const map = readStorageMap();
|
||||
map[key] = {
|
||||
...snapshot,
|
||||
savedAtMs: Date.now(),
|
||||
};
|
||||
writeStorageMap(map);
|
||||
return map[key];
|
||||
}
|
||||
|
||||
export function clearStoredBlockchainSnapshot(login) {
|
||||
const key = storageBucketKey(login);
|
||||
const map = readStorageMap();
|
||||
delete map[key];
|
||||
writeStorageMap(map);
|
||||
}
|
||||
|
||||
export async function buildBlockchainSnapshotFile({
|
||||
authService,
|
||||
login,
|
||||
blockchainName,
|
||||
lastBlockNumber,
|
||||
} = {}) {
|
||||
const cleanLogin = normalizeLogin(login);
|
||||
const cleanBlockchainName = String(blockchainName || '').trim();
|
||||
const maxBlockNumber = Number(lastBlockNumber);
|
||||
if (!authService?.ws?.request) throw new Error('Сервис сервера недоступен.');
|
||||
if (!cleanLogin) throw new Error('Не указан логин.');
|
||||
if (!cleanBlockchainName) throw new Error('Не указано имя блокчейна.');
|
||||
if (!Number.isFinite(maxBlockNumber) || maxBlockNumber < 0) {
|
||||
throw new Error('На сервере нет блоков для слепка.');
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
let totalBytes = 0;
|
||||
for (let blockNumber = 0; blockNumber <= maxBlockNumber; blockNumber += 1) {
|
||||
const response = await authService.ws.request('GetBlockchainBlock', {
|
||||
blockchainName: cleanBlockchainName,
|
||||
blockNumber,
|
||||
});
|
||||
if (response?.status !== 200) {
|
||||
const message = String(response?.payload?.message || response?.message || 'Не удалось получить блок.');
|
||||
throw new Error(`Не удалось скачать блок ${blockNumber}: ${message}`);
|
||||
}
|
||||
const blockBytes = decodeBase64ToBytes(response?.payload?.blockBytesB64 || '');
|
||||
parts.push(blockBytes);
|
||||
totalBytes += blockBytes.length;
|
||||
}
|
||||
|
||||
const file = new File(parts, `${cleanBlockchainName}.shine-blockchain`, {
|
||||
type: 'application/octet-stream',
|
||||
lastModified: Date.now(),
|
||||
});
|
||||
|
||||
return {
|
||||
file,
|
||||
blockCount: maxBlockNumber + 1,
|
||||
totalBytes,
|
||||
lastBlockNumber: maxBlockNumber,
|
||||
login: cleanLogin,
|
||||
blockchainName: cleanBlockchainName,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user