rippled
Taker_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/tx/impl/Taker.h>
21 #include <ripple/beast/core/LexicalCast.h>
22 #include <ripple/beast/unit_test.h>
23 #include <type_traits>
24 
25 namespace ripple {
26 
27 class Taker_test : public beast::unit_test::suite
28 {
29  static bool const Buy = false;
30  static bool const Sell = true;
31 
32  class TestTaker : public BasicTaker
33  {
36 
37  public:
40  Amounts const& amount,
41  Quality const& quality,
42  STAmount const& funds,
43  std::uint32_t flags,
44  Rate const& rate_in,
45  Rate const& rate_out)
46  : BasicTaker(
47  cross_type,
48  AccountID(0x4701),
49  amount,
50  quality,
51  flags,
52  rate_in,
53  rate_out)
54  , funds_(funds)
55  {
56  }
57 
58  void
59  set_funds(STAmount const& funds)
60  {
61  cross_funds = funds;
62  }
63 
64  STAmount
65  get_funds(AccountID const& owner, STAmount const& funds) const override
66  {
67  if (owner == account())
68  return funds_;
69 
70  return cross_funds;
71  }
72 
73  Amounts
74  cross(Amounts offer, Quality quality)
75  {
76  if (reject(quality))
77  return Amounts(offer.in.zeroed(), offer.out.zeroed());
78 
79  // we need to emulate "unfunded offers" behavior
80  if (get_funds(AccountID(0x4702), offer.out) == beast::zero)
81  return Amounts(offer.in.zeroed(), offer.out.zeroed());
82 
83  if (done())
84  return Amounts(offer.in.zeroed(), offer.out.zeroed());
85 
86  auto result = do_cross(offer, quality, AccountID(0x4702));
87 
88  funds_ -= result.order.in;
89 
90  return result.order;
91  }
92 
95  Amounts offer1,
96  Quality quality1,
97  Amounts offer2,
98  Quality quality2)
99  {
100  /* check if composed quality should be rejected */
101  Quality const quality(composed_quality(quality1, quality2));
102 
103  if (reject(quality))
104  return std::make_pair(
105  Amounts{offer1.in.zeroed(), offer1.out.zeroed()},
106  Amounts{offer2.in.zeroed(), offer2.out.zeroed()});
107 
108  if (done())
109  return std::make_pair(
110  Amounts{offer1.in.zeroed(), offer1.out.zeroed()},
111  Amounts{offer2.in.zeroed(), offer2.out.zeroed()});
112 
113  auto result = do_cross(
114  offer1,
115  quality1,
116  AccountID(0x4703),
117  offer2,
118  quality2,
119  AccountID(0x4704));
120 
121  return std::make_pair(result.first.order, result.second.order);
122  }
123  };
124 
125 private:
126  Issue const&
127  usd() const
128  {
129  static Issue const issue(
130  Currency(0x5553440000000000), AccountID(0x4985601));
131  return issue;
132  }
133 
134  Issue const&
135  eur() const
136  {
137  static Issue const issue(
138  Currency(0x4555520000000000), AccountID(0x4985602));
139  return issue;
140  }
141 
142  Issue const&
143  xrp() const
144  {
145  static Issue const issue(xrpCurrency(), xrpAccount());
146  return issue;
147  }
148 
149  STAmount
150  parse_amount(std::string const& amount, Issue const& issue)
151  {
152  return amountFromString(issue, amount);
153  }
154 
155  Amounts
157  std::string const& amount_in,
158  Issue const& issue_in,
159  std::string const& amount_out,
160  Issue const& issue_out)
161  {
162  STAmount const in(parse_amount(amount_in, issue_in));
163  STAmount const out(parse_amount(amount_out, issue_out));
164 
165  return {in, out};
166  }
167 
169  {
170  cross_attempt_offer(std::string const& in_, std::string const& out_)
171  : in(in_), out(out_)
172  {
173  }
174 
177  };
178 
179 private:
181  format_amount(STAmount const& amount)
182  {
183  std::string txt = amount.getText();
184  txt += "/";
185  txt += to_string(amount.issue().currency);
186  return txt;
187  }
188 
189  void
191  bool sell,
192  std::string name,
193  Quality taker_quality,
194  cross_attempt_offer const offer,
195  std::string const funds,
196  Quality cross_quality,
197  cross_attempt_offer const cross,
198  std::string const cross_funds,
200  Issue const& issue_in,
201  Issue const& issue_out,
202  Rate rate_in = parityRate,
203  Rate rate_out = parityRate)
204  {
205  Amounts taker_offer(
206  parse_amounts(offer.in, issue_in, offer.out, issue_out));
207 
208  Amounts cross_offer(
209  parse_amounts(cross.in, issue_in, cross.out, issue_out));
210 
211  CrossType cross_type;
212 
213  if (isXRP(issue_out))
214  cross_type = CrossType::IouToXrp;
215  else if (isXRP(issue_in))
216  cross_type = CrossType::XrpToIou;
217  else
218  cross_type = CrossType::IouToIou;
219 
220  // FIXME: We are always invoking the IOU-to-IOU taker. We should select
221  // the correct type dynamically.
222  TestTaker taker(
223  cross_type,
224  taker_offer,
225  taker_quality,
226  parse_amount(funds, issue_in),
227  sell ? tfSell : 0,
228  rate_in,
229  rate_out);
230 
231  taker.set_funds(parse_amount(cross_funds, issue_out));
232 
233  auto result = taker.cross(cross_offer, cross_quality);
234 
235  Amounts const expected(
236  parse_amounts(flow.in, issue_in, flow.out, issue_out));
237 
238  BEAST_EXPECT(expected == result);
239 
240  if (expected != result)
241  {
242  log << "Expected: " << format_amount(expected.in) << " : "
243  << format_amount(expected.out) << '\n'
244  << " Actual: " << format_amount(result.in) << " : "
245  << format_amount(result.out) << std::endl;
246  }
247  }
248 
249  Quality
251  {
252  return Quality(parse_amounts(in, xrp(), out, xrp()));
253  }
254 
255 public:
256  // Notation for clamp scenario descriptions:
257  //
258  // IN:OUT (with the last in the list being limiting factor)
259  // N = Nothing
260  // T = Taker Offer Balance
261  // A = Taker Account Balance
262  // B = Owner Account Balance
263  //
264  // (s) = sell semantics: taker wants unlimited output
265  // (b) = buy semantics: taker wants a limited amount out
266 
267  // NIKB TODO: Augment TestTaker so currencies and rates can be specified
268  // once without need for repetition.
269  void
271  {
272  testcase("XRP Quantization: input");
273 
274  Quality q1 = get_quality("1", "1");
275 
276  for (auto NumberSwitchOver : {false, true})
277  {
278  NumberSO stNumberSO{NumberSwitchOver};
279  // TAKER OWNER
280  // QUAL OFFER FUNDS QUAL OFFER FUNDS
281  // EXPECTED
282  // XRP USD
283  attempt(
284  Sell,
285  "N:N",
286  q1,
287  {"2", "2"},
288  "2",
289  q1,
290  {"2", "2"},
291  "2",
292  {"2", "2"},
293  xrp(),
294  usd());
295  if (NumberSwitchOver)
296  {
297  attempt(
298  Sell,
299  "N:B",
300  q1,
301  {"2", "2"},
302  "2",
303  q1,
304  {"2", "2"},
305  "1.8",
306  {"2", "1.8"},
307  xrp(),
308  usd());
309  }
310  else
311  {
312  attempt(
313  Sell,
314  "N:B",
315  q1,
316  {"2", "2"},
317  "2",
318  q1,
319  {"2", "2"},
320  "1.8",
321  {"1", "1.8"},
322  xrp(),
323  usd());
324  }
325  attempt(
326  Buy,
327  "N:T",
328  q1,
329  {"1", "1"},
330  "2",
331  q1,
332  {"2", "2"},
333  "2",
334  {"1", "1"},
335  xrp(),
336  usd());
337  attempt(
338  Buy,
339  "N:BT",
340  q1,
341  {"1", "1"},
342  "2",
343  q1,
344  {"2", "2"},
345  "1.8",
346  {"1", "1"},
347  xrp(),
348  usd());
349  if (NumberSwitchOver)
350  {
351  attempt(
352  Buy,
353  "N:TB",
354  q1,
355  {"1", "1"},
356  "2",
357  q1,
358  {"2", "2"},
359  "0.8",
360  {"1", "0.8"},
361  xrp(),
362  usd());
363  }
364  else
365  {
366  attempt(
367  Buy,
368  "N:TB",
369  q1,
370  {"1", "1"},
371  "2",
372  q1,
373  {"2", "2"},
374  "0.8",
375  {"0", "0.8"},
376  xrp(),
377  usd());
378  }
379  attempt(
380  Sell,
381  "T:N",
382  q1,
383  {"1", "1"},
384  "2",
385  q1,
386  {"2", "2"},
387  "2",
388  {"1", "1"},
389  xrp(),
390  usd());
391  if (NumberSwitchOver)
392  {
393  attempt(
394  Sell,
395  "T:B",
396  q1,
397  {"1", "1"},
398  "2",
399  q1,
400  {"2", "2"},
401  "1.8",
402  {"1", "1"},
403  xrp(),
404  usd());
405  }
406  else
407  {
408  attempt(
409  Sell,
410  "T:B",
411  q1,
412  {"1", "1"},
413  "2",
414  q1,
415  {"2", "2"},
416  "1.8",
417  {"1", "1.8"},
418  xrp(),
419  usd());
420  }
421  attempt(
422  Buy,
423  "T:T",
424  q1,
425  {"1", "1"},
426  "2",
427  q1,
428  {"2", "2"},
429  "2",
430  {"1", "1"},
431  xrp(),
432  usd());
433  attempt(
434  Buy,
435  "T:BT",
436  q1,
437  {"1", "1"},
438  "2",
439  q1,
440  {"2", "2"},
441  "1.8",
442  {"1", "1"},
443  xrp(),
444  usd());
445  if (NumberSwitchOver)
446  {
447  attempt(
448  Buy,
449  "T:TB",
450  q1,
451  {"1", "1"},
452  "2",
453  q1,
454  {"2", "2"},
455  "0.8",
456  {"1", "0.8"},
457  xrp(),
458  usd());
459  }
460  else
461  {
462  attempt(
463  Buy,
464  "T:TB",
465  q1,
466  {"1", "1"},
467  "2",
468  q1,
469  {"2", "2"},
470  "0.8",
471  {"0", "0.8"},
472  xrp(),
473  usd());
474  }
475 
476  attempt(
477  Sell,
478  "A:N",
479  q1,
480  {"2", "2"},
481  "1",
482  q1,
483  {"2", "2"},
484  "2",
485  {"1", "1"},
486  xrp(),
487  usd());
488  if (NumberSwitchOver)
489  {
490  attempt(
491  Sell,
492  "A:B",
493  q1,
494  {"2", "2"},
495  "1",
496  q1,
497  {"2", "2"},
498  "1.8",
499  {"1", "1"},
500  xrp(),
501  usd());
502  }
503  else
504  {
505  attempt(
506  Sell,
507  "A:B",
508  q1,
509  {"2", "2"},
510  "1",
511  q1,
512  {"2", "2"},
513  "1.8",
514  {"1", "1.8"},
515  xrp(),
516  usd());
517  }
518  attempt(
519  Buy,
520  "A:T",
521  q1,
522  {"2", "2"},
523  "1",
524  q1,
525  {"3", "3"},
526  "3",
527  {"1", "1"},
528  xrp(),
529  usd());
530  attempt(
531  Buy,
532  "A:BT",
533  q1,
534  {"2", "2"},
535  "1",
536  q1,
537  {"3", "3"},
538  "2.4",
539  {"1", "1"},
540  xrp(),
541  usd());
542  if (NumberSwitchOver)
543  {
544  attempt(
545  Buy,
546  "A:TB",
547  q1,
548  {"2", "2"},
549  "1",
550  q1,
551  {"3", "3"},
552  "0.8",
553  {"1", "0.8"},
554  xrp(),
555  usd());
556  }
557  else
558  {
559  attempt(
560  Buy,
561  "A:TB",
562  q1,
563  {"2", "2"},
564  "1",
565  q1,
566  {"3", "3"},
567  "0.8",
568  {"0", "0.8"},
569  xrp(),
570  usd());
571  }
572 
573  attempt(
574  Sell,
575  "TA:N",
576  q1,
577  {"2", "2"},
578  "1",
579  q1,
580  {"2", "2"},
581  "2",
582  {"1", "1"},
583  xrp(),
584  usd());
585  if (NumberSwitchOver)
586  {
587  attempt(
588  Sell,
589  "TA:B",
590  q1,
591  {"2", "2"},
592  "1",
593  q1,
594  {"3", "3"},
595  "1.8",
596  {"1", "1"},
597  xrp(),
598  usd());
599  }
600  else
601  {
602  attempt(
603  Sell,
604  "TA:B",
605  q1,
606  {"2", "2"},
607  "1",
608  q1,
609  {"3", "3"},
610  "1.8",
611  {"1", "1.8"},
612  xrp(),
613  usd());
614  }
615  attempt(
616  Buy,
617  "TA:T",
618  q1,
619  {"2", "2"},
620  "1",
621  q1,
622  {"3", "3"},
623  "3",
624  {"1", "1"},
625  xrp(),
626  usd());
627  if (NumberSwitchOver)
628  {
629  attempt(
630  Buy,
631  "TA:BT",
632  q1,
633  {"2", "2"},
634  "1",
635  q1,
636  {"3", "3"},
637  "1.8",
638  {"1", "1"},
639  xrp(),
640  usd());
641  attempt(
642  Buy,
643  "TA:TB",
644  q1,
645  {"2", "2"},
646  "1",
647  q1,
648  {"3", "3"},
649  "1.8",
650  {"1", "1"},
651  xrp(),
652  usd());
653  }
654  else
655  {
656  attempt(
657  Buy,
658  "TA:BT",
659  q1,
660  {"2", "2"},
661  "1",
662  q1,
663  {"3", "3"},
664  "1.8",
665  {"1", "1.8"},
666  xrp(),
667  usd());
668  attempt(
669  Buy,
670  "TA:TB",
671  q1,
672  {"2", "2"},
673  "1",
674  q1,
675  {"3", "3"},
676  "1.8",
677  {"1", "1.8"},
678  xrp(),
679  usd());
680  }
681 
682  attempt(
683  Sell,
684  "AT:N",
685  q1,
686  {"2", "2"},
687  "1",
688  q1,
689  {"3", "3"},
690  "3",
691  {"1", "1"},
692  xrp(),
693  usd());
694  if (NumberSwitchOver)
695  {
696  attempt(
697  Sell,
698  "AT:B",
699  q1,
700  {"2", "2"},
701  "1",
702  q1,
703  {"3", "3"},
704  "1.8",
705  {"1", "1"},
706  xrp(),
707  usd());
708  }
709  else
710  {
711  attempt(
712  Sell,
713  "AT:B",
714  q1,
715  {"2", "2"},
716  "1",
717  q1,
718  {"3", "3"},
719  "1.8",
720  {"1", "1.8"},
721  xrp(),
722  usd());
723  }
724  attempt(
725  Buy,
726  "AT:T",
727  q1,
728  {"2", "2"},
729  "1",
730  q1,
731  {"3", "3"},
732  "3",
733  {"1", "1"},
734  xrp(),
735  usd());
736  if (NumberSwitchOver)
737  {
738  attempt(
739  Buy,
740  "AT:BT",
741  q1,
742  {"2", "2"},
743  "1",
744  q1,
745  {"3", "3"},
746  "1.8",
747  {"1", "1"},
748  xrp(),
749  usd());
750  attempt(
751  Buy,
752  "AT:TB",
753  q1,
754  {"2", "2"},
755  "1",
756  q1,
757  {"3", "3"},
758  "0.8",
759  {"1", "0.8"},
760  xrp(),
761  usd());
762  }
763  else
764  {
765  attempt(
766  Buy,
767  "AT:BT",
768  q1,
769  {"2", "2"},
770  "1",
771  q1,
772  {"3", "3"},
773  "1.8",
774  {"1", "1.8"},
775  xrp(),
776  usd());
777  attempt(
778  Buy,
779  "AT:TB",
780  q1,
781  {"2", "2"},
782  "1",
783  q1,
784  {"3", "3"},
785  "0.8",
786  {"0", "0.8"},
787  xrp(),
788  usd());
789  }
790  }
791  }
792 
793  void
795  {
796  testcase("XRP Quantization: output");
797 
798  for (auto NumberSwitchOver : {false, true})
799  {
800  NumberSO stNumberSO{NumberSwitchOver};
801  Quality q1 = get_quality("1", "1");
802 
803  // TAKER OWNER
804  // QUAL OFFER FUNDS QUAL OFFER FUNDS
805  // EXPECTED
806  // USD XRP
807  attempt(
808  Sell,
809  "N:N",
810  q1,
811  {"3", "3"},
812  "3",
813  q1,
814  {"3", "3"},
815  "3",
816  {"3", "3"},
817  usd(),
818  xrp());
819  attempt(
820  Sell,
821  "N:B",
822  q1,
823  {"3", "3"},
824  "3",
825  q1,
826  {"3", "3"},
827  "2",
828  {"2", "2"},
829  usd(),
830  xrp());
831  if (NumberSwitchOver)
832  {
833  attempt(
834  Buy,
835  "N:T",
836  q1,
837  {"3", "3"},
838  "2.5",
839  q1,
840  {"5", "5"},
841  "5",
842  {"2.5", "3"},
843  usd(),
844  xrp());
845  attempt(
846  Buy,
847  "N:BT",
848  q1,
849  {"3", "3"},
850  "1.5",
851  q1,
852  {"5", "5"},
853  "4",
854  {"1.5", "2"},
855  usd(),
856  xrp());
857  }
858  else
859  {
860  attempt(
861  Buy,
862  "N:T",
863  q1,
864  {"3", "3"},
865  "2.5",
866  q1,
867  {"5", "5"},
868  "5",
869  {"2.5", "2"},
870  usd(),
871  xrp());
872  attempt(
873  Buy,
874  "N:BT",
875  q1,
876  {"3", "3"},
877  "1.5",
878  q1,
879  {"5", "5"},
880  "4",
881  {"1.5", "1"},
882  usd(),
883  xrp());
884  }
885  attempt(
886  Buy,
887  "N:TB",
888  q1,
889  {"3", "3"},
890  "2.2",
891  q1,
892  {"5", "5"},
893  "1",
894  {"1", "1"},
895  usd(),
896  xrp());
897 
898  attempt(
899  Sell,
900  "T:N",
901  q1,
902  {"1", "1"},
903  "2",
904  q1,
905  {"2", "2"},
906  "2",
907  {"1", "1"},
908  usd(),
909  xrp());
910  attempt(
911  Sell,
912  "T:B",
913  q1,
914  {"2", "2"},
915  "2",
916  q1,
917  {"3", "3"},
918  "1",
919  {"1", "1"},
920  usd(),
921  xrp());
922  attempt(
923  Buy,
924  "T:T",
925  q1,
926  {"1", "1"},
927  "2",
928  q1,
929  {"2", "2"},
930  "2",
931  {"1", "1"},
932  usd(),
933  xrp());
934  attempt(
935  Buy,
936  "T:BT",
937  q1,
938  {"1", "1"},
939  "2",
940  q1,
941  {"3", "3"},
942  "2",
943  {"1", "1"},
944  usd(),
945  xrp());
946  attempt(
947  Buy,
948  "T:TB",
949  q1,
950  {"2", "2"},
951  "2",
952  q1,
953  {"3", "3"},
954  "1",
955  {"1", "1"},
956  usd(),
957  xrp());
958 
959  if (NumberSwitchOver)
960  {
961  attempt(
962  Sell,
963  "A:N",
964  q1,
965  {"2", "2"},
966  "1.5",
967  q1,
968  {"2", "2"},
969  "2",
970  {"1.5", "2"},
971  usd(),
972  xrp());
973  attempt(
974  Sell,
975  "A:B",
976  q1,
977  {"2", "2"},
978  "1.8",
979  q1,
980  {"3", "3"},
981  "2",
982  {"1.8", "2"},
983  usd(),
984  xrp());
985  }
986  else
987  {
988  attempt(
989  Sell,
990  "A:N",
991  q1,
992  {"2", "2"},
993  "1.5",
994  q1,
995  {"2", "2"},
996  "2",
997  {"1.5", "1"},
998  usd(),
999  xrp());
1000  attempt(
1001  Sell,
1002  "A:B",
1003  q1,
1004  {"2", "2"},
1005  "1.8",
1006  q1,
1007  {"3", "3"},
1008  "2",
1009  {"1.8", "1"},
1010  usd(),
1011  xrp());
1012  }
1013  attempt(
1014  Buy,
1015  "A:T",
1016  q1,
1017  {"2", "2"},
1018  "1.2",
1019  q1,
1020  {"3", "3"},
1021  "3",
1022  {"1.2", "1"},
1023  usd(),
1024  xrp());
1025  if (NumberSwitchOver)
1026  {
1027  attempt(
1028  Buy,
1029  "A:BT",
1030  q1,
1031  {"2", "2"},
1032  "1.5",
1033  q1,
1034  {"4", "4"},
1035  "3",
1036  {"1.5", "2"},
1037  usd(),
1038  xrp());
1039  }
1040  else
1041  {
1042  attempt(
1043  Buy,
1044  "A:BT",
1045  q1,
1046  {"2", "2"},
1047  "1.5",
1048  q1,
1049  {"4", "4"},
1050  "3",
1051  {"1.5", "1"},
1052  usd(),
1053  xrp());
1054  }
1055  attempt(
1056  Buy,
1057  "A:TB",
1058  q1,
1059  {"2", "2"},
1060  "1.5",
1061  q1,
1062  {"4", "4"},
1063  "1",
1064  {"1", "1"},
1065  usd(),
1066  xrp());
1067 
1068  if (NumberSwitchOver)
1069  {
1070  attempt(
1071  Sell,
1072  "TA:N",
1073  q1,
1074  {"2", "2"},
1075  "1.5",
1076  q1,
1077  {"2", "2"},
1078  "2",
1079  {"1.5", "2"},
1080  usd(),
1081  xrp());
1082  }
1083  else
1084  {
1085  attempt(
1086  Sell,
1087  "TA:N",
1088  q1,
1089  {"2", "2"},
1090  "1.5",
1091  q1,
1092  {"2", "2"},
1093  "2",
1094  {"1.5", "1"},
1095  usd(),
1096  xrp());
1097  }
1098  attempt(
1099  Sell,
1100  "TA:B",
1101  q1,
1102  {"2", "2"},
1103  "1.5",
1104  q1,
1105  {"3", "3"},
1106  "1",
1107  {"1", "1"},
1108  usd(),
1109  xrp());
1110  if (NumberSwitchOver)
1111  {
1112  attempt(
1113  Buy,
1114  "TA:T",
1115  q1,
1116  {"2", "2"},
1117  "1.5",
1118  q1,
1119  {"3", "3"},
1120  "3",
1121  {"1.5", "2"},
1122  usd(),
1123  xrp());
1124  attempt(
1125  Buy,
1126  "TA:BT",
1127  q1,
1128  {"2", "2"},
1129  "1.8",
1130  q1,
1131  {"4", "4"},
1132  "3",
1133  {"1.8", "2"},
1134  usd(),
1135  xrp());
1136  }
1137  else
1138  {
1139  attempt(
1140  Buy,
1141  "TA:T",
1142  q1,
1143  {"2", "2"},
1144  "1.5",
1145  q1,
1146  {"3", "3"},
1147  "3",
1148  {"1.5", "1"},
1149  usd(),
1150  xrp());
1151  attempt(
1152  Buy,
1153  "TA:BT",
1154  q1,
1155  {"2", "2"},
1156  "1.8",
1157  q1,
1158  {"4", "4"},
1159  "3",
1160  {"1.8", "1"},
1161  usd(),
1162  xrp());
1163  }
1164  attempt(
1165  Buy,
1166  "TA:TB",
1167  q1,
1168  {"2", "2"},
1169  "1.2",
1170  q1,
1171  {"3", "3"},
1172  "1",
1173  {"1", "1"},
1174  usd(),
1175  xrp());
1176 
1177  attempt(
1178  Sell,
1179  "AT:N",
1180  q1,
1181  {"2", "2"},
1182  "2.5",
1183  q1,
1184  {"4", "4"},
1185  "4",
1186  {"2", "2"},
1187  usd(),
1188  xrp());
1189  attempt(
1190  Sell,
1191  "AT:B",
1192  q1,
1193  {"2", "2"},
1194  "2.5",
1195  q1,
1196  {"3", "3"},
1197  "1",
1198  {"1", "1"},
1199  usd(),
1200  xrp());
1201  attempt(
1202  Buy,
1203  "AT:T",
1204  q1,
1205  {"2", "2"},
1206  "2.5",
1207  q1,
1208  {"3", "3"},
1209  "3",
1210  {"2", "2"},
1211  usd(),
1212  xrp());
1213  attempt(
1214  Buy,
1215  "AT:BT",
1216  q1,
1217  {"2", "2"},
1218  "2.5",
1219  q1,
1220  {"4", "4"},
1221  "3",
1222  {"2", "2"},
1223  usd(),
1224  xrp());
1225  attempt(
1226  Buy,
1227  "AT:TB",
1228  q1,
1229  {"2", "2"},
1230  "2.5",
1231  q1,
1232  {"3", "3"},
1233  "1",
1234  {"1", "1"},
1235  usd(),
1236  xrp());
1237  }
1238  }
1239 
1240  void
1242  {
1243  testcase("IOU to IOU");
1244 
1245  for (auto NumberSwitchOver : {false, true})
1246  {
1247  NumberSO stNumberSO{NumberSwitchOver};
1248  Quality q1 = get_quality("1", "1");
1249 
1250  // Highly exaggerated 50% transfer rate for the input and output:
1251  Rate const rate{parityRate.value + (parityRate.value / 2)};
1252 
1253  // TAKER OWNER
1254  // QUAL OFFER FUNDS QUAL OFFER FUNDS
1255  // EXPECTED
1256  // EUR USD
1257  attempt(
1258  Sell,
1259  "N:N",
1260  q1,
1261  {"2", "2"},
1262  "10",
1263  q1,
1264  {"2", "2"},
1265  "10",
1266  {"2", "2"},
1267  eur(),
1268  usd(),
1269  rate,
1270  rate);
1271  if (NumberSwitchOver)
1272  {
1273  attempt(
1274  Sell,
1275  "N:B",
1276  q1,
1277  {"4", "4"},
1278  "10",
1279  q1,
1280  {"4", "4"},
1281  "4",
1282  {"2.666666666666667", "2.666666666666667"},
1283  eur(),
1284  usd(),
1285  rate,
1286  rate);
1287  }
1288  else
1289  {
1290  attempt(
1291  Sell,
1292  "N:B",
1293  q1,
1294  {"4", "4"},
1295  "10",
1296  q1,
1297  {"4", "4"},
1298  "4",
1299  {"2.666666666666666", "2.666666666666666"},
1300  eur(),
1301  usd(),
1302  rate,
1303  rate);
1304  }
1305  attempt(
1306  Buy,
1307  "N:T",
1308  q1,
1309  {"1", "1"},
1310  "10",
1311  q1,
1312  {"2", "2"},
1313  "10",
1314  {"1", "1"},
1315  eur(),
1316  usd(),
1317  rate,
1318  rate);
1319  attempt(
1320  Buy,
1321  "N:BT",
1322  q1,
1323  {"2", "2"},
1324  "10",
1325  q1,
1326  {"6", "6"},
1327  "5",
1328  {"2", "2"},
1329  eur(),
1330  usd(),
1331  rate,
1332  rate);
1333  attempt(
1334  Buy,
1335  "N:TB",
1336  q1,
1337  {"2", "2"},
1338  "2",
1339  q1,
1340  {"6", "6"},
1341  "1",
1342  {"0.6666666666666667", "0.6666666666666667"},
1343  eur(),
1344  usd(),
1345  rate,
1346  rate);
1347  if (NumberSwitchOver)
1348  {
1349  attempt(
1350  Sell,
1351  "A:N",
1352  q1,
1353  {"2", "2"},
1354  "2.5",
1355  q1,
1356  {"2", "2"},
1357  "10",
1358  {"1.666666666666667", "1.666666666666667"},
1359  eur(),
1360  usd(),
1361  rate,
1362  rate);
1363  }
1364  else
1365  {
1366  attempt(
1367  Sell,
1368  "A:N",
1369  q1,
1370  {"2", "2"},
1371  "2.5",
1372  q1,
1373  {"2", "2"},
1374  "10",
1375  {"1.666666666666666", "1.666666666666666"},
1376  eur(),
1377  usd(),
1378  rate,
1379  rate);
1380  }
1381  }
1382  }
1383 
1384  void
1385  run() override
1386  {
1387  test_xrp_to_iou();
1388  test_iou_to_xrp();
1389  test_iou_to_iou();
1390  }
1391 };
1392 
1393 BEAST_DEFINE_TESTSUITE(Taker, tx, ripple);
1394 
1395 } // namespace ripple
ripple::Taker_test::TestTaker::set_funds
void set_funds(STAmount const &funds)
Definition: Taker_test.cpp:59
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::Rate
Represents a transfer rate.
Definition: Rate.h:37
ripple::composed_quality
Quality composed_quality(Quality const &lhs, Quality const &rhs)
Definition: Quality.cpp:101
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::Taker_test::xrp
Issue const & xrp() const
Definition: Taker_test.cpp:143
std::pair
ripple::Taker_test::attempt
void attempt(bool sell, std::string name, Quality taker_quality, cross_attempt_offer const offer, std::string const funds, Quality cross_quality, cross_attempt_offer const cross, std::string const cross_funds, cross_attempt_offer const flow, Issue const &issue_in, Issue const &issue_out, Rate rate_in=parityRate, Rate rate_out=parityRate)
Definition: Taker_test.cpp:190
ripple::Taker_test::Sell
static const bool Sell
Definition: Taker_test.cpp:30
ripple::BasicTaker::do_cross
BasicTaker::Flow do_cross(Amounts offer, Quality quality, AccountID const &owner)
Perform direct crossing through given offer.
Definition: Taker.cpp:385
ripple::Taker_test::TestTaker::funds_
STAmount funds_
Definition: Taker_test.cpp:34
ripple::BasicTaker::reject
bool reject(Quality const &quality) const noexcept
Returns true if the quality does not meet the taker's requirements.
Definition: Taker.h:179
ripple::NumberSO
RAII class to set and restore the Number switchover.
Definition: IOUAmount.h:201
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:571
ripple::CrossType::XrpToIou
@ XrpToIou
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::CrossType::IouToXrp
@ IouToXrp
ripple::QualityDirection::in
@ in
ripple::BasicTaker
State for the active party during order book or payment operations.
Definition: Taker.h:39
ripple::Taker_test
Definition: Taker_test.cpp:27
ripple::Taker_test::eur
Issue const & eur() const
Definition: Taker_test.cpp:135
ripple::Taker_test::TestTaker::cross
Amounts cross(Amounts offer, Quality quality)
Definition: Taker_test.cpp:74
ripple::Taker_test::cross_attempt_offer::out
std::string out
Definition: Taker_test.cpp:176
ripple::BasicTaker::cross_type
CrossType cross_type() const
Returns the type of crossing that is being performed.
Definition: Taker.h:186
ripple::parityRate
const Rate parityRate(QUALITY_ONE)
A transfer rate signifying a 1:1 exchange.
Definition: Rate.h:101
ripple::Taker_test::parse_amounts
Amounts parse_amounts(std::string const &amount_in, Issue const &issue_in, std::string const &amount_out, Issue const &issue_out)
Definition: Taker_test.cpp:156
ripple::Taker_test::format_amount
std::string format_amount(STAmount const &amount)
Definition: Taker_test.cpp:181
ripple::Taker_test::TestTaker
Definition: Taker_test.cpp:32
ripple::base_uint< 160, detail::AccountIDTag >
ripple::flow
path::RippleCalc::Output flow(PaymentSandbox &view, STAmount const &deliver, AccountID const &src, AccountID const &dst, STPathSet const &paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, bool offerCrossing, std::optional< Quality > const &limitQuality, std::optional< STAmount > const &sendMax, beast::Journal j, path::detail::FlowDebugInfo *flowDebugInfo=nullptr)
Make a payment from the src account to the dst account.
ripple::CrossType
CrossType
The flavor of an offer crossing.
Definition: Taker.h:36
ripple::CrossType::IouToIou
@ IouToIou
ripple::QualityDirection::out
@ out
ripple::Taker_test::test_xrp_to_iou
void test_xrp_to_iou()
Definition: Taker_test.cpp:270
ripple::Taker_test::cross_attempt_offer::in
std::string in
Definition: Taker_test.cpp:175
ripple::Taker_test::TestTaker::get_funds
STAmount get_funds(AccountID const &owner, STAmount const &funds) const override
Definition: Taker_test.cpp:65
ripple::STAmount
Definition: STAmount.h:45
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:168
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
ripple::Taker_test::test_iou_to_iou
void test_iou_to_iou()
Definition: Taker_test.cpp:1241
ripple::Taker_test::cross_attempt_offer::cross_attempt_offer
cross_attempt_offer(std::string const &in_, std::string const &out_)
Definition: Taker_test.cpp:170
std::uint32_t
ripple::Taker_test::test_iou_to_xrp
void test_iou_to_xrp()
Definition: Taker_test.cpp:794
ripple::Taker_test::TestTaker::TestTaker
TestTaker(CrossType cross_type, Amounts const &amount, Quality const &quality, STAmount const &funds, std::uint32_t flags, Rate const &rate_in, Rate const &rate_out)
Definition: Taker_test.cpp:38
ripple::Taker_test::usd
Issue const & usd() const
Definition: Taker_test.cpp:127
ripple::Taker_test::parse_amount
STAmount parse_amount(std::string const &amount, Issue const &issue)
Definition: Taker_test.cpp:150
ripple::BasicTaker::done
bool done() const
Returns true if order crossing should not continue.
Definition: Taker.cpp:112
ripple::Currency
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
ripple::Rate::value
std::uint32_t value
Definition: Rate.h:39
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::amountFromString
STAmount amountFromString(Issue const &issue, std::string const &amount)
Definition: STAmount.cpp:864
ripple::tfSell
constexpr std::uint32_t tfSell
Definition: TxFlags.h:96
std::endl
T endl(T... args)
ripple::Taker_test::cross_attempt_offer
Definition: Taker_test.cpp:168
ripple::Taker_test::Buy
static const bool Buy
Definition: Taker_test.cpp:29
ripple::Taker_test::TestTaker::cross_funds
STAmount cross_funds
Definition: Taker_test.cpp:35
ripple::Taker_test::TestTaker::cross
std::pair< Amounts, Amounts > cross(Amounts offer1, Quality quality1, Amounts offer2, Quality quality2)
Definition: Taker_test.cpp:94
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::Taker_test::get_quality
Quality get_quality(std::string in, std::string out)
Definition: Taker_test.cpp:250
ripple::BasicTaker::account
AccountID const & account() const noexcept
Returns the account identifier of the taker.
Definition: Taker.h:172
type_traits
ripple::xrpCurrency
Currency const & xrpCurrency()
XRP currency.
Definition: UintTypes.cpp:121
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47
ripple::Taker_test::run
void run() override
Definition: Taker_test.cpp:1385