Вступление

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

Телеграм

Телега - тот самый крайний оплот свободы. На сегодняшний день TG обладает самым удобным и мощным бот апи, если сравнивать с другими мессенджерами и платформами. Но не смотря на это, он не является обязательным элементом этой схемы обмена и для реализации такого приложения можно использовать практически любой популярный мессенджер или социальную сеть - например Discord, VK или одноклассники. Немного изучая материал, а так же, имея за плечами многолетний опыт работы с соц сетями и мессенджерами, я пришел к выводу что многие не осознают тот факт, что сам по себе "бот" - это универсальный механизм, который может работать с любым интерфейсом. Иными словами - это код, реализованный с использованием паттерна Finite-state machine. А апи, с которым он будет работать - он может быть любым, и хорошего бота можно в два счета перевести из телеги в контакт. Много ли я видел хороших ботов за свой многолетний опыт? Не много - я не видел хороших ботов. Я склонен считать, что вообще все программы и весь их исходный код - они не очень.

Крипта

А вот крипта - крипта, да. Крипта - это классно! В ней я тоже не эксперт и, пожалуй, обращаться за советом лучше не ко мне, но словечко замолвить я должен. С криптой я знаком уже очень давно и что такое p2p обмен знаю не понаслышке.

Как хранить крипту в обменнике? Я уже пытался высказать что-то не очень внятное в предыдущей статье, посвященной полуавтоматическому обмену. В случае с p2p - ситуация повторяется. Каждому пользователю обменника, для каждой криптовалюты мы генерируем кошельки. Эти кошельки фактически не принадлежат пользователям - пользователи не имеют прямого доступа к средствам, которые хранятся на этих кошельках. Все что известно конечному юзеру - это адрес кошелька. Зная адрес, можно посмотреть сколько на этом кошельке реально хранится монет - ведь блокчейн открыт для всех, а вся информация там прозрачна и доступна. Так что зайдите на свой любимый p2p обменник и сравните, совпадает ли баланс который вам показывают, с тем, который реально хранится на созданном для вас кошельке.

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

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

class CryptoUnit():
    bot = None

    def __init__(self, token: str) -> None:
        self.bot = Bot(token=token)

    def create_wallet_for_user(self, profile: UserProfile) -> str:
        return ""

    def get_balance(self, profile: UserProfile) -> Decimal:
        return Decimal(f'0')

    def send_money(self, from_addr: Address, to_addr: Address, amount: Decimal) -> str:
        return "" # transaction hash

Примерно такая конструкция позволит в дальнейшем подключить любое количество разных криптовалют:

@staticmethod
def get_unit(coin_symbol: str) -> CryptoUnit:
    return {
        COIN_SYMBOLS["btc"]: BtcUnit,
        COIN_SYMBOLS["eth"]: EthUnit,
        COIN_SYMBOLS["trx"]: TrxUnit,
        COIN_SYMBOLS["ton"]: TonUnit,
        ...
    }[coin_symbol]

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

Далее все упирается в каждую конкретную криптовалюту и в тонкости ее реализации - но каково же было мое удивление, когда я осознал, что все это работает практически одинаково.

Разработка

В случае с p2p обменом на первый план выходит админка. Если полуавтоматический обменник в админке нуждается веьма относительно, то в случае прямого обмена между пользователями, без нормальной и удобной админки обойтись не получится. Представим себе ситуацию, когда была задействована схема треугольник. Для тех, кто не в курсе - это популярная схема мошенничства на бирже. Мошенник открывает сделку на покупку с человеком А, а затем сделку на продажу (с другого акка, например) с человеком Б. Когда он получает платежные реквизиты для оплаты от человека А он отправляет их человеку Б, тот оплачивает, а деньги попадают на кошелек мошенника. Выявить такую схему на этапе сделки можно только внимательно изучив профиль пользователя, с которым вы эту сделку совершаете - наличие верификации, рейтинг, количество сделок. Если вы администратор такого обменника, то найти и заблокировать мошенника поможет удобная админка. В админку стоит вынести все необходимые настройки, которых может быть огромное множество! Несмотря на обманчиваю простоту - процесс p2p обмена хранит в себе не так уж и мало особенностей.

Первое, что заставит вас, как разработчика обязательно улыбнуться, это то, что у всех монет разные курсы. И если биткоин может стоить 20000$, то какой-нибудь Ripple будет стоить меньше 1 доллара. Это вносит определенного рода трудности при округлении и приведении всего барахла к единому формату. Ведь любой обменник должен уметь конвертировать курсы валют из одной в другую. Есть 4 направления, если быть точным:

  1. Крипта в крипту

  2. Крипта в фиат

  3. Фиат в крипту

  4. Фиат в фиат

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

Второе - это локализация на разные языки. Стоит обратить некоторое внимание на нюансы перевода при совершении сделки. В определенный момент времени peer1 имеет возможность отправить сообщение peer2. Это может быть как какое-то стандартное сообщение, так и личное сообщение - личная переписка. Предположим peer1 имеет локаль ru_RU, а peer2 - en_EN. В момент отправки личных сообщений peer1 должен использовать локаль от peer2 иначе второй пользователь получит сообщение на русском языке, хотя в настройках у него значится английский. Интересно - согласитесь.

Что обязательно должно работать очень надежно - так это сделка. Не очень будет здорово, если в момент совершения обмена, peer1 отправить фиатные деньги по реквизитам peer2, а у peer2 на кошельке не будет нужного количества монет. Первый пользователь окажется обманут, и его деньги лягут тяжким грузом на совесть честного администратора обменного пункта. Фиаско. Многие обменники используют механику резервирования суммы на момент совершения сделки - т.е. какая-то часть монет блокируется, и пользователь не может ее потратить. На мой взгляд, надежным решением станет полная блокировка возможности списания с кошелька пользователя, при условии наличия открытой сделки.
Активная сделка, на мой взгляд, тоже должна быть только одна.

Возможности

P2P обменник - это доска объявлений. Т.е. пользователи создают объявления (как на бирже) на покупку/продажу монет. Другие пользователи могут просматривать эти объявления и предлагать сделки. Если оба пользователя договорились о сделке, они производят обмен и сделка завершается. Т.е. сделки не может быть без объявления.

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

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

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

Пользователи должны иметь возможность настроить валюты - те в которых они планируют вести обмен и те в которых они хотят видеть текущий курс крипты. Фильтрация объявлений на доске объявлений должна происходить по первой из них. Пересчет всех значений - стоимость в обявлениях, суммы в сделках и т.п. должен происходить по второй.

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

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

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

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

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

Администратор должен иметь возможность заблокировать пользователя. После такой блокировки пользователь с этим id уже не сможет взаимодействовать с ботом.

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

Админстратор должен иметь возможность настроить все лимиты, комиссии, цены за газ, секретную фразу для подключения кошелька, а так же платежные шлюзы и фиатные валюты.

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

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

Тестирование

Сразу скажу, что самый сложный этап тестирования - этап тестирования сделки. Для сделки нужно два peer, и у каждого из них должно быть определнное состояние. Не мне вам рассказывать, что тесты бывают разные. В случае с p2p обменником, помимо привычных любимых unit тестов нам наверняка пригодятся интеграционные тесты.

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

Такие тесты имеет смысл реализовывать отдельным микросервисом, а так же добавить возмможность создавать, редактировать, запускать их из админки.

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

Инфраструктура

Раньше я как-то брезговал всякими новомодными приблудами - для большинства ваших нужд хватит и терминала. Но теперь я стал особенно ленивый и настроил простенький процесс непрерывной интеграции - это правда экономит время. Надо понимать, что обменник будет работать не только в production окружении - у него наверняка еще будут dev и stage веточки со своими серверами - а ведь в них тоже нужно как-то заливаться. Переменые окружения нужно задать таким образом, чтобы для тестовых серверов разработки использовались тестовые блокчейны, для production версии - боевые.

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

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

Ресурсы

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

Результат

У меня ушло больше 4 месяцев, чтобы сделать что-то, с чем можно работать. Это оказалось сложнее чем я думал, но опыт очень классный. Сейчас хочется продвигать и развивать проект - есть много интересных идей, которые, надеюсь, найдут свое воплощение в жизнь в ближайшее время. Результат моей скромной работы можно найти в Телеграм: @CryptedRobot

Комментарии (3)


  1. anonymous
    05.09.2022 14:26

    НЛО прилетело и опубликовало эту надпись здесь


    1. born2fish Автор
      05.09.2022 14:31

      Дело в том, что отправка криптовалюты происходит строго ПОСЛЕ получения фиатных средств и зачисления их на баланс в банке.


  1. lohabr
    05.09.2022 14:36

    ton ?