183 lines
11 KiB
HTML
183 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Обновление PDA сервера — SHiNE Server Admin</title>
|
||
<link rel="stylesheet" href="styles.css" />
|
||
<style>
|
||
.pwd-wrap { display: flex; }
|
||
.pwd-wrap input { flex: 1; border-radius: var(--radius) 0 0 var(--radius); }
|
||
.btn-eye { border: 1px solid var(--border); border-left: none; background: #0d0d0d;
|
||
color: var(--text-muted); border-radius: 0 var(--radius) var(--radius) 0;
|
||
padding: 0 16px; cursor: pointer; font-size: 13px; }
|
||
.btn-eye:hover { color: var(--accent); border-color: var(--accent); }
|
||
.gen-msg { font-size: 12px; margin-top: 8px; padding: 8px 12px; border-radius: var(--radius); display: none; }
|
||
.gen-msg.ok { display:block; background:#1a2e1a; border:1px solid #2a4a2a; color:#7dcc7d; }
|
||
.gen-msg.err { display:block; background:#2e1a1a; border:1px solid #5a2a2a; color:#f08080; }
|
||
.kp-title { font-size:11px; font-weight:700; color:var(--accent); text-transform:uppercase; letter-spacing:.06em; margin-bottom:8px; }
|
||
.kp-row { display:flex; gap:8px; align-items:flex-start; margin-bottom:6px; }
|
||
.kp-row:last-child { margin-bottom:0; }
|
||
.kp-lbl { font-size:11px; color:var(--text-muted); min-width:60px; padding-top:10px; }
|
||
.kp-inp { flex:1; font-size:11px; font-family:monospace; padding:8px 10px; }
|
||
.kp-block { margin-bottom:14px; padding-bottom:14px; border-bottom:1px solid var(--border); }
|
||
.kp-block:last-child { border-bottom:none; margin-bottom:0; padding-bottom:0; }
|
||
.sec-lbl { font-size:11px; color:var(--text-muted); text-transform:uppercase; letter-spacing:.06em; margin:16px 0 10px; }
|
||
.sol-box { margin-top:14px; background:#0d1a0d; border:1px solid #2a4a2a; border-radius:var(--radius); padding:10px 14px; display:none; }
|
||
.sol-box.show { display:block; }
|
||
.sol-ttl { font-size:12px; font-weight:600; color:#7dcc7d; }
|
||
.sol-adr { font-family:monospace; font-size:12px; word-break:break-all; margin-top:4px; }
|
||
.sol-ht { font-size:11px; color:var(--text-muted); margin-top:4px; }
|
||
.muted { font-size:12px; color:var(--text-muted); margin-bottom:14px; line-height:1.6; }
|
||
.sol-topup-btn { margin-top:10px; width:100%; }
|
||
.sol-balance-btn { margin-top:10px; width:100%; }
|
||
.sol-balance { font-size:11px; color:var(--text-muted); margin-top:8px; word-break:break-all; }
|
||
.expected-card { margin-top:14px; background:#111520; border:1px solid #243147; border-radius:var(--radius); padding:12px 14px; }
|
||
.expected-ttl { font-size:12px; font-weight:600; color:#9dc4ff; margin-bottom:8px; }
|
||
.expected-row { margin-bottom:8px; }
|
||
.expected-row:last-child { margin-bottom:0; }
|
||
.expected-lbl { font-size:11px; color:var(--text-muted); margin-bottom:4px; }
|
||
.expected-val { font-family:monospace; font-size:11px; word-break:break-all; }
|
||
.gen-msg.warn { display:block; background:#2f2614; border:1px solid #5f4b22; color:#ffd37a; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="nav-links">
|
||
<a href="../server-ui.html">← Назад</a>
|
||
<a href="create-server-pda.html">Создать PDA</a>
|
||
</div>
|
||
|
||
<h1>Обновление PDA сервера</h1>
|
||
<p class="subtitle">Меняет адрес сервера или список серверов синхронизации</p>
|
||
|
||
<div class="card">
|
||
<h2>Параметры Solana</h2>
|
||
<div class="field">
|
||
<label>Solana Endpoint</label>
|
||
<input type="text" id="endpoint" value="https://api.devnet.solana.com" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Загрузить существующую PDA</h2>
|
||
<div class="field">
|
||
<label>Логин сервера</label>
|
||
<input type="text" id="login" placeholder="Логин сервера" maxlength="20" />
|
||
</div>
|
||
<div class="btn-row">
|
||
<button class="btn-secondary" id="btnLoad">Загрузить PDA</button>
|
||
</div>
|
||
<div class="pda-info" id="pdaInfo">
|
||
<hr class="section-divider" />
|
||
<div class="pda-row"><span class="pda-key">PDA адрес</span><span class="pda-value" id="iAddr"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Версия</span><span class="pda-value" id="iVer"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Создан</span><span class="pda-value" id="iCreated"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Обновлён</span><span class="pda-value" id="iUpdated"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Адрес сервера</span><span class="pda-value" id="iSrvAddr"></span></div>
|
||
<div class="pda-row"><span class="pda-key">sync_servers</span><span class="pda-value" id="iSync"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Blockchain</span><span class="pda-value" id="iBch"></span></div>
|
||
<div class="pda-row"><span class="pda-key">Paid limit</span><span class="pda-value" id="iLimit"></span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="updateForm" style="display:none">
|
||
<div class="card">
|
||
<h2>Новые параметры сервера</h2>
|
||
<div class="field">
|
||
<label>Новый адрес сервера (URL)</label>
|
||
<input type="text" id="serverAddress" placeholder="Адрес сервера" />
|
||
</div>
|
||
<div class="field">
|
||
<label>Новые серверы синхронизации (sync_servers)</label>
|
||
<textarea id="syncServers" placeholder="По одному логину на строку (можно оставить пустым)"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Ключи для подписи и оплаты</h2>
|
||
<p class="muted">Root-ключ подписывает новую PDA-запись. Device-ключ оплачивает транзакцию.<br/>Blockchain-ключ не нужен — подпись LastBlockState из PDA переиспользуется автоматически.</p>
|
||
|
||
<div class="field">
|
||
<label>Пароль</label>
|
||
<div class="pwd-wrap">
|
||
<input type="password" id="password" name="server-ui-password-update" placeholder="Пароль аккаунта сервера" autocomplete="new-password" autocapitalize="off" spellcheck="false" />
|
||
<button class="btn-eye" id="btnEye" type="button">Показать</button>
|
||
</div>
|
||
<div class="hint">Нажмите «Сгенерировать» — поля ниже заполнятся из логина + пароля.<br/>Или введите ключи вручную.</div>
|
||
</div>
|
||
<div class="btn-row">
|
||
<button class="btn-secondary" id="btnGen" type="button">Сгенерировать ключи</button>
|
||
</div>
|
||
<div class="gen-msg" id="genMsg"></div>
|
||
|
||
<div class="sec-lbl">Секрет (master secret, base58)</div>
|
||
<div class="field" style="margin-bottom:0">
|
||
<input type="text" id="masterSecret" placeholder="32-байтовый master secret в base58 (~44 символа)" />
|
||
</div>
|
||
|
||
<div class="sec-lbl">Ключевые пары (base58)</div>
|
||
|
||
<div class="kp-block">
|
||
<div class="kp-title">Recovery Key — восстановление аккаунта</div>
|
||
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="recoveryPub" placeholder="base58, ~44 символа" /></div>
|
||
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="recoveryPriv" placeholder="seed base58, ~44 символа" /></div>
|
||
</div>
|
||
<div class="kp-block">
|
||
<div class="kp-title">Root Key — подпись PDA-записи</div>
|
||
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="rootPub" placeholder="base58, ~44 символа" /></div>
|
||
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="rootPriv" placeholder="seed base58, ~44 символа" /></div>
|
||
</div>
|
||
<div class="kp-block">
|
||
<div class="kp-title">Blockchain Key — справочно, при обновлении не используется</div>
|
||
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="bchPub" placeholder="base58, ~44 символа" /></div>
|
||
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="bchPriv" placeholder="seed base58, ~44 символа" /></div>
|
||
</div>
|
||
<div class="kp-block">
|
||
<div class="kp-title">Device Key — оплата транзакции Solana</div>
|
||
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="devPub" placeholder="base58, ~44 символа (= Solana-адрес)" /></div>
|
||
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="devPriv" placeholder="seed base58, ~44 символа" /></div>
|
||
<div class="sol-box" id="solBox">
|
||
<div class="sol-ttl">Положите SOL на этот адрес перед обновлением:</div>
|
||
<div class="sol-adr" id="solAdr"></div>
|
||
<div class="sol-ht">Это Solana-адрес (base58) device-ключа. С него оплачивается транзакция.</div>
|
||
<button class="btn-secondary sol-topup-btn" id="btnTopupDevnet" type="button">Открыть пополнение DEVNET</button>
|
||
<button class="btn-secondary sol-balance-btn" id="btnRefreshBalance" type="button">Показать / обновить баланс device</button>
|
||
<div class="sol-balance" id="deviceBalance">Баланс device ещё не запрашивался.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="expected-card" id="expectedKeysBox" style="display:none">
|
||
<div class="expected-ttl">Какие ключи ожидаются по уже загруженной PDA</div>
|
||
<div class="expected-row">
|
||
<div class="expected-lbl">Ожидаемый recovery public key</div>
|
||
<div class="expected-val" id="expectedRecoveryPub"></div>
|
||
</div>
|
||
<div class="expected-row">
|
||
<div class="expected-lbl">Ожидаемый root public key</div>
|
||
<div class="expected-val" id="expectedRootPub"></div>
|
||
</div>
|
||
<div class="expected-row">
|
||
<div class="expected-lbl">Ожидаемый blockchain public key</div>
|
||
<div class="expected-val" id="expectedBchPub"></div>
|
||
</div>
|
||
<div class="expected-row">
|
||
<div class="expected-lbl">Ожидаемый device public key</div>
|
||
<div class="expected-val" id="expectedDevPub"></div>
|
||
</div>
|
||
<div class="gen-msg" id="expectedKeysStatus"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="btn-row">
|
||
<button class="btn-primary" id="btnUpdate">Обновить PDA</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="status" id="status"></div>
|
||
</div>
|
||
|
||
<script type="module" src="./js/update-server-pda-page.js"></script>
|
||
</body>
|
||
</html>
|