Исправить клиентскую Solana-регистрацию после ухода от Anchor

This commit is contained in:
AidarKC 2026-06-07 10:58:06 +04:00
parent b0b8c7a445
commit 6bf5d1d5ed
5 changed files with 77 additions and 7 deletions

View File

@ -0,0 +1,30 @@
# Клиентская Solana-регистрация после ухода от Anchor
## Краткое описание
Исправлен рассинхрон обычного клиентского UI с no-Anchor ABI программ:
- `shine_login_guard`
- `shine_users`
Исправлены клиентские вызовы:
1. Solana-предпроверка логина в обычном UI.
2. `init_users_economy_config` в обычном UI.
## Что проверять
1. На странице регистрации проверка свободного логина не выдаёт `InvalidInstructionData`.
2. Для свободного обычного логина отображается корректный статус без fallback-предупреждения про недоступную Solana-предпроверку.
3. Регистрация пользователя через обычный UI проходит до конца.
4. Страница `Solana: init регистрации` в обычном UI отправляет корректную транзакцию и не падает из-за старого Anchor discriminator.
## Ожидаемый результат
1. `shine_login_guard` принимает клиентский precheck.
2. `init_users_economy_config` из обычного UI совместим с текущей программой `shine_users`.
3. Обычный клиентский UI ведёт себя так же, как серверный UI, там где используется общий no-Anchor путь.
## Статус
- `pending`

View File

@ -1,2 +1,2 @@
client.version=1.2.132 client.version=1.2.133
server.version=1.2.124 server.version=1.2.125

View File

@ -116,7 +116,6 @@ export function render({ navigate }) {
const connection = new solana.Connection(String(state.entrySettings.solanaServer || ''), 'confirmed'); const connection = new solana.Connection(String(state.entrySettings.solanaServer || ''), 'confirmed');
const programPubkey = new solana.PublicKey(programId); const programPubkey = new solana.PublicKey(programId);
const discriminator = Uint8Array.from([13, 16, 103, 175, 121, 137, 166, 222]);
const ix = new solana.TransactionInstruction({ const ix = new solana.TransactionInstruction({
programId: programPubkey, programId: programPubkey,
keys: [ keys: [
@ -124,7 +123,7 @@ export function render({ navigate }) {
{ pubkey: economyPda, isSigner: false, isWritable: true }, { pubkey: economyPda, isSigner: false, isWritable: true },
{ pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
], ],
data: discriminator, data: Uint8Array.from([1]),
}); });
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed'); const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');

View File

@ -4,7 +4,7 @@ import {
SHINE_LOGIN_GUARD_PROGRAM_ID, SHINE_LOGIN_GUARD_PROGRAM_ID,
} from '../solana-programs.js'; } from '../solana-programs.js';
const CLASSIFY_LOGIN_DISCRIMINATOR = new Uint8Array([112, 97, 152, 32, 255, 73, 108, 86]); const CLASSIFY_LOGIN_INSTRUCTION_TAG = 1;
const PRECHECK_SIM_PAYER = 'FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P'; const PRECHECK_SIM_PAYER = 'FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P';
let solanaLibPromise = null; let solanaLibPromise = null;
@ -33,7 +33,7 @@ class BorshBuf {
function serializeClassifyLoginArgs(login) { function serializeClassifyLoginArgs(login) {
const b = new BorshBuf(); const b = new BorshBuf();
b.raw(CLASSIFY_LOGIN_DISCRIMINATOR); b.u8(CLASSIFY_LOGIN_INSTRUCTION_TAG);
b.str(String(login || '')); b.str(String(login || ''));
return b.result(); return b.result();
} }
@ -78,7 +78,7 @@ export async function precheckLoginClassOnSolana({ login, solanaEndpoint }) {
const payer = new solana.PublicKey(PRECHECK_SIM_PAYER); const payer = new solana.PublicKey(PRECHECK_SIM_PAYER);
const ix = new solana.TransactionInstruction({ const ix = new solana.TransactionInstruction({
programId: loginGuardProgram, programId: loginGuardProgram,
keys: [{ pubkey: payer, isSigner: true, isWritable: false }], keys: [],
data: serializeClassifyLoginArgs(String(login || '').toLowerCase()), data: serializeClassifyLoginArgs(String(login || '').toLowerCase()),
}); });
const { blockhash } = await connection.getLatestBlockhash('confirmed'); const { blockhash } = await connection.getLatestBlockhash('confirmed');

View File

@ -0,0 +1,41 @@
# План тестирования `shine_payments` после переписи без Anchor и добавления `Q3`
## Назначение документа
Это не описание бизнес-логики программы и не формат PDA.
Это отдельный план ручной и полуавтоматической проверки для сценария:
- перепись `shine_payments` на чистый `solana_program`;
- отказ от `programs/common`;
- добавление очереди `Q3`;
- обновление тестового HTML UI.
## Что проверять
1. Деплой новой версии программы и единый актуальный `program id` в коде и UI.
2. Однократный `init` на пустых PDA.
3. Покупку билетов через `buy_ticket_usd` и `buy_ticket_sol`.
4. DAO-управление:
- `update_coef_limit`
- `grant_manager_limits`
5. Создание менеджерских тикетов во все три очереди:
- `Q1`
- `Q2`
- `Q3`
6. Приоритет выплат:
- сначала `Q1`
- потом `Q2`
- потом `Q3`
7. Частичные выплаты с минимальным пополнением `inflow_vault`.
8. Повторную покупку билета между выплатами.
9. Финальное погашение всех очередей.
10. Возврат максимально возможных остатков лампортов на базовый кошелёк.
## Где смотреть подробный сценарий
Актуальный подробный сценарий тестирования и его статус ведётся в:
- `Dev_Docs/Pending_Features/2026-06-06_1659_shine_payments_e2e_перепись_и_q3.md`
Этот файл в `shine-solana/shine/doc/` оставлен как постоянная заметка, что у программы есть отдельный e2e-план проверки.