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