rippled
AccountOffers.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 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/app/main/Application.h>
21 #include <ripple/json/json_value.h>
22 #include <ripple/ledger/ReadView.h>
23 #include <ripple/ledger/View.h>
24 #include <ripple/net/RPCErr.h>
25 #include <ripple/protocol/ErrorCodes.h>
26 #include <ripple/protocol/jss.h>
27 #include <ripple/resource/Fees.h>
28 #include <ripple/rpc/Context.h>
29 #include <ripple/rpc/impl/RPCHelpers.h>
30 #include <ripple/rpc/impl/Tuning.h>
31 
32 namespace ripple {
33 
34 void
36 {
37  STAmount dirRate =
38  amountFromQuality(getQuality(offer->getFieldH256(sfBookDirectory)));
39  Json::Value& obj(offers.append(Json::objectValue));
40  offer->getFieldAmount(sfTakerPays).setJson(obj[jss::taker_pays]);
41  offer->getFieldAmount(sfTakerGets).setJson(obj[jss::taker_gets]);
42  obj[jss::seq] = offer->getFieldU32(sfSequence);
43  obj[jss::flags] = offer->getFieldU32(sfFlags);
44  obj[jss::quality] = dirRate.getText();
45  if (offer->isFieldPresent(sfExpiration))
46  obj[jss::expiration] = offer->getFieldU32(sfExpiration);
47 };
48 
49 // {
50 // account: <account>
51 // ledger_hash : <ledger>
52 // ledger_index : <ledger_index>
53 // limit: integer // optional
54 // marker: opaque // optional, resume previous query
55 // }
58 {
59  auto const& params(context.params);
60  if (!params.isMember(jss::account))
61  return RPC::missing_field_error(jss::account);
62 
64  auto result = RPC::lookupLedger(ledger, context);
65  if (!ledger)
66  return result;
67 
68  auto id = parseBase58<AccountID>(params[jss::account].asString());
69  if (!id)
70  {
72  return result;
73  }
74  auto const accountID{std::move(id.value())};
75 
76  // Get info on account.
77  result[jss::account] = toBase58(accountID);
78 
79  if (!ledger->exists(keylet::account(accountID)))
80  return rpcError(rpcACT_NOT_FOUND);
81 
82  unsigned int limit;
83  if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context))
84  return *err;
85 
86  if (limit == 0)
88 
89  Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
91  uint256 startAfter = beast::zero;
92  std::uint64_t startHint = 0;
93 
94  if (params.isMember(jss::marker))
95  {
96  if (!params[jss::marker].isString())
97  return RPC::expected_field_error(jss::marker, "string");
98 
99  // Marker is composed of a comma separated index and start hint. The
100  // former will be read as hex, and the latter using boost lexical cast.
101  std::stringstream marker(params[jss::marker].asString());
102  std::string value;
103  if (!std::getline(marker, value, ','))
104  return rpcError(rpcINVALID_PARAMS);
105 
106  if (!startAfter.parseHex(value))
107  return rpcError(rpcINVALID_PARAMS);
108 
109  if (!std::getline(marker, value, ','))
110  return rpcError(rpcINVALID_PARAMS);
111 
112  try
113  {
114  startHint = boost::lexical_cast<std::uint64_t>(value);
115  }
116  catch (boost::bad_lexical_cast&)
117  {
118  return rpcError(rpcINVALID_PARAMS);
119  }
120 
121  // We then must check if the object pointed to by the marker is actually
122  // owned by the account in the request.
123  auto const sle = ledger->read({ltANY, startAfter});
124 
125  if (!sle)
126  return rpcError(rpcINVALID_PARAMS);
127 
128  if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
129  return rpcError(rpcINVALID_PARAMS);
130  }
131 
132  auto count = 0;
133  std::optional<uint256> marker = {};
134  std::uint64_t nextHint = 0;
135  if (!forEachItemAfter(
136  *ledger,
137  accountID,
138  startAfter,
139  startHint,
140  limit + 1,
141  [&offers, &count, &marker, &limit, &nextHint, &accountID](
142  std::shared_ptr<SLE const> const& sle) {
143  if (!sle)
144  {
145  assert(false);
146  return false;
147  }
148 
149  if (++count == limit)
150  {
151  marker = sle->key();
152  nextHint = RPC::getStartHint(sle, accountID);
153  }
154 
155  if (count <= limit && sle->getType() == ltOFFER)
156  {
157  offers.emplace_back(sle);
158  }
159 
160  return true;
161  }))
162  {
163  return rpcError(rpcINVALID_PARAMS);
164  }
165 
166  // Both conditions need to be checked because marker is set on the limit-th
167  // item, but if there is no item on the limit + 1 iteration, then there is
168  // no need to return a marker.
169  if (count == limit + 1 && marker)
170  {
171  result[jss::limit] = limit;
172  result[jss::marker] =
173  to_string(*marker) + "," + std::to_string(nextHint);
174  }
175 
176  for (auto const& offer : offers)
177  appendOfferJson(offer, jsonOffers);
178 
180  return result;
181 }
182 
183 } // namespace ripple
ripple::STLedgerEntry::key
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
Definition: STLedgerEntry.h:113
ripple::RPC::JsonContext
Definition: Context.h:53
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::appendOfferJson
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Definition: AccountOffers.cpp:35
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:176
ripple::forEachItemAfter
bool forEachItemAfter(ReadView const &view, Keylet const &root, uint256 const &after, std::uint64_t const hint, unsigned int limit, std::function< bool(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items after an item in the given directory.
Definition: View.cpp:394
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
std::vector
STL class.
ripple::sfBookDirectory
const SF_UINT256 sfBookDirectory
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:571
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
std::stringstream
STL class.
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:675
ripple::RPC::expected_field_error
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:328
ripple::sfExpiration
const SF_UINT32 sfExpiration
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:262
ripple::base_uint< 256 >
ripple::sfTakerPays
const SF_AMOUNT sfTakerPays
ripple::ltOFFER
@ ltOFFER
A ledger object which describes an offer on the DEX.
Definition: LedgerFormats.h:92
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
std::to_string
T to_string(T... args)
ripple::STAmount
Definition: STAmount.h:45
ripple::ReadView::exists
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
ripple::sfTakerGets
const SF_AMOUNT sfTakerGets
ripple::doAccountOffers
Json::Value doAccountOffers(RPC::JsonContext &context)
Definition: AccountOffers.cpp:57
std::uint64_t
ripple::amountFromQuality
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:852
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
ripple::RPC::Tuning::accountOffers
static constexpr LimitRange accountOffers
Limits for the account_offers command.
Definition: rpc/impl/Tuning.h:46
std::getline
T getline(T... args)
ripple::sfFlags
const SF_UINT32 sfFlags
ripple::RPC::getStartHint
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
Definition: RPCHelpers.cpp:96
std::optional
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::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:108
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:212
ripple::RPC::isRelatedToAccount
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
Definition: RPCHelpers.cpp:113
Json::Value
Represents a JSON value.
Definition: json_value.h:145