Регистрация Solana: промо-topup URL с wallet(base58) и порог 0.01 SOL
This commit is contained in:
parent
2c68dedea2
commit
50da3e868d
@ -1,2 +1,2 @@
|
|||||||
client.version=1.2.17
|
client.version=1.2.18
|
||||||
server.version=1.2.17
|
server.version=1.2.18
|
||||||
|
|||||||
@ -6,9 +6,15 @@ import {
|
|||||||
state,
|
state,
|
||||||
} from '../state.js';
|
} from '../state.js';
|
||||||
import { toUserMessage } from '../services/ui-error-texts.js';
|
import { toUserMessage } from '../services/ui-error-texts.js';
|
||||||
import { deriveWalletFromPassword, formatSol, getBalanceSol } from '../services/solana-wallet-service.js';
|
import {
|
||||||
|
deriveWalletFromPassword,
|
||||||
|
formatSol,
|
||||||
|
getBalanceSol,
|
||||||
|
getTopupSiteUrl,
|
||||||
|
} from '../services/solana-wallet-service.js';
|
||||||
|
|
||||||
export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false };
|
export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false };
|
||||||
|
const MIN_REQUIRED_SOL = 0.01;
|
||||||
|
|
||||||
function parseBalanceSol(value) {
|
function parseBalanceSol(value) {
|
||||||
const parsed = Number.parseFloat(String(value || '').replace(',', '.'));
|
const parsed = Number.parseFloat(String(value || '').replace(',', '.'));
|
||||||
@ -77,9 +83,9 @@ export function render({ navigate }) {
|
|||||||
refreshButton.textContent = '↻';
|
refreshButton.textContent = '↻';
|
||||||
refreshButton.title = 'Обновить';
|
refreshButton.title = 'Обновить';
|
||||||
|
|
||||||
const refreshBalance = async () => {
|
const refreshBalance = async ({ showError = true } = {}) => {
|
||||||
const address = String(walletValue.value || '').trim();
|
const address = String(walletValue.value || '').trim();
|
||||||
if (!address) return;
|
if (!address) return null;
|
||||||
refreshButton.disabled = true;
|
refreshButton.disabled = true;
|
||||||
try {
|
try {
|
||||||
const balance = await getBalanceSol({
|
const balance = await getBalanceSol({
|
||||||
@ -88,10 +94,14 @@ export function render({ navigate }) {
|
|||||||
});
|
});
|
||||||
state.registrationPayment.balanceSOL = String(balance.sol);
|
state.registrationPayment.balanceSOL = String(balance.sol);
|
||||||
balanceValue.textContent = `${formatSol(balance.sol, 6)} SOL`;
|
balanceValue.textContent = `${formatSol(balance.sol, 6)} SOL`;
|
||||||
|
return Number(balance.sol) || 0;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (showError) {
|
||||||
status.className = 'status-line is-unavailable';
|
status.className = 'status-line is-unavailable';
|
||||||
status.textContent = `Не удалось обновить баланс: ${error?.message || 'unknown'}`;
|
status.textContent = `Не удалось обновить баланс: ${error?.message || 'unknown'}`;
|
||||||
status.style.display = '';
|
status.style.display = '';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
refreshButton.disabled = false;
|
refreshButton.disabled = false;
|
||||||
}
|
}
|
||||||
@ -106,8 +116,11 @@ export function render({ navigate }) {
|
|||||||
const topupButton = document.createElement('button');
|
const topupButton = document.createElement('button');
|
||||||
topupButton.className = 'ghost-btn';
|
topupButton.className = 'ghost-btn';
|
||||||
topupButton.type = 'button';
|
topupButton.type = 'button';
|
||||||
topupButton.textContent = 'Пополнить счет';
|
topupButton.textContent = 'Пополнить кошелёк';
|
||||||
topupButton.addEventListener('click', () => navigate('topup-view'));
|
topupButton.addEventListener('click', () => {
|
||||||
|
const walletAddress = String(walletValue.value || '').trim();
|
||||||
|
window.open(getTopupSiteUrl(walletAddress), '_blank', 'noopener,noreferrer');
|
||||||
|
});
|
||||||
|
|
||||||
const submitButton = document.createElement('button');
|
const submitButton = document.createElement('button');
|
||||||
submitButton.className = 'primary-btn';
|
submitButton.className = 'primary-btn';
|
||||||
@ -128,6 +141,27 @@ export function render({ navigate }) {
|
|||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
submitButton.textContent = 'Регистрация...';
|
submitButton.textContent = 'Регистрация...';
|
||||||
|
|
||||||
|
const walletAddress = String(walletValue.value || '').trim();
|
||||||
|
if (!walletAddress) {
|
||||||
|
status.className = 'status-line is-unavailable';
|
||||||
|
status.textContent = 'Кошелёк не подготовлен. Нажмите «Обновить» и попробуйте снова.';
|
||||||
|
status.style.display = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentBalance = await refreshBalance({ showError: true });
|
||||||
|
if (currentBalance == null) return;
|
||||||
|
if (currentBalance < MIN_REQUIRED_SOL) {
|
||||||
|
status.className = 'status-line is-unavailable';
|
||||||
|
status.textContent = `Для регистрации нужно минимум ${MIN_REQUIRED_SOL} SOL. Сейчас на кошельке ${formatSol(currentBalance, 6)} SOL. Пополните на промо-странице или попросите перевод у знакомого с тестовыми SOL.`;
|
||||||
|
status.style.display = '';
|
||||||
|
const openTopup = window.confirm('Открыть страницу пополнения с вашим кошельком?');
|
||||||
|
if (openTopup) {
|
||||||
|
window.open(getTopupSiteUrl(walletAddress), '_blank', 'noopener,noreferrer');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await authService.reconnect(state.entrySettings.shineServer);
|
await authService.reconnect(state.entrySettings.shineServer);
|
||||||
const result = await authService.registerUser(state.registrationDraft.login, state.registrationDraft.password);
|
const result = await authService.registerUser(state.registrationDraft.login, state.registrationDraft.password);
|
||||||
state.registrationDraft.flowType = 'registration';
|
state.registrationDraft.flowType = 'registration';
|
||||||
@ -151,7 +185,7 @@ export function render({ navigate }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
card.innerHTML = `
|
card.innerHTML = `
|
||||||
<p class="auth-copy">Для регистрации в Solana нужно заплатить 0,01 SOL (примерно 1 доллар).</p>
|
<p class="auth-copy">Для регистрации в тестовой Solana нужно минимум 0,01 SOL на вашем кошельке.</p>
|
||||||
<label class="stack"><span class="field-label">Номер кошелька (wallet.key = device.key)</span></label>
|
<label class="stack"><span class="field-label">Номер кошелька (wallet.key = device.key)</span></label>
|
||||||
<div class="stack">
|
<div class="stack">
|
||||||
<span class="field-label">Баланс (Solana)</span>
|
<span class="field-label">Баланс (Solana)</span>
|
||||||
|
|||||||
@ -50,10 +50,10 @@ export function render({ navigate }) {
|
|||||||
card.innerHTML = `
|
card.innerHTML = `
|
||||||
<p class="auth-copy">Кнопка «Пополнить» в кошельке будет переводить на отдельный сайт. Пока доступно тестовое пополнение.</p>
|
<p class="auth-copy">Кнопка «Пополнить» в кошельке будет переводить на отдельный сайт. Пока доступно тестовое пополнение.</p>
|
||||||
<div class="stack" style="gap:6px;">
|
<div class="stack" style="gap:6px;">
|
||||||
<p class="meta-muted">1. Вы можете открыть сайт для покупки SOL.</p>
|
<p class="meta-muted">1. Вы можете открыть промо-сайт пополнения с подставленным кошельком.</p>
|
||||||
<p class="meta-muted">2. Либо нажать «Тестовое пополнение» и получить 1 SOL через DevNet airdrop.</p>
|
<p class="meta-muted">2. Либо нажать «Тестовое пополнение» и получить 1 SOL через DevNet airdrop.</p>
|
||||||
</div>
|
</div>
|
||||||
<a class="link-card" href="${getTopupSiteUrl()}" target="_blank" rel="noreferrer">Открыть сайт пополнения</a>
|
<a class="link-card" id="topup-site-link" href="${getTopupSiteUrl(state.registrationPayment.walletAddress || '')}" target="_blank" rel="noreferrer">Открыть сайт пополнения</a>
|
||||||
<div class="card stack" style="padding:12px; max-width:320px;">
|
<div class="card stack" style="padding:12px; max-width:320px;">
|
||||||
<div class="field-label" style="margin-bottom:6px;">Кошелёк для пополнения (wallet.key)</div>
|
<div class="field-label" style="margin-bottom:6px;">Кошелёк для пополнения (wallet.key)</div>
|
||||||
</div>
|
</div>
|
||||||
@ -107,6 +107,10 @@ export function render({ navigate }) {
|
|||||||
state.registrationPayment.walletAddress = wallet.address;
|
state.registrationPayment.walletAddress = wallet.address;
|
||||||
walletValue.value = wallet.address;
|
walletValue.value = wallet.address;
|
||||||
}
|
}
|
||||||
|
const topupSiteLink = card.querySelector('#topup-site-link');
|
||||||
|
if (topupSiteLink instanceof HTMLAnchorElement) {
|
||||||
|
topupSiteLink.href = getTopupSiteUrl(walletValue.value);
|
||||||
|
}
|
||||||
const balance = await getBalanceSol({
|
const balance = await getBalanceSol({
|
||||||
endpoint: state.entrySettings.solanaServer,
|
endpoint: state.entrySettings.solanaServer,
|
||||||
address: walletValue.value,
|
address: walletValue.value,
|
||||||
@ -130,4 +134,3 @@ export function render({ navigate }) {
|
|||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -242,7 +242,7 @@ export function render({ navigate }) {
|
|||||||
'Кнопка будет переводить на отдельный сайт пополнения.\n\nНажмите OK, чтобы открыть сайт.\nНажмите Отмена, чтобы выполнить тестовое пополнение (airdrop 1 SOL на DevNet).',
|
'Кнопка будет переводить на отдельный сайт пополнения.\n\nНажмите OK, чтобы открыть сайт.\nНажмите Отмена, чтобы выполнить тестовое пополнение (airdrop 1 SOL на DevNet).',
|
||||||
);
|
);
|
||||||
if (openSite) {
|
if (openSite) {
|
||||||
window.open(getTopupSiteUrl(), '_blank', 'noopener,noreferrer');
|
window.open(getTopupSiteUrl(walletAddress), '_blank', 'noopener,noreferrer');
|
||||||
setStatus('Открыт сайт пополнения. Пока также доступно тестовое пополнение.');
|
setStatus('Открыт сайт пополнения. Пока также доступно тестовое пополнение.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { extractDeviceKey32FromStoredValue } from './device-key-utils.js';
|
|||||||
import { loadEncryptedUserSecrets } from './key-vault.js';
|
import { loadEncryptedUserSecrets } from './key-vault.js';
|
||||||
|
|
||||||
const DEFAULT_SOLANA_ENDPOINT = 'https://api.devnet.solana.com';
|
const DEFAULT_SOLANA_ENDPOINT = 'https://api.devnet.solana.com';
|
||||||
const TOPUP_SITE_URL = 'https://www.moonpay.com/buy/sol';
|
const TOPUP_SITE_URL = 'https://shine-promo-solana-devnet.shineup.me/';
|
||||||
|
|
||||||
let solanaLibPromise = null;
|
let solanaLibPromise = null;
|
||||||
|
|
||||||
@ -115,6 +115,14 @@ export function formatSol(value, digits = 6) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTopupSiteUrl() {
|
export function getTopupSiteUrl(walletAddress = '') {
|
||||||
return TOPUP_SITE_URL;
|
const cleanWallet = String(walletAddress || '').trim();
|
||||||
|
if (!cleanWallet) return TOPUP_SITE_URL;
|
||||||
|
try {
|
||||||
|
const url = new URL(TOPUP_SITE_URL);
|
||||||
|
url.searchParams.set('wallet', cleanWallet);
|
||||||
|
return url.toString();
|
||||||
|
} catch {
|
||||||
|
return `${TOPUP_SITE_URL}?wallet=${encodeURIComponent(cleanWallet)}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user