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,
429 flags,
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,
449 asset1In,
450 asset2In,
451 maxEP,
452 flags,
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,
555 flags,
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,
573 asset1Out,
574 asset2Out,
575 maxEP,
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 }
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) {
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:149
Value & append(Value const &value)
Append value to array at the end.
std::string toStyledString() const
bool isMember(char const *key) const
Return true if the object has a member named key.
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:33
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:795
XRPAmount xrp() const
Definition STAmount.cpp:306
void setJson(Json::Value &) const
Definition STAmount.cpp:666
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:118
A transaction testing environment.
Definition Env.h:121
TER ter() const
Return the TER for the last JTx.
Definition Env.h:598
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:121
bool enabled(uint256 feature) const
Definition Env.h:638
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:791
A balance matches.
Definition balance.h:39
Set the fee on a JTx.
Definition fee.h:37
Match set account flags.
Definition flags.h:128
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)
T is_same_v
@ nullValue
'null' value
Definition json_value.h:38
@ arrayValue
array value (ordered list)
Definition json_value.h:44
static constexpr auto apiInvalidVersion
Definition ApiVersion.h:55
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:25
constexpr std::uint32_t tfSingleAsset
Definition TxFlags.h:247
@ fhZERO_IF_FROZEN
Definition View.h:77
@ fhIGNORE_FREEZE
Definition View.h:77
bool isXRP(AccountID const &c)
Definition AccountID.h:90
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:250
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:249
constexpr std::uint32_t tfTwoAsset
Definition TxFlags.h:248
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:113
Json::Value to_json(Asset const &asset)
Definition Asset.h:123
constexpr std::uint32_t tfDepositSubTx
Definition TxFlags.h:255
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:31
constexpr std::uint32_t tfLPToken
Definition TxFlags.h:244
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
@ 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:384
constexpr std::uint32_t tfWithdrawSubTx
Definition TxFlags.h:252
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)