xrpld
Loading...
Searching...
No Matches
src/test/jtx/AMM.h
1#pragma once
2
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/multisign.h>
6#include <test/jtx/seq.h>
7#include <test/jtx/ter.h>
8
9#include <xrpl/basics/Number.h>
10#include <xrpl/basics/base_uint.h>
11#include <xrpl/basics/contract.h>
12#include <xrpl/json/json_value.h>
13#include <xrpl/json/json_writer.h> // IWYU pragma: keep
14#include <xrpl/protocol/AccountID.h>
15#include <xrpl/protocol/ApiVersion.h>
16#include <xrpl/protocol/Asset.h>
17#include <xrpl/protocol/IOUAmount.h>
18#include <xrpl/protocol/Issue.h>
19#include <xrpl/protocol/STAmount.h>
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/protocol/jss.h>
22
23#include <nudb/detail/stream.hpp>
24
25#include <cstdint>
26#include <iostream>
27#include <optional>
28#include <ostream>
29#include <stdexcept>
30#include <string>
31#include <tuple>
32#include <utility>
33#include <variant>
34#include <vector>
35
36namespace xrpl::test::jtx {
37
39{
42
43public:
53 [[nodiscard]] STAmount
54 tokens() const
55 {
56 return STAmount{asset_, tokens_};
57 }
58 [[nodiscard]] STAmount
59 tokens(Issue const& ammIssue) const
60 {
61 return STAmount{ammIssue, tokens_};
62 }
63};
64
66{
67 bool log = false;
73 std::optional<Ter> err = std::nullopt;
74 bool close = true;
75};
76
90
103
113
123
133
137class AMM
138{
144 bool log_;
146 // Predict next purchase price
150 // Multi-signature
152 // Transaction fee
157
158public:
159 AMM(Env& env,
160 Account account,
161 STAmount asset1,
162 STAmount asset2,
163 bool log = false,
164 std::uint16_t tfee = 0,
165 std::uint32_t fee = 0,
166 std::optional<std::uint32_t> flags = std::nullopt,
167 std::optional<jtx::Seq> seq = std::nullopt,
168 std::optional<jtx::Msig> ms = std::nullopt,
169 std::optional<Ter> const& ter = std::nullopt,
170 bool close = true);
171 AMM(Env& env,
172 Account const& account,
173 STAmount const& asset1,
174 STAmount const& asset2,
175 Ter const& ter,
176 bool log = false,
177 bool close = true);
178 AMM(Env& env,
179 Account const& account,
180 STAmount const& asset1,
181 STAmount const& asset2,
182 CreateArg const& arg);
183
184 static json::Value
185 createJv(
186 AccountID const& account,
187 STAmount const& asset1,
188 STAmount const& asset2,
189 std::uint16_t const& tfee);
190
194 [[nodiscard]] json::Value
196 std::optional<AccountID> const& account = std::nullopt,
197 std::optional<std::string> const& ledgerIndex = std::nullopt,
198 std::optional<Asset> const& asset1 = std::nullopt,
199 std::optional<Asset> const& asset2 = std::nullopt,
200 std::optional<AccountID> const& ammAccount = std::nullopt,
201 bool ignoreParams = false,
202 unsigned apiVersion = rpc::kApiInvalidVersion) const;
203
204 [[nodiscard]] json::Value
206 std::optional<json::Value> const& account,
207 std::optional<std::string> const& ledgerIndex,
208 std::optional<Asset> const& asset1,
209 std::optional<Asset> const& asset2,
211 bool ignoreParams,
212 unsigned apiVersion) const;
213
217 [[nodiscard]] bool
219 STAmount const& asset1,
220 STAmount const& asset2,
221 IOUAmount const& lpt,
222 std::optional<AccountID> const& account = std::nullopt) const;
223
228 balances(
229 Asset const& asset1,
230 Asset const& asset2,
231 std::optional<AccountID> const& account = std::nullopt) const;
232
234 balances(std::optional<AccountID> const& account = std::nullopt) const
235 {
236 return balances(asset1_.asset(), asset2_.asset(), account);
237 }
238
239 [[nodiscard]] bool
240 expectLPTokens(AccountID const& account, IOUAmount const& tokens) const;
241
247 [[nodiscard]] bool
249 std::uint32_t fee,
251 IOUAmount expectedPrice) const;
252
253 [[nodiscard]] bool
254 expectAuctionSlot(std::vector<AccountID> const& authAccount) const;
255
256 [[nodiscard]] bool
258
259 [[nodiscard]] bool
261 STAmount const& asset1,
262 STAmount const& asset2,
263 IOUAmount const& balance,
264 std::optional<AccountID> const& account = std::nullopt,
265 std::optional<std::string> const& ledgerIndex = std::nullopt,
266 std::optional<AccountID> const& ammAccount = std::nullopt) const;
267
268 [[nodiscard]] bool
269 ammExists() const;
270
271 static json::Value
272 depositJv(DepositArg const& arg);
273
275 deposit(
276 std::optional<Account> const& account,
278 std::optional<STAmount> const& asset1InDetails = std::nullopt,
279 std::optional<std::uint32_t> const& flags = std::nullopt,
280 std::optional<Ter> const& ter = std::nullopt);
281
283 deposit(
284 std::optional<Account> const& account,
285 STAmount const& asset1InDetails,
286 std::optional<STAmount> const& asset2InAmount = std::nullopt,
287 std::optional<STAmount> const& maxEP = std::nullopt,
288 std::optional<std::uint32_t> const& flags = std::nullopt,
289 std::optional<Ter> const& ter = std::nullopt);
290
292 deposit(
293 std::optional<Account> const& account,
295 std::optional<STAmount> const& asset1In,
296 std::optional<STAmount> const& asset2In,
297 std::optional<STAmount> const& maxEP,
298 std::optional<std::uint32_t> const& flags,
300 std::optional<jtx::Seq> const& seq,
301 std::optional<std::uint16_t> const& tfee = std::nullopt,
302 std::optional<Ter> const& ter = std::nullopt);
303
305 deposit(DepositArg const& arg);
306
307 static json::Value
308 withdrawJv(WithdrawArg const& arg);
309
311 withdraw(
312 std::optional<Account> const& account,
314 std::optional<STAmount> const& asset1OutDetails = std::nullopt,
315 std::optional<std::uint32_t> const& flags = std::nullopt,
316 std::optional<Ter> const& ter = std::nullopt);
317
320 std::optional<Account> const& account,
321 std::optional<STAmount> const& asset1OutDetails = std::nullopt,
322 std::optional<Ter> const& ter = std::nullopt)
323 {
324 return withdraw(
325 account,
326 std::nullopt,
327 asset1OutDetails,
328 asset1OutDetails ? tfOneAssetWithdrawAll : tfWithdrawAll,
329 ter);
330 }
331
333 withdraw(
334 std::optional<Account> const& account,
335 STAmount const& asset1Out,
336 std::optional<STAmount> const& asset2Out = std::nullopt,
337 std::optional<LPToken> const& maxEP = std::nullopt,
338 std::optional<Ter> const& ter = std::nullopt);
339
341 withdraw(
342 std::optional<Account> const& account,
344 std::optional<STAmount> const& asset1Out,
345 std::optional<STAmount> const& asset2Out,
346 std::optional<LPToken> const& maxEP,
347 std::optional<std::uint32_t> const& flags,
349 std::optional<jtx::Seq> const& seq,
350 std::optional<Ter> const& ter = std::nullopt);
351
353 withdraw(WithdrawArg const& arg);
354
355 static json::Value
356 voteJv(VoteArg const& arg);
357
358 void
359 vote(
360 std::optional<Account> const& account,
361 std::uint32_t feeVal,
362 std::optional<std::uint32_t> const& flags = std::nullopt,
363 std::optional<jtx::Seq> const& seq = std::nullopt,
364 std::optional<std::pair<Asset, Asset>> const& assets = std::nullopt,
365 std::optional<Ter> const& ter = std::nullopt);
366
367 void
368 vote(VoteArg const& arg);
369
371 bid(BidArg const& arg);
372
373 void
374 clawback(ClawbackArg const& arg);
375
376 [[nodiscard]] AccountID const&
378 {
379 return ammAccount_;
380 }
381
382 [[nodiscard]] Issue
383 lptIssue() const
384 {
385 return lptIssue_;
386 }
387
388 [[nodiscard]] IOUAmount
389 tokens() const
390 {
391 return initialLPTokens_;
392 }
393
394 [[nodiscard]] IOUAmount
395 getLPTokensBalance(std::optional<AccountID> const& account = std::nullopt) const;
396
398 operator<<(std::ostream& s, AMM const& amm)
399 {
400 if (auto const res = amm.ammRpcInfo())
401 s << res.toStyledString();
402 return s;
403 }
404
406 operator[](AccountID const& lp) const
407 {
408 return ammRpcInfo(lp).toStyledString();
409 }
410
412 operator()(AccountID const& lp) const
413 {
414 return ammRpcInfo(lp);
415 }
416
417 static json::Value
418 deleteJv(AccountID const& account, Asset const& asset1, Asset const& assets);
419
420 void
421 ammDelete(AccountID const& account, std::optional<Ter> const& ter = std::nullopt);
422
423 void
424 setClose(bool close)
425 {
426 doClose_ = close;
427 }
428
429 [[nodiscard]] uint256
430 ammID() const
431 {
432 return ammID_;
433 }
434
435 void
436 setTokens(json::Value& jv, std::optional<std::pair<Asset, Asset>> const& assets = std::nullopt);
437
438 Asset const&
440 {
441 if (i > 1)
442 Throw<std::runtime_error>("AMM: operator[], invalid index");
443 return i == 0 ? asset1_.asset() : asset2_.asset();
444 }
445
446 struct Pool
447 {
448 AMM const& amm;
450 Pool(AMM const& a, std::vector<json::StaticString> const& n = {}) : amm(a), names(n)
451 {
452 }
454 operator<<(std::ostream& s, Pool const& p)
455 {
456 auto const& jr = p.amm.ammRpcInfo();
457 auto out = [&](json::Value const& jv) {
458 if (jv.isMember(jss::value))
459 {
460 std::cout << jv[jss::value].asString();
461 }
462 else
463 {
464 std::cout << jv.asString();
465 }
466 std::cout << " ";
467 };
468 if (p.names.empty())
469 {
470 out(jr[jss::amm][jss::amount]);
471 out(jr[jss::amm][jss::amount2]);
472 out(jr[jss::amm][jss::lp_token]);
473 }
474 else
475 {
476 for (auto const& n : p.names)
477 out(jr[jss::amm][n]);
478 }
480 return s;
481 }
482 };
483 struct Offers
484 {
486 Offers(json::Value const& j) : jv(j)
487 {
488 }
491 {
492 auto out = [&](json::Value const& jv) {
493 if (jv.isMember(jss::value))
494 {
495 s << jv[jss::value].asString();
496 }
497 else
498 {
499 s << jv;
500 }
501 };
502 for (auto const& o : offers.jv[jss::offers])
503 {
504 s << "taker_pays: ";
505 out(o[jss::taker_pays]);
506 s << " taker_gets: ";
507 out(o[jss::taker_gets]);
508 s << std::endl;
509 }
510 return s;
511 }
512 };
513
514private:
516 create(
517 std::uint32_t tfee = 0,
518 std::optional<std::uint32_t> const& flags = std::nullopt,
519 std::optional<jtx::Seq> const& seq = std::nullopt,
520 std::optional<Ter> const& ter = std::nullopt);
521
522 void
523 log(bool log)
524 {
525 log_ = log;
526 }
527
528 [[nodiscard]] bool
530 STAmount const& asset1,
531 STAmount const& asset2,
532 IOUAmount const& balance,
533 json::Value const& jv) const;
534
535 void
536 submit(
537 json::Value const& jv,
538 std::optional<jtx::Seq> const& seq,
539 std::optional<Ter> const& ter);
540
541 [[nodiscard]] bool
542 expectAuctionSlot(auto&& cb) const;
543
546};
547
548namespace amm {
549
552 Account const& issuer,
553 Account const& holder,
554 Asset const& asset,
555 Asset const& asset2,
556 std::optional<STAmount> const& amount);
557} // namespace amm
558
559} // namespace xrpl::test::jtx
Represents a JSON value.
Definition json_value.h:117
std::string toStyledString() const
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:26
A currency issued by an account.
Definition Issue.h:18
Number is a floating point type that can represent a wide range of values.
Definition Number.h:351
bool expectTradingFee(std::uint16_t fee) const
Definition AMM.cpp:337
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
Definition AMM.cpp:351
json::Value bid(BidArg const &arg)
Definition AMM.cpp:734
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition AMM.cpp:282
std::optional< IOUAmount > bidMax_
static json::Value withdrawJv(WithdrawArg const &arg)
Definition AMM.cpp:554
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:153
AccountID const ammAccount_
bool ammExists() const
Definition AMM.cpp:344
IOUAmount withdrawAll(std::optional< Account > const &account, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
friend std::ostream & operator<<(std::ostream &s, AMM const &amm)
json::Value operator()(AccountID const &lp) const
static json::Value deleteJv(AccountID const &account, Asset const &asset1, Asset const &assets)
Definition AMM.cpp:887
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition AMM.cpp:307
Asset const & operator[](std::uint8_t i)
IOUAmount tokens() 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)
Definition AMM.cpp:604
Account const creatorAccount_
std::uint32_t const fee_
void submit(json::Value const &jv, std::optional< jtx::Seq > const &seq, std::optional< Ter > const &ter)
Definition AMM.cpp:815
void ammDelete(AccountID const &account, std::optional< Ter > const &ter=std::nullopt)
Definition AMM.cpp:900
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.
Definition AMM.cpp:183
AccountID const & ammAccount() const
std::optional< Msig > const msig_
static json::Value createJv(AccountID const &account, STAmount const &asset1, STAmount const &asset2, std::uint16_t const &tfee)
Definition AMM.cpp:136
void setTokens(json::Value &jv, std::optional< std::pair< Asset, Asset > > const &assets=std::nullopt)
Definition AMM.cpp:392
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)
Definition AMM.cpp:708
std::tuple< STAmount, STAmount, STAmount > balances(std::optional< AccountID > const &account=std::nullopt) const
static json::Value voteJv(VoteArg const &arg)
Definition AMM.cpp:690
void setClose(bool close)
std::optional< IOUAmount > bidMin_
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition AMM.cpp:296
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, json::Value const &jv) const
Definition AMM.cpp:364
IOUAmount initialTokens()
Definition AMM.cpp:52
AMM(Env &env, Account account, STAmount asset1, STAmount 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:62
void clawback(ClawbackArg const &arg)
Definition AMM.cpp:799
std::tuple< STAmount, STAmount, STAmount > balances(Asset const &asset1, Asset const &asset2, std::optional< AccountID > const &account=std::nullopt) const
Get AMM balances for the token pair.
Definition AMM.cpp:246
std::string operator[](AccountID const &lp) const
static json::Value depositJv(DepositArg const &arg)
Definition AMM.cpp:407
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:269
IOUAmount const initialLPTokens_
Immutable cryptographic account descriptor.
Definition jtx/Account.h:21
A transaction testing environment.
Definition Env.h:161
STAmount tokens(Issue const &ammIssue) const
LPToken(std::uint64_t tokens)
LPToken(IOUAmount tokens)
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:18
T empty(T... args)
T endl(T... args)
static constexpr auto kApiInvalidVersion
Definition ApiVersion.h:41
json::Value ammClawback(Account const &issuer, Account const &holder, Asset const &asset, Asset const &asset2, std::optional< STAmount > const &amount)
Definition AMM.cpp:911
Deposit preauthorize operations.
Definition deposit.h:16
OwnerCount< ltOFFER > offers
Match the number of offers in the account's owner directory.
Definition owners.h:137
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition Issue.h:108
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
BaseUInt< 256 > uint256
Definition base_uint.h:580
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
friend std::ostream & operator<<(std::ostream &s, Offers const &offers)
Offers(json::Value const &j)
std::vector< json::StaticString > names
friend std::ostream & operator<<(std::ostream &s, Pool const &p)
Pool(AMM const &a, std::vector< json::StaticString > const &n={})
std::optional< Account > account
std::optional< std::variant< int, IOUAmount, STAmount > > bidMin
std::vector< Account > authAccounts
std::optional< std::variant< int, IOUAmount, STAmount > > bidMax
std::optional< std::uint32_t > flags
std::optional< std::pair< Asset, Asset > > assets
std::optional< STAmount > amount
std::optional< std::uint32_t > flags
std::optional< std::pair< Asset, Asset > > assets
std::optional< Ter > err
std::optional< jtx::Msig > ms
std::optional< jtx::Seq > seq
std::optional< std::uint32_t > flags
std::optional< std::uint32_t > flags
std::optional< std::uint16_t > tfee
std::optional< LPToken > tokens
std::optional< STAmount > maxEP
std::optional< std::pair< Asset, Asset > > assets
std::optional< jtx::Seq > seq
std::optional< Account > account
std::optional< STAmount > asset2In
std::optional< STAmount > asset1In
std::optional< std::pair< Asset, Asset > > assets
std::optional< Ter > err
std::optional< jtx::Seq > seq
std::optional< Account > account
std::optional< std::uint32_t > flags
std::optional< STAmount > asset2Out
std::optional< jtx::Seq > seq
std::optional< std::pair< Asset, Asset > > assets
std::optional< LPToken > maxEP
std::optional< STAmount > asset1Out
std::optional< std::uint32_t > flags
std::optional< Account > account
std::optional< LPToken > tokens