Fixed to follow QUOTE:BASE semantics. Cleanup and added in wallet calls that were missed in last merge. #592
This commit is contained in:
parent
a675023b9f
commit
4b346579a8
4 changed files with 286 additions and 126 deletions
|
|
@ -31,6 +31,8 @@
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
|
|
||||||
#include <boost/range/iterator_range.hpp>
|
#include <boost/range/iterator_range.hpp>
|
||||||
|
#include <boost/rational.hpp>
|
||||||
|
#include <boost/multiprecision/cpp_int.hpp>
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
|
|
@ -1025,56 +1027,37 @@ market_ticker database_api_impl::get_ticker( const string& base, const string& q
|
||||||
try {
|
try {
|
||||||
if( base_id > quote_id ) std::swap(base_id, quote_id);
|
if( base_id > quote_id ) std::swap(base_id, quote_id);
|
||||||
|
|
||||||
const auto& bidx = _db.get_index_type<bucket_index>();
|
uint32_t day = 86400;
|
||||||
const auto& by_key_idx = bidx.indices().get<by_key>();
|
|
||||||
uint32_t bucket_size = 86400;
|
|
||||||
auto now = fc::time_point_sec( fc::time_point::now() );
|
auto now = fc::time_point_sec( fc::time_point::now() );
|
||||||
|
|
||||||
auto itr = by_key_idx.lower_bound( bucket_key( base_id, quote_id, bucket_size,
|
|
||||||
now - bucket_size ) );
|
|
||||||
|
|
||||||
auto orders = get_order_book( base, quote, 1 );
|
auto orders = get_order_book( base, quote, 1 );
|
||||||
|
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
|
||||||
|
|
||||||
if( itr != by_key_idx.end() && itr->key.base == base_id && itr->key.quote == quote_id && itr->key.seconds == bucket_size )
|
|
||||||
{
|
|
||||||
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
|
||||||
|
|
||||||
if (assets[0]->id == base_id)
|
|
||||||
{
|
|
||||||
result.latest = trades[0].price;
|
result.latest = trades[0].price;
|
||||||
result.percent_change = ( result.latest / ( price_to_real( itr->open_quote, assets[1]->precision ) / price_to_real( itr->open_base, assets[0]->precision ) ) - 1 ) * 100;
|
|
||||||
//result.lowest_ask = price_to_real( itr->low_quote, assets[1]->precision ) / price_to_real( itr->low_base, assets[0]->precision );
|
|
||||||
//result.highest_bid = price_to_real( itr->high_quote, assets[1]->precision ) / price_to_real( itr->high_base, assets[0]->precision );
|
|
||||||
result.lowest_ask = orders.asks[0].first;
|
|
||||||
result.highest_bid = orders.bids[0].first;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.latest = trades[0].price;
|
|
||||||
result.percent_change = ( result.latest / ( price_to_real( itr->open_base, assets[1]->precision ) / price_to_real( itr->open_quote, assets[0]->precision ) ) - 1) * 100;
|
|
||||||
//result.lowest_ask = price_to_real( itr->low_base, assets[1]->precision ) / price_to_real( itr->low_quote, assets[0]->precision );
|
|
||||||
//result.highest_bid = price_to_real( itr->high_base, assets[1]->precision ) / price_to_real( itr->high_quote, assets[0]->precision );
|
|
||||||
result.lowest_ask = orders.bids[0].first;
|
|
||||||
result.highest_bid = orders.asks[0].first;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( market_trade t: trades )
|
for ( market_trade t: trades )
|
||||||
{
|
{
|
||||||
result.base_volume += t.amount;
|
result.base_volume += t.value;
|
||||||
result.quote_volume += t.value;
|
result.quote_volume += t.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (trades.size() == 100)
|
while (trades.size() == 100)
|
||||||
{
|
{
|
||||||
|
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
|
||||||
|
|
||||||
for ( market_trade t: trades )
|
for ( market_trade t: trades )
|
||||||
{
|
{
|
||||||
result.base_volume += t.amount;
|
result.base_volume += t.value;
|
||||||
result.quote_volume += t.value;
|
result.quote_volume += t.amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
trades = get_trade_history( base, quote, trades.back().date, fc::time_point_sec(), 1 );
|
||||||
}
|
result.percent_change = trades.size() > 0 ? ( ( result.latest / trades.back().price ) - 1 ) * 100 : 0;
|
||||||
|
|
||||||
|
//if (assets[0]->id == base_id)
|
||||||
|
{
|
||||||
|
result.lowest_ask = orders.asks[0].price;
|
||||||
|
result.highest_bid = orders.bids[0].price;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1111,19 +1094,19 @@ market_volume database_api_impl::get_24_volume( const string& base, const string
|
||||||
|
|
||||||
for ( market_trade t: trades )
|
for ( market_trade t: trades )
|
||||||
{
|
{
|
||||||
result.base_volume += t.amount;
|
result.base_volume += t.value;
|
||||||
result.quote_volume += t.value;
|
result.quote_volume += t.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (trades.size() == 100)
|
while (trades.size() == 100)
|
||||||
{
|
{
|
||||||
|
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
||||||
|
|
||||||
for ( market_trade t: trades )
|
for ( market_trade t: trades )
|
||||||
{
|
{
|
||||||
result.base_volume += t.amount;
|
result.base_volume += t.value;
|
||||||
result.quote_volume += t.value;
|
result.quote_volume += t.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1137,6 +1120,7 @@ order_book database_api::get_order_book( const string& base, const string& quote
|
||||||
|
|
||||||
order_book database_api_impl::get_order_book( const string& base, const string& quote, unsigned limit )const
|
order_book database_api_impl::get_order_book( const string& base, const string& quote, unsigned limit )const
|
||||||
{
|
{
|
||||||
|
using boost::multiprecision::uint128_t;
|
||||||
FC_ASSERT( limit <= 50 );
|
FC_ASSERT( limit <= 50 );
|
||||||
|
|
||||||
order_book result;
|
order_book result;
|
||||||
|
|
@ -1156,21 +1140,28 @@ order_book database_api_impl::get_order_book( const string& base, const string&
|
||||||
auto price_to_real = [&]( const price& p )
|
auto price_to_real = [&]( const price& p )
|
||||||
{
|
{
|
||||||
if( p.base.asset_id == base_id )
|
if( p.base.asset_id == base_id )
|
||||||
return asset_to_real( p.quote, assets[1]->precision ) / asset_to_real( p.base, assets[0]->precision );
|
return asset_to_real( p.base, assets[0]->precision ) / asset_to_real( p.quote, assets[1]->precision );
|
||||||
else
|
else
|
||||||
return asset_to_real( p.base, assets[1]->precision ) / asset_to_real( p.quote, assets[0]->precision );
|
return asset_to_real( p.quote, assets[0]->precision ) / asset_to_real( p.base, assets[1]->precision );
|
||||||
};
|
};
|
||||||
|
|
||||||
for( const auto& o : orders ) {
|
for( const auto& o : orders )
|
||||||
|
{
|
||||||
if( o.sell_price.base.asset_id == base_id )
|
if( o.sell_price.base.asset_id == base_id )
|
||||||
{
|
{
|
||||||
result.asks.push_back( std::make_pair( price_to_real(o.sell_price),
|
order ord;
|
||||||
asset_to_real(o.sell_price.base, assets[0]->precision)) );
|
ord.price = price_to_real( o.sell_price );
|
||||||
|
ord.quote = asset_to_real( share_type( ( uint128_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ), assets[1]->precision );
|
||||||
|
ord.base = asset_to_real( o.for_sale, assets[0]->precision );
|
||||||
|
result.bids.push_back( ord );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.bids.push_back( std::make_pair( price_to_real(o.sell_price),
|
order ord;
|
||||||
asset_to_real(o.sell_price.quote, assets[0]->precision ) ) );
|
ord.price = price_to_real( o.sell_price );
|
||||||
|
ord.quote = asset_to_real( o.for_sale, assets[1]->precision );
|
||||||
|
ord.base = asset_to_real( share_type( ( uint64_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ), assets[0]->precision );
|
||||||
|
result.asks.push_back( ord );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1225,13 +1216,13 @@ vector<market_trade> database_api_impl::get_trade_history( const string& base,
|
||||||
|
|
||||||
if( assets[0]->id == itr->op.receives.asset_id )
|
if( assets[0]->id == itr->op.receives.asset_id )
|
||||||
{
|
{
|
||||||
trade.amount = price_to_real( itr->op.receives.amount, assets[0]->precision );
|
trade.amount = price_to_real( itr->op.pays.amount, assets[1]->precision );
|
||||||
trade.value = price_to_real( itr->op.pays.amount, assets[1]->precision );
|
trade.value = price_to_real( itr->op.receives.amount, assets[0]->precision );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trade.amount = price_to_real( itr->op.pays.amount, assets[0]->precision );
|
trade.amount = price_to_real( itr->op.receives.amount, assets[1]->precision );
|
||||||
trade.value = price_to_real( itr->op.receives.amount, assets[1]->precision );
|
trade.value = price_to_real( itr->op.pays.amount, assets[0]->precision );
|
||||||
}
|
}
|
||||||
|
|
||||||
trade.date = itr->time;
|
trade.date = itr->time;
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,19 @@ using namespace std;
|
||||||
|
|
||||||
class database_api_impl;
|
class database_api_impl;
|
||||||
|
|
||||||
|
struct order
|
||||||
|
{
|
||||||
|
double price;
|
||||||
|
double quote;
|
||||||
|
double base;
|
||||||
|
};
|
||||||
|
|
||||||
struct order_book
|
struct order_book
|
||||||
{
|
{
|
||||||
string base;
|
string base;
|
||||||
string quote;
|
string quote;
|
||||||
vector< pair<double,double> > bids;
|
vector< order > bids;
|
||||||
vector< pair<double,double> > asks;
|
vector< order > asks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct market_ticker
|
struct market_ticker
|
||||||
|
|
@ -553,6 +560,8 @@ class database_api
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::app::order, (price)(quote)(base) );
|
||||||
FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) );
|
FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) );
|
||||||
FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) );
|
FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) );
|
||||||
FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) );
|
FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) );
|
||||||
|
|
|
||||||
|
|
@ -850,6 +850,51 @@ class wallet_api
|
||||||
bool fill_or_kill = false,
|
bool fill_or_kill = false,
|
||||||
bool broadcast = false);
|
bool broadcast = false);
|
||||||
|
|
||||||
|
/** Place a limit order attempting to sell one asset for another.
|
||||||
|
*
|
||||||
|
* This API call abstracts away some of the details of the sell_asset call to be more
|
||||||
|
* user friendly. All orders placed with sell never timeout and will not be killed if they
|
||||||
|
* cannot be filled immediately. If you wish for one of these parameters to be different,
|
||||||
|
* then sell_asset should be used instead.
|
||||||
|
*
|
||||||
|
* @param seller_account the account providing the asset being sold, and which will
|
||||||
|
* receive the processed of the sale.
|
||||||
|
* @param base The name or id of the asset to sell.
|
||||||
|
* @param quote The name or id of the asset to recieve.
|
||||||
|
* @param rate The rate in base:quote at which you want to sell.
|
||||||
|
* @param amount The amount of base you want to sell.
|
||||||
|
* @param broadcast true to broadcast the transaction on the network.
|
||||||
|
* @returns The signed transaction selling the funds.
|
||||||
|
*/
|
||||||
|
signed_transaction sell( string seller_account,
|
||||||
|
string base,
|
||||||
|
string quote,
|
||||||
|
double rate,
|
||||||
|
double amount,
|
||||||
|
bool broadcast );
|
||||||
|
|
||||||
|
/** Place a limit order attempting to buy one asset with another.
|
||||||
|
*
|
||||||
|
* This API call abstracts away some of the details of the sell_asset call to be more
|
||||||
|
* user friendly. All orders placed with buy never timeout and will not be killed if they
|
||||||
|
* cannot be filled immediately. If you wish for one of these parameters to be different,
|
||||||
|
* then sell_asset should be used instead.
|
||||||
|
*
|
||||||
|
* @param buyer_account The account buying the asset for another asset.
|
||||||
|
* @param base The name or id of the asset to buy.
|
||||||
|
* @param quote The name or id of the assest being offered as payment.
|
||||||
|
* @param rate The rate in base:quote at which you want to buy.
|
||||||
|
* @param amount the amount of base you want to buy.
|
||||||
|
* @param broadcast true to broadcast the transaction on the network.
|
||||||
|
* @param The signed transaction selling the funds.
|
||||||
|
*/
|
||||||
|
signed_transaction buy( string buyer_account,
|
||||||
|
string base,
|
||||||
|
string quote,
|
||||||
|
double rate,
|
||||||
|
double amount,
|
||||||
|
bool broadcast );
|
||||||
|
|
||||||
/** Borrow an asset or update the debt/collateral ratio for the loan.
|
/** Borrow an asset or update the debt/collateral ratio for the loan.
|
||||||
*
|
*
|
||||||
* This is the first step in shorting an asset. Call \c sell_asset() to complete the short.
|
* This is the first step in shorting an asset. Call \c sell_asset() to complete the short.
|
||||||
|
|
@ -1402,6 +1447,8 @@ class wallet_api
|
||||||
bool broadcast /* = false */
|
bool broadcast /* = false */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
order_book get_order_book( const string& base, const string& quote, unsigned limit = 50);
|
||||||
|
|
||||||
void dbg_make_uia(string creator, string symbol);
|
void dbg_make_uia(string creator, string symbol);
|
||||||
void dbg_make_mia(string creator, string symbol);
|
void dbg_make_mia(string creator, string symbol);
|
||||||
void flood_network(string prefix, uint32_t number_of_transactions);
|
void flood_network(string prefix, uint32_t number_of_transactions);
|
||||||
|
|
@ -1517,6 +1564,8 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(upgrade_account)
|
(upgrade_account)
|
||||||
(create_account_with_brain_key)
|
(create_account_with_brain_key)
|
||||||
(sell_asset)
|
(sell_asset)
|
||||||
|
(sell)
|
||||||
|
(buy)
|
||||||
(borrow_asset)
|
(borrow_asset)
|
||||||
(cancel_order)
|
(cancel_order)
|
||||||
(transfer)
|
(transfer)
|
||||||
|
|
@ -1589,4 +1638,5 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(blind_transfer)
|
(blind_transfer)
|
||||||
(blind_history)
|
(blind_history)
|
||||||
(receive_blind_transfer)
|
(receive_blind_transfer)
|
||||||
|
(get_order_book)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2166,6 +2166,89 @@ public:
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
};
|
};
|
||||||
|
m["get_order_book"] = [this](variant result, const fc::variants& a)
|
||||||
|
{
|
||||||
|
auto orders = result.as<order_book>();
|
||||||
|
auto bids = orders.bids;
|
||||||
|
auto asks = orders.asks;
|
||||||
|
std::stringstream ss;
|
||||||
|
std::stringstream sum_stream;
|
||||||
|
sum_stream << "Sum(" << orders.base << ')';
|
||||||
|
double bid_sum = 0;
|
||||||
|
double ask_sum = 0;
|
||||||
|
const int spacing = 20;
|
||||||
|
|
||||||
|
auto prettify_num = [&]( double n )
|
||||||
|
{
|
||||||
|
//ss << n;
|
||||||
|
if (abs( round( n ) - n ) < 0.00000000001 )
|
||||||
|
{
|
||||||
|
ss << setiosflags( !ios::fixed ) << (int) n;
|
||||||
|
}
|
||||||
|
else if (n - floor(n) < 0.000001)
|
||||||
|
{
|
||||||
|
ss << setiosflags( ios::fixed ) << setprecision(10) << n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << setiosflags( ios::fixed ) << setprecision(6) << n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ss << setprecision( 8 ) << setiosflags( ios::fixed ) << setiosflags( ios::left );
|
||||||
|
|
||||||
|
ss << ' ' << setw( (spacing * 4) + 6 ) << "BUY ORDERS" << "SELL ORDERS\n"
|
||||||
|
<< ' ' << setw( spacing + 1 ) << "Price" << setw( spacing ) << orders.quote << ' ' << setw( spacing )
|
||||||
|
<< orders.base << ' ' << setw( spacing ) << sum_stream.str()
|
||||||
|
<< " " << setw( spacing + 1 ) << "Price" << setw( spacing ) << orders.quote << ' ' << setw( spacing )
|
||||||
|
<< orders.base << ' ' << setw( spacing ) << sum_stream.str()
|
||||||
|
<< "\n====================================================================================="
|
||||||
|
<< "|=====================================================================================\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < bids.size() || i < asks.size() ; i++)
|
||||||
|
{
|
||||||
|
if ( i < bids.size() )
|
||||||
|
{
|
||||||
|
bid_sum += bids[i].base;
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( bids[i].price );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( bids[i].quote );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( bids[i].base );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( bid_sum );
|
||||||
|
ss << ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << setw( (spacing * 4) + 5 ) << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << '|';
|
||||||
|
|
||||||
|
if ( i < asks.size() )
|
||||||
|
{
|
||||||
|
ask_sum += asks[i].base;
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( asks[i].price );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( asks[i].quote );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( asks[i].base );
|
||||||
|
ss << ' ' << setw( spacing );
|
||||||
|
prettify_num( ask_sum );
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << endl
|
||||||
|
<< "Buy Total: " << bid_sum << ' ' << orders.base << endl
|
||||||
|
<< "Sell Total: " << ask_sum << ' ' << orders.base << endl;
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
};
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
@ -3552,6 +3635,28 @@ signed_transaction wallet_api::sell_asset(string seller_account,
|
||||||
symbol_to_receive, expiration, fill_or_kill, broadcast);
|
symbol_to_receive, expiration, fill_or_kill, broadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::sell( string seller_account,
|
||||||
|
string base,
|
||||||
|
string quote,
|
||||||
|
double rate,
|
||||||
|
double amount,
|
||||||
|
bool broadcast )
|
||||||
|
{
|
||||||
|
return my->sell_asset( seller_account, std::to_string( amount ), base,
|
||||||
|
std::to_string( rate * amount ), quote, 0, false, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::buy( string buyer_account,
|
||||||
|
string base,
|
||||||
|
string quote,
|
||||||
|
double rate,
|
||||||
|
double amount,
|
||||||
|
bool broadcast )
|
||||||
|
{
|
||||||
|
return my->sell_asset( buyer_account, std::to_string( rate * amount ), quote,
|
||||||
|
std::to_string( amount ), base, 0, false, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
signed_transaction wallet_api::borrow_asset(string seller_name, string amount_to_sell,
|
signed_transaction wallet_api::borrow_asset(string seller_name, string amount_to_sell,
|
||||||
string asset_symbol, string amount_of_collateral, bool broadcast)
|
string asset_symbol, string amount_of_collateral, bool broadcast)
|
||||||
{
|
{
|
||||||
|
|
@ -4091,6 +4196,11 @@ vector<blind_receipt> wallet_api::blind_history( string key_or_account )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
order_book wallet_api::get_order_book( const string& base, const string& quote, unsigned limit )
|
||||||
|
{
|
||||||
|
return( my->_remote_db->get_order_book( base, quote, limit ) );
|
||||||
|
}
|
||||||
|
|
||||||
signed_block_with_info::signed_block_with_info( const signed_block& block )
|
signed_block_with_info::signed_block_with_info( const signed_block& block )
|
||||||
: signed_block( block )
|
: signed_block( block )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue