rippled
Loading...
Searching...
No Matches
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#include <test/jtx/Env.h>
22#include <xrpld/app/misc/AMMUtils.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
24#include <xrpl/protocol/AMMCore.h>
25#include <xrpl/protocol/AmountConversions.h>
26#include <xrpl/protocol/jss.h>
27
28namespace ripple {
29namespace test {
30namespace jtx {
31
32static Number
34{
35 if (isXRP(a))
36 return a.xrp();
37 return a;
38}
39
40static IOUAmount
41initialTokens(STAmount const& asset1, STAmount const& asset2)
42{
43 auto const product = number(asset1) * number(asset2);
44 return (IOUAmount)(product.mantissa() >= 0 ? root2(product)
45 : root2(-product));
46}
47
49 Env& env,
50 Account const& account,
51 STAmount const& asset1,
52 STAmount const& asset2,
53 bool log,
54 std::uint16_t tfee,
60 bool close)
61 : env_(env)
62 , creatorAccount_(account)
63 , asset1_(asset1)
64 , asset2_(asset2)
65 , ammID_(keylet::amm(asset1_.issue(), asset2_.issue()).key)
66 , initialLPTokens_(initialTokens(asset1, asset2))
67 , log_(log)
68 , doClose_(close)
69 , lastPurchasePrice_(0)
70 , bidMin_()
71 , bidMax_()
72 , msig_(ms)
73 , fee_(fee)
74 , ammAccount_(create(tfee, flags, seq, ter))
75 , lptIssue_(ripple::ammLPTIssue(
76 asset1_.issue().currency,
77 asset2_.issue().currency,
78 ammAccount_))
79{
80}
81
83 Env& env,
84 Account const& account,
85 STAmount const& asset1,
86 STAmount const& asset2,
87 ter const& ter,
88 bool log,
89 bool close)
90 : AMM(env,
91 account,
92 asset1,
93 asset2,
94 log,
95 0,
96 0,
97 std::nullopt,
98 std::nullopt,
99 std::nullopt,
100 ter,
101 close)
102{
103}
104
106 Env& env,
107 Account const& account,
108 STAmount const& asset1,
109 STAmount const& asset2,
110 CreateArg const& arg)
111 : AMM(env,
112 account,
113 asset1,
114 asset2,
115 arg.log,
116 arg.tfee,
117 arg.fee,
118 arg.flags,
119 arg.seq,
120 arg.ms,
121 arg.err,
122 arg.close)
123{
124}
125
126[[nodiscard]] AccountID
128 std::uint32_t tfee,
131 std::optional<ter> const& ter)
132{
133 Json::Value jv;
134 jv[jss::Account] = creatorAccount_.human();
135 jv[jss::Amount] = asset1_.getJson(JsonOptions::none);
136 jv[jss::Amount2] = asset2_.getJson(JsonOptions::none);
137 jv[jss::TradingFee] = tfee;
138 jv[jss::TransactionType] = jss::AMMCreate;
139 if (flags)
140 jv[jss::Flags] = *flags;
141 if (fee_ != 0)
142 jv[sfFee] = std::to_string(fee_);
143 else
144 jv[jss::Fee] = std::to_string(env_.current()->fees().increment.drops());
145 submit(jv, seq, ter);
146
147 if (!ter || env_.ter() == tesSUCCESS)
148 {
149 if (auto const amm = env_.current()->read(
151 {
152 return amm->getAccountID(sfAccount);
153 }
154 }
155 return {};
156}
157
160 std::optional<AccountID> const& account,
161 std::optional<std::string> const& ledgerIndex,
164 std::optional<AccountID> const& ammAccount,
165 bool ignoreParams,
166 unsigned apiVersion) const
167{
168 Json::Value jv;
169 if (account)
170 jv[jss::account] = to_string(*account);
171 if (ledgerIndex)
172 jv[jss::ledger_index] = *ledgerIndex;
173 if (!ignoreParams)
174 {
175 if (issue1 || issue2)
176 {
177 if (issue1)
178 jv[jss::asset] =
179 STIssue(sfAsset, *issue1).getJson(JsonOptions::none);
180 if (issue2)
181 jv[jss::asset2] =
182 STIssue(sfAsset2, *issue2).getJson(JsonOptions::none);
183 }
184 else if (!ammAccount)
185 {
186 jv[jss::asset] =
188 jv[jss::asset2] =
190 }
191 if (ammAccount)
192 jv[jss::amm_account] = to_string(*ammAccount);
193 }
194 auto jr =
195 (apiVersion == RPC::apiInvalidVersion
196 ? env_.rpc("json", "amm_info", to_string(jv))
197 : env_.rpc(apiVersion, "json", "amm_info", to_string(jv)));
198 if (jr.isObject() && jr.isMember(jss::result) &&
199 jr[jss::result].isMember(jss::status))
200 return jr[jss::result];
201 return Json::nullValue;
202}
203
206 Issue const& issue1,
207 Issue const& issue2,
208 std::optional<AccountID> const& account) const
209{
210 if (auto const amm =
212 {
213 auto const ammAccountID = amm->getAccountID(sfAccount);
214 auto const [asset1Balance, asset2Balance] = ammPoolHolds(
215 *env_.current(),
217 issue1,
218 issue2,
220 env_.journal);
221 auto const lptAMMBalance = account
222 ? ammLPHolds(*env_.current(), *amm, *account, env_.journal)
223 : amm->getFieldAmount(sfLPTokenBalance);
224 return {asset1Balance, asset2Balance, lptAMMBalance};
225 }
226 return {STAmount{}, STAmount{}, STAmount{}};
227}
228
229bool
231 STAmount const& asset1,
232 STAmount const& asset2,
233 IOUAmount const& lpt,
234 std::optional<AccountID> const& account) const
235{
236 auto const [asset1Balance, asset2Balance, lptAMMBalance] =
237 balances(asset1.issue(), asset2.issue(), account);
238 return asset1 == asset1Balance && asset2 == asset2Balance &&
239 lptAMMBalance == STAmount{lpt, lptIssue_};
240}
241
244{
245 if (account)
246 return accountHolds(
247 *env_.current(),
248 *account,
249 lptIssue_,
252 .iou();
253 if (auto const amm =
255 return amm->getFieldAmount(sfLPTokenBalance).iou();
256 return IOUAmount{0};
257}
258
259bool
260AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
261{
262 if (auto const amm =
264 {
265 auto const lptAMMBalance =
266 ammLPHolds(*env_.current(), *amm, account, env_.journal);
267 return lptAMMBalance == STAmount{expTokens, lptIssue_};
268 }
269 return false;
270}
271
272bool
276 IOUAmount expectedPrice) const
277{
278 return expectAuctionSlot([&](std::uint32_t slotFee,
279 std::optional<std::uint8_t> slotInterval,
280 IOUAmount const& slotPrice,
281 auto const&) {
282 return slotFee == fee &&
283 // Auction slot might be expired, in which case slotInterval is
284 // 0
285 ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) &&
286 slotPrice == expectedPrice;
287 });
288}
289
290bool
292{
295 IOUAmount const&,
296 STArray const& accounts) {
297 for (auto const& account : accounts)
298 {
299 if (std::find(
300 authAccounts.cbegin(),
301 authAccounts.cend(),
302 account.getAccountID(sfAccount)) == authAccounts.end())
303 return false;
304 }
305 return true;
306 });
307}
308
309bool
311{
312 auto const amm =
314 return amm && (*amm)[sfTradingFee] == fee;
315}
316
317bool
319{
320 return env_.current()->read(keylet::account(ammAccount_)) != nullptr &&
322 nullptr;
323}
324
325bool
327 STAmount const& asset1,
328 STAmount const& asset2,
329 IOUAmount const& balance,
330 std::optional<AccountID> const& account,
331 std::optional<std::string> const& ledger_index,
332 std::optional<AccountID> const& ammAccount) const
333{
334 auto const jv = ammRpcInfo(
335 account, ledger_index, std::nullopt, std::nullopt, ammAccount);
336 return expectAmmInfo(asset1, asset2, balance, jv);
337}
338
339bool
341 STAmount const& asset1,
342 STAmount const& asset2,
343 IOUAmount const& balance,
344 Json::Value const& jvres) const
345{
346 if (!jvres.isMember(jss::amm))
347 return false;
348 auto const& jv = jvres[jss::amm];
349 if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) ||
350 !jv.isMember(jss::lp_token))
351 return false;
352 STAmount asset1Info;
353 if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount]))
354 return false;
355 STAmount asset2Info;
356 if (!amountFromJsonNoThrow(asset2Info, jv[jss::amount2]))
357 return false;
358 STAmount lptBalance;
359 if (!amountFromJsonNoThrow(lptBalance, jv[jss::lp_token]))
360 return false;
361 // ammRpcInfo returns unordered assets
362 if (asset1Info.issue() != asset1.issue())
363 std::swap(asset1Info, asset2Info);
364 return asset1 == asset1Info && asset2 == asset2Info &&
365 lptBalance == STAmount{balance, lptIssue_};
366}
367
368void
370 Json::Value& jv,
372{
373 if (assets)
374 {
375 jv[jss::Asset] =
376 STIssue(sfAsset, assets->first).getJson(JsonOptions::none);
377 jv[jss::Asset2] =
378 STIssue(sfAsset, assets->second).getJson(JsonOptions::none);
379 }
380 else
381 {
382 jv[jss::Asset] =
384 jv[jss::Asset2] =
386 }
387}
388
391 std::optional<Account> const& account,
392 Json::Value& jv,
395 std::optional<ter> const& ter)
396{
397 auto const& acct = account ? *account : creatorAccount_;
398 auto const lpTokens = getLPTokensBalance(acct);
399 jv[jss::Account] = acct.human();
400 setTokens(jv, assets);
401 jv[jss::TransactionType] = jss::AMMDeposit;
402 if (fee_ != 0)
403 jv[jss::Fee] = std::to_string(fee_);
404 submit(jv, seq, ter);
405 return getLPTokensBalance(acct) - lpTokens;
406}
407
410 std::optional<Account> const& account,
411 LPToken tokens,
412 std::optional<STAmount> const& asset1In,
414 std::optional<ter> const& ter)
415{
416 return deposit(
417 account,
418 tokens,
419 asset1In,
420 std::nullopt,
421 std::nullopt,
422 flags,
423 std::nullopt,
424 std::nullopt,
425 std::nullopt,
426 ter);
427}
428
431 std::optional<Account> const& account,
432 STAmount const& asset1In,
433 std::optional<STAmount> const& asset2In,
434 std::optional<STAmount> const& maxEP,
436 std::optional<ter> const& ter)
437{
438 assert(!(asset2In && maxEP));
439 return deposit(
440 account,
441 std::nullopt,
442 asset1In,
443 asset2In,
444 maxEP,
445 flags,
446 std::nullopt,
447 std::nullopt,
448 std::nullopt,
449 ter);
450}
451
454 std::optional<Account> const& account,
456 std::optional<STAmount> const& asset1In,
457 std::optional<STAmount> const& asset2In,
458 std::optional<STAmount> const& maxEP,
463 std::optional<ter> const& ter)
464{
465 Json::Value jv;
466 if (tokens)
467 tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenOut]);
468 if (asset1In)
469 asset1In->setJson(jv[jss::Amount]);
470 if (asset2In)
471 asset2In->setJson(jv[jss::Amount2]);
472 if (maxEP)
473 maxEP->setJson(jv[jss::EPrice]);
474 if (tfee)
475 jv[jss::TradingFee] = *tfee;
476 std::uint32_t jvflags = 0;
477 if (flags)
478 jvflags = *flags;
479 // If including asset1In and asset2In or tokens as
480 // deposit min amounts then must set the flags
481 // explicitly instead of relying on this logic.
482 if (!(jvflags & tfDepositSubTx))
483 {
484 if (tokens && !asset1In)
485 jvflags |= tfLPToken;
486 else if (tokens && asset1In)
487 jvflags |= tfOneAssetLPToken;
488 else if (asset1In && asset2In)
489 jvflags |= tfTwoAsset;
490 else if (maxEP && asset1In)
491 jvflags |= tfLimitLPToken;
492 else if (asset1In)
493 jvflags |= tfSingleAsset;
494 }
495 jv[jss::Flags] = jvflags;
496 return deposit(account, jv, assets, seq, ter);
497}
498
501{
502 return deposit(
503 arg.account,
504 arg.tokens,
505 arg.asset1In,
506 arg.asset2In,
507 arg.maxEP,
508 arg.flags,
509 arg.assets,
510 arg.seq,
511 arg.tfee,
512 arg.err);
513}
514
517 std::optional<Account> const& account,
518 Json::Value& jv,
521 std::optional<ter> const& ter)
522{
523 auto const& acct = account ? *account : creatorAccount_;
524 auto const lpTokens = getLPTokensBalance(acct);
525 jv[jss::Account] = acct.human();
526 setTokens(jv, assets);
527 jv[jss::TransactionType] = jss::AMMWithdraw;
528 if (fee_ != 0)
529 jv[jss::Fee] = std::to_string(fee_);
530 submit(jv, seq, ter);
531 return lpTokens - getLPTokensBalance(acct);
532}
533
536 std::optional<Account> const& account,
537 std::optional<LPToken> const& tokens,
538 std::optional<STAmount> const& asset1Out,
540 std::optional<ter> const& ter)
541{
542 return withdraw(
543 account,
544 tokens,
545 asset1Out,
546 std::nullopt,
547 std::nullopt,
548 flags,
549 std::nullopt,
550 std::nullopt,
551 ter);
552}
553
556 std::optional<Account> const& account,
557 STAmount const& asset1Out,
558 std::optional<STAmount> const& asset2Out,
559 std::optional<IOUAmount> const& maxEP,
560 std::optional<ter> const& ter)
561{
562 assert(!(asset2Out && maxEP));
563 return withdraw(
564 account,
565 std::nullopt,
566 asset1Out,
567 asset2Out,
568 maxEP,
569 std::nullopt,
570 std::nullopt,
571 std::nullopt,
572 ter);
573}
574
577 std::optional<Account> const& account,
578 std::optional<LPToken> const& tokens,
579 std::optional<STAmount> const& asset1Out,
580 std::optional<STAmount> const& asset2Out,
581 std::optional<IOUAmount> const& maxEP,
585 std::optional<ter> const& ter)
586{
587 Json::Value jv;
588 if (tokens)
589 tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenIn]);
590 if (asset1Out)
591 asset1Out->setJson(jv[jss::Amount]);
592 if (asset2Out)
593 asset2Out->setJson(jv[jss::Amount2]);
594 if (maxEP)
595 {
596 STAmount const saMaxEP{*maxEP, lptIssue_};
597 saMaxEP.setJson(jv[jss::EPrice]);
598 }
599 std::uint32_t jvflags = 0;
600 if (flags)
601 jvflags = *flags;
602 if (!(jvflags & tfWithdrawSubTx))
603 {
604 if (tokens && !asset1Out)
605 jvflags |= tfLPToken;
606 else if (asset1Out && asset2Out)
607 jvflags |= tfTwoAsset;
608 else if (tokens && asset1Out)
609 jvflags |= tfOneAssetLPToken;
610 else if (asset1Out && maxEP)
611 jvflags |= tfLimitLPToken;
612 else if (asset1Out)
613 jvflags |= tfSingleAsset;
614 }
615 jv[jss::Flags] = jvflags;
616 return withdraw(account, jv, seq, assets, ter);
617}
618
621{
622 return withdraw(
623 arg.account,
624 arg.tokens,
625 arg.asset1Out,
626 arg.asset2Out,
627 arg.maxEP,
628 arg.flags,
629 arg.assets,
630 arg.seq,
631 arg.err);
632}
633
634void
636 std::optional<Account> const& account,
637 std::uint32_t feeVal,
641 std::optional<ter> const& ter)
642{
643 Json::Value jv;
644 jv[jss::Account] = account ? account->human() : creatorAccount_.human();
645 setTokens(jv, assets);
646 jv[jss::TradingFee] = feeVal;
647 jv[jss::TransactionType] = jss::AMMVote;
648 if (flags)
649 jv[jss::Flags] = *flags;
650 if (fee_ != 0)
651 jv[jss::Fee] = std::to_string(fee_);
652 submit(jv, seq, ter);
653}
654
655void
657{
658 return vote(arg.account, arg.tfee, arg.flags, arg.seq, arg.assets, arg.err);
659}
660
662AMM::bid(BidArg const& arg)
663{
664 if (auto const amm =
666 {
667 assert(
668 !env_.current()->rules().enabled(fixInnerObjTemplate) ||
669 amm->isFieldPresent(sfAuctionSlot));
670 if (amm->isFieldPresent(sfAuctionSlot))
671 {
672 auto const& auctionSlot =
673 static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
674 lastPurchasePrice_ = auctionSlot[sfPrice].iou();
675 }
676 }
677 bidMin_ = std::nullopt;
678 bidMax_ = std::nullopt;
679
680 Json::Value jv;
681 jv[jss::Account] =
682 arg.account ? arg.account->human() : creatorAccount_.human();
683 setTokens(jv, arg.assets);
684 auto getBid = [&](auto const& bid) {
685 if (std::holds_alternative<int>(bid))
686 return STAmount{lptIssue_, std::get<int>(bid)};
687 else if (std::holds_alternative<IOUAmount>(bid))
688 return toSTAmount(std::get<IOUAmount>(bid), lptIssue_);
689 else
690 return std::get<STAmount>(bid);
691 };
692 if (arg.bidMin)
693 {
694 STAmount saTokens = getBid(*arg.bidMin);
695 saTokens.setJson(jv[jss::BidMin]);
696 bidMin_ = saTokens.iou();
697 }
698 if (arg.bidMax)
699 {
700 STAmount saTokens = getBid(*arg.bidMax);
701 saTokens.setJson(jv[jss::BidMax]);
702 bidMax_ = saTokens.iou();
703 }
704 if (arg.authAccounts.size() > 0)
705 {
707 for (auto const& account : arg.authAccounts)
708 {
709 Json::Value acct;
710 Json::Value authAcct;
711 acct[jss::Account] = account.human();
712 authAcct[jss::AuthAccount] = acct;
713 accounts.append(authAcct);
714 }
715 jv[jss::AuthAccounts] = accounts;
716 }
717 if (arg.flags)
718 jv[jss::Flags] = *arg.flags;
719 jv[jss::TransactionType] = jss::AMMBid;
720 if (fee_ != 0)
721 jv[jss::Fee] = std::to_string(fee_);
722 return jv;
723}
724
725void
727 Json::Value const& jv,
729 std::optional<ter> const& ter)
730{
731 if (log_)
733 if (msig_)
734 {
735 if (seq && ter)
736 env_(jv, *msig_, *seq, *ter);
737 else if (seq)
738 env_(jv, *msig_, *seq);
739 else if (ter)
740 env_(jv, *msig_, *ter);
741 else
742 env_(jv, *msig_);
743 }
744 else if (seq && ter)
745 env_(jv, *seq, *ter);
746 else if (seq)
747 env_(jv, *seq);
748 else if (ter)
749 env_(jv, *ter);
750 else
751 env_(jv);
752 if (doClose_)
753 env_.close();
754}
755
756bool
758{
759 if (auto const amm =
761 {
762 assert(
763 !env_.current()->rules().enabled(fixInnerObjTemplate) ||
764 amm->isFieldPresent(sfAuctionSlot));
765 if (amm->isFieldPresent(sfAuctionSlot))
766 {
767 auto const& auctionSlot =
768 static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
769 if (auctionSlot.isFieldPresent(sfAccount))
770 {
771 // This could fail in pre-fixInnerObjTemplate tests
772 // if the submitted transactions recreate one of
773 // the failure scenarios. Access as optional
774 // to avoid the failure.
775 auto const slotFee = auctionSlot[~sfDiscountedFee].value_or(0);
776 auto const slotInterval = ammAuctionTimeSlot(
777 env_.app().timeKeeper().now().time_since_epoch().count(),
778 auctionSlot);
779 auto const slotPrice = auctionSlot[sfPrice].iou();
780 auto const authAccounts =
781 auctionSlot.getFieldArray(sfAuthAccounts);
782 return cb(slotFee, slotInterval, slotPrice, authAccounts);
783 }
784 }
785 }
786 return false;
787}
788
789void
791{
792 Json::Value jv;
793 jv[jss::Account] = to_string(deleter);
794 setTokens(jv);
795 jv[jss::TransactionType] = jss::AMMDelete;
796 if (fee_ != 0)
797 jv[jss::Fee] = std::to_string(fee_);
798 submit(jv, std::nullopt, ter);
799}
800
801namespace amm {
803trust(AccountID const& account, STAmount const& amount, std::uint32_t flags)
804{
805 if (isXRP(amount))
806 Throw<std::runtime_error>("trust() requires IOU");
807 Json::Value jv;
808 jv[jss::Account] = to_string(account);
809 jv[jss::LimitAmount] = amount.getJson(JsonOptions::none);
810 jv[jss::TransactionType] = jss::TrustSet;
811 jv[jss::Flags] = flags;
812 return jv;
813}
815pay(Account const& account, AccountID const& to, STAmount const& amount)
816{
817 Json::Value jv;
818 jv[jss::Account] = account.human();
819 jv[jss::Amount] = amount.getJson(JsonOptions::none);
820 jv[jss::Destination] = to_string(to);
821 jv[jss::TransactionType] = jss::Payment;
822 jv[jss::Flags] = tfUniversal;
823 return jv;
824}
825
828 Account const& issuer,
829 Account const& holder,
830 Issue const& asset,
831 Issue const& asset2,
832 std::optional<STAmount> const& amount)
833{
834 Json::Value jv;
835 jv[jss::TransactionType] = jss::AMMClawback;
836 jv[jss::Account] = issuer.human();
837 jv[jss::Holder] = holder.human();
838 jv[jss::Asset] = to_json(asset);
839 jv[jss::Asset2] = to_json(asset2);
840 if (amount)
841 jv[jss::Amount] = amount->getJson(JsonOptions::none);
842
843 return jv;
844}
845} // namespace amm
846} // namespace jtx
847} // namespace test
848} // namespace ripple
T cbegin(T... args)
Represents a JSON value.
Definition: json_value.h:148
std::string toStyledString() const
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:897
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:949
virtual TimeKeeper & timeKeeper()=0
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:47
A currency issued by an account.
Definition: Issue.h:36
void setJson(Json::Value &jv) const
Definition: Issue.cpp:58
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:636
IOUAmount iou() const
Definition: STAmount.cpp:320
XRPAmount xrp() const
Definition: STAmount.cpp:305
void setJson(Json::Value &) const
Definition: STAmount.cpp:507
Issue const & issue() const
Definition: STAmount.h:487
Json::Value getJson(JsonOptions) const override
Definition: STIssue.cpp:102
time_point now() const override
Returns the current time, using the server's clock.
Definition: TimeKeeper.h:64
Convenience class to test AMM functionality.
Definition: AMM.h:122
std::optional< IOUAmount > bidMin_
Definition: AMM.h:133
Issue const lptIssue_
Definition: AMM.h:140
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< Issue > issue1=std::nullopt, std::optional< Issue > issue2=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt, bool ignoreParams=false, unsigned apiVersion=RPC::apiInvalidVersion) const
Send amm_info RPC command.
Definition: AMM.cpp:159
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
Definition: AMM.cpp:726
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:635
std::uint32_t const fee_
Definition: AMM.h:138
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:127
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition: AMM.cpp:273
STAmount const asset2_
Definition: AMM.h:126
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:205
STAmount const asset1_
Definition: AMM.h:125
void ammDelete(AccountID const &deleter, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:790
IOUAmount tokens() const
Definition: AMM.h:335
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
Definition: AMM.cpp:340
IOUAmount lastPurchasePrice_
Definition: AMM.h:132
AccountID const & ammAccount() const
Definition: AMM.h:323
AccountID const ammAccount_
Definition: AMM.h:139
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:310
std::optional< msig > const msig_
Definition: AMM.h:136
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:535
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:230
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:409
Account const creatorAccount_
Definition: AMM.h:124
std::optional< IOUAmount > bidMax_
Definition: AMM.h:134
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition: AMM.cpp:243
Json::Value bid(BidArg const &arg)
Definition: AMM.cpp:662
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, std::optional< AccountID > const &ammAccount=std::nullopt) const
Definition: AMM.cpp:326
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue > > const &assets=std::nullopt)
Definition: AMM.cpp:369
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, bool close=true)
Definition: AMM.cpp:48
bool ammExists() const
Definition: AMM.cpp:318
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition: AMM.cpp:260
Immutable cryptographic account descriptor.
Definition: Account.h:39
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:114
A transaction testing environment.
Definition: Env.h:118
TER ter() const
Return the TER for the last JTx.
Definition: Env.h:581
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:326
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:115
Application & app()
Definition: Env.h:256
beast::Journal const journal
Definition: Env.h:159
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:765
A balance matches.
Definition: balance.h:39
Set the fee on a JTx.
Definition: fee.h:36
Match set account flags.
Definition: flags.h:112
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:35
T cend(T... args)
T find(T... args)
@ nullValue
'null' value
Definition: json_value.h:37
@ arrayValue
array value (ordered list)
Definition: json_value.h:43
static constexpr auto apiInvalidVersion
Definition: ApiVersion.h:56
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:437
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:175
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:803
Json::Value ammClawback(Account const &issuer, Account const &holder, Issue const &asset, Issue const &asset2, std::optional< STAmount > const &amount)
Definition: AMM.cpp:827
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:815
static Number number(STAmount const &a)
Definition: AMM.cpp:33
static IOUAmount initialTokens(STAmount const &asset1, STAmount const &asset2)
Definition: AMM.cpp:41
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)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
constexpr std::uint32_t tfSingleAsset
Definition: TxFlags.h:206
@ fhZERO_IF_FROZEN
Definition: View.h:75
@ fhIGNORE_FREEZE
Definition: View.h:75
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition: AMMCore.cpp:120
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
constexpr std::uint32_t tfLimitLPToken
Definition: TxFlags.h:209
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
Definition: AMMCore.cpp:69
constexpr std::uint32_t tfOneAssetLPToken
Definition: TxFlags.h:208
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:43
constexpr std::uint32_t tfTwoAsset
Definition: TxFlags.h:207
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:111
Json::Value to_json(Asset const &asset)
Definition: Asset.cpp:82
constexpr std::uint32_t tfDepositSubTx
Definition: TxFlags.h:214
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
constexpr std::uint32_t tfLPToken
Definition: TxFlags.h:203
constexpr std::uint32_t tfUniversal
Definition: TxFlags.h:61
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1061
@ tesSUCCESS
Definition: TER.h:242
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:308
constexpr std::uint32_t tfWithdrawSubTx
Definition: TxFlags.h:211
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
Number root2(Number f)
Definition: Number.cpp:700
STL namespace.
std::vector< Account > authAccounts
Definition: AMM.h:114
std::optional< std::variant< int, IOUAmount, STAmount > > bidMin
Definition: AMM.h:112
std::optional< std::uint32_t > flags
Definition: AMM.h:115
std::optional< std::variant< int, IOUAmount, STAmount > > bidMax
Definition: AMM.h:113
std::optional< Account > account
Definition: AMM.h:111
std::optional< std::pair< Issue, Issue > > assets
Definition: AMM.h:116
std::optional< std::uint32_t > flags
Definition: AMM.h:79
std::optional< jtx::seq > seq
Definition: AMM.h:81
std::optional< Account > account
Definition: AMM.h:74
std::optional< STAmount > asset1In
Definition: AMM.h:76
std::optional< std::pair< Issue, Issue > > assets
Definition: AMM.h:80
std::optional< ter > err
Definition: AMM.h:83
std::optional< STAmount > maxEP
Definition: AMM.h:78
std::optional< STAmount > asset2In
Definition: AMM.h:77
std::optional< std::uint16_t > tfee
Definition: AMM.h:82
std::optional< LPToken > tokens
Definition: AMM.h:75
std::optional< ter > err
Definition: AMM.h:106
std::optional< Account > account
Definition: AMM.h:101
std::uint32_t tfee
Definition: AMM.h:102
std::optional< jtx::seq > seq
Definition: AMM.h:104
std::optional< std::uint32_t > flags
Definition: AMM.h:103
std::optional< std::pair< Issue, Issue > > assets
Definition: AMM.h:105
std::optional< STAmount > asset2Out
Definition: AMM.h:91
std::optional< IOUAmount > maxEP
Definition: AMM.h:92
std::optional< Account > account
Definition: AMM.h:88
std::optional< std::uint32_t > flags
Definition: AMM.h:93
std::optional< STAmount > asset1Out
Definition: AMM.h:90
std::optional< std::pair< Issue, Issue > > assets
Definition: AMM.h:94
std::optional< LPToken > tokens
Definition: AMM.h:89
std::optional< ter > err
Definition: AMM.h:96
std::optional< jtx::seq > seq
Definition: AMM.h:95
Set the sequence number on a JTx.
Definition: seq.h:34
T swap(T... args)
T to_string(T... args)