Телеграм бот для автоматизации обменника криптовалюты

Телеграм бот для автоматизации обменника криптовалюты
Телеграм бот для автоматизации обменника криптовалюты

Вместо предисловия

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

Полуавтоматический обменник криптовалюты.

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

  • полуавтоматические

  • ручные

  • автоматические

  • p2p — обменники

  • биржи

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

Необходимый набор навыков.

Говоря довольно простой, я наверное выражаюсь не совсем корректно. В наше время навыки, которыми должен обладать разработчик, оцениваются в тысячи часов времени, которое он должен потратить на свое обучение. Я сегодня буду предельно краток, так что давайте сразу перейдем к делу. Для реализации задачи нам понадобится следующий набор инструментов:

  1. Linux, zsh, vim, systemd

  2. nginx, ssl

  3. ES6, Material Ui, React, eslint, webpack, scss

  4. python3, asyncio, aiohttp, peewee

  5. postgresql

  6. telegram bot api

  7. docker

И такие паттерны как:

  1. MVC — шаблон архитектуры системы

  2. Abstract Factory, Factory Method, Builder, Facade, Prototype — генерация объектов

  3. Scheduler — многопоточный постановщик задач

  4. Event Listner, State — события, состояния

  5. Proxy — заместитель для балансировки нагрузки

В общих чертах это вроде как все, что должно пригодится, согласитесь не мало. Давайте пробежимся теперь немного более подробно, чтобы понимать как все это барахло должно быть настроено, чтобы даже работать.

Теперь я начинаю с фронта

Если вы попробуете поискать в сети с чего начинать веб разработку — с фронтенда или с бэкэнда, вы наверное не найдете ничего более дельного, чем информация о том, что все это лучше делать параллельно и каких-то особых протоколов на этот счет нет. Т.е. фронтендер делает свою работу, бэкэндер свою, они встречаются на созвонах и в чате, обсуждают все проблемы: все хорошо. Но что, если вы собираетесь делать и фронт и бэк самостоятельно (например в случае небольшого приложения как криптообменник) — какая будет точка отправления?

Начинать лучше с фронта, потому как он может работать на моковых данных и бэкэнд ему собственно нужен только абсолютно гипотетически. Фронтенд — независимое приложение, он должен работать корректно в разных браузерах, на разных устройствах. Мы будем делать Single Page Application, а значит нам потребуется протокол взаимодействия, давайте выберем json-rpc. Для транспортного протокола используем tcp,а на прикладном уровне остановимся на http.

Дальше все довольно не трудно. Ставим Node Package Manager, создаем новое React приложение, добавляем туда react router,настраиваем eslint для форматирования кода, node-sass для возможности использования css препроцессора, webpack для сборки проекта.

Правильная структура проекта — залог успеха. Компоненты делаем модульными — файлы стилей лежат внутри директории рядом с компонентом. Компоненты по мере возможностей реализуем как stateless. Я бы пожалуй еще рекомендовал дважды задуматься перед внедрением redux в приложение — делайте это только если вы точно уверены, что вам это нужно.

При работа с фронтом важно всегда помнить об области видимости переменных, потому как современный фронтенд это сложное многопоточное, асинхронное приложение. При этом при правильной организации файлов и компонентов, react и material ui позволяют делать все достаточно быстро. Если у вас нет готового дизайна — просто выберите сайт обменника, который вам нравится и не стесняясь копируйте его, привнося свои изменения — в дальнейшем ваш обменник все равно еще претерпит кучу изменений и не стоит сейчас беспокоится о том как это выглядит на текущей стадии.

Вот так может выглядеть ваш React компонент, отвечающий за рендеринг главной страницы:

Бэкэнд — это сложно, но куда веселее

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

asyncio позволяет работать с петлей событий, что в свою очередь предоставляет возможность асинхронного программирования и управления заданиями. В нашем случае у нас будет несколько заданий, которые должны будут работать независимо и параллельно основному приложению. Это задание на обновление курсов BTC/USD и USD/RUB, и задание, которое будет отменять устаревшие заявки на обмен валюты. Курсы валют можно получать get запросом из api всех популярных бирж, например coinbase, kraken, bitmex. Благо aiohttp clientпозволяет это делать в несколько строчек:

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

При создании моделей стоит особое внимание уделить инкапсуляции и наследованию — хорошей идеей будет сразу создать BaseModel, в которую поместить, например, поля created_at, updated_at и, например, datetime_serializer, который вам точно пригодится, а остальные модели наследовать от этой модели:

Для взаимодействия с blockchain придется получить API KEY, например на blockchain.com. Хочу сразу отметить, что тут есть своего рода «подводный камень». Как работает blockchain api? После того, как создается транзакция, для ее завершения необходимы подтверждения от майнеров. Каждое подтверждение — это своего рода события, информацию о котором вы будете получать на свой сервер. В этом событии есть адрес кошелька, на который поступает криптовалюта. Теперь предположим, что для покупки криптовалюты в нашем обменнике мы всем пользователям будем предоставлять одинаковый кошелек для перевода. Это было бы довольно удобно, так как все биткоины были бы сосредоточены у нас на одном адресе, одной суммой. На первый взгляд. Но в таком случае при поступлении средств от пользователя на кошелек и последующих веб хуках от blockchain на callback_url, мы не сможем определить от какого конкретно пользователя поступил платеж. Можно конечно использовать параметр в webhook url но есть еще один интересный нюанс. Нам важно знать курс по которому была совершена та или иная транзакция. Опять же, есть вариант хранить связь между транзакцией и курсом, но есть и альтернативное решение. Оно состоит в том, что каждому пользователю системы должен генерироваться свой уникальный BTC кошелек. И в случае, когда этот самый пользователь хочет совершить сделку в нашем обменном пункте и продавать свои кровные BTC, мы будем скидывать ему его уникальный адрес.

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

Таким образом получается, что баланс нашего обменника сосредоточен децентрализовано на разных кошельках всех пользователей. При каждой транзакции мы записываем курс, по которому она была осуществлена, а ее статус (так же как впрочем и статус документа по этой транзакции) мы меняем в зависимости от подтверждений blockchain.К слову сразу имеет смысл подумать над реализацией классов Billing и Processing, для создания и проводки документов.

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

Telegram bot

Тут все совсем не трудно. Создаем бота у @BotFather, настраиваем, берем токен, кладем его в конфиг (делаем два конфига и два бота — один на прод, один на дев).

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

Теперь мы можем слать сообщения в телеграм из нашего бэкэнда, для этого мы создадим приватный чат и добавим бота администратором туда. Далее нам потребуется создать вебхук и контроллер для его обработки (читайте об этом в предыдущем материале про мониторинг). В контроллере нам необходимо создать диспетчер запросов, который будет определять обработчик.

Запросы от тг могут быть разные, нам пока нужы будут только message и callback_query (reply клавиатура и inline клавиатура).

Далее мы будем отправлять в этот чат сообщения с кнопками, которые позволят контролировать значения в базе данных. Здесь обращу внимание на race condition, и трудно-уловимые ошибки, по этому всегда используйте atomic_db_query

async with objects.atomic() as atomic_db_query:
	try:
  	pass  # some database change
  except:  
		atomic_db_query.rollback()

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

Это довольно удобно, ведь телеграм всегда под рукой, особенно после разблокировки . 24/7 все, кто находятся в приватной группе, смогут получать информационные сообщения, а так же управлять состоянием документов:

Настройка production

Нужно все это барахло завернуть в докер, настроить системные демон для запускать юнита, в идеале конечно настроить CI-CD, но это все наверное уже детали.

В базовом варианте можно деплоится через Git, использовать переменные окружения для чтения конфигов, использовать ipython для проведения миграций в бд:

Нужно уметь использовать настраивать nginx, и понимать, как работает mod_rewrite.

location = /api/rates/rates.xml {
  rewrite .* /api/rates/ last;
}   

Кстати для добавления вашего обменника в мониторинги, вам понадобится xml выгрузки файла курсов, так что этот rewrite вам может еще пригодится.

Наверное вы захотите сделать какую-то админку — для этого отлично сгодится механизм Basic Auth и bootstrap admin template . Вам останется только пробросить в шаблоны необходимый контекст и немного поиграть с контролями:

Вывод

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

Благодарю за внимание!!!
Надеюсь статья  «Телеграм бот для автоматизации обменника криптовалюты» была полезной для Вас
Специально для сайта ITWORLD.UZ. Статья взята с сайта Хабр