rippled
Loading...
Searching...
No Matches
AMM.cpp
1#include <test/jtx/AMM.h>
2#include <test/jtx/Env.h>
3
4#include <xrpld/app/misc/AMMHelpers.h>
5#include <xrpld/app/misc/AMMUtils.h>
6
7#include <xrpl/protocol/AMMCore.h>
8#include <xrpl/protocol/AmountConversions.h>
9#include <xrpl/protocol/ApiVersion.h>
10#include <xrpl/protocol/jss.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 , bidMin_()
57 , bidMax_()
58 , msig_(ms)
59 , fee_(fee)
60 , ammAccount_(create(tfee, flags, seq, ter))
61 , lptIssue_(xrpl::ammLPTIssue(asset1_.issue().currency, asset2_.issue().currency, ammAccount_))
62 , initialLPTokens_(initialTokens())
63{
64}
65
67 Env& env,
68 Account const& account,
69 STAmount const& asset1,
70 STAmount const& asset2,
71 ter const& ter,
72 bool log,
73 bool close)
74 : AMM(env, account, asset1, asset2, log, 0, 0, std::nullopt, std::nullopt, std::nullopt, ter, close)
75{
76}
77
78AMM::AMM(Env& env, Account const& account, STAmount const& asset1, STAmount const& asset2, CreateArg const& arg)
79 : AMM(env, account, asset1, asset2, arg.log, arg.tfee, arg.fee, arg.flags, arg.seq, arg.ms, arg.err, arg.close)
80{
81}
82
83[[nodiscard]] AccountID
85 std::uint32_t tfee,
89{
90 Json::Value jv;
91 jv[jss::Account] = creatorAccount_.human();
92 jv[jss::Amount] = asset1_.getJson(JsonOptions::none);
93 jv[jss::Amount2] = asset2_.getJson(JsonOptions::none);
94 jv[jss::TradingFee] = tfee;
95 jv[jss::TransactionType] = jss::AMMCreate;
96 if (flags)
97 jv[jss::Flags] = *flags;
98 if (fee_ != 0)
99 jv[sfFee] = std::to_string(fee_);
100 else
101 jv[jss::Fee] = std::to_string(env_.current()->fees().increment.drops());
102 submit(jv, seq, ter);
103
104 if (!ter || env_.ter() == tesSUCCESS)
105 {
106 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
107 {
108 return amm->getAccountID(sfAccount);
109 }
110 }
111 return {};
112}
113
116 std::optional<AccountID> const& account,
117 std::optional<std::string> const& ledgerIndex,
120 std::optional<AccountID> const& ammAccount,
121 bool ignoreParams,
122 unsigned apiVersion) const
123{
124 Json::Value jv;
125 if (account)
126 jv[jss::account] = to_string(*account);
127 if (ledgerIndex)
128 jv[jss::ledger_index] = *ledgerIndex;
129 if (!ignoreParams)
130 {
131 if (issue1 || issue2)
132 {
133 if (issue1)
134 jv[jss::asset] = STIssue(sfAsset, *issue1).getJson(JsonOptions::none);
135 if (issue2)
136 jv[jss::asset2] = STIssue(sfAsset2, *issue2).getJson(JsonOptions::none);
137 }
138 else if (!ammAccount)
139 {
140 jv[jss::asset] = STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
141 jv[jss::asset2] = STIssue(sfAsset2, asset2_.issue()).getJson(JsonOptions::none);
142 }
143 if (ammAccount)
144 jv[jss::amm_account] = to_string(*ammAccount);
145 }
146 auto jr =
147 (apiVersion == RPC::apiInvalidVersion ? env_.rpc("json", "amm_info", to_string(jv))
148 : env_.rpc(apiVersion, "json", "amm_info", to_string(jv)));
149 if (jr.isObject() && jr.isMember(jss::result) && jr[jss::result].isMember(jss::status))
150 return jr[jss::result];
151 return Json::nullValue;
152}
153
155AMM::balances(Issue const& issue1, Issue const& issue2, std::optional<AccountID> const& account) const
156{
157 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
158 {
159 auto const ammAccountID = amm->getAccountID(sfAccount);
160 auto const [asset1Balance, asset2Balance] =
161 ammPoolHolds(*env_.current(), ammAccountID, issue1, issue2, FreezeHandling::fhIGNORE_FREEZE, env_.journal);
162 auto const lptAMMBalance =
163 account ? ammLPHolds(*env_.current(), *amm, *account, env_.journal) : amm->getFieldAmount(sfLPTokenBalance);
164 return {asset1Balance, asset2Balance, lptAMMBalance};
165 }
166 return {STAmount{}, STAmount{}, STAmount{}};
167}
168
169bool
171 STAmount const& asset1,
172 STAmount const& asset2,
173 IOUAmount const& lpt,
174 std::optional<AccountID> const& account) const
175{
176 auto const [asset1Balance, asset2Balance, lptAMMBalance] = balances(asset1.issue(), asset2.issue(), account);
177 return asset1 == asset1Balance && asset2 == asset2Balance && lptAMMBalance == STAmount{lpt, lptIssue_};
178}
179
182{
183 if (account)
185 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
186 return amm->getFieldAmount(sfLPTokenBalance).iou();
187 return IOUAmount{0};
188}
189
190bool
191AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
192{
193 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
194 {
195 auto const lptAMMBalance = ammLPHolds(*env_.current(), *amm, account, env_.journal);
196 return lptAMMBalance == STAmount{expTokens, lptIssue_};
197 }
198 return false;
199}
200
201bool
203{
204 return expectAuctionSlot(
205 [&](std::uint32_t slotFee, std::optional<std::uint8_t> slotInterval, IOUAmount const& slotPrice, auto const&) {
206 return slotFee == fee &&
207 // Auction slot might be expired, in which case slotInterval is
208 // 0
209 ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) && slotPrice == expectedPrice;
210 });
211}
212
213bool
215{
216 return expectAuctionSlot(
217 [&](std::uint32_t, std::optional<std::uint8_t>, IOUAmount const&, STArray const& accounts) {
218 for (auto const& account : accounts)
219 {
220 if (std::find(authAccounts.cbegin(), authAccounts.cend(), account.getAccountID(sfAccount)) ==
221 authAccounts.end())
222 return false;
223 }
224 return true;
225 });
226}
227
228bool
230{
231 auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()));
232 return amm && (*amm)[sfTradingFee] == fee;
233}
234
235bool
237{
238 return env_.current()->read(keylet::account(ammAccount_)) != nullptr &&
239 env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) != nullptr;
240}
241
242bool
244 STAmount const& asset1,
245 STAmount const& asset2,
246 IOUAmount const& balance,
247 std::optional<AccountID> const& account,
248 std::optional<std::string> const& ledger_index,
249 std::optional<AccountID> const& ammAccount) const
250{
251 auto const jv = ammRpcInfo(account, ledger_index, std::nullopt, std::nullopt, ammAccount);
252 return expectAmmInfo(asset1, asset2, balance, jv);
253}
254
255bool
256AMM::expectAmmInfo(STAmount const& asset1, STAmount const& asset2, IOUAmount const& balance, Json::Value const& jvres)
257 const
258{
259 if (!jvres.isMember(jss::amm))
260 return false;
261 auto const& jv = jvres[jss::amm];
262 if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) || !jv.isMember(jss::lp_token))
263 return false;
264 STAmount asset1Info;
265 if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount]))
266 return false;
267 STAmount asset2Info;
268 if (!amountFromJsonNoThrow(asset2Info, jv[jss::amount2]))
269 return false;
270 STAmount lptBalance;
271 if (!amountFromJsonNoThrow(lptBalance, jv[jss::lp_token]))
272 return false;
273 // ammRpcInfo returns unordered assets
274 if (asset1Info.issue() != asset1.issue())
275 std::swap(asset1Info, asset2Info);
276 return asset1 == asset1Info && asset2 == asset2Info && lptBalance == STAmount{balance, lptIssue_};
277}
278
279void
281{
282 if (assets)
283 {
284 jv[jss::Asset] = STIssue(sfAsset, assets->first).getJson(JsonOptions::none);
285 jv[jss::Asset2] = STIssue(sfAsset, assets->second).getJson(JsonOptions::none);
286 }
287 else
288 {
289 jv[jss::Asset] = STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
290 jv[jss::Asset2] = STIssue(sfAsset, asset2_.issue()).getJson(JsonOptions::none);
291 }
292}
293
296 std::optional<Account> const& account,
297 Json::Value& jv,
300 std::optional<ter> const& ter)
301{
302 auto const& acct = account ? *account : creatorAccount_;
303 auto const lpTokens = getLPTokensBalance(acct);
304 jv[jss::Account] = acct.human();
305 setTokens(jv, assets);
306 jv[jss::TransactionType] = jss::AMMDeposit;
307 if (fee_ != 0)
308 jv[jss::Fee] = std::to_string(fee_);
309 submit(jv, seq, ter);
310 return getLPTokensBalance(acct) - lpTokens;
311}
312
315 std::optional<Account> const& account,
316 LPToken tokens,
317 std::optional<STAmount> const& asset1In,
319 std::optional<ter> const& ter)
320{
321 return deposit(
323}
324
327 std::optional<Account> const& account,
328 STAmount const& asset1In,
329 std::optional<STAmount> const& asset2In,
330 std::optional<STAmount> const& maxEP,
332 std::optional<ter> const& ter)
333{
334 assert(!(asset2In && maxEP));
335 return deposit(
336 account, std::nullopt, asset1In, asset2In, maxEP, flags, std::nullopt, std::nullopt, std::nullopt, ter);
337}
338
341 std::optional<Account> const& account,
343 std::optional<STAmount> const& asset1In,
344 std::optional<STAmount> const& asset2In,
345 std::optional<STAmount> const& maxEP,
350 std::optional<ter> const& ter)
351{
352 Json::Value jv;
353 if (tokens)
354 tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenOut]);
355 if (asset1In)
356 asset1In->setJson(jv[jss::Amount]);
357 if (asset2In)
358 asset2In->setJson(jv[jss::Amount2]);
359 if (maxEP)
360 maxEP->setJson(jv[jss::EPrice]);
361 if (tfee)
362 jv[jss::TradingFee] = *tfee;
363 std::uint32_t jvflags = 0;
364 if (flags)
365 jvflags = *flags;
366 // If including asset1In and asset2In or tokens as
367 // deposit min amounts then must set the flags
368 // explicitly instead of relying on this logic.
369 if (!(jvflags & tfDepositSubTx))
370 {
371 if (tokens && !asset1In)
372 jvflags |= tfLPToken;
373 else if (tokens && asset1In)
374 jvflags |= tfOneAssetLPToken;
375 else if (asset1In && asset2In)
376 jvflags |= tfTwoAsset;
377 else if (maxEP && asset1In)
378 jvflags |= tfLimitLPToken;
379 else if (asset1In)
380 jvflags |= tfSingleAsset;
381 }
382 jv[jss::Flags] = jvflags;
383 return deposit(account, jv, assets, seq, ter);
384}
385
388{
389 return deposit(
390 arg.account,
391 arg.tokens,
392 arg.asset1In,
393 arg.asset2In,
394 arg.maxEP,
395 arg.flags,
396 arg.assets,
397 arg.seq,
398 arg.tfee,
399 arg.err);
400}
401
404 std::optional<Account> const& account,
405 Json::Value& jv,
408 std::optional<ter> const& ter)
409{
410 auto const& acct = account ? *account : creatorAccount_;
411 auto const lpTokens = getLPTokensBalance(acct);
412 jv[jss::Account] = acct.human();
413 setTokens(jv, assets);
414 jv[jss::TransactionType] = jss::AMMWithdraw;
415 if (fee_ != 0)
416 jv[jss::Fee] = std::to_string(fee_);
417 submit(jv, seq, ter);
418 return lpTokens - getLPTokensBalance(acct);
419}
420
423 std::optional<Account> const& account,
424 std::optional<LPToken> const& tokens,
425 std::optional<STAmount> const& asset1Out,
427 std::optional<ter> const& ter)
428{
429 return withdraw(account, tokens, asset1Out, std::nullopt, std::nullopt, flags, std::nullopt, std::nullopt, ter);
430}
431
434 std::optional<Account> const& account,
435 STAmount const& asset1Out,
436 std::optional<STAmount> const& asset2Out,
437 std::optional<IOUAmount> const& maxEP,
438 std::optional<ter> const& ter)
439{
440 assert(!(asset2Out && maxEP));
441 return withdraw(account, std::nullopt, asset1Out, asset2Out, maxEP, std::nullopt, std::nullopt, std::nullopt, ter);
442}
443
446 std::optional<Account> const& account,
447 std::optional<LPToken> const& tokens,
448 std::optional<STAmount> const& asset1Out,
449 std::optional<STAmount> const& asset2Out,
450 std::optional<IOUAmount> const& maxEP,
454 std::optional<ter> const& ter)
455{
456 Json::Value jv;
457 if (tokens)
458 tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenIn]);
459 if (asset1Out)
460 asset1Out->setJson(jv[jss::Amount]);
461 if (asset2Out)
462 asset2Out->setJson(jv[jss::Amount2]);
463 if (maxEP)
464 {
465 STAmount const saMaxEP{*maxEP, lptIssue_};
466 saMaxEP.setJson(jv[jss::EPrice]);
467 }
468 std::uint32_t jvflags = 0;
469 if (flags)
470 jvflags = *flags;
471 if (!(jvflags & tfWithdrawSubTx))
472 {
473 if (tokens && !asset1Out)
474 jvflags |= tfLPToken;
475 else if (asset1Out && asset2Out)
476 jvflags |= tfTwoAsset;
477 else if (tokens && asset1Out)
478 jvflags |= tfOneAssetLPToken;
479 else if (asset1Out && maxEP)
480 jvflags |= tfLimitLPToken;
481 else if (asset1Out)
482 jvflags |= tfSingleAsset;
483 }
484 jv[jss::Flags] = jvflags;
485 return withdraw(account, jv, seq, assets, ter);
486}
487
490{
491 return withdraw(
492 arg.account, arg.tokens, arg.asset1Out, arg.asset2Out, arg.maxEP, arg.flags, arg.assets, arg.seq, arg.err);
493}
494
495void
497 std::optional<Account> const& account,
498 std::uint32_t feeVal,
502 std::optional<ter> const& ter)
503{
504 Json::Value jv;
505 jv[jss::Account] = account ? account->human() : creatorAccount_.human();
506 setTokens(jv, assets);
507 jv[jss::TradingFee] = feeVal;
508 jv[jss::TransactionType] = jss::AMMVote;
509 if (flags)
510 jv[jss::Flags] = *flags;
511 if (fee_ != 0)
512 jv[jss::Fee] = std::to_string(fee_);
513 submit(jv, seq, ter);
514}
515
516void
518{
519 return vote(arg.account, arg.tfee, arg.flags, arg.seq, arg.assets, arg.err);
520}
521
523AMM::bid(BidArg const& arg)
524{
525 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
526 {
527 assert(!env_.current()->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot));
528 if (amm->isFieldPresent(sfAuctionSlot))
529 {
530 auto const& auctionSlot = static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
531 lastPurchasePrice_ = auctionSlot[sfPrice].iou();
532 }
533 }
536
537 Json::Value jv;
538 jv[jss::Account] = arg.account ? arg.account->human() : creatorAccount_.human();
539 setTokens(jv, arg.assets);
540 auto getBid = [&](auto const& bid) {
544 return toSTAmount(std::get<IOUAmount>(bid), lptIssue_);
545 else
546 return std::get<STAmount>(bid);
547 };
548 if (arg.bidMin)
549 {
550 STAmount saTokens = getBid(*arg.bidMin);
551 saTokens.setJson(jv[jss::BidMin]);
552 bidMin_ = saTokens.iou();
553 }
554 if (arg.bidMax)
555 {
556 STAmount saTokens = getBid(*arg.bidMax);
557 saTokens.setJson(jv[jss::BidMax]);
558 bidMax_ = saTokens.iou();
559 }
560 if (arg.authAccounts.size() > 0)
561 {
563 for (auto const& account : arg.authAccounts)
564 {
565 Json::Value acct;
566 Json::Value authAcct;
567 acct[jss::Account] = account.human();
568 authAcct[jss::AuthAccount] = acct;
569 accounts.append(authAcct);
570 }
571 jv[jss::AuthAccounts] = accounts;
572 }
573 if (arg.flags)
574 jv[jss::Flags] = *arg.flags;
575 jv[jss::TransactionType] = jss::AMMBid;
576 if (fee_ != 0)
577 jv[jss::Fee] = std::to_string(fee_);
578 return jv;
579}
580
581void
583{
584 if (log_)
586 if (msig_)
587 {
588 if (seq && ter)
589 env_(jv, *msig_, *seq, *ter);
590 else if (seq)
591 env_(jv, *msig_, *seq);
592 else if (ter)
593 env_(jv, *msig_, *ter);
594 else
595 env_(jv, *msig_);
596 }
597 else if (seq && ter)
598 env_(jv, *seq, *ter);
599 else if (seq)
600 env_(jv, *seq);
601 else if (ter)
602 env_(jv, *ter);
603 else
604 env_(jv);
605 if (doClose_)
606 env_.close();
607}
608
609bool
611{
612 if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
613 {
614 assert(!env_.current()->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot));
615 if (amm->isFieldPresent(sfAuctionSlot))
616 {
617 auto const& auctionSlot = static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
618 if (auctionSlot.isFieldPresent(sfAccount))
619 {
620 // This could fail in pre-fixInnerObjTemplate tests
621 // if the submitted transactions recreate one of
622 // the failure scenarios. Access as optional
623 // to avoid the failure.
624 auto const slotFee = auctionSlot[~sfDiscountedFee].value_or(0);
625 auto const slotInterval =
626 ammAuctionTimeSlot(env_.app().timeKeeper().now().time_since_epoch().count(), auctionSlot);
627 auto const slotPrice = auctionSlot[sfPrice].iou();
628 auto const authAccounts = auctionSlot.getFieldArray(sfAuthAccounts);
629 return cb(slotFee, slotInterval, slotPrice, authAccounts);
630 }
631 }
632 }
633 return false;
634}
635
636void
638{
639 Json::Value jv;
640 jv[jss::Account] = to_string(deleter);
641 setTokens(jv);
642 jv[jss::TransactionType] = jss::AMMDelete;
643 if (fee_ != 0)
644 jv[jss::Fee] = std::to_string(fee_);
645 submit(jv, std::nullopt, ter);
646}
647
648namespace amm {
651{
652 if (isXRP(amount))
653 Throw<std::runtime_error>("trust() requires IOU");
654 Json::Value jv;
655 jv[jss::Account] = to_string(account);
656 jv[jss::LimitAmount] = amount.getJson(JsonOptions::none);
657 jv[jss::TransactionType] = jss::TrustSet;
658 jv[jss::Flags] = flags;
659 return jv;
660}
662pay(Account const& account, AccountID const& to, STAmount const& amount)
663{
664 Json::Value jv;
665 jv[jss::Account] = account.human();
666 jv[jss::Amount] = amount.getJson(JsonOptions::none);
667 jv[jss::Destination] = to_string(to);
668 jv[jss::TransactionType] = jss::Payment;
669 return jv;
670}
671
674 Account const& issuer,
675 Account const& holder,
676 Issue const& asset,
677 Issue const& asset2,
679{
680 Json::Value jv;
681 jv[jss::TransactionType] = jss::AMMClawback;
682 jv[jss::Account] = issuer.human();
683 jv[jss::Holder] = holder.human();
684 jv[jss::Asset] = to_json(asset);
685 jv[jss::Asset2] = to_json(asset2);
686 if (amount)
687 jv[jss::Amount] = amount->getJson(JsonOptions::none);
688
689 return jv;
690}
691} // namespace amm
692} // namespace jtx
693} // namespace test
694} // namespace xrpl
T cbegin(T... args)
Represents a JSON value.
Definition json_value.h:131
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:26
A currency issued by an account.
Definition Issue.h:14
void setJson(Json::Value &jv) const
Definition Issue.cpp:39
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:721
Issue const & issue() const
Definition STAmount.h:455
void setJson(Json::Value &) const
Definition STAmount.cpp:599
IOUAmount iou() const
Definition STAmount.cpp:264
XRPAmount xrp() const
Definition STAmount.cpp:249
Json::Value getJson(JsonOptions) const override
Definition STIssue.cpp:78
time_point now() const override
Returns the current time, using the server's clock.
Definition TimeKeeper.h:44
Convenience class to test AMM functionality.
Definition AMM.h:105
bool expectTradingFee(std::uint16_t fee) const
Definition AMM.cpp:229
Issue const lptIssue_
Definition AMM.h:122
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition AMM.cpp:181
std::optional< IOUAmount > bidMax_
Definition AMM.h:116
AccountID const ammAccount_
Definition AMM.h:121
bool ammExists() const
Definition AMM.cpp:236
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue > > const &assets=std::nullopt)
Definition AMM.cpp:280
IOUAmount lastPurchasePrice_
Definition AMM.h:114
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:496
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition AMM.cpp:202
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
Definition AMM.cpp:582
void ammDelete(AccountID const &deleter, std::optional< ter > const &ter=std::nullopt)
Definition AMM.cpp:637
IOUAmount tokens() const
Definition AMM.h:310
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:155
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:243
Account const creatorAccount_
Definition AMM.h:107
std::uint32_t const fee_
Definition AMM.h:120
std::optional< msig > const msig_
Definition AMM.h:118
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:422
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:314
STAmount const asset2_
Definition AMM.h:109
AccountID const & ammAccount() const
Definition AMM.h:298
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:115
Json::Value bid(BidArg const &arg)
Definition AMM.cpp:523
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:84
std::optional< IOUAmount > bidMin_
Definition AMM.h:115
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition AMM.cpp:191
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
Definition AMM.cpp:256
IOUAmount initialTokens()
Definition AMM.cpp:25
STAmount const asset1_
Definition AMM.h:108
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:170
Immutable cryptographic account descriptor.
Definition Account.h:20
std::string const & human() const
Returns the human readable public key.
Definition Account.h:95
A transaction testing environment.
Definition Env.h:98
Application & app()
Definition Env.h:230
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:97
TER ter() const
Return the TER for the last JTx.
Definition Env.h:560
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:749
bool enabled(uint256 feature) const
Definition Env.h:600
beast::Journal const journal
Definition Env.h:139
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:298
A balance matches.
Definition balance.h:20
Set the fee on a JTx.
Definition fee.h:18
Match set account flags.
Definition flags.h:109
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:16
T cend(T... args)
T find(T... args)
T is_same_v
@ nullValue
'null' value
Definition json_value.h:20
@ arrayValue
array value (ordered list)
Definition json_value.h:26
STL namespace.
static constexpr auto apiInvalidVersion
Definition ApiVersion.h:41
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:393
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:650
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition AMM.cpp:662
Json::Value ammClawback(Account const &issuer, Account const &holder, Issue const &asset, Issue const &asset2, std::optional< STAmount > const &amount)
Definition AMM.cpp:673
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
auto const amount
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ fhZERO_IF_FROZEN
Definition View.h:59
@ fhIGNORE_FREEZE
Definition View.h:59
bool isXRP(AccountID const &c)
Definition AccountID.h:71
constexpr std::uint32_t tfSingleAsset
Definition TxFlags.h:228
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
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)
Definition View.cpp:392
constexpr std::uint32_t tfTwoAsset
Definition TxFlags.h:229
constexpr std::uint32_t tfOneAssetLPToken
Definition TxFlags.h:230
constexpr std::uint32_t tfDepositSubTx
Definition TxFlags.h:236
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
constexpr std::uint32_t tfWithdrawSubTx
Definition TxFlags.h:233
Json::Value to_json(Asset const &asset)
Definition Asset.h:122
Number root2(Number f)
Definition Number.cpp:1010
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
constexpr std::uint32_t tfLimitLPToken
Definition TxFlags.h:231
constexpr std::uint32_t tfLPToken
Definition TxFlags.h:225
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition AMMCore.cpp:77
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:226
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:80
T size(T... args)
std::optional< Account > account
Definition AMM.h:94
std::optional< std::variant< int, IOUAmount, STAmount > > bidMin
Definition AMM.h:95
std::vector< Account > authAccounts
Definition AMM.h:97
std::optional< std::variant< int, IOUAmount, STAmount > > bidMax
Definition AMM.h:96
std::optional< std::pair< Issue, Issue > > assets
Definition AMM.h:99
std::optional< std::uint32_t > flags
Definition AMM.h:98
std::optional< std::uint32_t > flags
Definition AMM.h:62
std::optional< std::uint16_t > tfee
Definition AMM.h:65
std::optional< LPToken > tokens
Definition AMM.h:58
std::optional< STAmount > maxEP
Definition AMM.h:61
std::optional< jtx::seq > seq
Definition AMM.h:64
std::optional< std::pair< Issue, Issue > > assets
Definition AMM.h:63
std::optional< ter > err
Definition AMM.h:66
std::optional< Account > account
Definition AMM.h:57
std::optional< STAmount > asset2In
Definition AMM.h:60
std::optional< STAmount > asset1In
Definition AMM.h:59
std::optional< ter > err
Definition AMM.h:89
std::uint32_t tfee
Definition AMM.h:85
std::optional< std::pair< Issue, Issue > > assets
Definition AMM.h:88
std::optional< jtx::seq > seq
Definition AMM.h:87
std::optional< Account > account
Definition AMM.h:84
std::optional< std::uint32_t > flags
Definition AMM.h:86
std::optional< STAmount > asset2Out
Definition AMM.h:74
std::optional< std::pair< Issue, Issue > > assets
Definition AMM.h:77
std::optional< IOUAmount > maxEP
Definition AMM.h:75
std::optional< ter > err
Definition AMM.h:79
std::optional< STAmount > asset1Out
Definition AMM.h:73
std::optional< std::uint32_t > flags
Definition AMM.h:76
std::optional< Account > account
Definition AMM.h:71
std::optional< LPToken > tokens
Definition AMM.h:72
std::optional< jtx::seq > seq
Definition AMM.h:78
Set the sequence number on a JTx.
Definition seq.h:15
T swap(T... args)
T to_string(T... args)