Skip to content

Commit 123556f

Browse files
Progress bitshares#1604: Basic implementation
Define and implement the limit_order_update_operation. Still needs testing.
1 parent 5503152 commit 123556f

File tree

4 files changed

+109
-2
lines changed

4 files changed

+109
-2
lines changed

libraries/chain/include/graphene/chain/market_evaluator.hpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ namespace graphene { namespace chain {
6363
const asset_object* _receive_asset = nullptr;
6464
};
6565

66+
class limit_order_update_evaluator : public evaluator<limit_order_update_operation>
67+
{
68+
public:
69+
using operation_type = limit_order_update_operation;
70+
71+
void_result do_evaluate(const limit_order_update_operation& o);
72+
void_result do_apply(const limit_order_update_operation& o);
73+
74+
const limit_order_object* _order = nullptr;
75+
};
76+
6677
class limit_order_cancel_evaluator : public evaluator<limit_order_cancel_evaluator>
6778
{
6879
public:
@@ -71,7 +82,7 @@ namespace graphene { namespace chain {
7182
void_result do_evaluate( const limit_order_cancel_operation& o );
7283
asset do_apply( const limit_order_cancel_operation& o );
7384

74-
const limit_order_object* _order;
85+
const limit_order_object* _order = nullptr;
7586
};
7687

7788
class call_order_update_evaluator : public evaluator<call_order_update_evaluator>

libraries/chain/include/graphene/chain/protocol/market.hpp

+31
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,35 @@ namespace graphene { namespace chain {
7373
price get_price()const { return amount_to_sell / min_to_receive; }
7474
};
7575

76+
/**
77+
* @ingroup operations
78+
* Used to update an existing limit order.
79+
*
80+
* Charges a higher fee if @ref delta_amount_to_sell is set, as this requires updating
81+
* the account balance as well as the order object.
82+
*/
83+
struct limit_order_update_operation : public base_operation
84+
{
85+
struct fee_parameters_type {
86+
uint64_t price_fee = GRAPHENE_BLOCKCHAIN_PRECISION / 2;
87+
uint64_t amount_fee = GRAPHENE_BLOCKCHAIN_PRECISION;
88+
};
89+
90+
asset fee;
91+
account_id_type seller;
92+
limit_order_id_type order;
93+
optional<price> new_price;
94+
optional<asset> delta_amount_to_sell;
95+
optional<time_point_sec> new_expiration;
96+
97+
extensions_type extensions;
98+
99+
account_id_type fee_payer() { return seller; }
100+
void validate() const;
101+
share_type calculate_fee(const fee_parameters_type& k) const {
102+
return delta_amount_to_sell? k.amount_fee : k.price_fee;
103+
}
104+
};
76105

77106
/**
78107
* @ingroup operations
@@ -219,6 +248,7 @@ namespace graphene { namespace chain {
219248
} } // graphene::chain
220249

221250
FC_REFLECT( graphene::chain::limit_order_create_operation::fee_parameters_type, (fee) )
251+
FC_REFLECT( graphene::chain::limit_order_update_operation::fee_parameters_type, (price_fee)(amount_fee) )
222252
FC_REFLECT( graphene::chain::limit_order_cancel_operation::fee_parameters_type, (fee) )
223253
FC_REFLECT( graphene::chain::call_order_update_operation::fee_parameters_type, (fee) )
224254
FC_REFLECT( graphene::chain::bid_collateral_operation::fee_parameters_type, (fee) )
@@ -230,6 +260,7 @@ FC_REFLECT( graphene::chain::call_order_update_operation::options_type, (target_
230260
FC_REFLECT_TYPENAME( graphene::chain::call_order_update_operation::extensions_type )
231261

232262
FC_REFLECT( graphene::chain::limit_order_create_operation,(fee)(seller)(amount_to_sell)(min_to_receive)(expiration)(fill_or_kill)(extensions))
263+
FC_REFLECT( graphene::chain::limit_order_update_operation,(fee)(seller)(order)(new_price)(delta_amount_to_sell)(new_expiration)(extensions))
233264
FC_REFLECT( graphene::chain::limit_order_cancel_operation,(fee)(fee_paying_account)(order)(extensions) )
234265
FC_REFLECT( graphene::chain::call_order_update_operation, (fee)(funding_account)(delta_collateral)(delta_debt)(extensions) )
235266
FC_REFLECT( graphene::chain::fill_order_operation, (fee)(order_id)(account_id)(pays)(receives)(fill_price)(is_maker) )

libraries/chain/market_evaluator.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,58 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o
126126
return order_id;
127127
} FC_CAPTURE_AND_RETHROW( (op) ) }
128128

129+
void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o)
130+
{ try {
131+
const database& d = db();
132+
_order = &o.order(d);
133+
134+
// Check this is my order
135+
FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order");
136+
137+
// Check new price is compatible
138+
if (o.new_price)
139+
FC_ASSERT(o.new_price->base.asset_id == _order->sell_price.base.asset_id &&
140+
o.new_price->quote.asset_id == _order->sell_price.quote.asset_id,
141+
"Cannot update limit order with incompatible price");
142+
143+
// Check delta asset is compatible
144+
if (o.delta_amount_to_sell) {
145+
const auto& delta = *o.delta_amount_to_sell;
146+
FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id,
147+
"Cannot update limit order with incompatible asset");
148+
if (delta.amount > 0)
149+
FC_ASSERT(d.get_balance(o.seller, delta.asset_id) > delta,
150+
"Insufficient balance to increase order amount");
151+
else
152+
FC_ASSERT(_order->for_sale > -delta.amount,
153+
"Cannot deduct more from order than order contains");
154+
}
155+
156+
// Check expiration is in the future
157+
if (o.new_expiration)
158+
FC_ASSERT(*o.new_expiration >= d.head_block_time(),
159+
"Cannot update limit order with past expiration");
160+
} FC_CAPTURE_AND_RETHROW((o)) }
161+
162+
void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o)
163+
{ try {
164+
database& d = db();
165+
166+
// Adjust account balance
167+
if (o.delta_amount_to_sell)
168+
d.adjust_balance(o.seller, *o.delta_amount_to_sell);
169+
170+
// Update order
171+
d.modify(*_order, [&o](limit_order_object& loo) {
172+
if (o.new_price)
173+
loo.sell_price = *o.new_price;
174+
if (o.delta_amount_to_sell)
175+
loo.for_sale += o.delta_amount_to_sell->amount;
176+
if (o.new_expiration)
177+
loo.expiration = *o.new_expiration;
178+
});
179+
} FC_CAPTURE_AND_RETHROW((o)) }
180+
129181
void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o)
130182
{ try {
131183
database& d = db();

libraries/chain/protocol/market.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ void limit_order_create_operation::validate()const
3333
FC_ASSERT( min_to_receive.amount > 0 );
3434
}
3535

36+
void limit_order_update_operation::validate() const
37+
{
38+
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
39+
FC_ASSERT(new_price || delta_amount_to_sell || new_expiration,
40+
"Cannot update limit order if nothing is specified to update");
41+
if (new_price)
42+
new_price->validate();
43+
if (delta_amount_to_sell)
44+
FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero");
45+
}
46+
3647
void limit_order_cancel_operation::validate()const
3748
{
3849
FC_ASSERT( fee.amount >= 0 );
@@ -54,4 +65,6 @@ void bid_collateral_operation::validate()const
5465
FC_ASSERT( debt_covered.amount == 0 || (debt_covered.amount > 0 && additional_collateral.amount > 0) );
5566
} FC_CAPTURE_AND_RETHROW((*this)) }
5667

57-
} } // graphene::chain
68+
}
69+
70+
} // graphene::chain

0 commit comments

Comments
 (0)