SHA256
chore: зафиксированы все текущие изменения проекта
This commit is contained in:
@@ -1,14 +1,42 @@
|
||||
# Будущие фичи
|
||||
|
||||
Эта папка хранит задачи, которые сознательно отложены и сейчас не должны попадать в активную разработку или ручную проверку.
|
||||
Эта папка хранит задачи, которые сознательно отложены и сейчас не должны попадать в активную разработку или ручную проверку без отдельной команды пользователя.
|
||||
|
||||
## Горизонты планирования
|
||||
|
||||
- `near/` - ближайшие планы: задачи, к которым можно вернуться сегодня или завтра.
|
||||
- `medium/` - среднесрочные планы: задачи на ближайшие недели или 1-2 месяца.
|
||||
- `far/` - дальнее будущее: идеи без понятного срока возврата.
|
||||
|
||||
Если пользователь спрашивает, какие есть планы, агент должен смотреть эти три папки и кратко перечислять задачи по горизонтам.
|
||||
|
||||
## Как использовать
|
||||
|
||||
1. Каждая будущая фича описывается отдельным markdown-файлом.
|
||||
1. Каждая будущая фича описывается отдельным markdown-файлом в одном из горизонтов.
|
||||
2. В файле нужно фиксировать:
|
||||
- зачем нужна фича;
|
||||
- что уже было сделано в коде;
|
||||
- что временно отключено или закомментировано;
|
||||
- к какому сроку или горизонту она относится;
|
||||
- что нужно сделать;
|
||||
- какие вопросы нужно уточнить перед реализацией;
|
||||
- что уже было сделано в коде, если фича частично реализована;
|
||||
- что временно отключено или закомментировано, если применимо;
|
||||
- какие документы нужно обновить при возврате к задаче;
|
||||
- с какого места продолжать разработку.
|
||||
3. Агент не должен начинать реализацию файлов из этой папки без явной просьбы пользователя.
|
||||
|
||||
## Текущие планы
|
||||
|
||||
### Ближайшие
|
||||
|
||||
- `near/2026-05-25_1106_telegram_agent_players.md` - разрешённые пользователи Telegram для агента, отдельные папки игроков, персональные истории и публикация краткого вопроса/ответа в общий канал.
|
||||
- `near/2026-05-25_1106_wallet_topup_solana_arweave.md` - пополнение Solana и Arweave через внешний сервис покупки с подсказкой и копированием адреса.
|
||||
- `near/2026-05-25_1106_channels_my_create_button.md` - поправить экран каналов: создание канала показывать только в разделе `Мои каналы`.
|
||||
|
||||
### Среднесрочные
|
||||
|
||||
- `medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md` - репосты в каналах и тредах.
|
||||
- `medium/2026-05-25_1106_shine_balance_wallet.md` - кошелёк и пополнение баланса сияния через блокчейн.
|
||||
|
||||
### Дальнее будущее
|
||||
|
||||
- Сейчас задач нет.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Дальнее будущее
|
||||
|
||||
Сейчас в этом горизонте нет активных идей.
|
||||
|
||||
Сюда переносить задачи, у которых нет понятного срока возврата и которые не нужно учитывать в ближайшем или среднесрочном планировании.
|
||||
+6
@@ -3,6 +3,12 @@
|
||||
- Статус:
|
||||
`future`
|
||||
|
||||
- Горизонт:
|
||||
`medium`
|
||||
|
||||
- Ориентир:
|
||||
1-2 месяца
|
||||
|
||||
- Решение от 2026-05-24:
|
||||
Репосты временно убраны из активной разработки. Фича уже была частично реализована, но не доведена до финальной проверки. Чтобы она не мешала запуску проекта, пользовательский вход в репосты отключён в UI, а сервер больше не принимает новые `TEXT_REPOST` через `AddBlock`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Кошелёк и пополнение баланса сияния
|
||||
|
||||
- Горизонт:
|
||||
`medium`
|
||||
- Ориентир:
|
||||
среднесрочно
|
||||
- Статус:
|
||||
`proposal`
|
||||
|
||||
## Кратко
|
||||
|
||||
Нужно добавить кошелёк для внутреннего баланса сияния и пополнение этого баланса через блокчейн-логику проекта. Задача связана с регистрацией пользователя и будущим учётом баланса.
|
||||
|
||||
## Предполагаемый сценарий
|
||||
|
||||
1. Пользователь регистрируется и получает/подключает нужные кошельки.
|
||||
2. В интерфейсе появляется баланс сияния.
|
||||
3. Пользователь открывает пополнение баланса сияния.
|
||||
4. Система создаёт или принимает блокчейн-операцию пополнения.
|
||||
5. После подтверждения баланса UI обновляет значение.
|
||||
|
||||
## Что нужно продумать
|
||||
|
||||
1. Что именно является единицей баланса сияния.
|
||||
2. Где хранится состояние баланса: в существующем блокчейне SHiNE, Solana-модуле или комбинированно.
|
||||
3. Какая операция отвечает за пополнение.
|
||||
4. Нужно ли делать отдельную регистрацию кошелька сияния или использовать существующую регистрацию пользователя.
|
||||
5. Как баланс восстанавливается после перезагрузки клиента.
|
||||
6. Какие права нужны для пополнения и списания.
|
||||
7. Нужна ли история операций баланса.
|
||||
|
||||
## Вопросы перед реализацией
|
||||
|
||||
1. Пополнение баланса сияния должно идти через основной блокчейн SHiNE или через Solana-программу.
|
||||
2. Нужна ли конвертация из SOL/AR в сияние.
|
||||
3. Кто может выпускать или начислять сияние.
|
||||
4. Нужно ли поддерживать перевод сияния между пользователями.
|
||||
5. Нужны ли лимиты, комиссии или статусы подтверждения.
|
||||
6. Какой экран должен показывать баланс: регистрация, профиль, кошелёк или отдельная страница.
|
||||
7. Нужно ли отображать неподтверждённый баланс отдельно от подтверждённого.
|
||||
|
||||
## Важное ограничение
|
||||
|
||||
Если для баланса сияния потребуется новый формат блокчейн-блока или изменение существующего формата, перед реализацией нужно отдельно предупредить пользователя и получить явное подтверждение на изменение формата блокчейна.
|
||||
|
||||
Если потребуется новый серверный API или изменение существующих `op`, перед реализацией нужно отдельно предупредить пользователя и получить явное подтверждение на изменение API.
|
||||
|
||||
## Документы, которые обновить при реализации
|
||||
|
||||
- `Dev_Docs/Blockchain/`, если появятся или изменятся блоки баланса.
|
||||
- `Dev_Docs/Blockchain/CHANGELOG.md`, если меняется блокчейн-формат.
|
||||
- `Dev_Docs/API/`, если меняется серверный API.
|
||||
- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации.
|
||||
- Документацию Solana-регистрации, если баланс будет связан с Solana-модулем.
|
||||
|
||||
## Минимальная проверка в будущем
|
||||
|
||||
1. Новый пользователь видит корректный начальный баланс.
|
||||
2. Пополнение создаёт правильную операцию.
|
||||
3. Баланс обновляется после подтверждения.
|
||||
4. После перезагрузки UI баланс остаётся корректным.
|
||||
5. Ошибочные или повторные операции не начисляют баланс дважды.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Кнопка создания канала только в разделе «Мои каналы»
|
||||
|
||||
- Горизонт:
|
||||
`near`
|
||||
- Ориентир:
|
||||
сегодня/завтра
|
||||
- Статус:
|
||||
`proposal`
|
||||
|
||||
## Кратко
|
||||
|
||||
Нужно поправить экран каналов: в общем списке должна быть простая надпись `Каналы` и переход к своим каналам, а кнопка создания канала должна появляться только в разделе `Мои каналы`.
|
||||
|
||||
## Ожидаемый сценарий
|
||||
|
||||
### Общий список
|
||||
|
||||
1. Заголовок: `Каналы`.
|
||||
2. Есть кнопка перехода в свои каналы: `Мои` или `Мои каналы`.
|
||||
3. Кнопки создания канала в общем списке нет.
|
||||
|
||||
### Раздел своих каналов
|
||||
|
||||
1. Заголовок: `Мои каналы`.
|
||||
2. Слева есть переход назад или кнопка `Ко всем каналам`.
|
||||
3. Справа от заголовка или в правой части шапки есть маленькая кнопка `+` для создания канала.
|
||||
4. Кнопка создания канала работает только здесь.
|
||||
|
||||
## Что нужно сделать
|
||||
|
||||
1. Найти компонент/страницу списка каналов в UI.
|
||||
2. Разделить состояние общего списка и списка своих каналов.
|
||||
3. Убрать кнопку создания канала из общего списка.
|
||||
4. Добавить или оставить кнопку создания канала в `Мои каналы`.
|
||||
5. Поправить заголовки:
|
||||
- общий список: `Каналы`;
|
||||
- свой список: `Мои каналы`.
|
||||
6. Проверить расположение кнопок на мобильном и desktop-экране.
|
||||
7. Убедиться, что существующее создание канала не ломается.
|
||||
|
||||
## Вопросы перед реализацией
|
||||
|
||||
1. Какой текст кнопки перехода лучше: `Мои`, `Мои каналы` или иконка с подписью.
|
||||
2. Нужна ли отдельная стрелка назад, если уже есть кнопка `Ко всем каналам`.
|
||||
3. Кнопка `+` должна быть иконкой без текста или `Создать канал`.
|
||||
4. Нужно ли сохранять выбранный режим после перезагрузки страницы.
|
||||
|
||||
## Риски и ограничения
|
||||
|
||||
- Нужно проверить, не завязаны ли текущие обработчики создания канала на общий экран.
|
||||
- На узких экранах заголовок, кнопка назад и `+` могут конфликтовать по ширине.
|
||||
- Если есть роутинг по query/state, важно не сломать прямые переходы.
|
||||
|
||||
## Документы, которые обновить при реализации
|
||||
|
||||
- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации.
|
||||
- UI-документацию, если в проекте есть отдельное описание экранов каналов.
|
||||
|
||||
## Минимальная проверка
|
||||
|
||||
1. В общем списке виден заголовок `Каналы`.
|
||||
2. В общем списке нет кнопки создания канала.
|
||||
3. Переход в `Мои каналы` работает.
|
||||
4. В `Мои каналы` видна кнопка создания канала.
|
||||
5. Создание канала из `Мои каналы` работает.
|
||||
6. Возврат ко всем каналам работает.
|
||||
7. На мобильном экране шапка не ломается.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Telegram-агент для разрешённых игроков
|
||||
|
||||
- Горизонт:
|
||||
`near`
|
||||
- Ориентир:
|
||||
сегодня/завтра
|
||||
- Статус:
|
||||
`proposal`
|
||||
|
||||
## Кратко
|
||||
|
||||
Нужно расширить `SHiNE-agent-bot-coder`, чтобы агент мог принимать личные сообщения от заранее разрешённых пользователей, вести по каждому отдельную рабочую папку и историю, помогать им с обсуждениями/документами без изменения кода, а краткий результат публиковать в общий канал.
|
||||
|
||||
## Пользовательский сценарий
|
||||
|
||||
1. Разрешённый пользователь пишет агенту в личные сообщения текстом или голосом.
|
||||
2. Голосовое сообщение распознаётся так же, как сейчас распознаются voice/audio-задачи.
|
||||
3. Сервис определяет пользователя по разрешённому списку логинов.
|
||||
4. Для пользователя используется отдельная папка в `Players/`.
|
||||
5. Codex запускается с системным контекстом: от имени какого человека он работает, где лежит его папка, какие у него локальные инструкции.
|
||||
6. Агент может читать код и документацию проекта, но писать должен только в папку этого пользователя, если нет отдельного согласования на изменение общего проекта.
|
||||
7. После ответа пользователю агент отправляет в общий канал короткую сводку двумя сообщениями или двумя блоками: вопрос пользователя и полученный ответ.
|
||||
8. Команда `/new` или `New` сбрасывает только сессию этого пользователя.
|
||||
|
||||
## Предлагаемая структура
|
||||
|
||||
- `Players/`
|
||||
- `Ivan/`
|
||||
- `AGENTS.md`
|
||||
- `history/`
|
||||
- `files/`
|
||||
- `Sergey/`
|
||||
- `AGENTS.md`
|
||||
- `history/`
|
||||
- `files/`
|
||||
- `Milana/`
|
||||
- `AGENTS.md`
|
||||
- `history/`
|
||||
- `files/`
|
||||
|
||||
Имена папок можно уточнить после получения точных Telegram-логинов.
|
||||
|
||||
## Что нужно сделать
|
||||
|
||||
1. Добавить конфигурацию разрешённых Telegram-пользователей.
|
||||
2. Описать соответствие `telegram username -> имя игрока -> папка`.
|
||||
3. Создавать или использовать отдельную историю диалога для каждого игрока.
|
||||
4. Поддержать личные сообщения от разрешённых пользователей.
|
||||
5. Запретить постановку задач от неизвестных пользователей.
|
||||
6. Для групп/каналов оставить текущую логику: команды Айдара имеют приоритет.
|
||||
7. При запуске Codex для игрока добавлять отдельный системный контекст:
|
||||
- имя пользователя;
|
||||
- путь к его папке;
|
||||
- правило записи только в эту папку;
|
||||
- путь к персональному `AGENTS.md`.
|
||||
8. После ответа игроку отправлять краткую сводку в общий канал.
|
||||
9. Поддержать `/new`/`New` как сброс только персональной сессии игрока.
|
||||
10. Добавить защиту от случайного изменения общего кода в режиме игрока.
|
||||
|
||||
## Вопросы перед реализацией
|
||||
|
||||
1. Точные Telegram-логины Ивана, Сергея и Миланы.
|
||||
2. Какой общий канал использовать для сводок: текущий `@shine_writing` или отдельный чат.
|
||||
3. Нужно ли отправлять в общий канал полный текст вопроса/ответа или краткую выжимку.
|
||||
4. Нужно ли пересылать вложения игроков в общий канал или только текстовые сводки.
|
||||
5. Разрешить ли игрокам читать все документы проекта, включая технические заметки деплоя.
|
||||
6. Что делать, если пользователь просит изменить код: отказать, создать предложение в своей папке или просить подтверждение Айдара.
|
||||
7. Нужны ли русские имена папок (`Иван`, `Сергей`, `Милана`) или ASCII-имена (`Ivan`, `Sergey`, `Milana`).
|
||||
8. Нужно ли хранить истории игроков в общей папке сервиса или внутри `Players/<name>/history/`.
|
||||
|
||||
## Риски и ограничения
|
||||
|
||||
- Нужно аккуратно разделить режим Айдара и режим игрока, чтобы игроки не могли случайно запустить изменение общего кода.
|
||||
- Нужно не смешать истории разных пользователей.
|
||||
- Нужно ограничить публикацию в общий канал, чтобы не утекали личные или слишком длинные ответы.
|
||||
- Нужна проверка Telegram-идентификации: username может меняться, поэтому желательно хранить и `user_id`.
|
||||
|
||||
## Документы, которые обновить при реализации
|
||||
|
||||
- `SHiNE-agent-bot-coder/AGENTS.md`
|
||||
- `SHiNE-agent-bot-coder/AGENT.md`
|
||||
- `SHiNE-agent-bot-coder/README.md`
|
||||
- `Dev_Docs/deploy/agent-bot-coder-local-systemd.md`, если появятся новые переменные окружения или настройки сервиса.
|
||||
|
||||
## Минимальная проверка
|
||||
|
||||
1. Айдар по-прежнему может ставить задачи из `@shine_writing`.
|
||||
2. Неизвестный пользователь не ставит задачу в очередь.
|
||||
3. Разрешённый игрок пишет личное текстовое сообщение и получает ответ.
|
||||
4. Разрешённый игрок отправляет voice, оно распознаётся и обрабатывается.
|
||||
5. История одного игрока не попадает в историю другого.
|
||||
6. `/new` сбрасывает только историю текущего игрока.
|
||||
7. Сводка вопрос/ответ появляется в общем канале.
|
||||
8. В режиме игрока агент не пишет за пределы `Players/<name>/` без отдельного подтверждения.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Пополнение Solana и Arweave через внешний сервис покупки
|
||||
|
||||
- Горизонт:
|
||||
`near`
|
||||
- Ориентир:
|
||||
сегодня/завтра
|
||||
- Статус:
|
||||
`proposal`
|
||||
|
||||
## Кратко
|
||||
|
||||
Нужно добавить удобное пополнение кошельков на экране регистрации/кошелька: для Solana и Arweave дать отдельные действия `Пополнить`, которые ведут на международный сервис покупки криптовалюты с карты и помогают пользователю скопировать адрес кошелька.
|
||||
|
||||
## Пользовательский сценарий
|
||||
|
||||
1. Пользователь видит адрес кошелька Solana или Arweave.
|
||||
2. Нажимает `Пополнить`.
|
||||
3. Открывается промежуточное окно с инструкцией:
|
||||
- сейчас пользователь перейдёт на страницу покупки/пополнения;
|
||||
- нужно указать или проверить адрес кошелька;
|
||||
- после оплаты нужно закрыть внешнюю страницу и вернуться назад;
|
||||
- Solana обычно приходит быстро, ориентир 10-15 секунд после подтверждения сети;
|
||||
- Arweave может идти дольше, точное время нужно уточнить по выбранному сервису.
|
||||
4. В окне есть кнопки:
|
||||
- `Скопировать адрес и перейти`;
|
||||
- `Перейти без копирования`.
|
||||
5. Для Solana и Arweave используются разные окна/инструкции и, возможно, разные внешние ссылки.
|
||||
|
||||
## Что нужно сделать
|
||||
|
||||
1. Найти текущий экран, где показываются кошельки при регистрации и пополнении.
|
||||
2. Найти текущую ссылку покупки Arweave, если она уже есть в UI.
|
||||
3. Выбрать международный сервис покупки Solana с карты, не российский.
|
||||
4. Проверить, поддерживает ли сервис deep link с предзаполненным адресом кошелька.
|
||||
5. Если deep link невозможен, реализовать промежуточное окно с копированием адреса.
|
||||
6. Добавить отдельные действия для Solana и Arweave.
|
||||
7. Сделать текст инструкции коротким и понятным.
|
||||
8. Проверить, что адрес копируется в буфер обмена в браузере.
|
||||
9. Проверить мобильный сценарий и desktop-сценарий.
|
||||
|
||||
## Вопросы перед реализацией
|
||||
|
||||
1. Какой сервис покупки Solana использовать: тот же провайдер, что для Arweave, или другой международный on-ramp.
|
||||
2. Нужно ли разрешать покупку только SOL или также USDC/SPL-токены на Solana.
|
||||
3. Где именно показывать кнопку `Пополнить`: только регистрация, настройки кошелька или оба места.
|
||||
4. Нужно ли показывать предупреждение о комиссиях и стороннем сервисе.
|
||||
5. Нужно ли открывать внешнюю страницу в новой вкладке или в текущем окне.
|
||||
6. Нужно ли логировать факт нажатия `Пополнить` на сервере.
|
||||
7. Какой точный текст использовать для времени прихода Arweave.
|
||||
|
||||
## Риски и ограничения
|
||||
|
||||
- On-ramp-сервисы меняют ссылки и параметры, поэтому deep link нужно проверять перед реализацией.
|
||||
- Clipboard API может требовать HTTPS и пользовательский жест.
|
||||
- Нельзя обещать точное время поступления средств: лучше писать ориентир и зависимость от сети/провайдера.
|
||||
- Внешний сервис может быть недоступен в отдельных странах или для отдельных карт.
|
||||
|
||||
## Документы, которые обновить при реализации
|
||||
|
||||
- Документацию UI/кошельков, если такая есть.
|
||||
- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации.
|
||||
- `Dev_Docs/API/`, только если появится новый серверный API или логирование.
|
||||
|
||||
## Минимальная проверка
|
||||
|
||||
1. На Solana-кошельке открывается правильное окно пополнения.
|
||||
2. Кнопка `Скопировать адрес и перейти` копирует Solana-адрес и открывает внешний сервис.
|
||||
3. Кнопка `Перейти без копирования` открывает внешний сервис без копирования.
|
||||
4. Аналогичный сценарий работает для Arweave.
|
||||
5. На мобильном экране текст и кнопки не перекрываются.
|
||||
6. Возврат назад в приложение не ломает состояние регистрации/кошелька.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Solana: init регистрации + деплой обязательных программ
|
||||
|
||||
- дата: 2026-05-24 20:35 (Europe/Moscow)
|
||||
- статус: `pending`
|
||||
|
||||
## Кратко
|
||||
|
||||
Добавлена dev-страница в UI для вызова `init_users_economy_config` программы `shine_users` через подключённый кошелёк Phantom.
|
||||
Задеплоены и зафиксированы адреса двух обязательных программ регистрации: `shine_users` и `shine_login_guard`.
|
||||
|
||||
## Что проверять вручную
|
||||
|
||||
1. Открыть UI и перейти в `Настройки разработчика`.
|
||||
2. Нажать `Solana: init регистрации`.
|
||||
3. Подключить Phantom devnet-кошелёк.
|
||||
4. Выполнить `init_users_economy_config`.
|
||||
5. Проверить отображение статуса и хэша транзакции.
|
||||
6. Повторно нажать init и убедиться, что корректно показывается "уже инициализировано".
|
||||
7. Выполнить тестовую регистрацию пользователя и убедиться, что CPI-вызов `shine_login_guard` не падает.
|
||||
|
||||
## Ожидаемый результат
|
||||
|
||||
- Первая транзакция выполняется успешно (если PDA ещё не создан).
|
||||
- Вторая попытка возвращает ожидаемую ошибку о повторной инициализации.
|
||||
- UI не падает, статус понятный, Program ID отображается корректно.
|
||||
- Регистрация пользователя проходит с подключённым `shine_login_guard`.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Отчёт private-запросов агента в группу
|
||||
|
||||
## Что сделано
|
||||
|
||||
После успешной обработки задачи из личного чата Айдара Telegram-бот агента отправляет итоговую копию в группу `@shine_writing`:
|
||||
|
||||
- первым сообщением исходный запрос;
|
||||
- вторым сообщением, reply на первое, финальный ответ Codex.
|
||||
|
||||
Промежуточные статусы выполнения в группу не дублируются.
|
||||
|
||||
## Что проверять
|
||||
|
||||
1. Отправить боту личный текстовый запрос.
|
||||
2. Дождаться полного ответа в личном чате.
|
||||
3. Проверить, что в `@shine_writing` появилось сообщение с запросом.
|
||||
4. Проверить, что итоговый ответ опубликован reply на это сообщение.
|
||||
5. Отправить личный voice-запрос и проверить, что в отчёте есть распознанный текст.
|
||||
|
||||
## Ожидаемый результат
|
||||
|
||||
Личный чат работает как раньше, а группа получает только итоговую пару сообщений по завершённой задаче.
|
||||
|
||||
## Статус
|
||||
|
||||
pending
|
||||
@@ -0,0 +1,23 @@
|
||||
# Отчёт voice/audio-запросов с исходным файлом
|
||||
|
||||
## Краткое описание
|
||||
|
||||
Публичный отчёт по приватным voice/audio-запросам агента должен отправлять исходный Telegram voice/audio-файл с подписью, где указан распознанный текст. `file_id` не должен показываться пользователям в тексте отчёта.
|
||||
|
||||
## Что проверить
|
||||
|
||||
1. Отправить боту приватный voice-запрос от Айдара.
|
||||
2. Дождаться обработки Codex.
|
||||
3. Проверить группу/канал публичных отчётов.
|
||||
4. Повторить сценарий для audio-файла, если он используется.
|
||||
|
||||
## Ожидаемый результат
|
||||
|
||||
- В публичном отчёте появляется исходное голосовое/audio-сообщение.
|
||||
- В подписи к нему есть распознанный текст.
|
||||
- В отчёте нет строки `Голосовой file_id` и самого `file_id`.
|
||||
- Итоговый ответ Codex отправляется ответом на сообщение с исходным файлом.
|
||||
|
||||
## Статус
|
||||
|
||||
pending
|
||||
@@ -0,0 +1,19 @@
|
||||
# Улучшенная обработка длинных voice/audio
|
||||
|
||||
## Что сделано
|
||||
- Увеличены и вынесены в `.env` тайм-ауты скачивания Telegram-файла и OpenAI-распознавания.
|
||||
- Добавлены подробные логи стадий распознавания: старт, скачивание, размер файла, завершение, причина ошибки.
|
||||
- Ошибки voice/audio теперь показываются пользователю как ошибка распознавания с понятной причиной.
|
||||
|
||||
## Как проверять
|
||||
- Отправить короткое голосовое сообщение и убедиться, что оно распознаётся и передаётся в Codex.
|
||||
- Отправить длинное голосовое сообщение и убедиться, что сервис не падает на прежнем коротком тайм-ауте.
|
||||
- Смоделировать ошибку распознавания или временно указать неверный OpenAI-ключ и проверить текст ошибки в Telegram.
|
||||
|
||||
## Ожидаемый результат
|
||||
- При успешном распознавании пользователь видит распознанный текст и задача уходит в Codex.
|
||||
- При ошибке пользователь видит, что не удалось именно распознать voice/audio, и получает конкретную причину.
|
||||
- В логах сервиса видны стадия и техническая причина сбоя.
|
||||
|
||||
## Статус
|
||||
pending
|
||||
@@ -51,7 +51,7 @@
|
||||
| N | Поле | Тип | Размер | Правило |
|
||||
|---|------|-----|--------|---------|
|
||||
| 1 | `magic` | bytes | 5 | Всегда `SHiNE`. |
|
||||
| 2 | `format_major` | `u8` | 1 | Для нового формата: `2`. |
|
||||
| 2 | `format_major` | `u8` | 1 | Для первого формата: `1`. |
|
||||
| 3 | `format_minor` | `u8` | 1 | Для первой версии нового формата: `0`. |
|
||||
| 4 | `record_len` | `u16` | 2 | Длина полезной записи от `magic` до `signature` включительно, без padding. |
|
||||
| 5 | `created_at_ms` | `u64` | 8 | Время создания записи, Unix time в миллисекундах. Не меняется. |
|
||||
@@ -63,7 +63,7 @@
|
||||
После первых 9 полей идет набор типизированных блоков:
|
||||
|
||||
```text
|
||||
UserPdaRecordV2
|
||||
UserPdaRecordV1
|
||||
- fixed_header: поля 1..9
|
||||
- blocks_count: u8
|
||||
- blocks: TypedBlock[blocks_count]
|
||||
@@ -89,7 +89,7 @@ UserPdaRecordV2
|
||||
|
||||
Правила:
|
||||
|
||||
- неизвестный `block_type` в `format_major = 2` считается ошибкой;
|
||||
- неизвестный `block_type` в `format_major = 1` считается ошибкой;
|
||||
- обязательные блоки: `RootKeyBlock`, `DeviceKeyBlock`, `BlockchainRegistryBlock`;
|
||||
- необязательные блоки: `ServerProfileBlock`, `AccessServersBlock`, `TrustedStateBlock`;
|
||||
- каждый обязательный блок должен встречаться ровно один раз;
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
# Архитектура Solana-программ SHiNE
|
||||
|
||||
Документ описывает рабочую архитектуру Solana-части SHiNE: три Anchor-программы, DAO, ключи управления, PDA-счета и движение денег.
|
||||
|
||||
Это архитектурная справка. Она не меняет код, формат PDA-записи пользователя, серверный API или формат блокчейна SHiNE.
|
||||
|
||||
Статус: актуализировано по коду `shine-solana/shine/programs/*` на 2026-05-25.
|
||||
|
||||
Связанные документы:
|
||||
|
||||
- `Dev_Docs/Инициализация_Solana_регистрации/README.md` — single source of truth по деплою и первичной инициализации регистрации пользователей.
|
||||
- `shine-solana/shine/doc/SHiNE-user-format-v.1.0.md` — точный формат `user_pda` для `shine_users`.
|
||||
- `shine-solana/shine/doc/FUNDS_FLOW.md` — короткая справка по денежным потокам внутри Solana-модуля.
|
||||
|
||||
## Кратко
|
||||
|
||||
В Solana-модуле сейчас три основные программы:
|
||||
|
||||
1. `shine_login_guard` — проверяет логин и возвращает класс логина: обычный, premium или trademark.
|
||||
2. `shine_users` — создает и обновляет пользовательскую PDA-запись, проверяет подписи и берет оплату за регистрацию/увеличение лимита.
|
||||
3. `shine_payments` — принимает входящий поток средств в `inflow_vault`, ведет очереди тикетов, позволяет DAO выдавать лимиты менеджерам и выполняет выплаты.
|
||||
|
||||
DAO в текущем виде не является отдельной Anchor-программой SHiNE внутри `programs/`. Это управляющая модель поверх кошельков, governance-скриптов и authority-адресов. Для проектирования ее удобно считать отдельным управляющим блоком: DAO голосует, назначает управляющие ключи, управляет казной и вызывает защищенные методы второй и третьей программ.
|
||||
|
||||
## Общая схема
|
||||
|
||||
Редактируемая Mermaid-схема находится в [schemes/architecture.mmd](schemes/architecture.mmd).
|
||||
|
||||
Картинки:
|
||||
|
||||
- [schemes/architecture.svg](schemes/architecture.svg)
|
||||
- [schemes/architecture.png](schemes/architecture.png)
|
||||
|
||||
## Программы и функции
|
||||
|
||||
| Блок | Папка/имя | Текущие функции из кода | Основной смысл |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `shine_login_guard` | `classify_login` | Проверка логина перед регистрацией. |
|
||||
| 2 | `shine_users` | `init_users_economy_config`, `update_users_economy_config`, `create_user_pda`, `update_user_pda` | Регистрация пользователя, обновление записи, экономика лимита. |
|
||||
| 3 | `shine_payments` | `init`, `update_coef_limit`, `grant_manager_limits`, `buy_ticket`, `buy_ticket_usd`, `buy_ticket_sol`, `manager_add_ticket`, `step_payout`, `change_ticket_recipient` | Vault, билеты, очереди, выплаты, DAO-настройки, лимиты менеджеров. |
|
||||
| DAO | governance/authority | Вызовы через governance и управляющие ключи | Управление правами, казной, настройками и будущими обновлениями программ. |
|
||||
|
||||
## Актуальные program id
|
||||
|
||||
Актуальные адреса заданы одновременно в `Anchor.toml`, `declare_id!` программ и `programs/common/src/deploy_config.rs`:
|
||||
|
||||
| Программа | Program ID |
|
||||
| --- | --- |
|
||||
| `shine_login_guard` | `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` |
|
||||
| `shine_users` | `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` |
|
||||
| `shine_payments` | `m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR` |
|
||||
|
||||
Если эти адреса меняются, нужно синхронно обновить:
|
||||
|
||||
1. `shine-solana/shine/Anchor.toml`
|
||||
2. `declare_id!` в `programs/*/src/lib.rs`
|
||||
3. `programs/common/src/deploy_config.rs`
|
||||
4. UI/серверные константы, перечисленные в `Dev_Docs/Инициализация_Solana_регистрации/README.md`
|
||||
|
||||
## Ключи и authority
|
||||
|
||||
Для удобного понимания на старте можно считать, что есть четыре группы ключей:
|
||||
|
||||
1. `key_1` / authority программы `shine_login_guard`.
|
||||
- Сейчас программа только классифицирует логин.
|
||||
- На первом этапе ее можно оставить под отдельным ключом.
|
||||
- В будущем право обновления можно передать DAO.
|
||||
|
||||
2. `key_2` / authority программы `shine_users`.
|
||||
- Отвечает за деплой/upgrade второй программы.
|
||||
- Защищенное обновление economy-конфига в коде уже проверяет `DAO_AUTHORITY`.
|
||||
- В целевой модели upgrade-authority второй программы нужно передать DAO.
|
||||
|
||||
3. `key_3` / authority программы `shine_payments`.
|
||||
- Отвечает за деплой/upgrade третьей программы.
|
||||
- Защищенные методы `update_coef_limit` и `grant_manager_limits` проверяют `dao_wallet` из `ConfigState`.
|
||||
- В целевой модели upgrade-authority третьей программы нужно передать DAO.
|
||||
|
||||
4. DAO-ключи.
|
||||
- Это управляющие кошельки/токены/realm governance.
|
||||
- DAO может добавлять и отзывать управляющие ключи по голосованию.
|
||||
- DAO-казна получает деньги от покупки тикетов и DAO-часть выплат из `inflow_vault`.
|
||||
|
||||
Адреса program id сейчас берутся из `programs/common/src/deploy_config.rs`. Для production/devnet можно подбирать vanity-адреса с понятным началом вроде `SHi...`, но это отдельная операция генерации ключей и деплоя.
|
||||
|
||||
## Счета и PDA
|
||||
|
||||
Постоянные PDA и счета:
|
||||
|
||||
1. `shine_users`
|
||||
- `user_pda` — пользовательская запись по seed `login=<login>`, создается для каждого логина.
|
||||
- `users_economy_config_pda` — общие параметры экономики регистрации и лимита.
|
||||
|
||||
2. `shine_payments`
|
||||
- `config_pda` — хранит `dao_wallet` и адрес `inflow_vault`.
|
||||
- `coef_limit_pda` — хранит коэффициент выплат, лимит очереди и награду вызывающему `step_payout`.
|
||||
- `queues_pda` — агрегаты очередей выплат.
|
||||
- `inflow_vault_pda` — PDA-вольт, куда `shine_users` переводит оплату регистрации и увеличения лимита.
|
||||
- `ticket_pda` — отдельная PDA-запись тикета на каждую покупку/менеджерскую выдачу.
|
||||
- `manager_allowance_pda` — PDA лимитов конкретного менеджера.
|
||||
|
||||
3. DAO
|
||||
- `dao_wallet` / treasury — казна DAO.
|
||||
- governance-аккаунты DAO — realm, governance, proposal/vote records и связанные аккаунты SPL Governance, если используется эта модель.
|
||||
|
||||
## Правило разделения с основным сервером
|
||||
|
||||
Solana-модуль лежит в основном репозитории как отдельная папка `shine-solana/shine/`, но не подключается автоматически к сборке или деплою основного сервера SHiNE. Команды `deployServer` и `deployUI` не должны деплоить Anchor-программы. Solana build/deploy выполняется отдельно из папки `shine-solana/shine/` по локальным правилам модуля.
|
||||
|
||||
## Движение денег
|
||||
|
||||
Основные потоки:
|
||||
|
||||
1. Регистрация пользователя через `shine_users::create_user_pda`.
|
||||
- Платит `signer`.
|
||||
- Деньги идут в `shine_payments::inflow_vault_pda`.
|
||||
- Сумма состоит из регистрационной комиссии и оплаты дополнительного лимита.
|
||||
|
||||
2. Увеличение лимита через `shine_users::update_user_pda`.
|
||||
- Платит `signer`.
|
||||
- Деньги идут в тот же `inflow_vault_pda`.
|
||||
- Сумма равна оплате дополнительного лимита.
|
||||
|
||||
3. Покупка тикета через `shine_payments::buy_ticket*`.
|
||||
- Платит покупатель.
|
||||
- Деньги сразу идут в `dao_wallet`.
|
||||
- Одновременно создается тикет на выплату.
|
||||
|
||||
4. Выплата через `shine_payments::step_payout`.
|
||||
- Вызвать может любой подписант.
|
||||
- Деньги берутся из `inflow_vault_pda`.
|
||||
- Часть идет получателю тикета.
|
||||
- Часть идет в `dao_wallet`.
|
||||
- Небольшая награда идет вызвавшему шаг выплат.
|
||||
- Если очереди пустые, весь доступный остаток `inflow_vault_pda` переводится в DAO.
|
||||
|
||||
## Передача прав DAO
|
||||
|
||||
Минимальная целевая модель:
|
||||
|
||||
1. `shine_login_guard`
|
||||
- Пока оставить на отдельном ключе `key_1`.
|
||||
- Передачу DAO сделать позже, когда логика premium/trademark стабилизируется.
|
||||
|
||||
2. `shine_users`
|
||||
- Economy-настройки уже должны обновляться DAO-authority.
|
||||
- Upgrade-authority программы после проверки можно передать DAO.
|
||||
|
||||
3. `shine_payments`
|
||||
- DAO уже управляет настройками выплат и лимитами менеджеров через `dao_wallet`.
|
||||
- Upgrade-authority программы после проверки можно передать DAO.
|
||||
|
||||
4. DAO
|
||||
- Управляет казной.
|
||||
- Принимает решения голосованием.
|
||||
- Добавляет/отзывает управляющие ключи.
|
||||
- Вызывает защищенные методы второй и третьей программ.
|
||||
- В будущем может принять управление первой программой.
|
||||
|
||||
## Детальные файлы
|
||||
|
||||
- [details/shine_login_guard.md](details/shine_login_guard.md)
|
||||
- [details/shine_users.md](details/shine_users.md)
|
||||
- [details/shine_payments.md](details/shine_payments.md)
|
||||
- [details/shine_dao.md](details/shine_dao.md)
|
||||
- [details/accounts_and_money_flow.md](details/accounts_and_money_flow.md)
|
||||
@@ -0,0 +1,110 @@
|
||||
# Счета, ключи и движение денег
|
||||
|
||||
## Кратко
|
||||
|
||||
В архитектуре есть три типа объектов:
|
||||
|
||||
1. Ключи программ и DAO.
|
||||
2. PDA-счета состояния.
|
||||
3. Денежные счета, через которые проходят SOL/lamports.
|
||||
|
||||
## Ключи
|
||||
|
||||
Минимальный набор для понимания:
|
||||
|
||||
1. `key_1` — deploy/upgrade authority `shine_login_guard`.
|
||||
2. `key_2` — deploy/upgrade authority `shine_users`.
|
||||
3. `key_3` — deploy/upgrade authority `shine_payments`.
|
||||
4. `DAO_AUTHORITY` — адрес, который имеет право менять защищенные настройки.
|
||||
5. `DAO_TREASURY_WALLET` / `dao_wallet` — казна DAO.
|
||||
6. `manager_wallet` — кошелек менеджера, которому DAO выдает лимиты на создание тикетов.
|
||||
7. `user root_key` — корневой ключ пользователя для подписи пользовательской записи.
|
||||
8. `user device_key` — ключ устройства пользователя.
|
||||
9. `server_key` — ключ сервера пользователя, если пользователь является сервером.
|
||||
|
||||
Текущие адреса из `programs/common/src/deploy_config.rs`:
|
||||
|
||||
| Роль | Адрес |
|
||||
| --- | --- |
|
||||
| `SHINE_LOGIN_GUARD_PROGRAM_ID` | `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` |
|
||||
| `SHINE_USERS_PROGRAM_ID` | `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` |
|
||||
| `SHINE_PAYMENTS_PROGRAM_ID` | `m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR` |
|
||||
| `DAO_AUTHORITY` | `FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P` |
|
||||
| `DAO_TREASURY_WALLET` | `FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P` |
|
||||
|
||||
## Постоянные PDA
|
||||
|
||||
`shine_users`:
|
||||
|
||||
- `user_pda` — создается для каждого логина, seed `login=` + normalized login.
|
||||
- `users_economy_config_pda` — один PDA с экономикой регистрации, seed `shine_users_economy_config`.
|
||||
|
||||
`shine_payments`:
|
||||
|
||||
- `config_pda` — один PDA конфига, seed `shine_payments_config`.
|
||||
- `coef_limit_pda` — один PDA коэффициента/лимита/награды, seed `shine_payments_coef_limit`.
|
||||
- `queues_pda` — один PDA агрегатов очередей, seed `shine_payments_queues`.
|
||||
- `inflow_vault_pda` — один PDA-вольт входящих средств, seed `shine_payments_inflow_vault`.
|
||||
- `ticket_pda` — много PDA, по одному на тикет, seed `shine_payments_q1_ticket` или `shine_payments_q2_ticket` + индекс.
|
||||
- `manager_allowance_pda` — много PDA, по одному на менеджера, seed `shine_p_manager_allow` + адрес менеджера.
|
||||
|
||||
## Денежные потоки
|
||||
|
||||
### Регистрация
|
||||
|
||||
```text
|
||||
user signer -> shine_users::create_user_pda -> shine_payments::inflow_vault_pda
|
||||
```
|
||||
|
||||
Состав платежа:
|
||||
|
||||
- регистрационная комиссия;
|
||||
- оплата `additional_limit`.
|
||||
|
||||
### Увеличение лимита
|
||||
|
||||
```text
|
||||
user signer -> shine_users::update_user_pda -> shine_payments::inflow_vault_pda
|
||||
```
|
||||
|
||||
Состав платежа:
|
||||
|
||||
- только оплата `additional_limit`.
|
||||
|
||||
### Покупка тикета
|
||||
|
||||
```text
|
||||
buyer signer -> shine_payments::buy_ticket* -> dao_wallet
|
||||
```
|
||||
|
||||
При этом создается `ticket_pda`, но деньги в `inflow_vault_pda` на этом шаге не идут.
|
||||
|
||||
### Выплата
|
||||
|
||||
```text
|
||||
shine_payments::inflow_vault_pda -> ticket_recipient_wallet
|
||||
shine_payments::inflow_vault_pda -> dao_wallet
|
||||
shine_payments::inflow_vault_pda -> step_payout caller
|
||||
```
|
||||
|
||||
Если очереди пустые:
|
||||
|
||||
```text
|
||||
shine_payments::inflow_vault_pda -> dao_wallet
|
||||
```
|
||||
|
||||
## Что нужно создать на старте
|
||||
|
||||
Минимально:
|
||||
|
||||
1. Три program id для `shine_login_guard`, `shine_users`, `shine_payments`.
|
||||
2. Три upgrade-authority ключа или один временный deploy-ключ с четким планом передачи прав.
|
||||
3. DAO authority/treasury.
|
||||
4. `users_economy_config_pda`.
|
||||
5. `shine_payments` PDA: `config_pda`, `coef_limit_pda`, `queues_pda`, `inflow_vault_pda`.
|
||||
|
||||
Динамически будут создаваться:
|
||||
|
||||
- `user_pda` на каждого пользователя;
|
||||
- `ticket_pda` на каждый тикет;
|
||||
- `manager_allowance_pda` на каждого менеджера.
|
||||
@@ -0,0 +1,74 @@
|
||||
# SHiNE DAO
|
||||
|
||||
## Кратко
|
||||
|
||||
DAO — управляющий слой Solana-части SHiNE. В текущем коде это не отдельная Anchor-программа в `programs/`, а модель управления через DAO-кошелек, DAO-authority, governance-скрипты и будущую передачу upgrade-authority программ.
|
||||
|
||||
## Что DAO должно уметь
|
||||
|
||||
1. Управлять казной.
|
||||
- Принимать средства на `dao_wallet`.
|
||||
- Выплачивать средства со счета DAO по решениям голосования.
|
||||
|
||||
2. Управлять настройками `shine_users`.
|
||||
- Обновлять регистрационную комиссию.
|
||||
- Обновлять цену шага лимита.
|
||||
- Обновлять стартовый бонус лимита.
|
||||
|
||||
3. Управлять настройками `shine_payments`.
|
||||
- Обновлять коэффициент выплат.
|
||||
- Обновлять лимит очереди.
|
||||
- Обновлять награду за вызов `step_payout`.
|
||||
|
||||
4. Управлять менеджерами.
|
||||
- Выдавать менеджеру лимит на добавление тикетов.
|
||||
- Отдельно учитывать лимиты Q1 и Q2.
|
||||
|
||||
5. Управлять правами программ.
|
||||
- Принять upgrade-authority `shine_users`.
|
||||
- Принять upgrade-authority `shine_payments`.
|
||||
- Позже принять upgrade-authority `shine_login_guard`, если это потребуется.
|
||||
|
||||
6. Управлять ключами DAO.
|
||||
- Добавлять управляющие ключи.
|
||||
- Отзывать или сжигать управляющие ключи.
|
||||
- Делать это через голосование, а не вручную одним админом.
|
||||
|
||||
7. Фиксировать решения.
|
||||
- Делать заявления/решения через governance-механику.
|
||||
- Привязывать важные изменения к proposal/vote/execute.
|
||||
|
||||
## Текущие адреса управления
|
||||
|
||||
В общем deploy-конфиге сейчас есть два важных адреса:
|
||||
|
||||
- `DAO_AUTHORITY` — используется `shine_users` для проверки права менять economy-конфиг.
|
||||
- `DAO_TREASURY_WALLET` — используется `shine_payments` как `dao_wallet`.
|
||||
|
||||
Сейчас они могут совпадать. В целевой DAO-модели их лучше рассматривать как разные роли:
|
||||
|
||||
- authority/governance signer — кто имеет право исполнять управленческие инструкции;
|
||||
- treasury wallet — счет, куда приходят деньги DAO.
|
||||
|
||||
## Передача прав
|
||||
|
||||
Рекомендуемый порядок:
|
||||
|
||||
1. Сначала стабилизировать и проверить `shine_users` и `shine_payments`.
|
||||
2. Передать DAO право обновлять настройки, если оно еще не передано.
|
||||
3. Передать DAO upgrade-authority второй и третьей программ.
|
||||
4. Оставить `shine_login_guard` на отдельном ключе до стабилизации словарей и правил логинов.
|
||||
5. После стабилизации решить отдельным голосованием, передавать ли первую программу DAO.
|
||||
|
||||
## Важное разделение
|
||||
|
||||
Есть два разных типа прав:
|
||||
|
||||
1. Право вызвать защищенную функцию программы.
|
||||
- Например, `update_coef_limit` или `grant_manager_limits`.
|
||||
- Проверяется внутри программы по `dao_wallet` или `DAO_AUTHORITY`.
|
||||
|
||||
2. Право обновить саму программу.
|
||||
- Это upgrade-authority Solana ProgramData.
|
||||
- Оно передается отдельной Solana-командой/DAO-транзакцией и не равно обычному PDA-счету.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# `shine_login_guard`
|
||||
|
||||
## Кратко
|
||||
|
||||
`shine_login_guard` — первая программа Solana-модуля SHiNE. Она проверяет логин перед регистрацией пользователя и возвращает класс логина.
|
||||
|
||||
Папка программы: `shine-solana/shine/programs/shine_login_guard/`.
|
||||
|
||||
## Текущая функция
|
||||
|
||||
1. `classify_login(login: String)`
|
||||
- Нормализует логин.
|
||||
- Проверяет длину и допустимые символы.
|
||||
- Сравнивает части логина со словарями premium/trademark.
|
||||
- Возвращает результат через `set_return_data`.
|
||||
|
||||
Классы результата:
|
||||
|
||||
- `0` — обычный логин, регистрацию можно продолжать.
|
||||
- `1` — premium-логин.
|
||||
- `2` — trademark-логин, нужна отдельная проверка/разрешение.
|
||||
|
||||
## Правила нормализации и классификации
|
||||
|
||||
Текущая логика из `programs/shine_login_guard/src/lib.rs`:
|
||||
|
||||
- пустой логин или логин длиннее 20 символов получает класс `premium`;
|
||||
- `_` при нормализации удаляется;
|
||||
- допустимы только ASCII-буквы и цифры, остальные символы дают класс `premium`;
|
||||
- после удаления `_` результат приводится к нижнему регистру;
|
||||
- логины длиной 7 символов или меньше считаются `premium`;
|
||||
- логин разбивается максимум на 3 словарных фрагмента;
|
||||
- если среди найденных фрагментов есть trademark-слово, результат `trademark`;
|
||||
- если найдены только premium-слова, результат `premium`;
|
||||
- если разбиение по словарям не найдено, результат `free`.
|
||||
|
||||
Словари собираются на этапе build из файлов:
|
||||
|
||||
- `programs/shine_login_guard/src/dictionaries/premium/*.txt`
|
||||
- `programs/shine_login_guard/src/dictionaries/trademarks/*.txt`
|
||||
|
||||
## Роль в общей схеме
|
||||
|
||||
`shine_users::create_user_pda` вызывает `shine_login_guard` через CPI и продолжает регистрацию только если логин получил класс `0`.
|
||||
|
||||
## Ключи и управление
|
||||
|
||||
На старте удобно считать, что у программы есть отдельный управляющий ключ `key_1`.
|
||||
|
||||
Текущая рекомендация:
|
||||
|
||||
- пока оставить `shine_login_guard` под отдельным ключом;
|
||||
- не передавать ее DAO до стабилизации правил premium/trademark;
|
||||
- позже можно передать upgrade-authority DAO, чтобы изменения словарей и правил проходили через голосование.
|
||||
|
||||
## Счета
|
||||
|
||||
Собственных постоянных PDA-счетов у программы сейчас нет. Для проверки нужен только подписант транзакции в `ClassifyLogin`.
|
||||
@@ -0,0 +1,173 @@
|
||||
# `shine_payments`
|
||||
|
||||
## Кратко
|
||||
|
||||
`shine_payments` — третья программа Solana-модуля SHiNE. Она отвечает за vault входящих средств, DAO-казну, покупку тикетов, менеджерские лимиты, очереди выплат и пошаговое исполнение выплат.
|
||||
|
||||
Папка программы: `shine-solana/shine/programs/shine_payments/`.
|
||||
|
||||
## Текущие функции
|
||||
|
||||
1. `init`
|
||||
- Создает основные PDA: `config_pda`, `coef_limit_pda`, `queues_pda`, `inflow_vault_pda`.
|
||||
- Записывает `dao_wallet` и стартовые параметры выплат.
|
||||
|
||||
2. `update_coef_limit`
|
||||
- Обновляет коэффициент выплаты, лимит очереди и награду вызвавшему `step_payout`.
|
||||
- Требует подпись DAO-кошелька из `ConfigState`.
|
||||
|
||||
3. `grant_manager_limits`
|
||||
- DAO выдает менеджеру лимиты на создание тикетов в очередях Q1/Q2.
|
||||
- Создает или обновляет `manager_allowance_pda`.
|
||||
|
||||
4. `buy_ticket`
|
||||
- Покупка тикета с суммой в lamports, пересчетом через Pyth SOL/USD.
|
||||
|
||||
5. `buy_ticket_usd`
|
||||
- Покупка тикета от USD-центов с защитой по максимальному платежу в lamports.
|
||||
|
||||
6. `buy_ticket_sol`
|
||||
- Покупка тикета в lamports с проверкой минимального ожидаемого USD-эквивалента.
|
||||
|
||||
7. `manager_add_ticket`
|
||||
- Менеджер создает тикет за счет выданного ему DAO-лимита.
|
||||
|
||||
8. `step_payout`
|
||||
- Любой подписант может вызвать шаг выплат.
|
||||
- Программа выплачивает следующий тикет, DAO-часть и награду вызывающему.
|
||||
|
||||
9. `change_ticket_recipient`
|
||||
- Текущий получатель тикета может поменять адрес получателя, если тикет еще не следующий на выплату.
|
||||
|
||||
## Аргументы инструкций
|
||||
|
||||
`init` аргументов не принимает.
|
||||
|
||||
`update_coef_limit`:
|
||||
|
||||
- `coef_ppm: u64`
|
||||
- `limit_usd_cents: u64`
|
||||
- `call_reward_lamports: u64`
|
||||
|
||||
`grant_manager_limits`:
|
||||
|
||||
- `manager_wallet: Pubkey`
|
||||
- `add_q1_usd_cents: u64`
|
||||
- `add_q2_usd_cents: u64`
|
||||
|
||||
`buy_ticket`:
|
||||
|
||||
- `amount_lamports: u64`
|
||||
- `recipient_wallet: Pubkey`
|
||||
|
||||
`buy_ticket_usd`:
|
||||
|
||||
- `amount_usd_cents: u64`
|
||||
- `max_pay_lamports: u64`
|
||||
- `recipient_wallet: Pubkey`
|
||||
|
||||
`buy_ticket_sol`:
|
||||
|
||||
- `amount_lamports: u64`
|
||||
- `min_expected_usd_cents: u64`
|
||||
- `recipient_wallet: Pubkey`
|
||||
|
||||
`manager_add_ticket`:
|
||||
|
||||
- `queue_id: u8` — только `1` или `2`
|
||||
- `recipient_wallet: Pubkey`
|
||||
- `payout_usd_cents: u64`
|
||||
|
||||
`change_ticket_recipient`:
|
||||
|
||||
- `new_recipient_wallet: Pubkey`
|
||||
|
||||
## Главные PDA
|
||||
|
||||
1. `config_pda`
|
||||
- Seed: `shine_payments_config`.
|
||||
- Хранит `dao_wallet` и `inflow_vault`.
|
||||
- Размер PDA: `8 + 160` байт.
|
||||
|
||||
2. `coef_limit_pda`
|
||||
- Seed: `shine_payments_coef_limit`.
|
||||
- Хранит коэффициент выплат, лимит и награду `step_payout`.
|
||||
- Размер PDA: `8 + 96` байт.
|
||||
|
||||
3. `queues_pda`
|
||||
- Seed: `shine_payments_queues`.
|
||||
- Хранит агрегаты очередей Q1/Q2.
|
||||
- Размер PDA: `8 + 192` байт.
|
||||
|
||||
4. `inflow_vault_pda`
|
||||
- Seed: `shine_payments_inflow_vault`.
|
||||
- Принимает деньги от `shine_users`.
|
||||
- Из него выполняются выплаты тикетам, DAO и вызывающему `step_payout`.
|
||||
- Размер PDA: `8 + 32` байт.
|
||||
|
||||
5. `ticket_pda`
|
||||
- Seed зависит от очереди и индекса тикета.
|
||||
- Отдельная PDA-запись на каждый тикет.
|
||||
- Q1 seed: `shine_payments_q1_ticket` + `ticket_index`.
|
||||
- Q2 seed: `shine_payments_q2_ticket` + `ticket_index`.
|
||||
- Размер PDA: `8 + 160` байт.
|
||||
|
||||
6. `manager_allowance_pda`
|
||||
- Seed: `shine_p_manager_allow` + адрес менеджера.
|
||||
- Хранит доступный лимит менеджера по Q1/Q2.
|
||||
- Размер PDA: `8 + 128` байт.
|
||||
|
||||
## Текущие параметры
|
||||
|
||||
Параметры initial config из `programs/shine_payments/src/settings.rs`:
|
||||
|
||||
| Поле | Значение | Смысл |
|
||||
| --- | --- | --- |
|
||||
| `START_COEF_PPM` | `5_000_000` | коэффициент 5.0x в ppm-масштабе |
|
||||
| `START_LIMIT_USD_CENTS` | `1_000_000` | стартовый лимит Q1: 10_000 USD |
|
||||
| `START_CALL_REWARD_LAMPORTS` | `8_000_000` | награда вызвавшему `step_payout`, 0.008 SOL |
|
||||
| `MAX_CALL_REWARD_LAMPORTS` | `10_000_000` | максимум награды, 0.01 SOL |
|
||||
| `ORACLE_MAX_AGE_SECS` | `120` | максимальный возраст цены Pyth |
|
||||
|
||||
Для расчетов используется Pyth SOL/USD:
|
||||
|
||||
- feed id: `0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d`
|
||||
- price update account: `7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE`
|
||||
|
||||
## Деньги
|
||||
|
||||
Входы:
|
||||
|
||||
- из `shine_users` в `inflow_vault_pda` при регистрации и увеличении лимита;
|
||||
- от покупателя тикета сразу в `dao_wallet` при `buy_ticket*`.
|
||||
|
||||
Выходы:
|
||||
|
||||
- из `inflow_vault_pda` получателю тикета;
|
||||
- из `inflow_vault_pda` в `dao_wallet`;
|
||||
- из `inflow_vault_pda` вызвавшему `step_payout`;
|
||||
- если очереди пустые, весь доступный остаток `inflow_vault_pda` переводится в DAO.
|
||||
|
||||
## Очереди и выплаты
|
||||
|
||||
Выплаты идут строго пошагово:
|
||||
|
||||
- если есть невыплаченные Q1-тикеты, `step_payout` берет следующий Q1;
|
||||
- если Q1 пустая, берется следующий Q2;
|
||||
- для Q1 DAO-часть равна сумме тикета в USD;
|
||||
- для Q2 DAO-часть равна двойной сумме тикета в USD;
|
||||
- перед выплатой суммы пересчитываются из USD-центов в lamports по Pyth SOL/USD;
|
||||
- если в `inflow_vault_pda` не хватает средств на тикет, DAO-часть и награду вызвавшему, шаг отклоняется.
|
||||
|
||||
`change_ticket_recipient` запрещает менять получателя у тикета, который является следующим на выплату.
|
||||
|
||||
## Ключи и управление
|
||||
|
||||
На старте удобно считать, что у программы есть отдельный управляющий ключ `key_3`.
|
||||
|
||||
Целевая модель:
|
||||
|
||||
- `update_coef_limit` вызывает DAO;
|
||||
- `grant_manager_limits` вызывает DAO;
|
||||
- upgrade-authority программы после проверки передается DAO;
|
||||
- `step_payout` остается открытым для любого подписанта, чтобы выплаты не зависели от одного оператора.
|
||||
@@ -0,0 +1,136 @@
|
||||
# `shine_users`
|
||||
|
||||
## Кратко
|
||||
|
||||
`shine_users` — вторая программа Solana-модуля SHiNE. Она отвечает за создание и обновление пользовательской PDA-записи, проверку подписи записи, проверку логина через `shine_login_guard` и оплату регистрации/дополнительного лимита.
|
||||
|
||||
Папка программы: `shine-solana/shine/programs/shine_users/`.
|
||||
|
||||
## Текущие функции
|
||||
|
||||
1. `init_users_economy_config`
|
||||
- Создает PDA с экономическими настройками пользователей.
|
||||
- Записывает стартовую регистрационную комиссию, цену шага лимита и стартовый бонус лимита.
|
||||
|
||||
2. `update_users_economy_config`
|
||||
- Обновляет экономические настройки.
|
||||
- Требует подпись `DAO_AUTHORITY` из общего deploy-конфига.
|
||||
|
||||
3. `create_user_pda`
|
||||
- Проверяет логин через `shine_login_guard`.
|
||||
- Проверяет структуру полей пользователя.
|
||||
- Проверяет подпись записи root-ключом пользователя.
|
||||
- Создает `user_pda` по seed `login=<normalized_login>`.
|
||||
- Переводит оплату регистрации и дополнительного лимита в `shine_payments::inflow_vault_pda`.
|
||||
|
||||
4. `update_user_pda`
|
||||
- Проверяет неизменяемые поля пользователя.
|
||||
- Проверяет `prev_hash`, новую подпись и новое состояние последнего блока.
|
||||
- При необходимости расширяет PDA.
|
||||
- Переводит оплату дополнительного лимита в `shine_payments::inflow_vault_pda`.
|
||||
|
||||
## Аргументы инструкций
|
||||
|
||||
`init_users_economy_config` аргументов не принимает.
|
||||
|
||||
`update_users_economy_config`:
|
||||
|
||||
- `registration_fee_lamports: u64`
|
||||
- `lamports_per_limit_step: u64`
|
||||
- `start_bonus_limit: u64`
|
||||
|
||||
`create_user_pda`:
|
||||
|
||||
- `login: String`
|
||||
- `root_key: Pubkey`
|
||||
- `created_at_ms: u64`
|
||||
- `additional_limit: u64`
|
||||
- `fields: UserMutableFields`
|
||||
- `signature: Vec<u8>`
|
||||
|
||||
`update_user_pda`:
|
||||
|
||||
- `login: String`
|
||||
- `root_key: Pubkey`
|
||||
- `created_at_ms: u64`
|
||||
- `updated_at_ms: u64`
|
||||
- `version: u32`
|
||||
- `prev_hash: Vec<u8>`
|
||||
- `additional_limit: u64`
|
||||
- `fields: UserMutableFields`
|
||||
- `signature: Vec<u8>`
|
||||
|
||||
`UserMutableFields`:
|
||||
|
||||
- `device_key: Pubkey`
|
||||
- `blockchain_public_key: Pubkey`
|
||||
- `blockchain_name: String`
|
||||
- `used_bytes: u64`
|
||||
- `last_block_number: u32`
|
||||
- `last_block_hash: Vec<u8>` — ровно 32 байта
|
||||
- `last_block_signature: Vec<u8>` — ровно 64 байта
|
||||
- `arweave_tx_id: String`
|
||||
- `is_server: bool`
|
||||
- `server_key: Pubkey`
|
||||
- `server_address: String`
|
||||
- `sync_servers: Vec<String>`
|
||||
- `access_servers: Vec<String>`
|
||||
- `trusted_count: u8`
|
||||
|
||||
## Главные PDA
|
||||
|
||||
1. `user_pda`
|
||||
- PDA записи пользователя.
|
||||
- Seed: `login=<normalized_login>`.
|
||||
- Создается отдельно для каждого логина.
|
||||
- Стартовый размер: `768` байт.
|
||||
- При обновлении может расширяться через `realloc`, но один auto-realloc ограничен `10_000` байт.
|
||||
|
||||
2. `users_economy_config_pda`
|
||||
- PDA с настройками экономики.
|
||||
- Seed: `shine_users_economy_config`.
|
||||
- Хранит регистрационную комиссию, цену шага лимита и стартовый бонус.
|
||||
- Размер PDA: `8 + 96` байт.
|
||||
|
||||
## Текущие параметры экономики
|
||||
|
||||
Параметры initial config из `programs/shine_users/src/settings.rs`:
|
||||
|
||||
| Поле | Значение | Смысл |
|
||||
| --- | --- | --- |
|
||||
| `START_REGISTRATION_FEE_LAMPORTS` | `10_000_000` | стартовая комиссия регистрации, 0.01 SOL |
|
||||
| `LIMIT_STEP` | `10_000` | шаг `additional_limit` |
|
||||
| `START_LAMPORTS_PER_LIMIT_STEP` | `100_000` | 0.0001 SOL за один шаг лимита |
|
||||
| `START_BONUS_LIMIT` | `100_000` | стартовый бесплатный лимит при регистрации |
|
||||
|
||||
`additional_limit` в create/update должен быть кратен `LIMIT_STEP`.
|
||||
|
||||
## Связь с другими программами
|
||||
|
||||
`shine_users` зависит от:
|
||||
|
||||
- `shine_login_guard` — для проверки логина при создании пользователя;
|
||||
- `shine_payments` — для вычисления и проверки `inflow_vault_pda`, куда уходят платежи.
|
||||
|
||||
`create_user_pda` делает CPI-вызов `shine_login_guard::classify_login` и принимает только результат `0`. Premium/trademark логины сейчас отклоняются ошибками `PremiumLogin` или `TrademarkLoginRequiresReview`.
|
||||
|
||||
Подпись `user_pda` и подпись состояния последнего блока проверяются через встроенную Solana Ed25519-инструкцию, которая должна идти раньше инструкции `shine_users` в той же транзакции.
|
||||
|
||||
## Деньги
|
||||
|
||||
Деньги из `shine_users` идут только в `inflow_vault_pda` программы `shine_payments`.
|
||||
|
||||
Потоки:
|
||||
|
||||
- `create_user_pda`: регистрационная комиссия + оплата `additional_limit`;
|
||||
- `update_user_pda`: оплата `additional_limit`, если она больше нуля.
|
||||
|
||||
## Ключи и управление
|
||||
|
||||
На старте удобно считать, что у программы есть отдельный управляющий ключ `key_2`.
|
||||
|
||||
Целевая модель:
|
||||
|
||||
- economy-настройки меняет DAO-authority;
|
||||
- upgrade-authority программы после проверки передается DAO;
|
||||
- пользовательские операции `create_user_pda` и `update_user_pda` остаются доступными обычным пользователям при корректных подписях и оплате.
|
||||
@@ -0,0 +1,54 @@
|
||||
flowchart LR
|
||||
U[Пользователь / signer]
|
||||
B[Покупатель тикета]
|
||||
M[Менеджер]
|
||||
C[Любой caller step_payout]
|
||||
|
||||
LG[1. shine_login_guard<br/>classify_login]
|
||||
USERS[2. shine_users<br/>create_user_pda / update_user_pda]
|
||||
PAY[3. shine_payments<br/>vault / tickets / payouts]
|
||||
DAO[SHiNE DAO<br/>governance / authority / treasury]
|
||||
|
||||
USERPDA[(user_pda<br/>по login)]
|
||||
ECON[(users_economy_config_pda)]
|
||||
CONFIG[(config_pda)]
|
||||
COEF[(coef_limit_pda)]
|
||||
QUEUES[(queues_pda)]
|
||||
VAULT[(inflow_vault_pda)]
|
||||
TICKET[(ticket_pda)]
|
||||
ALLOW[(manager_allowance_pda)]
|
||||
|
||||
U -->|логин| USERS
|
||||
USERS -->|CPI проверка| LG
|
||||
USERS -->|создает/обновляет| USERPDA
|
||||
USERS -->|читает экономику| ECON
|
||||
U -->|регистрация / лимит| VAULT
|
||||
|
||||
DAO -->|update economy| USERS
|
||||
DAO -->|update coef/limit| PAY
|
||||
DAO -->|grant manager limits| PAY
|
||||
DAO -->|создает/отзывает ключи| DAO
|
||||
|
||||
PAY --> CONFIG
|
||||
PAY --> COEF
|
||||
PAY --> QUEUES
|
||||
PAY --> VAULT
|
||||
PAY --> TICKET
|
||||
PAY --> ALLOW
|
||||
|
||||
B -->|buy_ticket*| PAY
|
||||
B -->|оплата покупки тикета| DAO
|
||||
PAY -->|создает тикет| TICKET
|
||||
|
||||
M -->|manager_add_ticket| PAY
|
||||
ALLOW -->|лимиты Q1/Q2| M
|
||||
|
||||
C -->|step_payout| PAY
|
||||
VAULT -->|выплата тикета| U
|
||||
VAULT -->|DAO-часть| DAO
|
||||
VAULT -->|call reward| C
|
||||
|
||||
DAO -. upgrade authority после передачи .-> USERS
|
||||
DAO -. upgrade authority после передачи .-> PAY
|
||||
DAO -. позже возможно .-> LG
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 234 KiB |
@@ -0,0 +1,139 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1400" height="900" viewBox="0 0 1400 900" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Архитектура Solana-программ SHiNE</title>
|
||||
<desc id="desc">Схема трех программ, DAO, PDA-счетов и движения денег.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,6 L9,3 z" fill="#2f3a45"/>
|
||||
</marker>
|
||||
<marker id="moneyArrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,6 L9,3 z" fill="#0a7f62"/>
|
||||
</marker>
|
||||
<style>
|
||||
.bg { fill: #f7f8fa; }
|
||||
.title { font: 700 30px Arial, sans-serif; fill: #1f2933; }
|
||||
.subtitle { font: 400 16px Arial, sans-serif; fill: #52606d; }
|
||||
.box { fill: #ffffff; stroke: #9aa5b1; stroke-width: 2; rx: 8; }
|
||||
.program { fill: #e8f1ff; stroke: #3465a4; }
|
||||
.dao { fill: #fff3d6; stroke: #b7791f; }
|
||||
.pda { fill: #edf7ed; stroke: #2f855a; }
|
||||
.actor { fill: #f3e8ff; stroke: #805ad5; }
|
||||
.txt { font: 700 17px Arial, sans-serif; fill: #1f2933; }
|
||||
.small { font: 400 13px Arial, sans-serif; fill: #3e4c59; }
|
||||
.line { stroke: #2f3a45; stroke-width: 2.2; fill: none; marker-end: url(#arrow); }
|
||||
.money { stroke: #0a7f62; stroke-width: 3; fill: none; marker-end: url(#moneyArrow); }
|
||||
.dashed { stroke-dasharray: 8 7; }
|
||||
.legend { font: 400 14px Arial, sans-serif; fill: #3e4c59; }
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<rect class="bg" x="0" y="0" width="1400" height="900"/>
|
||||
<text class="title" x="52" y="54">SHiNE Solana: программы, DAO, счета и движение денег</text>
|
||||
<text class="subtitle" x="52" y="82">Текущая модель: три Anchor-программы, DAO/authority как управляющий слой, inflow vault и DAO treasury.</text>
|
||||
|
||||
<rect class="box actor" x="52" y="150" width="210" height="78"/>
|
||||
<text class="txt" x="72" y="181">Пользователь</text>
|
||||
<text class="small" x="72" y="206">signer, root_key, device_key</text>
|
||||
|
||||
<rect class="box actor" x="52" y="310" width="210" height="78"/>
|
||||
<text class="txt" x="72" y="341">Покупатель тикета</text>
|
||||
<text class="small" x="72" y="366">buy_ticket*</text>
|
||||
|
||||
<rect class="box actor" x="52" y="470" width="210" height="78"/>
|
||||
<text class="txt" x="72" y="501">Менеджер</text>
|
||||
<text class="small" x="72" y="526">manager_add_ticket</text>
|
||||
|
||||
<rect class="box actor" x="52" y="630" width="210" height="78"/>
|
||||
<text class="txt" x="72" y="661">Любой caller</text>
|
||||
<text class="small" x="72" y="686">step_payout</text>
|
||||
|
||||
<rect class="box program" x="360" y="126" width="270" height="96"/>
|
||||
<text class="txt" x="382" y="160">1. shine_login_guard</text>
|
||||
<text class="small" x="382" y="186">classify_login</text>
|
||||
<text class="small" x="382" y="205">free / premium / trademark</text>
|
||||
|
||||
<rect class="box program" x="360" y="286" width="270" height="112"/>
|
||||
<text class="txt" x="382" y="320">2. shine_users</text>
|
||||
<text class="small" x="382" y="346">create_user_pda</text>
|
||||
<text class="small" x="382" y="365">update_user_pda</text>
|
||||
<text class="small" x="382" y="384">economy config</text>
|
||||
|
||||
<rect class="box program" x="360" y="518" width="270" height="122"/>
|
||||
<text class="txt" x="382" y="552">3. shine_payments</text>
|
||||
<text class="small" x="382" y="578">vault, tickets, queues</text>
|
||||
<text class="small" x="382" y="597">grant_manager_limits</text>
|
||||
<text class="small" x="382" y="616">step_payout</text>
|
||||
|
||||
<rect class="box dao" x="776" y="126" width="270" height="122"/>
|
||||
<text class="txt" x="798" y="160">SHiNE DAO</text>
|
||||
<text class="small" x="798" y="186">governance / authority</text>
|
||||
<text class="small" x="798" y="205">treasury dao_wallet</text>
|
||||
<text class="small" x="798" y="224">ключи через голосование</text>
|
||||
|
||||
<rect class="box pda" x="776" y="306" width="270" height="84"/>
|
||||
<text class="txt" x="798" y="340">shine_users PDA</text>
|
||||
<text class="small" x="798" y="365">user_pda, economy_config</text>
|
||||
|
||||
<rect class="box pda" x="776" y="500" width="270" height="150"/>
|
||||
<text class="txt" x="798" y="534">shine_payments PDA</text>
|
||||
<text class="small" x="798" y="560">config_pda, coef_limit_pda</text>
|
||||
<text class="small" x="798" y="579">queues_pda</text>
|
||||
<text class="small" x="798" y="598">inflow_vault_pda</text>
|
||||
<text class="small" x="798" y="617">ticket_pda, manager_allowance</text>
|
||||
|
||||
<rect class="box pda" x="1134" y="500" width="214" height="88"/>
|
||||
<text class="txt" x="1156" y="534">inflow_vault</text>
|
||||
<text class="small" x="1156" y="560">деньги регистрации</text>
|
||||
|
||||
<rect class="box dao" x="1134" y="170" width="214" height="88"/>
|
||||
<text class="txt" x="1156" y="204">DAO treasury</text>
|
||||
<text class="small" x="1156" y="230">dao_wallet</text>
|
||||
|
||||
<path class="line" d="M262 189 C300 189, 318 334, 360 334"/>
|
||||
<text class="small" x="270" y="286">регистрация / update</text>
|
||||
|
||||
<path class="line" d="M360 314 C322 250, 320 176, 360 174"/>
|
||||
<text class="small" x="330" y="250">CPI login</text>
|
||||
|
||||
<path class="line" d="M630 342 L776 342"/>
|
||||
<text class="small" x="646" y="329">создает/обновляет</text>
|
||||
|
||||
<path class="money" d="M262 205 C438 432, 1010 390, 1134 530"/>
|
||||
<text class="small" x="430" y="430">регистрация и лимит -> inflow_vault</text>
|
||||
|
||||
<path class="money" d="M262 349 C540 260, 870 244, 1134 214"/>
|
||||
<text class="small" x="538" y="270">покупка тикета -> DAO treasury</text>
|
||||
|
||||
<path class="line" d="M262 509 L360 579"/>
|
||||
<text class="small" x="276" y="540">создать тикет</text>
|
||||
|
||||
<path class="line" d="M630 579 L776 575"/>
|
||||
<text class="small" x="648" y="562">PDA состояния</text>
|
||||
|
||||
<path class="line" d="M1046 575 L1134 548"/>
|
||||
|
||||
<path class="money" d="M1134 560 C970 700, 580 728, 262 669"/>
|
||||
<text class="small" x="650" y="720">call reward caller</text>
|
||||
|
||||
<path class="money" d="M1134 536 C860 754, 426 238, 262 194"/>
|
||||
<text class="small" x="632" y="760">выплата получателю тикета</text>
|
||||
|
||||
<path class="money" d="M1241 500 L1241 258"/>
|
||||
<text class="small" x="1254" y="380">DAO-часть выплат</text>
|
||||
|
||||
<path class="line" d="M776 188 L630 342"/>
|
||||
<text class="small" x="642" y="250">update economy</text>
|
||||
|
||||
<path class="line" d="M776 216 C690 290, 666 516, 630 558"/>
|
||||
<text class="small" x="654" y="438">settings / managers</text>
|
||||
|
||||
<path class="line dashed" d="M910 248 C850 702, 620 720, 520 640"/>
|
||||
<text class="small" x="690" y="690">upgrade-authority: users/payments; login_guard позже</text>
|
||||
|
||||
<rect class="box" x="52" y="808" width="1296" height="54"/>
|
||||
<line x1="74" y1="835" x2="132" y2="835" class="line"/>
|
||||
<text class="legend" x="146" y="840">логические вызовы и управление</text>
|
||||
<line x1="374" y1="835" x2="432" y2="835" class="money"/>
|
||||
<text class="legend" x="446" y="840">движение SOL/lamports</text>
|
||||
<line x1="682" y1="835" x2="740" y2="835" class="line dashed"/>
|
||||
<text class="legend" x="754" y="840">будущая передача upgrade-authority DAO</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,91 @@
|
||||
# Деплой и инициализация Solana-регистрации (две обязательные программы)
|
||||
|
||||
## Коротко
|
||||
|
||||
Для рабочей регистрации пользователя нужны **обе** программы:
|
||||
|
||||
1. `shine_users` — хранение и обновление `user_pda`, economy-конфиг, логика регистрации.
|
||||
2. `shine_login_guard` — проверка/классификация логина (CPI из `shine_users`).
|
||||
|
||||
Если задеплоена только одна из них — регистрация неработоспособна.
|
||||
|
||||
## Актуальные адреса (devnet)
|
||||
|
||||
- `shine_users` (регистрация пользователей):
|
||||
`FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm`
|
||||
- `shine_login_guard`:
|
||||
`3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo`
|
||||
- `shine_payments`:
|
||||
`m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR`
|
||||
|
||||
## Подтверждение деплоя
|
||||
|
||||
- Сеть: `https://api.devnet.solana.com`
|
||||
- `shine_users`:
|
||||
- `Program ID`: `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm`
|
||||
- TX deploy: `5VzfpSirFCRqPUZfvAt3eADY9KnowW79PKZ1pCQAa2DJGiztj4dUYYXrSQNmWEhPVu6mPSDfcuHzFyEVmoKLa9DM`
|
||||
- `shine_login_guard`:
|
||||
- `Program ID`: `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo`
|
||||
- TX deploy: `5iptngPYrLLjPE3Xby24zyNW3edVUnBNLBx785vjojMoq5JNLFNQvLNAm3jNYHbpf2B36qtbpTNzcvUNyRDqm1Mf`
|
||||
|
||||
## Порядок деплоя (devnet)
|
||||
|
||||
1. Убедиться, что CLI смотрит в devnet и у кошелька есть SOL.
|
||||
2. Собрать и задеплоить `shine_login_guard`.
|
||||
3. Собрать и задеплоить `shine_users`.
|
||||
4. Проверить, что адреса совпадают между:
|
||||
- `Anchor.toml`
|
||||
- `declare_id!` в `programs/*/src/lib.rs`
|
||||
- UI/серверными константами.
|
||||
5. Выполнить `init_users_economy_config` (один раз на программу `shine_users`).
|
||||
|
||||
Пример команд:
|
||||
|
||||
```bash
|
||||
cd shine-solana/shine
|
||||
solana config get
|
||||
solana balance
|
||||
|
||||
anchor build -p shine_login_guard
|
||||
anchor deploy -p shine_login_guard
|
||||
|
||||
anchor build -p shine_users
|
||||
anchor deploy -p shine_users
|
||||
```
|
||||
|
||||
## Куда вписаны адреса в проекте
|
||||
|
||||
### UI
|
||||
|
||||
- Общие Solana-константы:
|
||||
- `shine-UI/js/solana-programs.js`
|
||||
- Страница инициализации:
|
||||
- `shine-UI/js/pages/solana-users-init-view.js`
|
||||
- Переход на страницу:
|
||||
- `shine-UI/js/pages/developer-settings-view.js`
|
||||
|
||||
### Сервер
|
||||
|
||||
- Серверные константы Solana:
|
||||
- `shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java`
|
||||
|
||||
## Как запустить инициализацию economy PDA
|
||||
|
||||
1. Открыть UI.
|
||||
2. Перейти: `Профиль -> Настройки -> Настройки разработчика -> Solana: init регистрации`.
|
||||
3. Подключить кошелёк (Phantom, devnet).
|
||||
4. Нажать `Запустить init_users_economy_config`.
|
||||
5. Дождаться статуса `Успешно`.
|
||||
|
||||
Страница сама вычисляет PDA `users_economy_config` по seed:
|
||||
|
||||
- seed: `shine_users_economy_config`
|
||||
- program: `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm`
|
||||
|
||||
## Важно
|
||||
|
||||
- `init_users_economy_config` выполняется один раз на программу.
|
||||
Если PDA уже создан, повторный вызов вернёт ошибку "already initialized" (это нормальное поведение).
|
||||
- Серверные приватные ключи для Solana не используются: подписание делается кошельком пользователя в UI.
|
||||
- `shine_users` внутри `create_user_pda` требует корректный адрес `shine_login_guard` для CPI-классификации логина.
|
||||
Несовпадение адреса приведёт к ошибке регистрации.
|
||||
Reference in New Issue
Block a user