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  startAfter.SetHex(marker.asString());
105  auto const sleOffer = ledger->read({ltOFFER, startAfter});
106 
107  if (!sleOffer || accountID != sleOffer->getAccountID(sfAccount))
108  {
109  return rpcError(rpcINVALID_PARAMS);
110  }
111 
112  startHint = sleOffer->getFieldU64(sfOwnerNode);
113  // Caller provided the first offer (startAfter), add it as first result
114  appendOfferJson(sleOffer, jsonOffers);
115  offers.reserve(reserve);
116  }
117  else
118  {
119  startHint = 0;
120  // We have no start point, limit should be one higher than requested.
121  offers.reserve(++reserve);
122  }
123 
124  if (!forEachItemAfter(
125  *ledger,
126  accountID,
127  startAfter,
128  startHint,
129  reserve,
130  [&offers](std::shared_ptr<SLE const> const& offer) {
131  if (offer->getType() == ltOFFER)
132  {
133  offers.emplace_back(offer);
134  return true;
135  }
136 
137  return false;
138  }))
139  {
140  return rpcError(rpcINVALID_PARAMS);
141  }
142 
143  if (offers.size() == reserve)
144  {
145  result[jss::limit] = limit;
146 
147  result[jss::marker] = to_string(offers.back()->key());
148  offers.pop_back();
149  }
150 
151  for (auto const& offer : offers)
152  appendOfferJson(offer, jsonOffers);
153 
155  return result;
156 }
157 
158 } // namespace ripple
ripple::RPC::JsonContext
Definition: Context.h:52
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::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
std::vector
STL class.
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:355
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:510
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:476
ripple::sfFlags
const SF_U32 sfFlags(access, STI_UINT32, 2, "Flags")
Definition: SField.h:353
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:442
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::sfOwnerNode
const SF_U64 sfOwnerNode(access, STI_UINT64, 4, "OwnerNode")
Definition: SField.h:397
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:481
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:302
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:236
ripple::base_uint
Definition: base_uint.h:63
ripple::sfBookDirectory
const SF_U256 sfBookDirectory(access, STI_HASH256, 16, "BookDirectory")
Definition: SField.h:427
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:120
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
ripple::STAmount
Definition: STAmount.h:42
ripple::base_uint::SetHex
bool SetHex(const char *psz, bool bStrict=false)
Parse a hex string into a base_uint The input can be:
Definition: base_uint.h:406
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::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::sfExpiration
const SF_U32 sfExpiration(access, STI_UINT32, 10, "Expiration")
Definition: SField.h:361
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::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:443
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:274
ripple::ltOFFER
@ ltOFFER
Definition: LedgerFormats.h:72
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:63
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:102
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:85
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:190
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469