Flex
Flex exchange system
dealer.hpp
Go to the documentation of this file.
1 
9 #pragma once
10 
11 #include "../PriceXchg.hpp"
12 #include "../FlexTransferPayloadArgs.hpp"
13 #include "process_queue_state.hpp"
14 #include "xchg_iterator.hpp"
15 
16 #include <tvm/suffixes.hpp>
17 #include <tvm/schema/build_chain_static.hpp>
18 
19 namespace tvm { namespace xchg {
20 
22 class dealer {
23 public:
25  price_t price,
26  address pair,
27  Tip3Config major_tip3cfg,
28  Tip3Config minor_tip3cfg,
29  EversConfig ev_cfg,
30  orders_queue sells,
31  orders_queue buys,
32  uint128 min_amount,
33  unsigned deals_limit,
34  unsigned msgs_limit,
35  IFlexNotifyPtr notify_addr,
36  address major_reserve_wallet,
37  address minor_reserve_wallet
38  ) : price_(price), pair_(pair), major_tip3cfg_(major_tip3cfg), minor_tip3cfg_(minor_tip3cfg),
39  ev_cfg_(ev_cfg), sells_(sells), buys_(buys),
40  min_amount_(min_amount), deals_limit_(deals_limit), msgs_limit_(msgs_limit),
41  deal_costs_(ev_cfg.transfer_tip3 * 3 + ev_cfg.send_notify),
42  tip3root_major_(major_tip3cfg.root_address), tip3root_minor_(minor_tip3cfg.root_address), notify_addr_(notify_addr),
43  major_reserve_wallet_(major_reserve_wallet), minor_reserve_wallet_(minor_reserve_wallet) {
44  }
45 
47  struct process_result {
50  opt<OrderRet> ret;
51  };
52 
54  process_result process(unsigned sell_idx, unsigned buy_idx) {
56  notify_addr_, sell_idx, buy_idx);
57 
58  {
60  xchg_iterator sells_iter(state, sells, deal_costs_, true);
62  xchg_iterator buys_iter(state, buys, deal_costs_, false);
63 
64  while (sells_iter.first_active() && buys_iter.first_active() && !state.overlimit()) {
65  auto res = make_deal(*sells_iter, *buys_iter);
66  if (res.sell_out_of_evers)
67  sells_iter.drop_with_ooc();
68  if (res.buy_out_of_evers)
69  buys_iter.drop_with_ooc();
70  if (!res.sell_out_of_evers && !res.buy_out_of_evers) {
71  sells_iter.on_deal(res.deal_amount, res.seller_costs, res.seller_lend_spent);
72  buys_iter.on_deal(res.deal_amount, res.buyer_costs, res.buyer_lend_spent);
73  state.on_deal(res.seller_taker, res.deal_amount);
74  }
75  }
76  // In case of overlimit, we need to send IPriceXchg::processQueue() to self
77  if (sells_iter.first_active() && buys_iter.first_active()) {
78  IPriceXchgPtr(address{tvm_myaddr()})(Evers(ev_cfg_.process_queue.get())).
79  processQueue();
80  }
81  }
82 
83  // We need to find orders without post_order flag and finish them
84  if (!state.overlimit()) {
85  const bool sells_empty = sells_.empty();
86  const bool buys_empty = buys_.empty();
87  if (sells_empty && !buys_empty) {
88  buys_.drop_no_post_orders(state, false);
89  } else if (!sells_empty && buys_empty) {
90  sells_.drop_no_post_orders(state, true);
91  }
92  }
93  state.finalize(sells_.all_amount_, buys_.all_amount_); // finalize state and send AMM notifications
94 
95  return {
96  sells_,
97  buys_,
98  state.ret_
99  };
100  }
101 
103  struct deal_result {
107  uint128 deal_amount;
108  uint128 seller_costs;
109  uint128 buyer_costs;
112  };
113 
116  auto deal_amount = std::min(sell.amount, buy.amount);
117 
118  bool last_tip3_sell = (sell.amount == deal_amount) || (sell.amount < deal_amount + min_amount_);
119  bool last_tip3_buy = (buy.amount == deal_amount) || (buy.amount < deal_amount + min_amount_);
120 
121  auto buy_payment = minor_cost(deal_amount, price_);
122  // it is unlikely here, because (amount * price) calculation is performed before for initial order
123  // so just removing ending orders from queues with 'out_of_evers' reason
124  if (!buy_payment)
125  return {.seller_taker = false, last_tip3_sell, last_tip3_buy, 0u128, 0u128, 0u128, 0u128};
126 
127  auto major_deal_amount = deal_amount;
128  auto minor_deal_amount = *buy_payment;
129 
130  auto sell_extra_return = last_tip3_sell ? (sell.lend_amount - major_deal_amount) : 0u128;
131  auto buy_extra_return = last_tip3_buy ? (buy.lend_amount - minor_deal_amount) : 0u128;
132 
133  // Smaller pays for tip3 transfer
134  // (if seller provides big sell order, he will not pay for each small transfer)
135  bool seller_pays_costs = last_tip3_sell;
136  bool sell_out_of_evers = seller_pays_costs && (sell.account < deal_costs_);
137  bool buy_out_of_evers = !seller_pays_costs && (buy.account < deal_costs_);
138  if (sell_out_of_evers || buy_out_of_evers)
139  return {.seller_taker = false, sell_out_of_evers, buy_out_of_evers, 0u128, 0u128, 0u128, 0u128};
140 
141  uint128 seller_costs = seller_pays_costs ? deal_costs_ : 0u128;
142  uint128 buyer_costs = !seller_pays_costs ? deal_costs_ : 0u128;
143 
144  uint128 seller_lend_spent;
145  uint128 buyer_lend_spent;
146 
147  // (seller_taker & buyer_maker) || (seller_maker & buyer_taker)
148  // We have values:
149  // * major_deal_amount
150  // * minor_deal_amount
151  // * if (seller_taker) {
152  // taker_fee_val = major_deal_amount * taker_fee;
153  // maker_vig_val = major_deal_amount * maker_vig;
154  // reserve_val = taker_fee_val - maker_vig_val;
155  // }
156  // * if (buyer_taker) {
157  // taker_fee_val = minor_deal_amount * taker_fee;
158  // maker_vig_val = minor_deal_amount * maker_vig;
159  // reserve_val = taker_fee_val - maker_vig_val;
160  // }
161  // *
162  // In `seller_taker` scheme, we need to perform token transfers:
163  // * transfer of seller.(major_deal_amount + maker_vig_val) tokens
164  // to buyer major token wallet (buyer.tip3_creds_receive).
165  // * transfer of buyer.minor_deal_amount tokens to seller minor token wallet (seller.tip3_creds_receive).
166  // * transfer of seller.reserve_val to major reserve wallet.
167  // In `buyer_taker` scheme, we need to perform token transfers:
168  // * transfer of buyer.(minor_deal_amount + maker_vig_val) tokens
169  // to seller minor token wallet (seller.tip3_creds_receive).
170  // * transfer of seller.major_deal_amount tokens to buyer major token wallet (buyer.tip3_creds_receive).
171  // * transfer of buyer.reserve_val to minor reserve wallet.
172 
173  bool seller_taker = (sell.ltime > buy.ltime);
174 
175  if (seller_taker) {
176  uint128 taker_fee_val = mul(major_deal_amount, taker_fee);
177  uint128 maker_vig_val = mul(major_deal_amount, maker_vig);
178  uint128 reserve_val = taker_fee_val - maker_vig_val;
179  seller_lend_spent = major_deal_amount + taker_fee_val;
180  buyer_lend_spent = minor_deal_amount;
181 
182  FlexTransferPayloadArgs seller_payload {
183  .sender_sell = true,
184  .sender_taker = true,
185  .sender_user_id = sell.user_id,
186  .receiver_user_id = buy.user_id,
187  .receiver_order_id = buy.order_id,
188  .another_tip3_root = tip3root_minor_,
189  .price_num = price_.numerator(),
190  .price_denum = price_.denominator(),
191  .taker_fee = taker_fee_val,
192  .maker_vig = maker_vig_val,
193  .pair = pair_,
194  .major_tip3cfg = major_tip3cfg_,
195  .minor_tip3cfg = minor_tip3cfg_
196  };
197  // Transfer of major tokens from seller to buyer
198  ITONTokenWalletPtr(sell.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
199  transferToRecipient({}, { buy.user_id, buy.client_addr }, major_deal_amount + maker_vig_val,
200  0u128, ev_cfg_.dest_wallet_keep_evers, true, 0u128,
201  build_chain_static(seller_payload));
202 
203  FlexTransferPayloadArgs buyer_payload {
204  .sender_sell = false,
205  .sender_taker = false,
206  .sender_user_id = buy.user_id,
207  .receiver_user_id = sell.user_id,
208  .receiver_order_id = sell.order_id,
209  .another_tip3_root = tip3root_major_,
210  .price_num = price_.numerator(),
211  .price_denum = price_.denominator(),
212  .taker_fee = taker_fee_val,
213  .maker_vig = maker_vig_val,
214  .pair = pair_,
215  .major_tip3cfg = major_tip3cfg_,
216  .minor_tip3cfg = minor_tip3cfg_
217  };
218  // Transfer of minor tokens from buyer to seller
219  ITONTokenWalletPtr(buy.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
220  transferToRecipient({}, { sell.user_id, sell.client_addr }, minor_deal_amount,
221  0u128, ev_cfg_.dest_wallet_keep_evers, true, buy_extra_return,
222  build_chain_static(buyer_payload));
223  // Transfer of major tokens from seller to major reserve wallet
224  if (reserve_val > 0) {
225  ITONTokenWalletPtr(sell.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
226  transfer({}, major_reserve_wallet_, reserve_val, 0u128, 0u128,
227  build_chain_static(seller_payload));
228  }
229  } else {
230  uint128 taker_fee_val = mul(minor_deal_amount, taker_fee);
231  uint128 maker_vig_val = mul(minor_deal_amount, maker_vig);
232  uint128 reserve_val = taker_fee_val - maker_vig_val;
233  seller_lend_spent = major_deal_amount;
234  buyer_lend_spent = minor_deal_amount + taker_fee_val;
235 
236  FlexTransferPayloadArgs buyer_payload {
237  .sender_sell = false,
238  .sender_taker = true,
239  .sender_user_id = buy.user_id,
240  .receiver_user_id = sell.user_id,
241  .receiver_order_id = sell.order_id,
242  .another_tip3_root = tip3root_major_,
243  .price_num = price_.numerator(),
244  .price_denum = price_.denominator(),
245  .taker_fee = taker_fee_val,
246  .maker_vig = maker_vig_val,
247  .pair = pair_,
248  .major_tip3cfg = major_tip3cfg_,
249  .minor_tip3cfg = minor_tip3cfg_
250  };
251  // transfer of minor tokens from buyer to seller
252  ITONTokenWalletPtr(buy.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
253  transferToRecipient({}, { sell.user_id, sell.client_addr }, minor_deal_amount + maker_vig_val,
254  0u128, ev_cfg_.dest_wallet_keep_evers, true, 0u128,
255  build_chain_static(buyer_payload));
256 
257  FlexTransferPayloadArgs seller_payload {
258  .sender_sell = true,
259  .sender_taker = false,
260  .sender_user_id = sell.user_id,
261  .receiver_user_id = buy.user_id,
262  .receiver_order_id = buy.order_id,
263  .another_tip3_root = tip3root_minor_,
264  .price_num = price_.numerator(),
265  .price_denum = price_.denominator(),
266  .taker_fee = taker_fee_val,
267  .maker_vig = maker_vig_val,
268  .pair = pair_,
269  .major_tip3cfg = major_tip3cfg_,
270  .minor_tip3cfg = minor_tip3cfg_
271  };
272  // transfer of major tokens from seller to buyer
273  ITONTokenWalletPtr(sell.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
274  transferToRecipient({}, { buy.user_id, buy.client_addr }, major_deal_amount,
275  0u128, ev_cfg_.dest_wallet_keep_evers, true, sell_extra_return,
276  build_chain_static(seller_payload));
277  // Transfer of minor tokens from buyer to minor reserve wallet
278  if (reserve_val > 0) {
279  ITONTokenWalletPtr(buy.tip3_wallet_provide)(Evers(ev_cfg_.transfer_tip3.get())).
280  transfer({}, minor_reserve_wallet_, reserve_val, 0u128, 0u128,
281  build_chain_static(buyer_payload));
282  }
283  }
284  return {
285  .seller_taker = seller_taker, false, false, deal_amount,
286  seller_costs, buyer_costs,
287  seller_lend_spent, buyer_lend_spent
288  };
289  }
290 
292  address pair_;
293  Tip3Config major_tip3cfg_;
294  Tip3Config minor_tip3cfg_;
298  uint128 min_amount_;
299  unsigned deals_limit_;
300  unsigned msgs_limit_;
301  uint128 deal_costs_;
302  address tip3root_major_;
303  address tip3root_minor_;
304  IFlexNotifyPtr notify_addr_;
307 };
308 
309 }} // namespace tvm::xchg
310 
__always_inline std::optional< uint128 > minor_cost(uint128 amount, price_t price)
Definition: PriceXchg.hpp:46
Class for iterating queue and processing deals.
Definition: dealer.hpp:22
uint128 seller_costs
Seller evers costs to be taken.
Definition: dealer.hpp:108
address tip3root_minor_
Address of RootTokenContract for minor tip3 token.
Definition: dealer.hpp:303
orders_queue buys
Buy orders queue.
Definition: dealer.hpp:49
unsigned msgs_limit_
Messages limit.
Definition: dealer.hpp:300
uint128 seller_lend_spent
Seller lend tokens spent (major tokens for seller)
Definition: dealer.hpp:110
price_t price_
Price (rational value)
Definition: dealer.hpp:291
Tip3Config major_tip3cfg_
Major tip3 configuration.
Definition: dealer.hpp:293
opt< OrderRet > ret
Return value for the called function.
Definition: dealer.hpp:50
orders_queue sells
Sell orders queue.
Definition: dealer.hpp:48
process_result process(unsigned sell_idx, unsigned buy_idx)
Process order queues and make deals.
Definition: dealer.hpp:54
deal_result make_deal(OrderInfoXchg sell, OrderInfoXchg buy)
Make tip3/tip exchange deal.
Definition: dealer.hpp:115
uint128 buyer_lend_spent
Buyer lend tokens spent (minor tokens for buyer)
Definition: dealer.hpp:111
IFlexNotifyPtr notify_addr_
Notification address for AMM.
Definition: dealer.hpp:304
unsigned deals_limit_
Deals limit.
Definition: dealer.hpp:299
uint128 deal_amount
Amount of major tokens for the deal (without fees)
Definition: dealer.hpp:107
orders_queue sells_
Sell orders queue.
Definition: dealer.hpp:296
bool sell_out_of_evers
Is the sell order out of evers.
Definition: dealer.hpp:105
uint128 min_amount_
Minimum amount of major tokens for a deal or an order.
Definition: dealer.hpp:298
Tip3Config minor_tip3cfg_
Minor tip3 configuration.
Definition: dealer.hpp:294
bool buy_out_of_evers
Is the buy order out of evers.
Definition: dealer.hpp:106
EversConfig ev_cfg_
Processing costs configuration (evers)
Definition: dealer.hpp:295
dealer(price_t price, address pair, Tip3Config major_tip3cfg, Tip3Config minor_tip3cfg, EversConfig ev_cfg, orders_queue sells, orders_queue buys, uint128 min_amount, unsigned deals_limit, unsigned msgs_limit, IFlexNotifyPtr notify_addr, address major_reserve_wallet, address minor_reserve_wallet)
Definition: dealer.hpp:24
address pair_
Address of XchgPair contract.
Definition: dealer.hpp:292
address major_reserve_wallet_
Major reserve wallet.
Definition: dealer.hpp:305
bool seller_taker
Seller is a taker in deal.
Definition: dealer.hpp:104
uint128 buyer_costs
Buyer evers costs to be taken.
Definition: dealer.hpp:109
uint128 deal_costs_
Deal costs in evers.
Definition: dealer.hpp:301
address minor_reserve_wallet_
Minor reserve wallet.
Definition: dealer.hpp:306
orders_queue buys_
Buy orders queue.
Definition: dealer.hpp:297
address tip3root_major_
Address of RootTokenContract for major tip3 token.
Definition: dealer.hpp:302
Result of make_deal.
Definition: dealer.hpp:103
Result of process() call.
Definition: dealer.hpp:47
Working version of orders_queue with cached head order.
Definition: orders_queue.hpp:40
Orders queue to keep orders and common state (tokens amount).
Definition: orders_queue.hpp:16
bool empty() const
Is queue empty.
Definition: orders_queue.hpp:22
uint128 all_amount_
Amount of tokens in all orders.
Definition: orders_queue.hpp:18
void drop_no_post_orders(process_queue_state &state, bool sell)
Drop orders without post_order flag.
Definition: orders_queue.hpp:25
Processing orders queue state for PriceXchg.
Definition: process_queue_state.hpp:17
bool overlimit() const
If we hit deals or messages limit.
Definition: process_queue_state.hpp:148
opt< OrderRet > ret_
Return value.
Definition: process_queue_state.hpp:197
void finalize(uint128 rest_sell_amount, uint128 rest_buy_amount)
Finalize state - send AMM notifications about processed deals and canceled orders.
Definition: process_queue_state.hpp:153
void on_deal(bool seller_taker, uint128 deal_amount)
When a deal is processed.
Definition: process_queue_state.hpp:133
Tip3/tip3 exchange orders iterator.
Definition: xchg_iterator.hpp:16
void on_deal(uint128 deal_amount, uint128 costs, uint128 lend_spent)
When deal is completed.
Definition: xchg_iterator.hpp:56
bool first_active()
Move to the first active order in the queue.
Definition: xchg_iterator.hpp:27
void drop_with_ooc()
When order is out-of-evers.
Definition: xchg_iterator.hpp:75
Class for keeping iteration state for PriceXchg.
Processing native funds value ...
Definition: EversConfig.hpp:12
uint128 process_queue
... to process processQueue function. Also is used for buyTip3 / onTip3LendOwnership / cancelSell / c...
Definition: EversConfig.hpp:21
uint128 transfer_tip3
... for executing tip3 transfer
Definition: EversConfig.hpp:14
uint128 dest_wallet_keep_evers
... to keep evers in destination wallet
Definition: EversConfig.hpp:25
Notification payload for wallet->transferWithNotify()
Definition: FlexTransferPayloadArgs.hpp:12
bool sender_sell
Sender is seller in deal (selling major tokens)
Definition: FlexTransferPayloadArgs.hpp:13
tip3-tip3 exchange order info
Definition: PriceXchg.hpp:54
uint128 account
Remaining native funds from client to pay for processing.
Definition: PriceXchg.hpp:59
uint128 amount
Current remaining amount of major tokens to buy or sell.
Definition: PriceXchg.hpp:58
addr_std_fixed client_addr
Definition: PriceXchg.hpp:62
uint64 ltime
Logical time of starting transaction for the order.
Definition: PriceXchg.hpp:67
addr_std_fixed tip3_wallet_provide
Client tip3 wallet to provide tokens (major for sell or minor for buy).
Definition: PriceXchg.hpp:61
uint128 lend_amount
Current remaining amount of lend tokens (major tokens for sell, minor tokens for buy).
Definition: PriceXchg.hpp:60
uint256 order_id
Order id.
Definition: PriceXchg.hpp:66
uint256 user_id
User id.
Definition: PriceXchg.hpp:65
Rational value - numerator/denominator.
Definition: RationalValue.hpp:12
uint128 denominator() const
Denominator part of rational number.
Definition: RationalValue.hpp:14
uint128 numerator() const
Numerator part of rational number.
Definition: RationalValue.hpp:13
Exchange orders iterator for PriceXchg.