Работаем с API биржи EXMO


Криптовалютная биржа Exmo (как и другие крупные биржи) предоставляет пользователям  два интерфейса для взаимодействия с его серверами:

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

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

Алгоритм получается следующий:
  1. Запрос балансов валют в кошельке
  2. Запрос текущих средних курсов обмена на рубли
  3. Поочередное умножение балансов на их рублёвые курсы с вычетом комиссии за сделку
  4. Сложение полученных в п. 3 чисел
  5. Вычет из суммы комиссии за вывод средств на Яндекс.Деньги

Запрос курсов валют на Exmo не требует регистрации на портале, однако для получения балансов кошелька потребуются API-ключи аккаунта, их можно найти в настройках профиля.



Реализовывать скрипт будем на Ruby.

Для работы понадобятся следующие библиотеки:
require 'net/https'
require 'uri'
require 'json'

Опишем класс Exmo и его метод initialize, в котором объявляются переменные класса, содержащие API-ключи
class Exmo
    def initialize(key,secret)
        @KEY = key
        @SECRET = secret
    end

В двух пунктах алгоритма фигурирует запрос к API. Дабы не повторяться в коде сделаем запрос отдельным методом, и далее просто будем обращаться к нему с разными аргументами, которыми послужат:
  1. название метода (trades - на получение сделок, ticker - статистика цен, и т.д.) - обязательный параметр
  2. параметры, например валюта + цена + объем для метода order_create (для создания ордера на покупку/продажу)
    def request(method, params = {})

Далее для авторизованных запросов требуется специальное число nonce:
Дополнительно во всех запросах должен находиться обязательный POST-параметр nonce с инкрементным числовым значением (>0). Это значение не должно повторяться или уменьшаться.

Для этого возьмем текущую дату-время и преобразуем в целое число, таким образом не придется хранить предыдущее число. Сразу же добавим nonce в хэш параметров
        nonce = Time.now.strftime("%s%6N")
        params['nonce'] = nonce

Далее распарсим экшен, обрабатывающий API-запросы
URL — необходимо использовать следующий адрес https://api.exmo.com/v1/{api_name} где api_name - это наименование API метода
api_name хранится в переменной method полученных аргументов
        uri = URI.parse(['https://api.exmo.com/v1', method].join('/'))
        post_data = URI.encode_www_form(params)

Создадим заголовки запроса и добавим их в хэш headers
Авторизация осуществляется с помощью отправки на сервер следующих заголовков:
Key — Публичный ключ, его нужно взять настройках профиля пользователя
(пример: K-7cc97c89aed2a2fd9ed7792d48d63f65800c447b)
Sign — POST данные (param=val&param1=val1), подписанные секретным ключом методом HMAC-SHA512, секретный ключ также нужно брать в настройках профиля пользователя

        digest = OpenSSL::Digest.new('sha512')
        sign = OpenSSL::HMAC.hexdigest(digest, @SECRET, post_data)
        headers = {'Sign' => sign, 'Key'  => @KEY}

Далее создадим объекты http и req класса Net
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true if uri.scheme == 'https'
        req = Net::HTTP::Post.new(uri.path, headers)
        req.body = post_data

Отправляем запрос и парсим ответ в объект JSON
        response = http.request(req)
        JSON.load response.body.to_s
     end

В итоге получаем следующий код:

Проверим работу метода request: получим ордера на сделки валютной пары BTC/RUB и выведем первый элемент массива
KEY    = "K-dnugio89hgu54h48systopthebest9uh556i94h54jhp49"    
SECRET = "S-mekgnbehappy4h8j6hijrtpgh498hji54of56uho4ihjtu94hj"
exmo = Exmo.new(KEY, SECRET)
puts exmo.request("trades",{pair: "BTC_USD"})["BTC_USD"][0]

Алгоритм:
  1. Запрос балансов валют в кошельке
  2. Запрос текущих средних курсов обмена на рубли
  3. Поочередное умножение балансов на их рублёвые курсы с вычетом комиссии за сделку
  4. Сложение полученных в п. 3 чисел
  5. Вычет из суммы комиссии за вывод средств на Яндекс.Деньги

Для остальных пунктов алгоритма создадим отдельный метод get_summ_in_rubles в классе Exmo:
    def get_summ_in_rubles

Обратимся к методу request и получим балансы криптовалют на кошельке (user_info) и статистику цен (ticker):
        user_info = request("user_info")
        ticker = request('ticker')

Обнуляем переменную суммы денег и запускаем цикл перебора хеша с балансами кошелька:
        yandex_rub = 0.0
        user_info["balances"].each do |key,val|

В случае, если баланс текущей в цикле валюты не равен нулю, то записываем в переменную price стоимость этой валюты в рублях, взятую из хэша ticker
            unless val == "0"
                price = ticker["#{key}_RUB"]["avg"]

Получаем рублевый эквивалент баланса текущей валюты из произведения величины баланса на стоимость. Вычитаем 0,2% комиссию за сделку:
                summ = val.to_f * price.to_f # summ in rubles
                summ -= summ*0.002 # summ in rubles after exchange

Прибавляем полученное значение к общей сумме и закрываем условие и цикл перебора
                yandex_rub += summ
            end
        end

Вычитаем комиссию 3% за вывод на Яндекс.Деньги и закрываем метод
        yandex_rub -= yandex_rub*0.03 # RUBLES after withdraw
    end

Проверим:

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


Полный код:
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.