134 lines
5.0 KiB
JavaScript
134 lines
5.0 KiB
JavaScript
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 };
|
||
|
||
export function render({ navigate }) {
|
||
const screen = document.createElement('section');
|
||
screen.className = 'stack';
|
||
|
||
const walletValue = document.createElement('input');
|
||
walletValue.className = 'input';
|
||
walletValue.type = 'text';
|
||
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';
|
||
copyButton.textContent = 'Скопировать';
|
||
copyButton.addEventListener('click', async () => {
|
||
try {
|
||
await navigator.clipboard.writeText(walletValue.value);
|
||
copyButton.textContent = 'Скопировано';
|
||
window.setTimeout(() => {
|
||
copyButton.textContent = 'Скопировать';
|
||
}, 1500);
|
||
} catch {
|
||
window.alert('Не удалось скопировать номер кошелька.');
|
||
}
|
||
});
|
||
|
||
const walletRow = document.createElement('div');
|
||
walletRow.className = 'inline-input-row';
|
||
walletRow.append(walletValue, copyButton);
|
||
|
||
const card = document.createElement('div');
|
||
card.className = 'card stack';
|
||
card.innerHTML = `
|
||
<p class="auth-copy">Кнопка «Пополнить» в кошельке будет переводить на отдельный сайт. Пока доступно тестовое пополнение.</p>
|
||
<div class="stack" style="gap:6px;">
|
||
<p class="meta-muted">1. Вы можете открыть сайт для покупки SOL.</p>
|
||
<p class="meta-muted">2. Либо нажать «Тестовое пополнение» и получить 1 SOL через DevNet airdrop.</p>
|
||
</div>
|
||
<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;">Кошелёк для пополнения (wallet.key)</div>
|
||
</div>
|
||
`;
|
||
card.children[3].append(walletRow);
|
||
|
||
const testButton = document.createElement('button');
|
||
testButton.className = 'ghost-btn';
|
||
testButton.type = 'button';
|
||
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');
|
||
backButton.className = 'primary-btn';
|
||
backButton.type = 'button';
|
||
backButton.textContent = 'Назад';
|
||
backButton.addEventListener('click', () => navigate('registration-payment-view'));
|
||
|
||
const actions = document.createElement('div');
|
||
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;
|
||
}
|
||
|