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 
35  Json::Value& offers)
36 {
37  STAmount dirRate = amountFromQuality (
38  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 // }
57 {
58  auto const& params (context.params);
59  if (! params.isMember (jss::account))
60  return RPC::missing_field_error (jss::account);
61 
63  auto result = RPC::lookupLedger (ledger, context);
64  if (! ledger)
65  return result;
66 
67  std::string strIdent (params[jss::account].asString ());
68  AccountID accountID;
69 
70  if (auto jv = RPC::accountFromString (accountID, strIdent))
71  {
72  for (auto it = jv.begin (); it != jv.end (); ++it)
73  result[it.memberName ()] = (*it);
74 
75  return result;
76  }
77 
78  // Get info on account.
79  result[jss::account] = context.app.accountIDCache().toBase58 (accountID);
80 
81  if (! ledger->exists(keylet::account (accountID)))
82  return rpcError (rpcACT_NOT_FOUND);
83 
84  unsigned int limit;
85  if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context))
86  return *err;
87 
88  Json::Value& jsonOffers (result[jss::offers] = Json::arrayValue);
90  unsigned int reserve (limit);
91  uint256 startAfter;
92  std::uint64_t startHint;
93 
94  if (params.isMember(jss::marker))
95  {
96  // We have a start point. Use limit - 1 from the result and use the
97  // very last one for the resume.
98  Json::Value const& marker (params[jss::marker]);
99 
100  if (! marker.isString ())
101  return RPC::expected_field_error (jss::marker, "string");
102 
103  startAfter.SetHex (marker.asString ());
104  auto const sleOffer = ledger->read({ltOFFER, startAfter});
105 
106  if (! sleOffer || accountID != sleOffer->getAccountID (sfAccount))
107  {
108  return rpcError (rpcINVALID_PARAMS);
109  }
110 
111  startHint = sleOffer->getFieldU64(sfOwnerNode);
112  // Caller provided the first offer (startAfter), add it as first result
113  appendOfferJson(sleOffer, jsonOffers);
114  offers.reserve (reserve);
115  }
116  else
117  {
118  startHint = 0;
119  // We have no start point, limit should be one higher than requested.
120  offers.reserve (++reserve);
121  }
122 
123  if (! forEachItemAfter(*ledger, accountID,
124  startAfter, startHint, reserve,
125  [&offers](std::shared_ptr<SLE const> const& offer)
126  {
127  if (offer->getType () == ltOFFER)
128  {
129  offers.emplace_back (offer);
130  return true;
131  }
132 
133  return false;
134  }))
135  {
136  return rpcError (rpcINVALID_PARAMS);
137  }
138 
139  if (offers.size () == reserve)
140  {
141  result[jss::limit] = limit;
142 
143  result[jss::marker] = to_string (offers.back ()->key ());
144  offers.pop_back ();
145  }
146 
147  for (auto const& offer : offers)
148  appendOfferJson(offer, jsonOffers);
149 
151  return result;
152 }
153 
154 } // 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:85
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1049
ripple::appendOfferJson
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Definition: AccountOffers.cpp:34
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:44
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:340
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:492
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:460
ripple::sfFlags
const SF_U32 sfFlags(access, STI_UINT32, 2, "Flags")
Definition: SField.h:338
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:426
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:382
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:484
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:286
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:229
ripple::base_uint
Definition: base_uint.h:65
ripple::sfBookDirectory
const SF_U256 sfBookDirectory(access, STI_HASH256, 16, "BookDirectory")
Definition: SField.h:412
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:71
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:362
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:56
std::uint64_t
ripple::amountFromQuality
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:729
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:28
ripple::sfExpiration
const SF_U32 sfExpiration(access, STI_UINT32, 10, "Expiration")
Definition: SField.h:346
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:45
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:427
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:266
ripple::ltOFFER
@ ltOFFER
Definition: LedgerFormats.h:73
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:63
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:135
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:86
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:199
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482