Back to Blog

Platform / B08

От идеи к продакшену: создание MERX за 30 дней

MERX перешел от концепции к живой production-системе за 30 дней. Не лендинг. Не прототип. Полностью функциональный блокчейн-обменник ресурсов с интеграцией семи провайдеров, агрегацией цен в реальном времени, on-chain выполнением ордеров, двойной бухгалтерией, полной документацией, SDK на двух языках и MCP-сервером с 60 инструментами для интеграции с AI агентами.

Эта статья — техническая история того, как это произошло: архитектурные решения, проблемы, которые мы решили, соглашения, которые мы сознательно не сделали, и уроки из построения финансовой платформы на скорости без компромиссов в том, что имеет значение.


День 0: Описание проблемы

Рынок энергии TRON фрагментирован. Семь или больше провайдеров предлагают услуги делегирования энергии, каждый со своим API, ценами и характеристиками надежности. Если вы хотите лучшую цену, вам нужно интегрироваться со всеми. Если вы хотите failover, вам нужно написать логику маршрутизации. Если вы хотите прозрачность, вам нужно создать мониторинг.

Каждый бизнес, отправляющий USDT на TRON, сталкивается с налогом на интеграцию. Решение — слой агрегации: единый API, который обрабатывает многопровайдерскую маршрутизацию, выбор лучшей цены и автоматический failover.

Никто еще это не построил. Мы решили это сделать.


Неделя 1: Фундамент

Сначала архитектура

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

Ключевые архитектурные решения, принятые за два дня:

Решение 1: Микросервисы с первого дня.

Не потому что микросервисы модные, а потому что финансовые системы нуждаются в изоляции. Подписант казначейства не должен быть доступен из сервиса API. Монитор цен не должен иметь доступ на запись к балансам пользователей. Docker-контейнеры обеспечивают эту изоляцию естественным образом.

services/
  api/              HTTP/WebSocket API
  price-monitor/    Опрос цен провайдеров
  order-executor/   Маршрутизация и выполнение ордеров
  ledger/           Двойная бухгалтерия
  deposit-monitor/  Обнаружение входящих платежей
  treasury-signer/  Подписание транзакций (изолировано)

Решение 2: PostgreSQL + Redis, без экзотических баз данных.

PostgreSQL для всего, что требует гарантий ACID (балансы, ордеры, записи в бухгалтерию). Redis для всего, что требует скорости (кеш цен, pub/sub, rate limiting). Оба — проверенные в боевых условиях, хорошо задокументированные и операционно простые.

Решение 3: Все суммы в SUN.

Каждое финансовое значение хранится как целое число в SUN (1 TRX = 1 000 000 SUN). Нет floating-point нигде в финансовой цепочке. Это исключило целую категорию ошибок до того, как мы написали нашу первую функцию.

Решение 4: Node.js + TypeScript для сервисов, Go для matching engine.

TypeScript для большинства системы — быстрая разработка, строгая типизация, отличный async I/O для API и мониторинга. Go зарезервирован для matching engine, где сырая производительность имеет значение.

Схема базы данных

Миграции базы данных были написаны на день 3. Каждая таблица была спроектирована с учетом финансовой целостности:

-- Основной принцип: каждая мутация баланса создает запись в бухгалтерию
CREATE TABLE ledger (
  id BIGSERIAL PRIMARY KEY,
  user_id UUID NOT NULL REFERENCES users(id),
  type VARCHAR(50) NOT NULL,
  amount_sun BIGINT NOT NULL,
  direction VARCHAR(6) NOT NULL CHECK (direction IN ('DEBIT', 'CREDIT')),
  reference_type VARCHAR(50),
  reference_id UUID,
  balance_before BIGINT NOT NULL,
  balance_after BIGINT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Нет триггеров UPDATE или DELETE — бухгалтерия append-only

Один файл на миграцию, названный YYYYMMDD_description.sql. К концу 30 дней было 14 файлов миграции, каждый аддитивный, ни один деструктивный.

Интерфейс провайдера

Интерфейс IEnergyProvider был определен на день 4. Это был контракт, который реализовал бы каждый адаптер провайдера:

interface IEnergyProvider {
  name: string;
  getPrices(): Promise<ProviderPriceResponse>;
  createOrder(params: OrderParams): Promise<OrderResult>;
  getOrderStatus(orderId: string): Promise<OrderStatus>;
  healthCheck(): Promise<boolean>;
}

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


Неделя 2: Основные сервисы

Монитор цен

Монитор цен был первым сервисом, выпущенным в production. Он опрашивает каждого провайдера каждые 30 секунд, нормализует цены, публикует в Redis и сохраняет историю в PostgreSQL. Реализация — примерно 180 строк TypeScript в трех файлах.

Самой сложной частью было не логика опроса — это была нормализация. Каждый провайдер возвращает цены в немного разных форматах:

Каждый адаптер переводит формат своего провайдера в стандартный ProviderPriceResponse. Монитор цен не волнует причудливость провайдеров; он видит только нормализованные данные.

Исполнитель ордеров

Исполнитель ордеров — самый сложный сервис. Он читает цены из Redis, определяет оптимальную маршрутизацию, отправляет ордеры провайдерам, мониторит on-chain подтверждение и публикует события расчета.

Цепь failover была критическим элементом дизайна. Если провайдер A падает, попробуй провайдера B. Если B падает, попробуй C. Вызов API покупателя завершается успешно, пока хотя бы один провайдер работает.

Ордер получен -> Читай цены -> Выбери дешевейшего
  -> Выполни у провайдера A
    -> Успех? Верифицируй on-chain -> Расчет
    -> Ошибка? Попробуй провайдера B
      -> Успех? Верифицируй on-chain -> Расчет
      -> Ошибка? Попробуй провайдера C
        -> ... и так далее

Сервис бухгалтерии

Сервис бухгалтерии обеспечивает ограничение двойной записи. Каждая мутация баланса создает спаренные записи. Сервис запускает проверку сверки каждый час:

SELECT SUM(CASE direction
  WHEN 'DEBIT' THEN amount_sun
  WHEN 'CREDIT' THEN -amount_sun
END) FROM ledger;
-- Должно быть 0. Если нет: немедленно алертировать.

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


Неделя 3: API, фронтенд и on-chain верификация

Дизайн API

API следует соглашениям REST со строгой версификацией (/api/v1/...). Каждый endpoint был спроектирован до реализации:

GET    /api/v1/prices          Текущие цены всех провайдеров
GET    /api/v1/prices/best     Лучшая текущая цена
POST   /api/v1/orders          Создать новый ордер
GET    /api/v1/orders/:id      Получить статус ордера
GET    /api/v1/balance         Получить баланс аккаунта
POST   /api/v1/deposit         Получить адрес депозита
POST   /api/v1/withdraw        Запросить вывод

Ответы об ошибках используют согласованный формат:

{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Account balance (5.2 TRX) is insufficient for this order (8.1 TRX)",
    "details": {
      "balance": 5200000,
      "required": 8100000
    }
  }
}

Ни один endpoint не был опубликован без валидации Zod на всех входных данных.

Фронтенд

Фронтенд — это Next.js приложение со строгой дизайн-системой: только темная тема, без округленных углов больше 2px, без градиентов, без теней, Cormorant Garamond для заголовков, IBM Plex Mono для всего остального. Визуальная идентичность была определена в документе архитектуры и реализована верно.

On-chain верификация

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

Восемь mainnet-транзакций были верифицированы во время фазы тестирования, подтверждая, что end-to-end поток — от вызова API к on-chain делегированию — работал корректно с реальными TRX и реальными провайдерами.


Неделя 4: SDK, MCP-сервер и документация

JavaScript SDK

JavaScript SDK был построен для Node.js и браузерных окружений:

import { MerxClient } from 'merx-sdk';

const client = new MerxClient({ apiKey: 'your-key' });
const prices = await client.getPrices({ energy: 65000 });
const order = await client.createOrder({
  energy: 65000,
  targetAddress: 'TAddress...',
  duration: '1h'
});

Источник: https://github.com/Hovsteder/merx-sdk-js

Python SDK

Python SDK отражает поверхность API JavaScript SDK:

from merx import MerxClient

client = MerxClient(api_key='your-key')
prices = client.get_prices(energy=65000)
order = client.create_order(
    energy=65000,
    target_address='TAddress...',
    duration='1h'
)

Источник: https://github.com/Hovsteder/merx-sdk-python

MCP-сервер: 52 инструмента

MCP (Model Context Protocol) сервер был, возможно, самым дальновидным компонентом. Он раскрывает функциональность MERX как инструменты, которые AI агенты могут использовать напрямую.

MCP-сервер вырос с 7 инструментов в его начальной версии до 60 инструментов к концу 30 дней:

Управление аккаунтом:    create_account, login, get_balance, get_deposit_info
Данные цен:              get_prices, get_best_price, compare_providers, analyze_prices
Управление ордерами:     create_order, get_order, list_orders, create_standing_order
Мониторинг ресурсов:     check_address_resources, estimate_transaction_cost
Утилиты TRON:            validate_address, convert_address, get_trx_balance
On-chain операции:       transfer_trx, transfer_trc20, approve_trc20
Аналитика:               calculate_savings, get_price_history, suggest_duration
... и 30 больше

Источник: https://github.com/Hovsteder/merx-mcp

Документация

Документация была расширена с 5 страниц до 36 страниц, охватывая полный справочник API, руководства по SDK, концепции TRON и учебники по интеграции. Документация находится на https://merx.exchange/docs.

Кроме того, были опубликованы 4 SEO-гайда и 7 страниц сравнения провайдеров, доведя карту сайта до 53 URL.


На чем мы не сделали компромиссов

Скорость создает давление для сокращения углов. Вот углы, которые мы сознательно не срезали:

Нет floating-point для денег

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

Нет конкатенации строк для SQL

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

Нет hardcoded секретов

Переменные окружения с первого дня. Docker секреты для ключа казначейства. .gitignore настроен до первого коммита.

Нет сервисов, напрямую делящих состояние

Сервисы общаются через Redis pub/sub или REST API вызовы. Нет прямых импортов между сервисами. Это сделало возможным независимое развертывание и предотвратило каскадные отказы.

Нет мутаций бухгалтерии

Append-only бухгалтерия с первой миграции. Нет UPDATE или DELETE на таблицах бухгалтерии. Исправления создают новые записи, а не изменения.


Что мы узнали

Урок 1: Документы архитектуры платят за себя

Два дня, потраченные на архитектуру, сэкономили недели переработок. Каждый вопрос разработчика был ответен документом. Каждый дизайн-конфликт был разрешен ссылкой на спецификацию. 40 разделов были не бюрократической нагрузкой; они были принуждающей функцией для обдумывания проблем до того, как они стали ошибками.

Урок 2: Provider API ненадежны

Из семи интегрированных провайдеров по крайней мере два испытали downtime в течение периода разработки из 30 дней. Цепь failover была не теоретическим удобством — она была задействована в течение первой недели тестирования.

Урок 3: Adapter Pattern стоит boilerplate

Написание семи адаптеров, которые все реализуют один интерфейс, казалось повторяющимся. Но когда провайдер C изменил формат ответа своего API на день 22, мы обновили один файл и больше ничего не изменилось. 10 минут, потраченные на обновление адаптера, против дней, которые мы потратили бы на обновление каждого места вызова, сделали ценность паттерна очевидной.

Урок 4: MCP — будущее интеграции сервисов

MCP-сервер был первоначально экспериментом. Но просмотр того, как AI агенты используют MERX инструменты для автономного управления снабжением энергией, был откровением. Это то, как сервисы будут потребляться в будущем — не через разработчиков, пишущих код интеграции, а через AI агентов, вызывающих инструмент API напрямую.

Урок 5: Лимит 200 строк на файл — это фича

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


По цифрам

Документ архитектуры:      40 разделов
Сервисы:                   9 Docker контейнеров
Интеграции провайдеров:    7
Миграции БД:               14
API endpoints:             20+
MCP инструменты:           52 (из начальных 7)
Языки SDK:                 2 (JavaScript, Python)
Страницы документации:     36 (из начальных 5)
URL на карте сайта:        53
Верифицированные mainnet-транзакции: 8
Комиссия:                  0%
Дней до production:        30

Что дальше

Платформа живет на https://merx.exchange. Немедленный фокус — тестирование, оптимизация и подключение первых production пользователей. Фундамент прочный — архитектура поддерживает горизонтальное масштабирование, новых провайдеров можно добавить за часы, и нулевая комиссионная модель убирает трение внедрения.

Рынок агрегации энергии на TRON ждет платформу, которая делает это просто. MERX — это та платформа.


MERX — первый блокчейн-обменник ресурсов. Исследуйте платформу на https://merx.exchange. Документация на https://merx.exchange/docs. Open-source SDK и MCP-сервер на GitHub.

Попробуйте сейчас с AI

Добавьте MERX в Claude Desktop или любой MCP-совместимый клиент — нулевая установка, без API ключа для инструментов только для чтения:

{
  "mcpServers": {
    "merx": {
      "url": "https://merx.exchange/mcp/sse"
    }
  }
}

Попросите вашего AI агента: "Какая самая дешевая энергия TRON прямо сейчас?" и получите живые цены от всех подключенных провайдеров.

Полная MCP документация: merx.exchange/docs/tools/mcp-server


All Articles