rippled
AMMInfo.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 #include <ripple/app/misc/AMMUtils.h>
20 #include <ripple/json/json_value.h>
21 #include <ripple/ledger/ReadView.h>
22 #include <ripple/net/RPCErr.h>
23 #include <ripple/protocol/AMMCore.h>
24 #include <ripple/protocol/Issue.h>
25 #include <ripple/rpc/Context.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
27 #include <grpcpp/support/status.h>
28 
29 namespace ripple {
30 
33 {
34  std::string strIdent(v.asString());
35  AccountID accountID;
36 
37  if (auto jv = RPC::accountFromString(accountID, strIdent))
38  {
39  for (auto it = jv.begin(); it != jv.end(); ++it)
40  result[it.memberName()] = (*it);
41 
42  return std::nullopt;
43  }
44  return std::optional<AccountID>(accountID);
45 }
46 
47 Expected<Issue, error_code_i>
49 {
50  try
51  {
52  return issueFromJson(v);
53  }
54  catch (std::runtime_error const& ex)
55  {
56  JLOG(j.debug()) << "getIssue " << ex.what();
57  }
59 }
60 
63 {
64  // 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC
65  using namespace std::chrono;
66  return date::format(
67  "%Y-%Om-%dT%H:%M:%OS%z",
68  date::sys_time<system_clock::duration>(
69  system_clock::time_point{tp.time_since_epoch() + 946684800s}));
70 }
71 
74 {
75  auto const& params(context.params);
76  Json::Value result;
77  std::optional<AccountID> accountID;
78 
79  Issue issue1;
80  Issue issue2;
81 
82  if (!params.isMember(jss::asset) || !params.isMember(jss::asset2))
83  {
85  return result;
86  }
87 
88  if (auto const i = getIssue(params[jss::asset], context.j); !i)
89  {
90  RPC::inject_error(i.error(), result);
91  return result;
92  }
93  else
94  issue1 = *i;
95  if (auto const i = getIssue(params[jss::asset2], context.j); !i)
96  {
97  RPC::inject_error(i.error(), result);
98  return result;
99  }
100  else
101  issue2 = *i;
102 
104  result = RPC::lookupLedger(ledger, context);
105  if (!ledger)
106  return result;
107 
108  if (params.isMember(jss::account))
109  {
110  accountID = getAccount(params[jss::account], result);
111  if (!accountID || !ledger->read(keylet::account(*accountID)))
112  {
114  return result;
115  }
116  }
117 
118  auto const ammKeylet = keylet::amm(issue1, issue2);
119  auto const amm = ledger->read(ammKeylet);
120  if (!amm)
121  return rpcError(rpcACT_NOT_FOUND);
122 
123  auto const ammAccountID = amm->getAccountID(sfAccount);
124 
125  // provide funds if frozen, specify asset_frozen flag
126  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
127  *ledger,
128  ammAccountID,
129  issue1,
130  issue2,
131  FreezeHandling::fhIGNORE_FREEZE,
132  context.j);
133  auto const lptAMMBalance = accountID
134  ? ammLPHolds(*ledger, *amm, *accountID, context.j)
135  : (*amm)[sfLPTokenBalance];
136 
137  Json::Value ammResult;
138  asset1Balance.setJson(ammResult[jss::amount]);
139  asset2Balance.setJson(ammResult[jss::amount2]);
140  lptAMMBalance.setJson(ammResult[jss::lp_token]);
141  ammResult[jss::trading_fee] = (*amm)[sfTradingFee];
142  ammResult[jss::account] = to_string(ammAccountID);
143  Json::Value voteSlots(Json::arrayValue);
144  if (amm->isFieldPresent(sfVoteSlots))
145  {
146  for (auto const& voteEntry : amm->getFieldArray(sfVoteSlots))
147  {
148  Json::Value vote;
149  vote[jss::account] = to_string(voteEntry.getAccountID(sfAccount));
150  vote[jss::trading_fee] = voteEntry[sfTradingFee];
151  vote[jss::vote_weight] = voteEntry[sfVoteWeight];
152  voteSlots.append(std::move(vote));
153  }
154  }
155  if (voteSlots.size() > 0)
156  ammResult[jss::vote_slots] = std::move(voteSlots);
157  if (amm->isFieldPresent(sfAuctionSlot))
158  {
159  auto const& auctionSlot =
160  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
161  if (auctionSlot.isFieldPresent(sfAccount))
162  {
163  Json::Value auction;
164  auto const timeSlot = ammAuctionTimeSlot(
165  ledger->info().parentCloseTime.time_since_epoch().count(),
166  auctionSlot);
167  auction[jss::time_interval] =
168  timeSlot ? *timeSlot : AUCTION_SLOT_TIME_INTERVALS;
169  auctionSlot[sfPrice].setJson(auction[jss::price]);
170  auction[jss::discounted_fee] = auctionSlot[sfDiscountedFee];
171  auction[jss::account] =
172  to_string(auctionSlot.getAccountID(sfAccount));
173  auction[jss::expiration] = to_iso8601(NetClock::time_point{
174  NetClock::duration{auctionSlot[sfExpiration]}});
175  if (auctionSlot.isFieldPresent(sfAuthAccounts))
176  {
177  Json::Value auth;
178  for (auto const& acct :
179  auctionSlot.getFieldArray(sfAuthAccounts))
180  {
181  Json::Value jv;
182  jv[jss::account] = to_string(acct.getAccountID(sfAccount));
183  auth.append(jv);
184  }
185  auction[jss::auth_accounts] = auth;
186  }
187  ammResult[jss::auction_slot] = std::move(auction);
188  }
189  }
190 
191  if (!isXRP(asset1Balance))
192  ammResult[jss::asset_frozen] =
193  isFrozen(*ledger, ammAccountID, issue1.currency, issue1.account);
194  if (!isXRP(asset2Balance))
195  ammResult[jss::asset2_frozen] =
196  isFrozen(*ledger, ammAccountID, issue2.currency, issue2.account);
197 
198  result[jss::amm] = std::move(ammResult);
199  if (!result.isMember(jss::ledger_index) &&
200  !result.isMember(jss::ledger_hash))
201  result[jss::ledger_current_index] = ledger->info().seq;
202  result[jss::validated] =
203  RPC::isValidated(context.ledgerMaster, *ledger, context.app);
204 
205  return result;
206 }
207 
208 } // namespace ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::sfDiscountedFee
const SF_UINT16 sfDiscountedFee
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::AUCTION_SLOT_TIME_INTERVALS
constexpr std::uint16_t AUCTION_SLOT_TIME_INTERVALS
Definition: AMMCore.h:35
ripple::sfVoteSlots
const SField sfVoteSlots
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::sfLPTokenBalance
const SF_AMOUNT sfLPTokenBalance
ripple::keylet::amm
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:375
ripple::Unexpected
Unexpected(E(&)[N]) -> Unexpected< E const * >
std::chrono::duration
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:83
ripple::sfPrice
const SF_AMOUNT sfPrice
ripple::sfVoteWeight
const SF_UINT32 sfVoteWeight
ripple::RPC::lookupLedger
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext &context, Json::Value &result)
Look up a ledger from a request and fill a Json::Result with the data representing a ledger.
Definition: RPCHelpers.cpp:676
ripple::ammAccountID
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
ripple::sfTradingFee
const SF_UINT16 sfTradingFee
ripple::to_iso8601
std::string to_iso8601(NetClock::time_point tp)
Definition: AMMInfo.cpp:62
ripple::ammPoolHolds
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:29
ripple::sfExpiration
const SF_UINT32 sfExpiration
ripple::RPC::Context::j
const beast::Journal j
Definition: Context.h:41
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::getIssue
Issue getIssue(T const &amt)
Definition: AmountConversions.h:156
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::sfAuthAccounts
const SField sfAuthAccounts
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
std::chrono::time_point
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:706
std::runtime_error
STL class.
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::issueFromJson
Issue issueFromJson(Json::Value const &v)
Definition: Issue.cpp:77
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::getAccount
std::optional< AccountID > getAccount(Json::Value const &v, Json::Value &result)
Definition: AMMInfo.cpp:32
ripple::doAMMInfo
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition: AMMInfo.cpp:73
ripple::STObject
Definition: STObject.h:52
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RPC::isValidated
bool isValidated(LedgerMaster &ledgerMaster, ReadView const &ledger, Application &app)
Definition: RPCHelpers.cpp:604
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
ripple::ammLPHolds
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
std::optional
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
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::sfAccount
const SF_ACCOUNT sfAccount
ripple::rpcISSUE_MALFORMED
@ rpcISSUE_MALFORMED
Definition: ErrorCodes.h:146
ripple::sfAuctionSlot
const SField sfAuctionSlot
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::inject_error
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:214
ripple::isFrozen
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:220
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:87
ripple::Issue::account
AccountID account
Definition: Issue.h:39
std::runtime_error::what
T what(T... args)
ripple::ammAuctionTimeSlot
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition: AMMCore.cpp:107
Json::Value
Represents a JSON value.
Definition: json_value.h:145
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:84
std::chrono