feat(ui): кошелек на device.key и проверки серверов (тоже пока не проверено)

This commit is contained in:
AidarKC
2026-04-21 03:12:22 +03:00
parent 8be56192cb
commit e63c53a855
9 changed files with 588 additions and 79 deletions
+62 -13
View File
@@ -1,10 +1,15 @@
import { renderHeader } from '../components/header.js';
import { state } from '../state.js';
import {
deriveWalletFromPassword,
formatSol,
getBalanceSol,
getTopupSiteUrl,
requestAirdropSol,
} from '../services/solana-wallet-service.js';
export const pageMeta = { id: 'topup-view', title: 'Пополнение счета', showAppChrome: false };
const BUY_LINK = 'https://www.moonpay.com/buy/sol';
export function render({ navigate }) {
const screen = document.createElement('section');
screen.className = 'stack';
@@ -12,10 +17,14 @@ export function render({ navigate }) {
const walletValue = document.createElement('input');
walletValue.className = 'input';
walletValue.type = 'text';
walletValue.value = state.registrationPayment.walletAddress;
walletValue.value = state.registrationPayment.walletAddress || '';
walletValue.readOnly = true;
walletValue.style.fontSize = '13px';
const status = document.createElement('p');
status.className = 'meta-muted';
status.textContent = 'Проверяем кошелек...';
const copyButton = document.createElement('button');
copyButton.className = 'ghost-btn';
copyButton.type = 'button';
@@ -39,15 +48,14 @@ export function render({ navigate }) {
const card = document.createElement('div');
card.className = 'card stack';
card.innerHTML = `
<p class="auth-copy">Для пополнения счета скопируйте номер кошелька.</p>
<p class="auth-copy">Кнопка «Пополнить» в кошельке будет переводить на отдельный сайт. Пока доступно тестовое пополнение.</p>
<div class="stack" style="gap:6px;">
<p class="meta-muted">1. Пополните через любое свое приложение, используя этот кошелек в сети Solana.</p>
<p class="meta-muted">2. Либо откройте страницу для покупки SOL.</p>
<p class="meta-muted">3. Либо используйте кнопку «Тестовое пополнение» (работает в тестовой Solana).</p>
<p class="meta-muted">1. Вы можете открыть сайт для покупки SOL.</p>
<p class="meta-muted">2. Либо нажать «Тестовое пополнение» и получить 1 SOL через DevNet airdrop.</p>
</div>
<a class="link-card" href="${BUY_LINK}" target="_blank" rel="noreferrer">Открыть страницу покупки SOL</a>
<a class="link-card" href="${getTopupSiteUrl()}" target="_blank" rel="noreferrer">Открыть сайт пополнения</a>
<div class="card stack" style="padding:12px; max-width:320px;">
<div class="field-label" style="margin-bottom:6px;">Кошелёк для пополнения</div>
<div class="field-label" style="margin-bottom:6px;">Кошелёк для пополнения (wallet.key)</div>
</div>
`;
card.children[3].append(walletRow);
@@ -55,10 +63,31 @@ export function render({ navigate }) {
const testButton = document.createElement('button');
testButton.className = 'ghost-btn';
testButton.type = 'button';
testButton.textContent = 'Тестовое пополнение';
testButton.addEventListener('click', () => {
state.registrationPayment.balanceSOL = '0.0250';
window.alert('Тестовое пополнение выполнено. Баланс обновлён.');
testButton.textContent = 'Тестовое пополнение (1 SOL)';
testButton.addEventListener('click', async () => {
const address = String(walletValue.value || '').trim();
if (!address) {
window.alert('Адрес кошелька не найден.');
return;
}
testButton.disabled = true;
try {
const drop = await requestAirdropSol({
endpoint: state.entrySettings.solanaServer,
address,
amountSol: 1,
});
const bal = await getBalanceSol({
endpoint: state.entrySettings.solanaServer,
address,
});
state.registrationPayment.balanceSOL = String(bal.sol);
status.textContent = `Тестовое пополнение выполнено. Новый баланс: ${formatSol(bal.sol, 6)} SOL. Signature: ${drop.signature}`;
} catch (error) {
status.textContent = `Ошибка тестового пополнения: ${error?.message || 'unknown'}`;
} finally {
testButton.disabled = false;
}
});
const backButton = document.createElement('button');
@@ -71,14 +100,34 @@ export function render({ navigate }) {
actions.className = 'auth-footer-actions';
actions.append(testButton, backButton);
(async () => {
try {
if (!walletValue.value) {
const wallet = await deriveWalletFromPassword(String(state.registrationDraft.password ?? ''));
state.registrationPayment.walletAddress = wallet.address;
walletValue.value = wallet.address;
}
const balance = await getBalanceSol({
endpoint: state.entrySettings.solanaServer,
address: walletValue.value,
});
state.registrationPayment.balanceSOL = String(balance.sol);
status.textContent = `Текущий баланс: ${formatSol(balance.sol, 6)} SOL`;
} catch (error) {
status.textContent = `Не удалось получить баланс: ${error?.message || 'unknown'}`;
}
})();
screen.append(
renderHeader({
title: 'Пополнение счета',
leftAction: { label: '←', onClick: () => navigate('registration-payment-view') },
}),
card,
status,
actions,
);
return screen;
}