SHA256
UI: показать пополнение при нехватке rent
This commit is contained in:
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
client.version=1.2.358
|
client.version=1.2.359
|
||||||
server.version=1.2.341
|
server.version=1.2.341
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { renderHeader } from '../components/header.js';
|
import { renderHeader } from '../components/header.js';
|
||||||
import { authService, state } from '../state.js';
|
import { authService, state } from '../state.js';
|
||||||
import { base64ToBytes } from '../services/crypto-utils.js';
|
import { base64ToBytes, bytesToBase58, publicKeyB64FromPkcs8Ed25519 } from '../services/crypto-utils.js';
|
||||||
import { loadEncryptedUserSecrets } from '../services/key-vault.js';
|
import { loadEncryptedUserSecrets } from '../services/key-vault.js';
|
||||||
import { resolveShineServerByServerLogin } from '../services/shine-server-resolver.js';
|
import { resolveShineServerByServerLogin } from '../services/shine-server-resolver.js';
|
||||||
import { readShineUserPda, updateShineUserPdaOnSolana } from '../services/shine-user-pda-service.js';
|
import { readShineUserPda, updateShineUserPdaOnSolana } from '../services/shine-user-pda-service.js';
|
||||||
|
import { getTopupSiteUrl } from '../services/solana-wallet-service.js';
|
||||||
|
|
||||||
export const pageMeta = { id: 'access-servers-view', title: 'Серверы доступа' };
|
export const pageMeta = { id: 'access-servers-view', title: 'Серверы доступа' };
|
||||||
|
|
||||||
@@ -48,6 +49,27 @@ function shortenSignature(value) {
|
|||||||
return `${text.slice(0, 8)}...${text.slice(-8)}`;
|
return `${text.slice(0, 8)}...${text.slice(-8)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isInsufficientFundsForRentError(error) {
|
||||||
|
const text = [
|
||||||
|
error?.message,
|
||||||
|
error?.transactionMessage,
|
||||||
|
Array.isArray(error?.logs) ? error.logs.join('\n') : '',
|
||||||
|
Array.isArray(error?.transactionLogs) ? error.transactionLogs.join('\n') : '',
|
||||||
|
Array.isArray(error?.simulationLogs) ? error.simulationLogs.join('\n') : '',
|
||||||
|
].filter(Boolean).join('\n').toLowerCase();
|
||||||
|
return text.includes('insufficient funds') && text.includes('rent');
|
||||||
|
}
|
||||||
|
|
||||||
|
function clientAddressFromPublicB64(publicKeyB64) {
|
||||||
|
const bytes = base64ToBytes(publicKeyB64);
|
||||||
|
if (bytes.length !== 32) throw new Error('client public key должен быть 32 байта');
|
||||||
|
return bytesToBase58(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function clientAddressFromPrivatePkcs8(privatePkcs8B64) {
|
||||||
|
return clientAddressFromPublicB64(await publicKeyB64FromPkcs8Ed25519(privatePkcs8B64));
|
||||||
|
}
|
||||||
|
|
||||||
function createConfirmModal() {
|
function createConfirmModal() {
|
||||||
const root = document.getElementById('modal-root');
|
const root = document.getElementById('modal-root');
|
||||||
if (!(root instanceof HTMLElement)) return null;
|
if (!(root instanceof HTMLElement)) return null;
|
||||||
@@ -460,6 +482,18 @@ export function render({ navigate }) {
|
|||||||
)).join('');
|
)).join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showTopupRequiredStatus = (target, clientAddress) => {
|
||||||
|
const address = String(clientAddress || '').trim();
|
||||||
|
const topupUrl = address ? getTopupSiteUrl(address) : '/devnet-topup';
|
||||||
|
target.innerHTML = `
|
||||||
|
<span style="display:block; margin-bottom:0.55rem;">
|
||||||
|
Не хватает SOL на client key для оплаты Solana rent/fee при обновлении user PDA.
|
||||||
|
</span>
|
||||||
|
${address ? `<span style="display:block; overflow-wrap:anywhere; margin-bottom:0.55rem;">Кошелёк: ${escapeHtml(address)}</span>` : ''}
|
||||||
|
<a class="primary-btn" href="${escapeHtml(topupUrl)}" target="_blank" rel="noopener" style="display:inline-flex; text-decoration:none;">Пополнить DEVNET кошелёк</a>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
const loadSuggestions = async () => {
|
const loadSuggestions = async () => {
|
||||||
const prefix = normalizeLogin(addInput.value);
|
const prefix = normalizeLogin(addInput.value);
|
||||||
if (suggestionsLoading || prefix.length < 2 || operationBusy) {
|
if (suggestionsLoading || prefix.length < 2 || operationBusy) {
|
||||||
@@ -508,6 +542,7 @@ export function render({ navigate }) {
|
|||||||
return {
|
return {
|
||||||
rootPrivatePkcs8B64: savedRoot,
|
rootPrivatePkcs8B64: savedRoot,
|
||||||
clientPrivatePkcs8B64: savedClient,
|
clientPrivatePkcs8B64: savedClient,
|
||||||
|
clientAddress: await clientAddressFromPrivatePkcs8(savedClient),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,6 +577,7 @@ export function render({ navigate }) {
|
|||||||
return {
|
return {
|
||||||
rootPrivatePkcs8B64: keyBundle.rootPair.privatePkcs8B64,
|
rootPrivatePkcs8B64: keyBundle.rootPair.privatePkcs8B64,
|
||||||
clientPrivatePkcs8B64: keyBundle.clientPair.privatePkcs8B64,
|
clientPrivatePkcs8B64: keyBundle.clientPair.privatePkcs8B64,
|
||||||
|
clientAddress: clientAddressFromPublicB64(keyBundle.clientPair.publicKeyB64),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -558,9 +594,10 @@ export function render({ navigate }) {
|
|||||||
const normalizedList = uniqueLogins(nextLogins);
|
const normalizedList = uniqueLogins(nextLogins);
|
||||||
setOperationBusy(true);
|
setOperationBusy(true);
|
||||||
target.textContent = String(inFlightText || 'Обновляем список серверов доступа...');
|
target.textContent = String(inFlightText || 'Обновляем список серверов доступа...');
|
||||||
|
let signingMaterial = null;
|
||||||
try {
|
try {
|
||||||
const currentPda = await readShineUserPda({ login: sessionLogin, solanaEndpoint });
|
const currentPda = await readShineUserPda({ login: sessionLogin, solanaEndpoint });
|
||||||
const signingMaterial = await resolveAccessServerSigningMaterial(currentPda);
|
signingMaterial = await resolveAccessServerSigningMaterial(currentPda);
|
||||||
const tx = await updateShineUserPdaOnSolana({
|
const tx = await updateShineUserPdaOnSolana({
|
||||||
login: sessionLogin,
|
login: sessionLogin,
|
||||||
solanaEndpoint,
|
solanaEndpoint,
|
||||||
@@ -575,7 +612,11 @@ export function render({ navigate }) {
|
|||||||
suggestEl.innerHTML = '';
|
suggestEl.innerHTML = '';
|
||||||
refreshAddButton();
|
refreshAddButton();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
target.textContent = error?.message || 'Не удалось обновить список серверов доступа.';
|
if (isInsufficientFundsForRentError(error)) {
|
||||||
|
showTopupRequiredStatus(target, signingMaterial?.clientAddress);
|
||||||
|
} else {
|
||||||
|
target.textContent = error?.message || 'Не удалось обновить список серверов доступа.';
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
setOperationBusy(false);
|
setOperationBusy(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user