151 lines
5.4 KiB
C++
151 lines
5.4 KiB
C++
/* Copyright 2022, Michele Santullo
|
|
* This file is part of duckticker.
|
|
*
|
|
* Wrenpp is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Wrenpp is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with duckticker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "bitcoinity_ticker_price.hpp"
|
|
#include "bitcoinity_reader.hpp"
|
|
#include "configure.hpp"
|
|
|
|
#include <wrenpp/vm_fun.hpp>
|
|
#include <wrenpp/callback_manager.hpp>
|
|
#include <cstdint>
|
|
|
|
namespace duck {
|
|
|
|
const std::string_view g_bitcoinity_wren_module {
|
|
R"wren(import "ticker_price" for TickerPrice
|
|
class Bitcoinity {
|
|
foreign static ticker(currency, exchange)
|
|
foreign static ticker_quick()
|
|
foreign static ticker_currency(currency)
|
|
foreign static ticker_exchange(exchange)
|
|
}
|
|
)wren"};
|
|
|
|
namespace {
|
|
constexpr std::string_view g_dummy_currency {"EUR"};
|
|
constexpr std::string_view g_dummy_exchange {"kraken"};
|
|
|
|
void quick_ticker_price_bitcoinity_wren (wren::VM& vm) {
|
|
TickerPrice* const tp = wren::make_foreign_object<TickerPrice>(vm, "ticker_price");
|
|
*tp = bitcoinity_ticker_price(g_dummy_exchange, g_dummy_currency, BitcoinityMatchType::Any);
|
|
}
|
|
|
|
void ticker_price_bitcoinity_wren (wren::VM& vm) {
|
|
TickerPrice* const tp = wren::make_foreign_object<TickerPrice>(vm, "ticker_price");
|
|
*tp = bitcoinity_ticker_price(wren::get<const char*>(vm, 1), wren::get<const char*>(vm, 2), BitcoinityMatchType::Exact);
|
|
}
|
|
|
|
void currency_ticker_price_bitcoinity_wren (wren::VM& vm) {
|
|
TickerPrice* const tp = wren::make_foreign_object<TickerPrice>(vm, "ticker_price");
|
|
*tp = bitcoinity_ticker_price(g_dummy_exchange, wren::get<const char*>(vm, 1), BitcoinityMatchType::CurrencyOnly);
|
|
}
|
|
|
|
void exchange_ticker_price_bitcoinity_wren (wren::VM& vm) {
|
|
TickerPrice* const tp = wren::make_foreign_object<TickerPrice>(vm, "ticker_price");
|
|
*tp = bitcoinity_ticker_price(wren::get<const char*>(vm, 1), g_dummy_currency, BitcoinityMatchType::ExchangeOnly);
|
|
}
|
|
|
|
std::string make_user_agent_string() {
|
|
#if defined(DUCKTICKER_DEFAULT_USER_AGENT)
|
|
std::string retval {g_program_name};
|
|
retval += "/";
|
|
retval += g_full_version;
|
|
retval += " beast/";
|
|
retval += duck::WebsocketReader::BeastVersionString;
|
|
|
|
#else
|
|
std::string retval{g_user_agent};
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
} //unnamed namespace
|
|
|
|
TickerPrice bitcoinity_ticker_price (std::string_view exchange, std::string_view currency, BitcoinityMatchType match_type) {
|
|
duck::BitcoinityReader bitcoinity{
|
|
make_user_agent_string(),
|
|
exchange,
|
|
currency
|
|
};
|
|
|
|
do {
|
|
//possible values I observed:
|
|
// {"event":"new_msg","payload":{"data":{"currency":"EUR","exchange_name":"paymium","last":28363.44}},"ref":null,"topic":"webs:markets"}
|
|
// {"event":"new_msg","payload":{"data":{"currency":"USD","depth":{"price":30071,"type":1,"volume":-1.4123},"exchange_name":"bitfinex"}},"ref":null,"topic":"webs:markets_bitfinex_USD"}
|
|
// {"event":"new_msg","payload":{"data":{"currency":"USD","exchange_name":"bitfinex","trade":{"amount":0.0486,"date":1652471682,"exchange_name":"bitfinex","price":30072}}},"ref":null,"topic":"webs:markets_bitfinex_USD"}
|
|
|
|
double price_out;
|
|
std::uint64_t timestamp_out = 0;
|
|
std::optional<double> price;
|
|
auto msg = bitcoinity.read();
|
|
|
|
if (msg.payload.has_key("data", "depth_shot"))
|
|
continue;
|
|
|
|
if ((price = msg.payload.get_double("data", "last")))
|
|
price_out = *price;
|
|
else if ((price = msg.payload.get_double("data", "depth", "price")))
|
|
price_out = *price;
|
|
else if ((price = msg.payload.get_double("data", "trade", "price")))
|
|
price_out = *price;
|
|
else
|
|
continue; //keep trying, sometimes I get a message like:
|
|
//{"event":"new_msg","payload":{"data":{"connected_count":1355}},"ref":null,"topic":"webs:markets"}
|
|
|
|
auto timestamp = msg.payload.get_uint64("data", "trade", "date");
|
|
if (timestamp)
|
|
timestamp_out = *timestamp;
|
|
|
|
std::string_view currency_out = msg.payload.get_string_or_empty("data", "currency");
|
|
std::string_view exchange_out = msg.payload.get_string_or_empty("data", "exchange_name");
|
|
switch (match_type) {
|
|
case BitcoinityMatchType::Any:
|
|
break;
|
|
case BitcoinityMatchType::Exact:
|
|
if (currency_out != currency or exchange_out != exchange)
|
|
continue; //wait 'til we get a better match
|
|
break;
|
|
case BitcoinityMatchType::CurrencyOnly:
|
|
if (currency_out != currency)
|
|
continue;
|
|
break;
|
|
case BitcoinityMatchType::ExchangeOnly:
|
|
if (exchange_out != exchange)
|
|
continue;
|
|
break;
|
|
}
|
|
|
|
return TickerPrice{
|
|
price_out,
|
|
timestamp_out,
|
|
std::string(currency_out),
|
|
std::string(exchange_out)
|
|
};
|
|
} while (true);
|
|
}
|
|
|
|
void register_bitcoinity_to_wren (wren::VM& vm) {
|
|
vm.callback_manager()
|
|
.add_callback(true, "bitcoinity", "Bitcoinity", "ticker(_,_)", &ticker_price_bitcoinity_wren)
|
|
.add_callback(true, "bitcoinity", "Bitcoinity", "ticker_quick()", &quick_ticker_price_bitcoinity_wren)
|
|
.add_callback(true, "bitcoinity", "Bitcoinity", "ticker_currency(_)", ¤cy_ticker_price_bitcoinity_wren)
|
|
.add_callback(true, "bitcoinity", "Bitcoinity", "ticker_exchange(_)", &exchange_ticker_price_bitcoinity_wren);
|
|
|
|
register_ticker_price_to_wren(vm);
|
|
}
|
|
} //namespace duck
|