1#include <test/jtx/AMM.h>
2#include <test/jtx/AMMTest.h>
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/flags.h>
7#include <test/jtx/mpt.h>
9#include <xrpl/beast/unit_test/suite.h>
10#include <xrpl/protocol/AccountID.h>
11#include <xrpl/protocol/Feature.h>
12#include <xrpl/protocol/Issue.h>
13#include <xrpl/protocol/TxFlags.h>
14#include <xrpl/protocol/UintTypes.h>
15#include <xrpl/protocol/XRPAmount.h>
16#include <xrpl/protocol/jss.h>
40 enum class TestAccount {
None, Alice, Bogie };
42 if (v == TestAccount::Alice)
46 if (v == TestAccount::Bogie)
57 auto const usd = gw[
"USD"];
58 auto const jv = ammAlice.
ammRpcInfo({}, {}, usd, usd);
59 BEAST_EXPECT(jv[jss::error_message] ==
"Account not found.");
65 BEAST_EXPECT(jv[jss::error_message] ==
"Account malformed.");
72 BEAST_EXPECT(jv[jss::error_message] ==
"Account malformed.");
85 BEAST_EXPECT(jv[jss::error_message] ==
"Account malformed.");
90 {
xrpIssue(), std::nullopt, TestAccount::None,
false},
91 {std::nullopt,
USD, TestAccount::None,
false},
92 {
xrpIssue(), std::nullopt, TestAccount::Alice,
false},
93 {std::nullopt,
USD, TestAccount::Alice,
false},
95 {std::nullopt, std::nullopt, TestAccount::None,
true}};
99 for (
auto const& [iss1, iss2, acct, ignoreParams] : invalidParams)
106 accountId(ammAlice, acct),
108 BEAST_EXPECT(jv[jss::error_message] ==
"Invalid parameters.");
114 for (
auto const& [iss1, iss2, acct, ignoreParams] : invalidParams)
121 accountId(ammAlice, acct),
123 BEAST_EXPECT(jv[jss::error_message] ==
"Invalid parameters.");
129 for (
auto const& [iss1, iss2, acct, ignoreParams] : invalidParams)
136 accountId(ammAlice, acct),
139 BEAST_EXPECT(jv[jss::error_message] ==
"Account malformed.");
146 std::nullopt, std::nullopt, std::nullopt, std::nullopt, bogie.
id());
147 BEAST_EXPECT(jv[jss::error_message] ==
"Account malformed.");
151 invalidParamsBadAccount = {
152 {
xrpIssue(), std::nullopt, TestAccount::None,
false},
153 {std::nullopt,
USD, TestAccount::None,
false},
154 {
xrpIssue(), std::nullopt, TestAccount::Bogie,
false},
155 {std::nullopt,
USD, TestAccount::Bogie,
false},
157 {std::nullopt, std::nullopt, TestAccount::None,
true}};
161 for (
auto const& [iss1, iss2, acct, ignoreParams] : invalidParamsBadAccount)
168 accountId(ammAlice, acct),
170 BEAST_EXPECT(jv[jss::error_message] ==
"Invalid parameters.");
176 for (
auto const& [iss1, iss2, acct, ignoreParams] : invalidParamsBadAccount)
183 accountId(ammAlice, acct),
187 jv[jss::error_message] ==
188 (acct == TestAccount::Bogie ?
std::string(
"Account malformed.")
214 mptTester.
create({.flags = tfMPTCanTransfer | tfMPTCanTrade});
216 mptTester1.
create({.flags = tfMPTCanTransfer | tfMPTCanTrade});
217 auto const mpt = mptTester[
"MPT"];
218 auto const mpt1 = mptTester1[
"MPT"];
223 for (
auto& pool : pools)
225 AMM const amm(env,
gw_, std::get<0>(pool), std::get<1>(pool));
226 BEAST_EXPECT(
amm.expectAmmRpcInfo(
244 [&](
AMM& ammAlice,
Env& env) {
249 for (
int i = 0; i < 7; ++i)
252 votes.insert({a.
human(), 50 * (i + 1)});
253 if (!features[fixAMMv1_3])
255 fund(env,
gw_, {a}, {
USD(10000)}, Fund::Acct);
259 fund(env,
gw_, {a}, {
USD(10001)}, Fund::Acct);
262 ammAlice.
vote(a, 50 * (i + 1));
268 env(ammAlice.
bid({.bidMin = 100, .authAccounts = {carol_, bob_, ed, bill}}));
269 if (!features[fixAMMv1_3])
289 for (
auto i = 0; i < 2; ++i)
292 carol_.human(),
bob_.human(), ed.human(), bill.human()};
293 auto const ammInfo = i ? ammAlice.
ammRpcInfo()
300 auto const&
amm = ammInfo[jss::amm];
304 auto const voteSlots =
amm[jss::vote_slots];
305 auto votesCopy = votes;
309 votes[voteSlots[i][jss::account].asString()] ==
310 voteSlots[i][jss::trading_fee].asUInt() &&
311 voteSlots[i][jss::vote_weight].asUInt() == 12500))
313 votes.erase(voteSlots[i][jss::account].asString());
315 if (!BEAST_EXPECT(votes.empty()))
320 auto const auctionSlot =
amm[jss::auction_slot];
323 if (!BEAST_EXPECT(authAccounts.
contains(
324 auctionSlot[jss::auth_accounts][i][jss::account].asString())))
327 auctionSlot[jss::auth_accounts][i][jss::account].asString());
329 if (!BEAST_EXPECT(authAccounts.
empty()))
332 auctionSlot[jss::account].asString() ==
alice_.human() &&
333 auctionSlot[jss::discounted_fee].asUInt() == 17 &&
334 auctionSlot[jss::price][jss::value].asString() ==
"5600" &&
335 auctionSlot[jss::price][jss::currency].asString() ==
337 auctionSlot[jss::price][jss::issuer].asString() ==
357 env(
fset(
gw_, asfGlobalFreeze));
359 auto test = [&](
bool freeze) {
361 BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool() == freeze);
377 auto const resp =
amm.ammRpcInfo(
378 std::nullopt, jss::validated.cStr(), std::nullopt, std::nullopt,
gw_);
379 BEAST_EXPECT(resp.isMember(
"error") && resp[
"error"] ==
"actNotFound");
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
Floating point representation of amounts with high dynamic range.
void testInvalidAmmField()
void run() override
Runs the suite.
void testVoteAndBid(FeatureBitset features)
jtx::Account const alice_
void testAMM(std::function< void(jtx::AMM &, jtx::Env &)> const &cb, std::optional< std::pair< STAmount, STAmount > > const &pool=std::nullopt, std::uint16_t tfee=0, std::optional< jtx::Ter > const &ter=std::nullopt, std::vector< FeatureBitset > const &features={testableAmendments()})
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
jtx::Account const carol_
Convenience class to test AMM functionality.
bool expectTradingFee(std::uint16_t fee) const
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt) const
json::Value bid(BidArg const &arg)
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)
AccountID const & ammAccount() const
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< Asset, Asset > > const &assets=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< Asset > const &asset1=std::nullopt, std::optional< Asset > const &asset2=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt, bool ignoreParams=false, unsigned apiVersion=RPC::kApiInvalidVersion) const
Send amm_info RPC command.
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
void create(MPTCreate const &arg=MPTCreate{})
std::vector< STAmount > fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string to_string(BaseUInt< Bits, Tag > const &a)