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>|<account_public_key>
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  std::string strIdent(params[jss::account].asString());
69  AccountID accountID;
70 
71  if (auto jv = RPC::accountFromString(accountID, strIdent))
72  {
73  for (auto it = jv.begin(); it != jv.end(); ++it)
74  result[it.memberName()] = (*it);
75 
76  return result;
77  }
78 
79  // Get info on account.
80  result[jss::account] = toBase58(accountID);
81 
82  if (!ledger->exists(keylet::account(accountID)))
83  return rpcError(rpcACT_NOT_FOUND);
84 
85  unsigned int limit;
86  if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context))
87  return *err;
88 
89  if (limit == 0)
91 
92  Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
94  uint256 startAfter = beast::zero;
95  std::uint64_t startHint = 0;
96 
97  if (params.isMember(jss::marker))
98  {
99  if (!params[jss::marker].isString())
100  return RPC::expected_field_error(jss::marker, "string");
101 
102  // Marker is composed of a comma separated index and start hint. The
103  // former will be read as hex, and the latter using boost lexical cast.
104  std::stringstream marker(params[jss::marker].asString());
105  std::string value;
106  if (!std::getline(marker, value, ','))
107  return rpcError(rpcINVALID_PARAMS);
108 
109  if (!startAfter.parseHex(value))
110  return rpcError(rpcINVALID_PARAMS);
111 
112  if (!std::getline(marker, value, ','))
113  return rpcError(rpcINVALID_PARAMS);
114 
115  try
116  {
117  startHint = boost::lexical_cast<std::uint64_t>(value);
118  }
119  catch (boost::bad_lexical_cast&)
120  {
121  return rpcError(rpcINVALID_PARAMS);
122  }
123 
124  // We then must check if the object pointed to by the marker is actually
125  // owned by the account in the request.
126  auto const sle = ledger->read({ltANY, startAfter});
127 
128  if (!sle)
129  return rpcError(rpcINVALID_PARAMS);
130 
131  if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
132  return rpcError(rpcINVALID_PARAMS);
133  }
134 
135  auto count = 0;
136  std::optional<uint256> marker = {};
137  std::uint64_t nextHint = 0;
138  if (!forEachItemAfter(
139  *ledger,
140  accountID,
141  startAfter,
142  startHint,
143  limit + 1,
144  [&offers, &count, &marker, &limit, &nextHint, &accountID](
145  std::shared_ptr<SLE const> const& sle) {
146  if (!sle)
147  {
148  assert(false);
149  return false;
150  }
151 
152  if (++count == limit)
153  {
154  marker = sle->key();
155  nextHint = RPC::getStartHint(sle, accountID);
156  }
157 
158  if (count <= limit && sle->getType() == ltOFFER)
159  {
160  offers.emplace_back(sle);
161  }
162 
163  return true;
164  }))
165  {
166  return rpcError(rpcINVALID_PARAMS);
167  }
168 
169  // Both conditions need to be checked because marker is set on the limit-th
170  // item, but if there is no item on the limit + 1 iteration, then there is
171  // no need to return a marker.
172  if (count == limit + 1 && marker)
173  {
174  result[jss::limit] = limit;
175  result[jss::marker] =
176  to_string(*marker) + "," + std::to_string(nextHint);
177  }
178 
179  for (auto const& offer : offers)
180  appendOfferJson(offer, jsonOffers);
181 
183  return result;
184 }
185 
186 } // 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:550
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
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
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:831
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::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::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:86
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