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