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