20 #include <test/jtx/AMM.h>
22 #include <ripple/app/misc/AMMUtils.h>
23 #include <ripple/protocol/AMMCore.h>
24 #include <ripple/protocol/AmountConversions.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
27 #include <test/jtx/Env.h>
46 product.mantissa() >= 0 ?
root2(product) :
root2(-product));
62 , creatorAccount_(account)
67 , lastPurchasePrice_(0)
74 asset1_.issue().currency,
75 asset2_.issue().currency,
112 jv[jss::TradingFee] = tfee;
113 jv[jss::TransactionType] = jss::AMMCreate;
115 jv[jss::Flags] = *
flags;
143 jv[jss::ledger_index] = *ledgerIndex;
159 if (jr.isObject() && jr.isMember(jss::result) &&
160 jr[jss::result].isMember(jss::status))
161 return jr[jss::result];
175 auto const [asset1Balance, asset2Balance] =
ammPoolHolds(
180 FreezeHandling::fhIGNORE_FREEZE,
182 auto const lptAMMBalance = account
185 return {asset1Balance, asset2Balance, lptAMMBalance};
197 auto const [asset1Balance, asset2Balance, lptAMMBalance] =
199 return asset1 == asset1Balance && asset2 == asset2Balance &&
212 FreezeHandling::fhZERO_IF_FROZEN,
227 auto const lptAMMBalance =
244 return slotFee ==
fee &&
247 ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) &&
248 slotPrice == expectedPrice;
259 for (
auto const& account : accounts)
295 auto const jv =
ammRpcInfo(account, ledger_index);
308 auto const& jv = jvres[jss::amm];
309 if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) ||
310 !jv.isMember(jss::lp_token))
324 return asset1 == asset1Info && asset2 == asset2Info &&
359 jv[jss::Account] = acct.human();
361 jv[jss::TransactionType] = jss::AMMDeposit;
397 assert(!(asset2In && maxEP));
426 asset1In->setJson(jv[jss::Amount]);
428 asset2In->setJson(jv[jss::Amount2]);
430 maxEP->setJson(jv[jss::EPrice]);
441 else if (
tokens && asset1In)
443 else if (asset1In && asset2In)
445 else if (maxEP && asset1In)
450 jv[jss::Flags] = jvflags;
464 jv[jss::Account] = acct.human();
466 jv[jss::TransactionType] = jss::AMMWithdraw;
501 assert(!(asset2Out && maxEP));
530 asset1Out->setJson(jv[jss::Amount]);
532 asset2Out->setJson(jv[jss::Amount2]);
536 saMaxEP.setJson(jv[jss::EPrice]);
545 else if (asset1Out && asset2Out)
547 else if (
tokens && asset1Out)
549 else if (asset1Out && maxEP)
554 jv[jss::Flags] = jvflags;
570 jv[jss::TradingFee] = feeVal;
571 jv[jss::TransactionType] = jss::AMMVote;
573 jv[jss::Flags] = *
flags;
595 auto const& auctionSlot =
606 auto getBid = [&](
auto const&
bid) {
607 if (std::holds_alternative<int>(
bid))
609 else if (std::holds_alternative<IOUAmount>(
bid))
612 return std::get<STAmount>(
bid);
616 STAmount saTokens = getBid(*bidMin);
617 saTokens.
setJson(jv[jss::BidMin]);
622 STAmount saTokens = getBid(*bidMax);
623 saTokens.
setJson(jv[jss::BidMax]);
626 if (authAccounts.
size() > 0)
629 for (
auto const& account : authAccounts)
633 acct[jss::Account] = account.human();
634 authAcct[jss::AuthAccount] = acct;
635 accounts.
append(authAcct);
637 jv[jss::AuthAccounts] = accounts;
640 jv[jss::Flags] = *
flags;
641 jv[jss::TransactionType] = jss::AMMBid;
684 auto const& auctionSlot =
686 if (auctionSlot.isFieldPresent(
sfAccount))
692 auto const slotPrice = auctionSlot[
sfPrice].iou();
693 auto const authAccounts = auctionSlot.getFieldArray(
sfAuthAccounts);
694 return cb(slotFee, slotInterval, slotPrice, authAccounts);
705 Throw<std::runtime_error>(
"trust() requires IOU");
709 jv[jss::TransactionType] = jss::TrustSet;
710 jv[jss::Flags] =
flags;
717 jv[jss::Account] = account.human();
720 jv[jss::TransactionType] = jss::Payment;
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
const SF_UINT16 sfDiscountedFee
A currency issued by an account.
const std::optional< msig > msig_
Issue const & issue() const
Set the expected result code for a JTx The test will fail if the code doesn't match.
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
@ arrayValue
array value (ordered list)
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< std::pair< Issue, Issue >> tokens=std::nullopt) const
Send amm_info RPC command.
const SF_AMOUNT sfLPTokenBalance
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Json::Value getJson(JsonOptions) const override
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)
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
std::string const & human() const
Returns the human readable public key.
const beast::Journal journal
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)
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, 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)
Floating point representation of amounts with high dynamic range.
Convenience class to test AMM functionality.
std::string toStyledString() const
virtual TimeKeeper & timeKeeper()=0
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
const Account creatorAccount_
TER ter() const
Return the TER for the last JTx.
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
const SF_UINT16 sfTradingFee
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
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.
Json::Value getJson(JsonOptions) const override
Value & append(const Value &value)
Append value to array at the end.
void setJson(Json::Value &) const
static IOUAmount initialTokens(STAmount const &asset1, STAmount const &asset2)
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Keylet account(AccountID const &id) noexcept
AccountID root.
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) const
IOUAmount lastPurchasePrice_
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
const SField sfAuthAccounts
constexpr std::uint32_t tfWithdrawSubTx
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::optional< IOUAmount > bidMax_
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
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 isXRP(AccountID const &c)
bool isMember(const char *key) const
Return true if the object has a member named key.
constexpr std::uint32_t tfSingleAsset
bool expectTradingFee(std::uint16_t fee) const
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)
Set the sequence number on a JTx.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt)
constexpr std::uint32_t tfLPToken
const AccountID ammAccount_
constexpr std::uint32_t tfDepositSubTx
constexpr std::uint32_t tfTwoAsset
static Number number(STAmount const &a)
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
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.
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
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)
Immutable cryptographic account descriptor.
const SF_ACCOUNT sfAccount
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
constexpr std::uint32_t tfOneAssetLPToken
constexpr std::uint32_t tfUniversal
const SField sfAuctionSlot
std::optional< IOUAmount > bidMin_
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
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)
A transaction testing environment.
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
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.
constexpr std::uint32_t tfLimitLPToken
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const