peerplays_migrated/libraries/chain/limit_order_evaluator.cpp

103 lines
4.6 KiB
C++
Raw Normal View History

2015-06-08 15:50:35 +00:00
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <graphene/chain/limit_order_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <fc/uint128.hpp>
namespace graphene { namespace chain {
void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_operation& op)
2015-06-23 21:33:06 +00:00
{ try {
2015-06-08 15:50:35 +00:00
database& d = db();
FC_ASSERT( op.expiration >= d.head_block_time() );
_seller = this->fee_paying_account;
_sell_asset = &op.amount_to_sell.asset_id(d);
_receive_asset = &op.min_to_receive.asset_id(d);
if( _sell_asset->options.whitelist_markets.size() )
FC_ASSERT( _sell_asset->options.whitelist_markets.find(_receive_asset->id) != _sell_asset->options.whitelist_markets.end() );
2015-06-08 15:50:35 +00:00
if( _sell_asset->options.blacklist_markets.size() )
FC_ASSERT( _sell_asset->options.blacklist_markets.find(_receive_asset->id) == _sell_asset->options.blacklist_markets.end() );
2015-06-08 15:50:35 +00:00
if( _sell_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_sell_asset ) );
if( _receive_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_receive_asset ) );
FC_ASSERT( d.get_balance( *_seller, *_sell_asset ) >= op.amount_to_sell, "insufficient balance",
("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) );
2015-06-08 15:50:35 +00:00
2015-06-23 21:33:06 +00:00
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
2015-06-08 15:50:35 +00:00
object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_operation& op)
2015-06-23 21:33:06 +00:00
{ try {
2015-06-08 15:50:35 +00:00
const auto& seller_stats = _seller->statistics(db());
db().modify(seller_stats, [&](account_statistics_object& bal) {
2015-06-08 15:50:35 +00:00
if( op.amount_to_sell.asset_id == asset_id_type() )
{
bal.total_core_in_orders += op.amount_to_sell.amount;
}
});
db().adjust_balance(op.seller, -op.amount_to_sell);
const auto& new_order_object = db().create<limit_order_object>([&](limit_order_object& obj){
2015-06-08 15:50:35 +00:00
obj.seller = _seller->id;
obj.for_sale = op.amount_to_sell.amount;
obj.sell_price = op.get_price();
obj.expiration = op.expiration;
});
limit_order_id_type order_id = new_order_object.id; // save this because we may remove the object by filling it
bool filled = db().apply_order(new_order_object);
FC_ASSERT( !op.fill_or_kill || filled );
return order_id;
2015-06-23 21:33:06 +00:00
} FC_CAPTURE_AND_RETHROW( (op) ) }
2015-06-08 15:50:35 +00:00
void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o)
2015-06-23 21:33:06 +00:00
{ try {
database& d = db();
2015-06-08 15:50:35 +00:00
_order = &o.order(d);
2015-06-23 21:33:06 +00:00
FC_ASSERT( _order->seller == o.fee_paying_account );
2015-06-08 15:50:35 +00:00
2015-06-23 21:33:06 +00:00
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
2015-06-08 15:50:35 +00:00
asset limit_order_cancel_evaluator::do_apply(const limit_order_cancel_operation& o)
2015-06-23 21:33:06 +00:00
{ try {
database& d = db();
2015-06-08 15:50:35 +00:00
auto base_asset = _order->sell_price.base.asset_id;
auto quote_asset = _order->sell_price.quote.asset_id;
auto refunded = _order->amount_for_sale();
db().cancel_order(*_order, false /* don't create a virtual op*/);
2015-06-08 15:50:35 +00:00
// Possible optimization: order can be called by canceling a limit order iff the canceled order was at the top of the book.
// Do I need to check calls in both assets?
db().check_call_orders(base_asset(d));
db().check_call_orders(quote_asset(d));
return refunded;
2015-06-23 21:33:06 +00:00
} FC_CAPTURE_AND_RETHROW( (o) ) }
2015-06-08 15:50:35 +00:00
} } // graphene::chain