rippled
AMM.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2023 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 <test/jtx/AMM.h>
21 
22 #include <ripple/app/misc/AMMUtils.h>
23 #include <ripple/protocol/AMMCore.h>
24 #include <ripple/protocol/AmountConversions.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
27 #include <test/jtx/Env.h>
28 
29 namespace ripple {
30 namespace test {
31 namespace jtx {
32 
33 static Number
34 number(STAmount const& a)
35 {
36  if (isXRP(a))
37  return a.xrp();
38  return a;
39 }
40 
41 static IOUAmount
42 initialTokens(STAmount const& asset1, STAmount const& asset2)
43 {
44  auto const product = number(asset1) * number(asset2);
45  return (IOUAmount)(
46  product.mantissa() >= 0 ? root2(product) : root2(-product));
47 }
48 
50  Env& env,
51  Account const& account,
52  STAmount const& asset1,
53  STAmount const& asset2,
54  bool log,
55  std::uint16_t tfee,
60  std::optional<ter> const& ter)
61  : env_(env)
62  , creatorAccount_(account)
63  , asset1_(asset1)
64  , asset2_(asset2)
65  , initialLPTokens_(initialTokens(asset1, asset2))
66  , log_(log)
67  , lastPurchasePrice_(0)
68  , bidMin_()
69  , bidMax_()
70  , msig_(ms)
71  , fee_(fee)
72  , ammAccount_(create(tfee, flags, seq, ter))
73  , lptIssue_(ripple::ammLPTIssue(
74  asset1_.issue().currency,
75  asset2_.issue().currency,
76  ammAccount_))
77 {
78 }
79 
81  Env& env,
82  Account const& account,
83  STAmount const& asset1,
84  STAmount const& asset2,
85  ter const& ter,
86  bool log)
87  : AMM(env,
88  account,
89  asset1,
90  asset2,
91  log,
92  0,
93  0,
94  std::nullopt,
95  std::nullopt,
96  std::nullopt,
97  ter)
98 {
99 }
100 
101 [[nodiscard]] AccountID
103  std::uint32_t tfee,
106  std::optional<ter> const& ter)
107 {
108  Json::Value jv;
109  jv[jss::Account] = creatorAccount_.human();
110  jv[jss::Amount] = asset1_.getJson(JsonOptions::none);
111  jv[jss::Amount2] = asset2_.getJson(JsonOptions::none);
112  jv[jss::TradingFee] = tfee;
113  jv[jss::TransactionType] = jss::AMMCreate;
114  if (flags)
115  jv[jss::Flags] = *flags;
116  if (fee_ != 0)
117  jv[jss::Fee] = std::to_string(fee_);
118  else
119  jv[jss::Fee] = std::to_string(env_.current()->fees().increment.drops());
120  submit(jv, seq, ter);
121 
122  if (!ter || env_.ter() == tesSUCCESS)
123  {
124  if (auto const amm = env_.current()->read(
126  {
127  return amm->getAccountID(sfAccount);
128  }
129  }
130  return {};
131 }
132 
135  std::optional<AccountID> const& account,
136  std::optional<std::string> const& ledgerIndex,
138 {
139  Json::Value jv;
140  if (account)
141  jv[jss::account] = to_string(*account);
142  if (ledgerIndex)
143  jv[jss::ledger_index] = *ledgerIndex;
144  if (tokens)
145  {
146  jv[jss::asset] =
148  jv[jss::asset2] =
150  }
151  else
152  {
153  jv[jss::asset] =
155  jv[jss::asset2] =
157  }
158  auto jr = env_.rpc("json", "amm_info", to_string(jv));
159  if (jr.isObject() && jr.isMember(jss::result) &&
160  jr[jss::result].isMember(jss::status))
161  return jr[jss::result];
162  return Json::nullValue;
163 }
164 
167  Issue const& issue1,
168  Issue const& issue2,
169  std::optional<AccountID> const& account) const
170 {
171  if (auto const amm =
173  {
174  auto const ammAccountID = amm->getAccountID(sfAccount);
175  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
176  *env_.current(),
177  ammAccountID,
178  issue1,
179  issue2,
180  FreezeHandling::fhIGNORE_FREEZE,
181  env_.journal);
182  auto const lptAMMBalance = account
183  ? ammLPHolds(*env_.current(), *amm, *account, env_.journal)
184  : amm->getFieldAmount(sfLPTokenBalance);
185  return {asset1Balance, asset2Balance, lptAMMBalance};
186  }
187  return {STAmount{}, STAmount{}, STAmount{}};
188 }
189 
190 bool
192  STAmount const& asset1,
193  STAmount const& asset2,
194  IOUAmount const& lpt,
195  std::optional<AccountID> const& account) const
196 {
197  auto const [asset1Balance, asset2Balance, lptAMMBalance] =
198  balances(asset1.issue(), asset2.issue(), account);
199  return asset1 == asset1Balance && asset2 == asset2Balance &&
200  lptAMMBalance == STAmount{lpt, lptIssue_};
201  return false;
202 }
203 
204 IOUAmount
206 {
207  if (account)
208  return accountHolds(
209  *env_.current(),
210  *account,
211  lptIssue_,
212  FreezeHandling::fhZERO_IF_FROZEN,
213  env_.journal)
214  .iou();
215  if (auto const amm =
217  return amm->getFieldAmount(sfLPTokenBalance).iou();
218  return IOUAmount{0};
219 }
220 
221 bool
222 AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
223 {
224  if (auto const amm =
226  {
227  auto const lptAMMBalance =
228  ammLPHolds(*env_.current(), *amm, account, env_.journal);
229  return lptAMMBalance == STAmount{expTokens, lptIssue_};
230  }
231  return false;
232 }
233 
234 bool
238  IOUAmount expectedPrice) const
239 {
240  return expectAuctionSlot([&](std::uint32_t slotFee,
241  std::optional<std::uint8_t> slotInterval,
242  IOUAmount const& slotPrice,
243  auto const&) {
244  return slotFee == fee &&
245  // Auction slot might be expired, in which case slotInterval is
246  // 0
247  ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) &&
248  slotPrice == expectedPrice;
249  });
250 }
251 
252 bool
254 {
255  return expectAuctionSlot([&](std::uint32_t,
257  IOUAmount const&,
258  STArray const& accounts) {
259  for (auto const& account : accounts)
260  {
261  if (std::find(
262  authAccounts.cbegin(),
263  authAccounts.cend(),
264  account.getAccountID(sfAccount)) == authAccounts.end())
265  return false;
266  }
267  return true;
268  });
269 }
270 
271 bool
273 {
274  auto const amm =
276  return amm && (*amm)[sfTradingFee] == fee;
277 }
278 
279 bool
281 {
282  return env_.current()->read(keylet::account(ammAccount_)) != nullptr &&
283  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) !=
284  nullptr;
285 }
286 
287 bool
289  STAmount const& asset1,
290  STAmount const& asset2,
291  IOUAmount const& balance,
292  std::optional<AccountID> const& account,
293  std::optional<std::string> const& ledger_index) const
294 {
295  auto const jv = ammRpcInfo(account, ledger_index);
296  return expectAmmInfo(asset1, asset2, balance, jv);
297 }
298 
299 bool
301  STAmount const& asset1,
302  STAmount const& asset2,
303  IOUAmount const& balance,
304  Json::Value const& jvres) const
305 {
306  if (!jvres.isMember(jss::amm))
307  return false;
308  auto const& jv = jvres[jss::amm];
309  if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) ||
310  !jv.isMember(jss::lp_token))
311  return false;
312  STAmount asset1Info;
313  if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount]))
314  return false;
315  STAmount asset2Info;
316  if (!amountFromJsonNoThrow(asset2Info, jv[jss::amount2]))
317  return false;
318  STAmount lptBalance;
319  if (!amountFromJsonNoThrow(lptBalance, jv[jss::lp_token]))
320  return false;
321  // ammRpcInfo returns unordered assets
322  if (asset1Info.issue() != asset1.issue())
323  std::swap(asset1Info, asset2Info);
324  return asset1 == asset1Info && asset2 == asset2Info &&
325  lptBalance == STAmount{balance, lptIssue_};
326 }
327 
328 void
330  Json::Value& jv,
331  std::optional<std::pair<Issue, Issue>> const& assets)
332 {
333  if (assets)
334  {
335  jv[jss::Asset] =
336  STIssue(sfAsset, assets->first).getJson(JsonOptions::none);
337  jv[jss::Asset2] =
338  STIssue(sfAsset, assets->second).getJson(JsonOptions::none);
339  }
340  else
341  {
342  jv[jss::Asset] =
344  jv[jss::Asset2] =
346  }
347 }
348 
349 IOUAmount
351  std::optional<Account> const& account,
352  Json::Value& jv,
353  std::optional<std::pair<Issue, Issue>> const& assets,
355  std::optional<ter> const& ter)
356 {
357  auto const& acct = account ? *account : creatorAccount_;
358  auto const lpTokens = getLPTokensBalance(acct);
359  jv[jss::Account] = acct.human();
360  setTokens(jv, assets);
361  jv[jss::TransactionType] = jss::AMMDeposit;
362  if (fee_ != 0)
363  jv[jss::Fee] = std::to_string(fee_);
364  submit(jv, seq, ter);
365  return getLPTokensBalance(acct) - lpTokens;
366 }
367 
368 IOUAmount
370  std::optional<Account> const& account,
371  LPToken tokens,
372  std::optional<STAmount> const& asset1In,
374  std::optional<ter> const& ter)
375 {
376  return deposit(
377  account,
378  tokens,
379  asset1In,
380  std::nullopt,
381  std::nullopt,
382  flags,
383  std::nullopt,
384  std::nullopt,
385  ter);
386 }
387 
388 IOUAmount
390  std::optional<Account> const& account,
391  STAmount const& asset1In,
392  std::optional<STAmount> const& asset2In,
393  std::optional<STAmount> const& maxEP,
395  std::optional<ter> const& ter)
396 {
397  assert(!(asset2In && maxEP));
398  return deposit(
399  account,
400  std::nullopt,
401  asset1In,
402  asset2In,
403  maxEP,
404  flags,
405  std::nullopt,
406  std::nullopt,
407  ter);
408 }
409 
410 IOUAmount
412  std::optional<Account> const& account,
413  std::optional<LPToken> tokens,
414  std::optional<STAmount> const& asset1In,
415  std::optional<STAmount> const& asset2In,
416  std::optional<STAmount> const& maxEP,
418  std::optional<std::pair<Issue, Issue>> const& assets,
420  std::optional<ter> const& ter)
421 {
422  Json::Value jv;
423  if (tokens)
424  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenOut]);
425  if (asset1In)
426  asset1In->setJson(jv[jss::Amount]);
427  if (asset2In)
428  asset2In->setJson(jv[jss::Amount2]);
429  if (maxEP)
430  maxEP->setJson(jv[jss::EPrice]);
431  std::uint32_t jvflags = 0;
432  if (flags)
433  jvflags = *flags;
434  // If including asset1In and asset2In or tokens as
435  // deposit min amounts then must set the flags
436  // explicitly instead of relying on this logic.
437  if (!(jvflags & tfDepositSubTx))
438  {
439  if (tokens && !asset1In)
440  jvflags |= tfLPToken;
441  else if (tokens && asset1In)
442  jvflags |= tfOneAssetLPToken;
443  else if (asset1In && asset2In)
444  jvflags |= tfTwoAsset;
445  else if (maxEP && asset1In)
446  jvflags |= tfLimitLPToken;
447  else if (asset1In)
448  jvflags |= tfSingleAsset;
449  }
450  jv[jss::Flags] = jvflags;
451  return deposit(account, jv, assets, seq, ter);
452 }
453 
454 IOUAmount
456  std::optional<Account> const& account,
457  Json::Value& jv,
459  std::optional<std::pair<Issue, Issue>> const& assets,
460  std::optional<ter> const& ter)
461 {
462  auto const& acct = account ? *account : creatorAccount_;
463  auto const lpTokens = getLPTokensBalance(acct);
464  jv[jss::Account] = acct.human();
465  setTokens(jv, assets);
466  jv[jss::TransactionType] = jss::AMMWithdraw;
467  if (fee_ != 0)
468  jv[jss::Fee] = std::to_string(fee_);
469  submit(jv, seq, ter);
470  return lpTokens - getLPTokensBalance(acct);
471 }
472 
473 IOUAmount
475  std::optional<Account> const& account,
476  std::optional<LPToken> const& tokens,
477  std::optional<STAmount> const& asset1Out,
479  std::optional<ter> const& ter)
480 {
481  return withdraw(
482  account,
483  tokens,
484  asset1Out,
485  std::nullopt,
486  std::nullopt,
487  flags,
488  std::nullopt,
489  std::nullopt,
490  ter);
491 }
492 
493 IOUAmount
495  std::optional<Account> const& account,
496  STAmount const& asset1Out,
497  std::optional<STAmount> const& asset2Out,
498  std::optional<IOUAmount> const& maxEP,
499  std::optional<ter> const& ter)
500 {
501  assert(!(asset2Out && maxEP));
502  return withdraw(
503  account,
504  std::nullopt,
505  asset1Out,
506  asset2Out,
507  maxEP,
508  std::nullopt,
509  std::nullopt,
510  std::nullopt,
511  ter);
512 }
513 
514 IOUAmount
516  std::optional<Account> const& account,
517  std::optional<LPToken> const& tokens,
518  std::optional<STAmount> const& asset1Out,
519  std::optional<STAmount> const& asset2Out,
520  std::optional<IOUAmount> const& maxEP,
522  std::optional<std::pair<Issue, Issue>> const& assets,
524  std::optional<ter> const& ter)
525 {
526  Json::Value jv;
527  if (tokens)
528  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenIn]);
529  if (asset1Out)
530  asset1Out->setJson(jv[jss::Amount]);
531  if (asset2Out)
532  asset2Out->setJson(jv[jss::Amount2]);
533  if (maxEP)
534  {
535  STAmount const saMaxEP{*maxEP, lptIssue_};
536  saMaxEP.setJson(jv[jss::EPrice]);
537  }
538  std::uint32_t jvflags = 0;
539  if (flags)
540  jvflags = *flags;
541  if (!(jvflags & tfWithdrawSubTx))
542  {
543  if (tokens && !asset1Out)
544  jvflags |= tfLPToken;
545  else if (asset1Out && asset2Out)
546  jvflags |= tfTwoAsset;
547  else if (tokens && asset1Out)
548  jvflags |= tfOneAssetLPToken;
549  else if (asset1Out && maxEP)
550  jvflags |= tfLimitLPToken;
551  else if (asset1Out)
552  jvflags |= tfSingleAsset;
553  }
554  jv[jss::Flags] = jvflags;
555  return withdraw(account, jv, seq, assets, ter);
556 }
557 
558 void
560  std::optional<Account> const& account,
561  std::uint32_t feeVal,
564  std::optional<std::pair<Issue, Issue>> const& assets,
565  std::optional<ter> const& ter)
566 {
567  Json::Value jv;
568  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
569  setTokens(jv, assets);
570  jv[jss::TradingFee] = feeVal;
571  jv[jss::TransactionType] = jss::AMMVote;
572  if (flags)
573  jv[jss::Flags] = *flags;
574  if (fee_ != 0)
575  jv[jss::Fee] = std::to_string(fee_);
576  submit(jv, seq, ter);
577 }
578 
579 void
581  std::optional<Account> const& account,
584  std::vector<Account> const& authAccounts,
587  std::optional<std::pair<Issue, Issue>> const& assets,
588  std::optional<ter> const& ter)
589 {
590  if (auto const amm =
592  {
593  if (amm->isFieldPresent(sfAuctionSlot))
594  {
595  auto const& auctionSlot =
596  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
597  lastPurchasePrice_ = auctionSlot[sfPrice].iou();
598  }
599  }
600  bidMin_ = std::nullopt;
601  bidMax_ = std::nullopt;
602 
603  Json::Value jv;
604  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
605  setTokens(jv, assets);
606  auto getBid = [&](auto const& bid) {
607  if (std::holds_alternative<int>(bid))
608  return STAmount{lptIssue_, std::get<int>(bid)};
609  else if (std::holds_alternative<IOUAmount>(bid))
610  return toSTAmount(std::get<IOUAmount>(bid), lptIssue_);
611  else
612  return std::get<STAmount>(bid);
613  };
614  if (bidMin)
615  {
616  STAmount saTokens = getBid(*bidMin);
617  saTokens.setJson(jv[jss::BidMin]);
618  bidMin_ = saTokens.iou();
619  }
620  if (bidMax)
621  {
622  STAmount saTokens = getBid(*bidMax);
623  saTokens.setJson(jv[jss::BidMax]);
624  bidMax_ = saTokens.iou();
625  }
626  if (authAccounts.size() > 0)
627  {
628  Json::Value accounts(Json::arrayValue);
629  for (auto const& account : authAccounts)
630  {
631  Json::Value acct;
632  Json::Value authAcct;
633  acct[jss::Account] = account.human();
634  authAcct[jss::AuthAccount] = acct;
635  accounts.append(authAcct);
636  }
637  jv[jss::AuthAccounts] = accounts;
638  }
639  if (flags)
640  jv[jss::Flags] = *flags;
641  jv[jss::TransactionType] = jss::AMMBid;
642  if (fee_ != 0)
643  jv[jss::Fee] = std::to_string(fee_);
644  submit(jv, seq, ter);
645 }
646 
647 void
649  Json::Value const& jv,
651  std::optional<ter> const& ter)
652 {
653  if (log_)
654  std::cout << jv.toStyledString();
655  if (msig_)
656  {
657  if (seq && ter)
658  env_(jv, *msig_, *seq, *ter);
659  else if (seq)
660  env_(jv, *msig_, *seq);
661  else if (ter)
662  env_(jv, *msig_, *ter);
663  else
664  env_(jv, *msig_);
665  }
666  else if (seq && ter)
667  env_(jv, *seq, *ter);
668  else if (seq)
669  env_(jv, *seq);
670  else if (ter)
671  env_(jv, *ter);
672  else
673  env_(jv);
674  env_.close();
675 }
676 
677 bool
678 AMM::expectAuctionSlot(auto&& cb) const
679 {
680  if (auto const amm =
682  amm && amm->isFieldPresent(sfAuctionSlot))
683  {
684  auto const& auctionSlot =
685  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
686  if (auctionSlot.isFieldPresent(sfAccount))
687  {
688  auto const slotFee = auctionSlot[sfDiscountedFee];
689  auto const slotInterval = ammAuctionTimeSlot(
690  env_.app().timeKeeper().now().time_since_epoch().count(),
691  auctionSlot);
692  auto const slotPrice = auctionSlot[sfPrice].iou();
693  auto const authAccounts = auctionSlot.getFieldArray(sfAuthAccounts);
694  return cb(slotFee, slotInterval, slotPrice, authAccounts);
695  }
696  }
697  return false;
698 }
699 
700 namespace amm {
702 trust(AccountID const& account, STAmount const& amount, std::uint32_t flags)
703 {
704  if (isXRP(amount))
705  Throw<std::runtime_error>("trust() requires IOU");
706  Json::Value jv;
707  jv[jss::Account] = to_string(account);
708  jv[jss::LimitAmount] = amount.getJson(JsonOptions::none);
709  jv[jss::TransactionType] = jss::TrustSet;
710  jv[jss::Flags] = flags;
711  return jv;
712 }
714 pay(Account const& account, AccountID const& to, STAmount const& amount)
715 {
716  Json::Value jv;
717  jv[jss::Account] = account.human();
718  jv[jss::Amount] = amount.getJson(JsonOptions::none);
719  jv[jss::Destination] = to_string(to);
720  jv[jss::TransactionType] = jss::Payment;
721  jv[jss::Flags] = tfUniversal;
722  return jv;
723 }
724 } // namespace amm
725 } // namespace jtx
726 } // namespace test
727 } // namespace ripple
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1021
ripple::root2
Number root2(Number f)
Definition: Number.cpp:689
ripple::sfDiscountedFee
const SF_UINT16 sfDiscountedFee
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
ripple::sfAsset
const SF_ISSUE sfAsset
ripple::test::jtx::AMM::msig_
const std::optional< msig > msig_
Definition: AMM.h:75
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::ammLPTIssue
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
Definition: AMMCore.cpp:56
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
std::pair
ripple::test::jtx::AMM::ammRpcInfo
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< std::pair< Issue, Issue >> tokens=std::nullopt) const
Send amm_info RPC command.
Definition: AMM.cpp:134
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
ripple::sfLPTokenBalance
const SF_AMOUNT sfLPTokenBalance
std::vector
STL class.
std::find
T find(T... args)
std::vector::size
T size(T... args)
ripple::accountHolds
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:243
ripple::keylet::amm
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:375
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:642
ripple::test::jtx::AMM::vote
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:559
ripple::test::jtx::amm::pay
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:714
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:113
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:144
ripple::test::jtx::AMM::deposit
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:369
std::tuple
ripple::test::jtx::AMM::bid
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:580
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:241
ripple::test::jtx::AMM
Convenience class to test AMM functionality.
Definition: AMM.h:62
Json::Value::toStyledString
std::string toStyledString() const
Definition: json_value.cpp:1039
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::test::jtx::AMM::expectAmmInfo
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
Definition: AMM.cpp:300
ripple::test::jtx::AMM::creatorAccount_
const Account creatorAccount_
Definition: AMM.h:65
ripple::sfPrice
const SF_AMOUNT sfPrice
ripple::STAmount::iou
IOUAmount iou() const
Definition: STAmount.cpp:349
ripple::test::jtx::Env::ter
TER ter() const
Return the TER for the last JTx.
Definition: Env.h:513
ripple::ammAccountID
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
ripple::STAmount::xrp
XRPAmount xrp() const
Definition: STAmount.cpp:334
ripple::sfTradingFee
const SF_UINT16 sfTradingFee
ripple::test::jtx::AMM::expectBalances
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Definition: AMM.cpp:191
ripple::ammPoolHolds
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:29
std::cout
ripple::STIssue::getJson
Json::Value getJson(JsonOptions) const override
Definition: STIssue.cpp:63
ripple::base_uint< 160, detail::AccountIDTag >
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::sfAsset2
const SF_ISSUE sfAsset2
ripple::STAmount::setJson
void setJson(Json::Value &) const
Definition: STAmount.cpp:517
ripple::test::jtx::initialTokens
static IOUAmount initialTokens(STAmount const &asset1, STAmount const &asset2)
Definition: AMM.cpp:42
ripple::test::jtx::AMM::expectLPTokens
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition: AMM.cpp:222
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::test::jtx::AMM::expectAmmRpcInfo
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledger_index=std::nullopt) const
Definition: AMM.cpp:288
ripple::test::jtx::AMM::lastPurchasePrice_
IOUAmount lastPurchasePrice_
Definition: AMM.h:71
ripple::JsonOptions::none
@ none
ripple::toSTAmount
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
Definition: AmountConversions.h:30
ripple::sfAuthAccounts
const SField sfAuthAccounts
ripple::tfWithdrawSubTx
constexpr std::uint32_t tfWithdrawSubTx
Definition: TxFlags.h:174
ripple::test::jtx::AMM::log_
bool log_
Definition: AMM.h:69
ripple::STArray
Definition: STArray.h:28
std::to_string
T to_string(T... args)
ripple::test::jtx::AMM::env_
Env & env_
Definition: AMM.h:64
ripple::test::jtx::AMM::lptIssue_
const Issue lptIssue_
Definition: AMM.h:79
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::test::jtx::AMM::bidMax_
std::optional< IOUAmount > bidMax_
Definition: AMM.h:73
ripple::STAmount
Definition: STAmount.h:45
ripple::test::jtx::amm::trust
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:702
ripple::test::jtx::AMM::AMM
AMM(Env &env, Account const &account, STAmount const &asset1, STAmount const &asset2, bool log=false, std::uint16_t tfee=0, std::uint32_t fee=0, std::optional< std::uint32_t > flags=std::nullopt, std::optional< jtx::seq > seq=std::nullopt, std::optional< jtx::msig > ms=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:49
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
std::uint16_t
ripple::tfSingleAsset
constexpr std::uint32_t tfSingleAsset
Definition: TxFlags.h:170
ripple::STIssue
Definition: STIssue.h:31
ripple::test::jtx::AMM::expectTradingFee
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:272
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:35
std::swap
T swap(T... args)
ripple::test::jtx::AMM::asset1_
const STAmount asset1_
Definition: AMM.h:66
ripple::test::jtx::AMM::withdraw
IOUAmount withdraw(std::optional< Account > const &account, std::optional< LPToken > const &tokens, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:474
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
ripple::test::jtx::AMM::ammExists
bool ammExists() const
Definition: AMM.cpp:280
ripple::STObject
Definition: STObject.h:52
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::jtx::AMM::asset2_
const STAmount asset2_
Definition: AMM.h:67
ripple::test::jtx::AMM::setTokens
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt)
Definition: AMM.cpp:329
ripple::tfLPToken
constexpr std::uint32_t tfLPToken
Definition: TxFlags.h:167
ripple::test::jtx::flags
Match set account flags.
Definition: flags.h:111
ripple::test::jtx::AMM::ammAccount_
const AccountID ammAccount_
Definition: AMM.h:78
ripple::tfDepositSubTx
constexpr std::uint32_t tfDepositSubTx
Definition: TxFlags.h:177
ripple::test::jtx::AMM::tokens
IOUAmount tokens() const
Definition: AMM.h:260
std::vector::cbegin
T cbegin(T... args)
std
STL namespace.
ripple::tfTwoAsset
constexpr std::uint32_t tfTwoAsset
Definition: TxFlags.h:171
ripple::test::jtx::number
static Number number(STAmount const &a)
Definition: AMM.cpp:34
Json::nullValue
@ nullValue
'null' value
Definition: json_value.h:36
ripple::TimeKeeper::now
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
ripple::ammLPHolds
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
ripple::test::jtx::AMM::expectAuctionSlot
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition: AMM.cpp:235
std::optional< std::uint32_t >
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
ripple::test::jtx::AMM::create
AccountID create(std::uint32_t tfee=0, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:102
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::test::jtx::AMM::submit
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
Definition: AMM.cpp:648
std::vector::cend
T cend(T... args)
ripple::test::jtx::LPToken
Definition: AMM.h:37
ripple::test::jtx::AMM::fee_
const std::uint32_t fee_
Definition: AMM.h:77
ripple::tfOneAssetLPToken
constexpr std::uint32_t tfOneAssetLPToken
Definition: TxFlags.h:172
ripple::tfUniversal
constexpr std::uint32_t tfUniversal
Definition: TxFlags.h:59
ripple::sfAuctionSlot
const SField sfAuctionSlot
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:225
ripple::test::jtx::AMM::bidMin_
std::optional< IOUAmount > bidMin_
Definition: AMM.h:72
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:300
ripple::test::jtx::create
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
Definition: TestHelpers.cpp:250
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:687
ripple::ammAuctionTimeSlot
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition: AMMCore.cpp:107
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::jtx::AMM::balances
std::tuple< STAmount, STAmount, STAmount > balances(Issue const &issue1, Issue const &issue2, std::optional< AccountID > const &account=std::nullopt) const
Get AMM balances for the token pair.
Definition: AMM.cpp:166
std::variant
ripple::tfLimitLPToken
constexpr std::uint32_t tfLimitLPToken
Definition: TxFlags.h:173
ripple::test::jtx::AMM::getLPTokensBalance
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition: AMM.cpp:205