Промежуточный коммит: состояние до нормальной Solana-first регистрации

This commit is contained in:
AidarKC
2026-05-27 18:33:26 +04:00
parent b345900459
commit 6f0bb01b61
17 changed files with 661 additions and 72 deletions
+46 -3
View File
@@ -4,10 +4,18 @@ import { loadEncryptedUserSecrets } from './key-vault.js';
import { SOLANA_ENDPOINT_DEFAULT } from '../solana-programs.js';
const DEFAULT_SOLANA_ENDPOINT = SOLANA_ENDPOINT_DEFAULT;
const TOPUP_SITE_URL = 'https://shine-promo-solana-devnet.shineup.me/';
const TOPUP_SITE_URL = '/devnet-topup-view';
let solanaLibPromise = null;
const BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]+$/;
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
const BASE58_MAP = (() => {
const out = Object.create(null);
for (let i = 0; i < BASE58_ALPHABET.length; i += 1) {
out[BASE58_ALPHABET[i]] = i;
}
return out;
})();
function normalizeEndpoint(url) {
const raw = String(url || '').trim();
@@ -22,6 +30,38 @@ async function loadSolanaLib() {
return solanaLibPromise;
}
function decodeBase58(input) {
const text = String(input || '').trim();
if (!text) return new Uint8Array(0);
const bytes = [0];
for (let i = 0; i < text.length; i += 1) {
const ch = text[i];
const value = BASE58_MAP[ch];
if (value == null) {
throw new Error('Недопустимый символ Base58');
}
let carry = value;
for (let j = 0; j < bytes.length; j += 1) {
const x = (bytes[j] * 58) + carry;
bytes[j] = x & 0xff;
carry = x >> 8;
}
while (carry > 0) {
bytes.push(carry & 0xff);
carry >>= 8;
}
}
for (let i = 0; i < text.length && text[i] === '1'; i += 1) {
bytes.push(0);
}
bytes.reverse();
return Uint8Array.from(bytes);
}
async function keypairFromPkcs8(pkcs8B64) {
const solana = await loadSolanaLib();
const seed32 = extractDeviceKey32FromStoredValue(pkcs8B64);
@@ -55,7 +95,7 @@ export async function createSolanaWalletFromPrivateBase58(privateKey32Base58) {
const clean = String(privateKey32Base58 || '').trim();
if (!clean) throw new Error('Введите приватный ключ');
if (!BASE58_RE.test(clean)) throw new Error('Разрешены только символы Base58');
const privateBytes = solana.bs58.decode(clean);
const privateBytes = decodeBase58(clean);
if (privateBytes.length !== 32) {
throw new Error('Приватный ключ должен быть ровно 32 байта в Base58');
}
@@ -149,7 +189,10 @@ export function getTopupSiteUrl(walletAddress = '') {
const cleanWallet = String(walletAddress || '').trim();
if (!cleanWallet) return TOPUP_SITE_URL;
try {
const url = new URL(TOPUP_SITE_URL);
const base = typeof window !== 'undefined' && window.location?.origin
? window.location.origin
: 'http://localhost:8088';
const url = new URL(TOPUP_SITE_URL, base);
url.searchParams.set('wallet', cleanWallet);
return url.toString();
} catch {