Перейти к содержанию

Web3: кабинет читателя и передача проекта

Оглавление курса «Web3: вход, смарт-аккаунты и индексатор» · Урок 30 из 30.

Мы прошли три линии разработки: вход читателя, индексирование реестра и операции смарт-аккаунта. Теперь соберём их в кабинет учебной библиотеки и определим, что передаётся следующему разработчику. Результатом урока станет явный паспорт проекта: какие данные публичны, какие относятся к сессии, какой срез показывает каталог и какие адаптеры пока существуют только как учебный договор.

Все материалы курса подготовлены локально. Примеры не запускались, сеть и кошельки не создавались, зависимости не устанавливались. Поэтому итогом не является сертификат готового продукта. Итог — связная программа реализации с исходниками моделей, ожидаемыми результатами и границами, которые можно проверить в отдельном проекте, когда такой запуск будет разрешён.

Разделим экран по происхождению данных

В верхней части кабинета показываем публичный каталог. Он может работать без входа: CourseCatalog хранит номер курса, contentHash и active, а проверенный материал даёт название и описание. Индексатор ускоряет историю, но не создаёт новые полномочия. Рядом указываем обработанный блок и состояние свежести.

В персональной части показываем прогресс читателя из серверного хранилища. Доступ к ней проверяется по действующей сессии и собственной политике прав. Публичный адрес, выбранный в кошельке, не подменяет серверную идентичность. Если аккаунт переключён, кабинет требует согласовать вход, а не молча переносит прогресс на новый адрес.

В преподавательской части показываем публикации от разрешённого publisher. Для прямого адреса используется один маршрут подписи и отправки. Для отдельного смарт-аккаунта — другой маршрут через выбранный профиль. Их нельзя подключить к одной кнопке, которая сама угадывает режим по наличию кода на адресе. Режим и его поддержка объявлены конфигурацией.

Паспорт окружения

Запишем минимальный собственный объект. Он не содержит реальных адресов и пока не пригоден для подключения: необходимые значения заполняются при отдельном развёртывании. Без них приложение показывает недоступность соответствующей функции, а не создаёт случайные значения.

export const teachingProfile = {
  environmentId: null,
  chainId: 31337,
  catalogAddress: null,
  deploymentBlock: null,
  nodeVersion: '22.14.0',
  viemVersion: '2.37.9',
  solidityVersion: '0.8.30',
  evmTarget: 'cancun',
  identity: { siweVersion: '1', sessionStore: 'not-configured' },
  indexer: { projectionVersion: 'library-courses-v1' },
  smartAccount: {
    enabled: false,
    accountVersion: null,
    entryPointVersion: null,
    entryPointAddress: null,
    operationSchema: null,
    bundlerProfile: null,
    paymasterProfile: null,
  },
};

Версии базовой линии закреплены в договоре серии, но это не утверждение о выполненной совместимости окружения. Блок smartAccount отключён явно: предыдущие главы объясняют архитектуру и собственные модели, не заменяя проверенный SDK. Перед включением необходимо выбрать взаимно совместимые реализации и сверить их первичные документы, а затем отдельно реализовать адаптеры и сценарии проверки.

Если продукт решит использовать React и wagmi из соседнего курса, берётся отдельно закреплённая линия React 19.1.1, wagmi 2.16.9 и TanStack Query 5.85.5. API другой основной версии wagmi не добавляются поверх неё случайно. Сам кабинет этого курса описан независимо от фреймворка, поэтому переход интерфейсной библиотеки не должен менять серверный договор авторизации.

Договор API кабинета

У каждого ответа существует назначение. Публичный /courses возвращает проекцию и source. Персональный /me/progress требует сессию и возвращает только разрешённые данные. /auth/challenge создаёт серверную задачу входа, а /auth/verify проверяет точное сообщение и атомарно потребляет nonce. /auth/logout отзывает серверное разрешение, даже если кошелёк остаётся подключённым.

Имена маршрутов являются учебным проектированием, а не существующими endpoints ProfessorWeb. Для действительного сервера нужно определить метод, формат ошибки, предел размера, CSRF-политику, cookie и кеширование. Публичный каталог допускает общий кеш с ключом окружения и среза. Персональные ответы не должны попасть в тот же CDN-слой.

Отдельный адаптер операций возвращает нормализованные статусы и связь с исходным намерением. Он не принимает от браузера готовое утверждение executionSuccess. Источник результата проверяется в контексте сети и выбранного механизма. Сохранённая подпись входа не используется как разрешение публикации; серверная cookie не является ключом смарт-аккаунта.

Приёмка по наблюдаемым свойствам

Договор передачи полезнее списка файлов без смысла. Для входа ожидаем отказ неправильного домена, истёкшего сообщения и повторно использованного nonce. Для сессии ожидаем серверный отзыв и невозможность перенести чужой прогресс сменой адреса в клиентском JSON. Для контракта подписи ожидаем отдельный результат unavailable, когда сеть не даёт достаточного наблюдения.

Для индексатора ожидаем непрерывные диапазоны, идемпотентные наблюдения и атомарность checkpoint с проекцией. Реорганизация меняет поколение и источник данных, а не незаметно редактирует старый паспорт. Пагинация относится к определённому срезу; курсор старой ветви не продолжает новую историю без явной политики.

Для операции ожидаем различие принятия, включения и выполнения. Успешный контейнер не заменяет результат пользователя. Состояние unknown сохраняет исходный идентификатор и не выпускает новый nonce автоматически. Резерв оплаты не возвращается по одному тайм-ауту, а отозванный ключ сессии не получает право повторной публикации через старый кеш.

Что передать в документации

Разработчик получает карту полей, источники документации, версии и перечень нереализованных адаптеров. Рядом с каждым исходником указывается его категория: чистая модель, фрагмент SQL, интерфейс адаптера или настоящий конфигурационный файл. Фрагмент не должен неожиданно выглядеть как полноценный сервис, который уже можно направить в production.

Нужно также описать управление секретами, резервные копии и восстановление. В репозиторий не входят действительные cookie, приватные ключи, рабочие подписанные пакеты и внутренние токены RPC. Безопасные идентификаторы, версии и ожидаемые состояния достаточны для редакционной передачи. Эксплуатационные секреты добавляются через отдельный защищённый контур при внедрении.

Старые URL учебных материалов остаются обычными публичными страницами. Новый кабинет может ссылаться на них и хранить отметки чтения, но авторизация не должна случайно закрыть всю библиотеку или заменить статью экраном подключения кошелька. Публичный материал и персональное состояние расширяют друг друга, сохраняя понятный доступ для читателя и поискового робота.

Итоговый маршрут

Читатель открывает каталог без входа, видит источник и выбирает курс 17. При сохранении прогресса получает отдельный поток входа. Преподаватель готовит публикацию в правильном окружении, видит пределы разрешения и отслеживает исходную операцию. Индексатор независимо догоняет сеть и обновляет публичную проекцию. Ни одна из линий не объявляет другую завершённой без её собственного наблюдения.

Именно эта независимость делает проект расширяемым. Можно менять интерфейс, хранение прогресса или инфраструктуру доставки, сохраняя договор каждой границы. Когда появится отдельное разрешение на запуск, программу проверки следует выполнять на закреплённом профиле и записывать фактические результаты. До этого все показанные результаты остаются ожидаемыми, что честно отражено в метаданных уроков.

Оглавление серии