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] = context.app.accountIDCache().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  Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
91  unsigned int reserve(limit);
92  uint256 startAfter;
93  std::uint64_t startHint;
94 
95  if (params.isMember(jss::marker))
96  {
97  // We have a start point. Use limit - 1 from the result and use the
98  // very last one for the resume.
99  Json::Value const& marker(params[jss::marker]);
100 
101  if (!marker.isString())
102  return RPC::expected_field_error(jss::marker, "string");
103 
104  if (!startAfter.parseHex(marker.asString()))
105  return rpcError(rpcINVALID_PARAMS);
106 
107  auto const sleOffer = ledger->read({ltOFFER, startAfter});
108 
109  if (!sleOffer || accountID != sleOffer->getAccountID(sfAccount))
110  {
111  return rpcError(rpcINVALID_PARAMS);
112  }
113 
114  startHint = sleOffer->getFieldU64(sfOwnerNode);
115  // Caller provided the first offer (startAfter), add it as first result
116  appendOfferJson(sleOffer, jsonOffers);
117  offers.reserve(reserve);
118  }
119  else
120  {
121  startHint = 0;
122  // We have no start point, limit should be one higher than requested.
123  offers.reserve(++reserve);
124  }
125 
126  if (!forEachItemAfter(
127  *ledger,
128  accountID,
129  startAfter,
130  startHint,
131  reserve,
132  [&offers](std::shared_ptr<SLE const> const& offer) {
133  if (offer->getType() == ltOFFER)
134  {
135  offers.emplace_back(offer);
136  return true;
137  }
138 
139  return false;
140  }))
141  {
142  return rpcError(rpcINVALID_PARAMS);
143  }
144 
145  if (offers.size() == reserve)
146  {
147  result[jss::limit] = limit;
148 
149  result[jss::marker] = to_string(offers.back()->key());
150  offers.pop_back();
151  }
152 
153  for (auto const& offer : offers)
154  appendOfferJson(offer, jsonOffers);
155 
157  return result;
158 }
159 
160 } // namespace ripple
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
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
ripple::appendOfferJson
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Definition: AccountOffers.cpp:35
ripple::sfOwnerNode
const SF_UINT64 sfOwnerNode
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::sfBookDirectory
const SF_HASH256 sfBookDirectory
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
std::vector
STL class.
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:510
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
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:535
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::RPC::expected_field_error
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:309
ripple::sfExpiration
const SF_UINT32 sfExpiration
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:243
ripple::base_uint< 160, detail::AccountIDTag >
ripple::sfTakerPays
const SF_AMOUNT sfTakerPays
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:134
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
ripple::STAmount
Definition: STAmount.h:42
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
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:749
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:29
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
ripple::base_uint::parseHex
bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:384
ripple::sfFlags
const SF_UINT32 sfFlags
ripple::forEachItemAfter
bool forEachItemAfter(ReadView const &view, AccountID const &id, uint256 const &after, std::uint64_t const hint, unsigned int limit, std::function< bool(std::shared_ptr< SLE const > const &)> f)
Iterate all items after an item in an owner directory.
Definition: View.cpp:277
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::ltOFFER
@ ltOFFER
Definition: LedgerFormats.h:72
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:109
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:82
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:134
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469