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 ripple {
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(
92 std::move(cb),
94 .pool = pool, .tfee = tfee, .ter = ter, .features = vfeatures});
95}
96
97void
99 std::function<void(jtx::AMM&, jtx::Env&)>&& cb,
100 TestAMMArg const& arg)
101{
102 using namespace jtx;
103
104 std::string logs;
105
106 for (auto const& features : arg.features)
107 {
108 Env env{
109 *this,
110 features,
111 arg.noLog ? std::make_unique<CaptureLogs>(&logs) : nullptr};
112
113 auto const [asset1, asset2] =
114 arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000));
115 auto tofund = [&](STAmount const& a) -> STAmount {
116 if (a.native())
117 {
118 auto const defXRP = XRP(30000);
119 if (a <= defXRP)
120 return defXRP;
121 return a + XRP(1000);
122 }
123 auto const defIOU = STAmount{a.issue(), 30000};
124 if (a <= defIOU)
125 return defIOU;
126 return a + STAmount{a.issue(), 1000};
127 };
128 auto const toFund1 = tofund(asset1);
129 auto const toFund2 = tofund(asset2);
130 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
131
132 if (!asset1.native() && !asset2.native())
133 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
134 else if (asset1.native())
135 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
136 else if (asset2.native())
137 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
138
139 AMM ammAlice(
140 env,
141 alice,
142 asset1,
143 asset2,
144 CreateArg{.log = false, .tfee = arg.tfee, .err = arg.ter});
145 if (BEAST_EXPECT(
146 ammAlice.expectBalances(asset1, asset2, ammAlice.tokens())))
147 cb(ammAlice, env);
148 }
149}
150
153{
154 return env.current()->fees().accountReserve(count);
155}
156
159{
160 return env.current()->fees().increment;
161}
162
165{
166 // These tests were originally written with search parameters that are
167 // different from the current defaults. This function creates an env
168 // with the search parameters that the tests were written for.
169 return Env(*this, envconfig([](std::unique_ptr<Config> cfg) {
170 cfg->PATH_SEARCH_OLD = 7;
171 cfg->PATH_SEARCH = 7;
172 cfg->PATH_SEARCH_MAX = 10;
173 return cfg;
174 }));
175}
176
179 jtx::Env& env,
180 jtx::Account const& src,
181 jtx::Account const& dst,
182 STAmount const& saDstAmount,
183 std::optional<STAmount> const& saSendMax,
184 std::optional<Currency> const& saSrcCurrency)
185{
186 using namespace jtx;
187
188 auto& app = env.app();
191
192 RPC::JsonContext context{
193 {env.journal,
194 app,
195 loadType,
196 app.getOPs(),
197 app.getLedgerMaster(),
198 c,
200 {},
201 {},
203 {},
204 {}};
205
207 params[jss::command] = "ripple_path_find";
208 params[jss::source_account] = toBase58(src);
209 params[jss::destination_account] = toBase58(dst);
210 params[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none);
211 if (saSendMax)
212 params[jss::send_max] = saSendMax->getJson(JsonOptions::none);
213 if (saSrcCurrency)
214 {
215 auto& sc = params[jss::source_currencies] = Json::arrayValue;
217 j[jss::currency] = to_string(saSrcCurrency.value());
218 sc.append(j);
219 }
220
221 Json::Value result;
222 gate g;
223 app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) {
224 context.params = std::move(params);
225 context.coro = coro;
226 RPC::doCommand(context, result);
227 g.signal();
228 });
229
230 using namespace std::chrono_literals;
231 BEAST_EXPECT(g.wait_for(5s));
232 BEAST_EXPECT(!result.isMember(jss::error));
233 return result;
234}
235
238 jtx::Env& env,
239 jtx::Account const& src,
240 jtx::Account const& dst,
241 STAmount const& saDstAmount,
242 std::optional<STAmount> const& saSendMax,
243 std::optional<Currency> const& saSrcCurrency)
244{
246 env, src, dst, saDstAmount, saSendMax, saSrcCurrency);
247 BEAST_EXPECT(!result.isMember(jss::error));
248
249 STAmount da;
250 if (result.isMember(jss::destination_amount))
251 da = amountFromJson(sfGeneric, result[jss::destination_amount]);
252
253 STAmount sa;
255 if (result.isMember(jss::alternatives))
256 {
257 auto const& alts = result[jss::alternatives];
258 if (alts.size() > 0)
259 {
260 auto const& path = alts[0u];
261
262 if (path.isMember(jss::source_amount))
263 sa = amountFromJson(sfGeneric, path[jss::source_amount]);
264
265 if (path.isMember(jss::destination_amount))
266 da = amountFromJson(sfGeneric, path[jss::destination_amount]);
267
268 if (path.isMember(jss::paths_computed))
269 {
270 Json::Value p;
271 p["Paths"] = path[jss::paths_computed];
272 STParsedJSONObject po("generic", p);
273 paths = po.object->getFieldPathSet(sfPaths);
274 }
275 }
276 }
277
278 return std::make_tuple(std::move(paths), std::move(sa), std::move(da));
279}
280
281} // namespace jtx
282} // namespace test
283} // namespace ripple
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:285
A consumption charge.
Definition Charge.h:11
An endpoint that consumes resources.
Definition Consumer.h:17
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:753
Issue const & issue() const
Definition STAmount.h:477
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
jtx::Account const alice
Definition AMMTest.h:58
jtx::Account const gw
Definition AMMTest.h:56
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:57
bool wait_for(std::chrono::duration< Rep, Period > const &rel_time)
Definition AMMTest.h:110
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:237
XRPAmount ammCrtFee(jtx::Env &env) const
Definition AMMTest.cpp:158
XRPAmount reserve(jtx::Env &env, std::uint32_t count) const
Definition AMMTest.cpp:152
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:178
Convenience class to test AMM functionality.
Definition AMM.h:105
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment.
Definition Env.h:102
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:312
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:103
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:302
Application & app()
Definition Env.h:242
beast::Journal const journal
Definition Env.h:143
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:271
Converts to IOU Issue or STAmount.
Add a path.
Definition paths.h:39
Set Paths, SendMax on a JTx.
Definition paths.h:16
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:16
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:44
Charge const feeReferenceRPC
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
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
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:35
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition STAmount.cpp:987
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
SField const sfGeneric
@ jtCLIENT
Definition Job.h:26
std::optional< std::pair< STAmount, STAmount > > pool
Definition AMMTest.h:21
T value(T... args)