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

Web3: тайм-аут транзакции и восстановление статуса

Оглавление курса «Web3-интерфейс: реестр в браузере» · Урок 21 из 30.

Тайм-аут ожидания означает, что приложение не получило нужный ответ за выбранный срок. Он не сообщает окончательный исход транзакции. В этом уроке сохраним неизвестное состояние и восстановим наблюдение после перезагрузки. Результат — посетитель продолжает следить за уже отправленной публикацией без новой подписи.

Предполагается журнал логической операции с текущим хешем и списком замен. Код относится к браузерной лаборатории и не запускался. LocalStorage используется как простой учебный способ сохранения, а не как надёжное серверное хранилище или защита от изменения данных посетителем.

Неизвестный результат является состоянием

После получения хеша транзакция могла ещё не попасть в блок, могла быть заменена или могла уже исполниться при недоступном RPC. Общий статус «ошибка» скрывает эти различия и подталкивает человека повторить действие. Лучше показать «наблюдение прервано; результат пока неизвестен» вместе с сохранённым идентификатором операции.

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

Если страница потеряла ответ отправки до получения хеша, восстановление сложнее. Сохранённое намерение не удостоверяет факт доставки. Пользователь сверяет кошелёк, а приложение не строит выдуманный хеш из аргументов. Для такого случая журнал содержит отдельный статус неопределённой отправки, а не притворяется обычным ожиданием receipt.

Схема сохранённой операции

В файл operation-storage.js поместим сериализацию минимальной истории. Большие числа представлены строками, как уже обсуждалось. Это собственная схема приложения с версией.

export function saveOperation(operation) {
  const document = {
    version: 1,
    id: operation.id,
    environmentId: operation.environmentId,
    chainId: operation.chainId,
    address: operation.address,
    account: operation.account,
    courseId: operation.courseId.toString(),
    contentHash: operation.contentHash,
    currentHash: operation.currentHash,
    attempts: operation.attempts,
    status: operation.status,
  };
  localStorage.setItem(`library-operation:${operation.id}`, JSON.stringify(document));
}

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

Исключение записи в хранилище также обрабатывается. Например, устройство не позволяет сохранять данные или исчерпана квота. Интерфейс сообщает, что автоматическое восстановление недоступно, и позволяет скопировать безопасные детали операции. Успешная сетeвая отправка не отменяется из-за отказа localStorage.

Возобновление без кошелька

При новой загрузке выбираем Public Client сохранённой сети и экземпляра. Для локальной лаборатории проверяем environmentId, потому что цепочку могли сбросить. Если окружение больше не соответствует, история остаётся архивной, а не перечитывается как текущая операция нового запуска.

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

Если receipt найден, сохраняем статус и данные блока, затем читаем текущее состояние курса. Если не найден, оставляем неизвестность или ожидание по политике приложения. Отсутствие receipt в одном endpoint не доказывает, что транзакция никогда не была передана. Не следует переводить такой ответ напрямую в «можно безопасно отправить ещё раз».

Срок хранения

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

Подписи входа, пароли и seed-фразы в этой схеме отсутствуют. Даже публичные адреса и время действий не нужно отправлять на сторонний сервер без задачи. Если история синхронизируется между устройствами, появляется серверная модель доступа, которую не решает один localStorage.

При нескольких вкладках одна операция может наблюдаться параллельно. Это безвреднее повторной отправки, но создаёт лишнюю нагрузку и гонки записи журнала. Обновления следует сравнивать по версии наблюдения, не позволяя старому неизвестному статусу перезаписать новый receipt. Координацию вкладок рассмотрим отдельно.

Изменение политики подтверждения

Если приложение прежде считало одно включение достаточным, а затем требует более устойчивое наблюдение, сохранённый статус нужно интерпретировать по версии политики. Нельзя просто переименовать все старые операции в «финальные». В записи полезно отделить факт receipt от решения интерфейса о достаточности подтверждения.

Это особенно важно при переносе курса на L2, где пользовательское подтверждение, публикация данных и финальность имеют собственные этапы. Наш журнал хранит первичные факты и применяет понятную текущую политику, не объявляя все сети одинаковыми. Расширение модели вводится явно, вместе с новой конфигурацией.

Для упражнения задайте тайм-аут, перезагрузку и поздний успешный receipt. Ожидается один исходный вызов подписи и несколько независимых попыток наблюдения. Затем добавьте сброс локальной цепочки: старая операция должна стать архивной с объяснением окружения. Результат урока — восстановление не равно повтору изменения. Семантика хранения описана в Web Storage, а ожидание — в viem.

Человек выбирает восстановление

На восстановленной странице полезно показать, когда был сохранён хеш, к какому действию он относился и какой последний факт известен. Затем доступна отдельная кнопка продолжения чтения. Автоматически обновить публичный receipt можно по политике приложения, но автоматически открыть кошелёк нельзя. Это различие сохраняется даже при знакомом аккаунте и неизменной форме.

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

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

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