Архитектура Monavo - как устроен Telegram-сервис для Solana swap
Недавно я запустил бета-версию Monavo - Telegram-сервиса для обмена токенов в сети Solana. Сейчас проект работает в режиме публичного тестирования, и основная цель этого этапа - посмотреть, как архитектура Monavo ведёт себя в реальной среде. В этой статье я хочу разобрать, как устроена архитектура Monavo, почему система разделена на edge-API и закрытый сервер, и какие инженерные решения помогают защититься от дублей запросов, сетевых ошибок и нестабильности внешних сервисов.
Когда речь идёт о криптовалютных операциях, инфраструктура играет не меньшую роль, чем интерфейс. Ошибка запроса или повторная отправка операции могут привести к некорректной транзакции. Поэтому при разработке Monavo основное внимание уделялось устойчивости системы. Важно было сделать сервис, который остаётся предсказуемым даже при нестабильной сети, повторных webhook и ограничениях внешних API.
Monavo задумывался как Telegram-first продукт. Telegram используется для входа, уведомлений и запуска действий. Подтверждение операций происходит в web-части приложения /app, где пользователь видит детали операции перед её выполнением.
🧩 Общая архитектура системы
Проект Monavo построен как монорепозиторий с разделением на несколько модулей. Это позволяет отделить бизнес-логику от инфраструктуры и упрощает развитие проекта.
В системе есть несколько основных компонентов. Публичный API работает на Cloudflare Workers и принимает все входящие запросы. Отдельный сервер выполняет тяжёлые операции и взаимодействует с инфраструктурой Solana. Web-часть приложения служит пользовательским интерфейсом.
В репозитории выделены отдельные модули для API, web-приложения, общих контрактов данных и схемы базы данных. Такой подход позволяет менять инфраструктуру или интерфейс без изменения доменной логики.
⚡ Edge-архитектура
Одним из ключевых решений в архитектуре Monavo стало использование edge-инфраструктуры.
Публичный API работает на Cloudflare Workers. Они принимают Telegram webhook, обрабатывают запросы web-приложения, управляют сессиями и применяют rate limiting.
Workers выполняют роль gateway между пользователями и внутренним сервером. Благодаря этому публичная часть системы остаётся быстрой, а критическая логика изолирована от прямого доступа.
Поскольку Workers запускаются на edge-узлах Cloudflare по всему миру, API отвечает быстро даже при географически распределённых пользователях.
🔐 Закрытый swap-engine
Тяжёлая бизнес-логика вынесена в отдельный внутренний сервис. Он отвечает за подготовку swap-транзакций и взаимодействие с инфраструктурой Solana.
Этот сервер не доступен напрямую из интернета. Он работает за Cloudflare Tunnel и принимает запросы только от Workers.
Таким образом публичный API и внутренний сервис разделены. Даже если публичный слой подвергнется атаке, внутренний swap-engine остаётся недоступным извне.
Workers обращаются к серверу через сервисный ключ, который проверяется на стороне backend. Это создаёт дополнительный уровень защиты между edge-слоем и внутренней инфраструктурой.
🧠 Контракты API и DTO
Передача данных внутри системы построена через DTO-контракты. Все входные и выходные payload проходят валидацию на границе API.
Контракты описаны через Zod и используются как единый источник типов для всех частей системы. Это позволяет избежать ситуаций, когда разные сервисы интерпретируют данные по-разному.
Такой подход делает API более предсказуемым и снижает вероятность ошибок при развитии проекта.
🧯 Result-подход вместо исключений
В Monavo используется подход, похожий на функциональные языки вроде Elixir или Rust. Методы не бросают исключения, а возвращают результат операции.
Каждый ответ содержит флаг isFault, который показывает, произошла ли ошибка. При необходимости возвращаются код ошибки и описание проблемы.
Это позволяет избежать ситуаций, когда исключение неожиданно прерывает цепочку вызовов. Клиент всегда получает структурированный ответ и может корректно обработать результат операции.
Пример такого ответа выглядит примерно так:
или
🔁 Защита от дублей запросов
Одна из распространённых проблем распределённых систем - повторные запросы. Они могут появляться из-за нестабильной сети, повторной отправки HTTP-запроса или дублирования webhook-событий.
В архитектуре Monavo для этого используется механизм idempotency. Каждый командный запрос получает уникальный ключ. Система сохраняет хэш запроса и его результат.
Если приходит повтор того же запроса, возвращается сохранённый результат. Если payload отличается, система возвращает конфликт.
Это позволяет избежать повторного выполнения операций и делает API устойчивым к сетевым ошибкам.
🛡 Безопасность сессий
Авторизация пользователя начинается в Telegram. После входа web-приложение получает одноразовый токен, который используется для создания сессии.
Этот токен имеет ограниченное время жизни и хранится в базе только в виде хэша. После использования он становится недействительным.
Сама сессия хранится через cookie с параметрами безопасности - HttpOnly, SameSite и Secure. Токены периодически ротируются, что уменьшает риск их компрометации.
⚙ Надёжность интеграций
Monavo взаимодействует с несколькими внешними сервисами, включая инфраструктуру Solana.
Чтобы избежать перегрузки API и случайных блокировок, интеграции обёрнуты в лимитеры частоты запросов. Также используется кэширование и периодическое обновление данных.
Это уменьшает нагрузку на внешние сервисы и делает ответы системы более стабильными.
📦 Деплой системы
Workers деплоятся через GitHub Actions. При обновлении кода выполняется автоматический деплой на Cloudflare.
При деплое используется режим, который предотвращает случайную перезапись секретов и runtime-переменных.
Внутренний сервер работает на VPS и управляется через PM2. Такой подход позволяет быстро обновлять сервис и контролировать его состояние.
⚠ Проблемы и чему я научился
Несмотря на продуманную архитектуру, при разработке Monavo возникло несколько проблем, которые пришлось решать уже после первых тестов.
Первая проблема была связана с обработкой Telegram webhook. Изначально система не использовала idempotency. На практике оказалось, что Telegram может отправлять одно и то же событие несколько раз. Иногда это происходило из-за сетевых задержек или повторной доставки webhook.
В результате одна и та же операция могла запускаться несколько раз. После этого в систему был добавлен механизм idempotency-ключей и хэширования payload.
Вторая проблема возникла при использовании edge-инфраструктуры. Cloudflare Workers отлично подходят для быстрых API-операций, но не предназначены для тяжёлых вычислений и длительных запросов к внешним сервисам.
Некоторые операции swap-flow занимали больше времени, чем комфортно для edge-функций. В итоге архитектура была изменена. Workers стали выполнять роль gateway, а тяжёлая бизнес-логика была вынесена в отдельный внутренний сервис.
Третья проблема появилась при работе с Solana RPC. В тестовой среде всё выглядело стабильно, но при увеличении количества запросов начали появляться ошибки rate limit и нестабильные ответы RPC-узлов.
Это привело к добавлению лимитеров, кэширования и очередей запросов.
Отдельный урок связан с обработкой ошибок. В первой версии системы активно использовались исключения. Это приводило к сложной цепочке try/catch и не всегда предсказуемым ответам API.
В итоге система была переписана на result-подход. Теперь методы возвращают структурированный объект результата, который содержит флаг ошибки и дополнительные данные.
Этот подход оказался гораздо более предсказуемым и упростил обработку ошибок на стороне клиента.
🧭 Почему архитектура Monavo устроена именно так
Основная идея архитектуры Monavo - разделить систему на быстрый публичный слой и закрытое ядро.
Edge-слой отвечает за взаимодействие с пользователями и работает максимально быстро. Ядро системы выполняет критическую бизнес-логику и изолировано от прямого доступа.
Такой подход уменьшает поверхность атаки, упрощает масштабирование и делает систему более устойчивой к сетевым проблемам.
🧪 Что дальше
Сейчас Monavo находится в стадии бета-тестирования. Основная задача этого этапа - понять, как архитектура ведёт себя под реальной нагрузкой и какие узкие места могут появиться при росте пользователей.
Если тестирование покажет стабильную работу системы, следующим шагом станет расширение функциональности и развитие инструментов для работы с Solana-экосистемой.
Бета-версия сервиса уже работает и постепенно открывается для пользователей, поэтому ближайшие месяцы будут хорошим тестом того, насколько выбранная архитектура оказалась удачной.