Архитектура 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, который показывает, произошла ли ошибка. При необходимости возвращаются код ошибки и описание проблемы.

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

Пример такого ответа выглядит примерно так:

{ isFault: false, data: {...}}

или

{ isFault: true, code: "RATE_LIMIT", message: "Too many requests"}

🔁 Защита от дублей запросов

Одна из распространённых проблем распределённых систем - повторные запросы. Они могут появляться из-за нестабильной сети, повторной отправки 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-экосистемой.

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

1
Начать дискуссию