rippled
AMMInfo_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2023 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/protocol/Feature.h>
21 #include <ripple/protocol/jss.h>
22 #include <test/jtx.h>
23 #include <test/jtx/AMM.h>
24 #include <test/jtx/AMMTest.h>
25 
26 #include <unordered_map>
27 
28 namespace ripple {
29 namespace test {
30 
32 {
33 public:
34  void
36  {
37  testcase("Errors");
38 
39  using namespace jtx;
40  // Invalid tokens pair
41  testAMM([&](AMM& ammAlice, Env&) {
42  Account const gw("gw");
43  auto const USD = gw["USD"];
44  auto const jv =
45  ammAlice.ammRpcInfo({}, {}, {{USD.issue(), USD.issue()}});
46  BEAST_EXPECT(jv[jss::error_message] == "Account not found.");
47  });
48 
49  // Invalid LP account id
50  testAMM([&](AMM& ammAlice, Env&) {
51  Account bogie("bogie");
52  auto const jv = ammAlice.ammRpcInfo(bogie.id());
53  BEAST_EXPECT(jv[jss::error_message] == "Account malformed.");
54  });
55  }
56 
57  void
59  {
60  testcase("RPC simple");
61 
62  using namespace jtx;
63  testAMM([&](AMM& ammAlice, Env&) {
64  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
65  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
66  });
67  }
68 
69  void
71  {
72  testcase("Vote and Bid");
73 
74  using namespace jtx;
75  testAMM([&](AMM& ammAlice, Env& env) {
76  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
77  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
79  votes.insert({alice.human(), 0});
80  for (int i = 0; i < 7; ++i)
81  {
82  Account a(std::to_string(i));
83  votes.insert({a.human(), 50 * (i + 1)});
84  fund(env, gw, {a}, {USD(10000)}, Fund::Acct);
85  ammAlice.deposit(a, 10000000);
86  ammAlice.vote(a, 50 * (i + 1));
87  }
88  BEAST_EXPECT(ammAlice.expectTradingFee(175));
89  Account ed("ed");
90  Account bill("bill");
91  env.fund(XRP(1000), bob, ed, bill);
92  ammAlice.bid(alice, 100, std::nullopt, {carol, bob, ed, bill});
93  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
94  XRP(80000), USD(80000), IOUAmount{79994400}));
95  std::unordered_set<std::string> authAccounts = {
96  carol.human(), bob.human(), ed.human(), bill.human()};
97  auto const ammInfo = ammAlice.ammRpcInfo();
98  auto const& amm = ammInfo[jss::amm];
99  try
100  {
101  // votes
102  auto const voteSlots = amm[jss::vote_slots];
103  for (std::uint8_t i = 0; i < 8; ++i)
104  {
105  if (!BEAST_EXPECT(
106  votes[voteSlots[i][jss::account].asString()] ==
107  voteSlots[i][jss::trading_fee].asUInt() &&
108  voteSlots[i][jss::vote_weight].asUInt() == 12500))
109  return;
110  votes.erase(voteSlots[i][jss::account].asString());
111  }
112  if (!BEAST_EXPECT(votes.empty()))
113  return;
114 
115  // bid
116  auto const auctionSlot = amm[jss::auction_slot];
117  for (std::uint8_t i = 0; i < 4; ++i)
118  {
119  if (!BEAST_EXPECT(authAccounts.contains(
120  auctionSlot[jss::auth_accounts][i][jss::account]
121  .asString())))
122  return;
123  authAccounts.erase(
124  auctionSlot[jss::auth_accounts][i][jss::account]
125  .asString());
126  }
127  if (!BEAST_EXPECT(authAccounts.empty()))
128  return;
129  BEAST_EXPECT(
130  auctionSlot[jss::account].asString() == alice.human() &&
131  auctionSlot[jss::discounted_fee].asUInt() == 17 &&
132  auctionSlot[jss::price][jss::value].asString() == "5600" &&
133  auctionSlot[jss::price][jss::currency].asString() ==
134  to_string(ammAlice.lptIssue().currency) &&
135  auctionSlot[jss::price][jss::issuer].asString() ==
136  to_string(ammAlice.lptIssue().account));
137  }
138  catch (std::exception const& e)
139  {
140  fail(e.what(), __FILE__, __LINE__);
141  }
142  });
143  }
144 
145  void
147  {
148  using namespace jtx;
149  testAMM([&](AMM& ammAlice, Env& env) {
150  env(fset(gw, asfGlobalFreeze));
151  env.close();
152  auto test = [&](bool freeze) {
153  auto const info = ammAlice.ammRpcInfo();
154  BEAST_EXPECT(
155  info[jss::amm][jss::asset2_frozen].asBool() == freeze);
156  };
157  test(true);
158  env(fclear(gw, asfGlobalFreeze));
159  env.close();
160  test(false);
161  });
162  }
163 
164  void
165  run() override
166  {
167  testErrors();
168  testSimpleRpc();
169  testVoteAndBid();
170  testFreeze();
171  }
172 };
173 
174 BEAST_DEFINE_TESTSUITE(AMMInfo, app, ripple);
175 
176 } // namespace test
177 } // namespace ripple
ripple::test::jtx::AMMTestBase::USD
const jtx::IOU USD
Definition: AMMTest.h:68
ripple::test::AMMInfo_test::testErrors
void testErrors()
Definition: AMMInfo_test.cpp:35
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
std::exception
STL class.
ripple::test::AMMInfo_test
Definition: AMMInfo_test.cpp:31
std::unordered_set
STL class.
ripple::test::jtx::AMM::ammRpcInfo
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.
Definition: AMM.cpp:136
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
ripple::test::jtx::AMM::vote
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)
Definition: AMM.cpp:566
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:113
ripple::test::jtx::AMMTestBase::gw
const jtx::Account gw
Definition: AMMTest.h:64
ripple::test::jtx::AMMTestBase::carol
const jtx::Account carol
Definition: AMMTest.h:65
ripple::test::jtx::AMM::deposit
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)
Definition: AMM.cpp:371
ripple::test::jtx::AMMTestBase::alice
const jtx::Account alice
Definition: AMMTest.h:66
ripple::test::jtx::IOU::issue
Issue issue() const
Definition: amount.h:303
ripple::test::jtx::AMM::bid
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)
Definition: AMM.cpp:587
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
ripple::test::jtx::AMM
Convenience class to test AMM functionality.
Definition: AMM.h:62
ripple::test::TrustFlag::freeze
@ freeze
std::unordered_set::contains
T contains(T... args)
ripple::test::jtx::Account::id
AccountID id() const
Returns the Account ID.
Definition: Account.h:106
ripple::test::jtx::AMMTestBase::bob
const jtx::Account bob
Definition: AMMTest.h:67
ripple::test::jtx::AMMTestBase
Definition: AMMTest.h:61
ripple::test::jtx::AMM::expectAmmRpcInfo
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
Definition: AMM.cpp:290
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
std::to_string
T to_string(T... args)
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
std::unordered_map::erase
T erase(T... args)
std::uint8_t
ripple::test::AMMInfo_test::testVoteAndBid
void testVoteAndBid()
Definition: AMMInfo_test.cpp:70
ripple::test::AMMInfo_test::run
void run() override
Definition: AMMInfo_test.cpp:165
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::test::jtx::AMM::expectTradingFee
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:274
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::unordered_map::insert
T insert(T... args)
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
ripple::test::jtx::fund
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:35
std::unordered_map::empty
T empty(T... args)
ripple::asfGlobalFreeze
constexpr std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:80
ripple::test::AMMInfo_test::testFreeze
void testFreeze()
Definition: AMMInfo_test.cpp:146
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::AMMInfo_test::testSimpleRpc
void testSimpleRpc()
Definition: AMMInfo_test.cpp:58
unordered_map
ripple::test::jtx::AMMTestBase::testAMM
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::optional< FeatureBitset > const &features=std::nullopt)
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
Definition: AMMTest.cpp:101
ripple::test::jtx::AMM::lptIssue
Issue lptIssue() const
Definition: AMM.h:257
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::Issue::account
AccountID account
Definition: Issue.h:39
std::exception::what
T what(T... args)
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)