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