rippled
Loading...
Searching...
No Matches
AMMTest.cpp
1#include <test/jtx/AMM.h>
2#include <test/jtx/AMMTest.h>
3#include <test/jtx/CaptureLogs.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/pay.h>
6
7#include <xrpld/rpc/RPCHandler.h>
8
9#include <xrpl/protocol/ApiVersion.h>
10#include <xrpl/protocol/STParsedJSON.h>
11#include <xrpl/resource/Fees.h>
12
13namespace xrpl {
14namespace test {
15namespace jtx {
16
17void
19 jtx::Env& env,
20 jtx::Account const& gw,
21 std::vector<jtx::Account> const& accounts,
22 std::vector<STAmount> const& amts,
23 Fund how)
24{
25 fund(env, gw, accounts, XRP(30000), amts, how);
26}
27
28void
30 jtx::Env& env,
31 std::vector<jtx::Account> const& accounts,
32 STAmount const& xrp,
33 std::vector<STAmount> const& amts,
34 Fund how)
35{
36 for (auto const& account : accounts)
37 {
38 if (how == Fund::All || how == Fund::Acct)
39 {
40 env.fund(xrp, account);
41 }
42 }
43 env.close();
44 for (auto const& account : accounts)
45 {
46 for (auto const& amt : amts)
47 {
48 env.trust(amt + amt, account);
49 env(pay(amt.issue().account, account, amt));
50 }
51 }
52 env.close();
53}
54
55void
57 jtx::Env& env,
58 jtx::Account const& gw,
59 std::vector<jtx::Account> const& accounts,
60 STAmount const& xrp,
61 std::vector<STAmount> const& amts,
62 Fund how)
63{
64 if (how == Fund::All || how == Fund::Gw)
65 env.fund(xrp, gw);
66 env.close();
67 fund(env, accounts, xrp, amts, how);
68}
69
71 : gw("gateway")
72 , carol("carol")
73 , alice("alice")
74 , bob("bob")
75 , USD(gw["USD"])
76 , EUR(gw["EUR"])
77 , GBP(gw["GBP"])
78 , BTC(gw["BTC"])
79 , BAD(jtx::IOU(gw, badCurrency()))
80{
81}
82
83void
85 std::function<void(jtx::AMM&, jtx::Env&)>&& cb,
87 std::uint16_t tfee,
89 std::vector<FeatureBitset> const& vfeatures)
90{
91 testAMM(std::move(cb), TestAMMArg{.pool = pool, .tfee = tfee, .ter = ter, .features = vfeatures});
92}
93
94void
96{
97 using namespace jtx;
98
99 std::string logs;
100
101 for (auto const& features : arg.features)
102 {
103 // Use small Number mantissas for the life of this test.
105
106 // For now, just disable SAV entirely, which locks in the small Number
107 // mantissas
108 Env env{
109 *this,
110 features - featureSingleAssetVault - featureLendingProtocol,
111 arg.noLog ? std::make_unique<CaptureLogs>(&logs) : nullptr};
112
113 auto const [asset1, asset2] = arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000));
114 auto toFund = [&](STAmount const& a) -> STAmount {
115 if (a.native())
116 {
117 auto const defXRP = XRP(30000);
118 if (a <= defXRP)
119 return defXRP;
120 return a + XRP(1000);
121 }
122 auto const defIOU = STAmount{a.issue(), 30000};
123 if (a <= defIOU)
124 return defIOU;
125 return a + STAmount{a.issue(), 1000};
126 };
127 auto const toFund1 = toFund(asset1);
128 auto const toFund2 = toFund(asset2);
129 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
130
131 if (!asset1.native() && !asset2.native())
132 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
133 else if (asset1.native())
134 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
135 else if (asset2.native())
136 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
137
138 AMM ammAlice(env, alice, asset1, asset2, CreateArg{.log = false, .tfee = arg.tfee, .err = arg.ter});
139 if (BEAST_EXPECT(ammAlice.expectBalances(asset1, asset2, ammAlice.tokens())))
140 cb(ammAlice, env);
141 }
142}
143
146{
147 return env.current()->fees().accountReserve(count);
148}
149
152{
153 return env.current()->fees().increment;
154}
155
158{
159 // These tests were originally written with search parameters that are
160 // different from the current defaults. This function creates an env
161 // with the search parameters that the tests were written for.
162 return Env(*this, envconfig([](std::unique_ptr<Config> cfg) {
163 cfg->PATH_SEARCH_OLD = 7;
164 cfg->PATH_SEARCH = 7;
165 cfg->PATH_SEARCH_MAX = 10;
166 return cfg;
167 }));
168}
169
172 jtx::Env& env,
173 jtx::Account const& src,
174 jtx::Account const& dst,
175 STAmount const& saDstAmount,
176 std::optional<STAmount> const& saSendMax,
177 std::optional<Currency> const& saSrcCurrency)
178{
179 using namespace jtx;
180
181 auto& app = env.app();
184
185 RPC::JsonContext context{
186 {env.journal,
187 app,
188 loadType,
189 app.getOPs(),
190 app.getLedgerMaster(),
191 c,
193 {},
194 {},
196 {},
197 {}};
198
200 params[jss::command] = "ripple_path_find";
201 params[jss::source_account] = toBase58(src);
202 params[jss::destination_account] = toBase58(dst);
203 params[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none);
204 if (saSendMax)
205 params[jss::send_max] = saSendMax->getJson(JsonOptions::none);
206 if (saSrcCurrency)
207 {
208 auto& sc = params[jss::source_currencies] = Json::arrayValue;
210 j[jss::currency] = to_string(saSrcCurrency.value());
211 sc.append(j);
212 }
213
214 Json::Value result;
215 gate g;
216 app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) {
217 context.params = std::move(params);
218 context.coro = coro;
219 RPC::doCommand(context, result);
220 g.signal();
221 });
222
223 using namespace std::chrono_literals;
224 BEAST_EXPECT(g.wait_for(5s));
225 BEAST_EXPECT(!result.isMember(jss::error));
226 return result;
227}
228
231 jtx::Env& env,
232 jtx::Account const& src,
233 jtx::Account const& dst,
234 STAmount const& saDstAmount,
235 std::optional<STAmount> const& saSendMax,
236 std::optional<Currency> const& saSrcCurrency)
237{
238 Json::Value result = find_paths_request(env, src, dst, saDstAmount, saSendMax, saSrcCurrency);
239 BEAST_EXPECT(!result.isMember(jss::error));
240
241 STAmount da;
242 if (result.isMember(jss::destination_amount))
243 da = amountFromJson(sfGeneric, result[jss::destination_amount]);
244
245 STAmount sa;
247 if (result.isMember(jss::alternatives))
248 {
249 auto const& alts = result[jss::alternatives];
250 if (alts.size() > 0)
251 {
252 auto const& path = alts[0u];
253
254 if (path.isMember(jss::source_amount))
255 sa = amountFromJson(sfGeneric, path[jss::source_amount]);
256
257 if (path.isMember(jss::destination_amount))
258 da = amountFromJson(sfGeneric, path[jss::destination_amount]);
259
260 if (path.isMember(jss::paths_computed))
261 {
262 Json::Value p;
263 p["Paths"] = path[jss::paths_computed];
264 STParsedJSONObject po("generic", p);
265 paths = po.object->getFieldPathSet(sfPaths);
266 }
267 }
268 }
269
270 return std::make_tuple(std::move(paths), std::move(sa), std::move(da));
271}
272
273} // namespace jtx
274} // namespace test
275} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
bool isMember(char const *key) const
Return true if the object has a member named key.
std::string const & arg() const
Return the argument associated with the runner.
Definition suite.h:276
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:800
A consumption charge.
Definition Charge.h:10
An endpoint that consumes resources.
Definition Consumer.h:16
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:721
Issue const & issue() const
Definition STAmount.h:454
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
jtx::Account const gw
Definition AMMTest.h:59
jtx::Account const alice
Definition AMMTest.h:61
void testAMM(std::function< void(jtx::AMM &, jtx::Env &)> &&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={testable_amendments()})
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
Definition AMMTest.cpp:84
jtx::Account const carol
Definition AMMTest.h:60
bool wait_for(std::chrono::duration< Rep, Period > const &rel_time)
Definition AMMTest.h:119
XRPAmount ammCrtFee(jtx::Env &env) const
Definition AMMTest.cpp:151
Json::Value find_paths_request(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax=std::nullopt, std::optional< Currency > const &saSrcCurrency=std::nullopt)
Definition AMMTest.cpp:171
XRPAmount reserve(jtx::Env &env, std::uint32_t count) const
Definition AMMTest.cpp:145
std::tuple< STPathSet, STAmount, STAmount > find_paths(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax=std::nullopt, std::optional< Currency > const &saSrcCurrency=std::nullopt)
Definition AMMTest.cpp:230
Convenience class to test AMM functionality.
Definition AMM.h:104
Immutable cryptographic account descriptor.
Definition Account.h:19
A transaction testing environment.
Definition Env.h:119
Application & app()
Definition Env.h:251
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:98
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:261
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:284
beast::Journal const journal
Definition Env.h:160
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:319
Converts to IOU Issue or STAmount.
Add a path.
Definition paths.h:37
Set Paths, SendMax on a JTx.
Definition paths.h:15
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:15
T is_same_v
T make_pair(T... args)
T make_tuple(T... args)
@ arrayValue
array value (ordered list)
Definition json_value.h:25
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
Status doCommand(RPC::JsonContext &context, Json::Value &result)
Execute an RPC command and store the results in a Json::Value.
static constexpr auto apiVersionIfUnspecified
Definition ApiVersion.h:43
Charge const feeReferenceRPC
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Definition AMMTest.cpp:18
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:90
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:34
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition STAmount.cpp:948
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597
SField const sfGeneric
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:92
@ jtCLIENT
Definition Job.h:24
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
std::optional< std::pair< STAmount, STAmount > > pool
Definition AMMTest.h:20
T value(T... args)