rippled
Loading...
Searching...
No Matches
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 <xrpld/rpc/Context.h>
21#include <xrpld/rpc/detail/RPCHelpers.h>
22#include <xrpld/rpc/detail/Tuning.h>
23
24#include <xrpl/json/json_value.h>
25#include <xrpl/ledger/ReadView.h>
26#include <xrpl/ledger/View.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/RPCErr.h>
29#include <xrpl/protocol/jss.h>
30#include <xrpl/resource/Fees.h>
31
32namespace ripple {
33
34void
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
63 if (!params[jss::account].isString())
64 return RPC::invalid_field_error(jss::account);
65
67 auto result = RPC::lookupLedger(ledger, context);
68 if (!ledger)
69 return result;
70
71 auto id = parseBase58<AccountID>(params[jss::account].asString());
72 if (!id)
73 {
75 return result;
76 }
77 auto const accountID{std::move(id.value())};
78
79 // Get info on account.
80 result[jss::account] = toBase58(accountID);
81
82 if (!ledger->exists(keylet::account(accountID)))
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 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 RPC::invalid_field_error(jss::marker);
105
106 if (!startAfter.parseHex(value))
107 return RPC::invalid_field_error(jss::marker);
108
109 if (!std::getline(marker, value, ','))
110 return RPC::invalid_field_error(jss::marker);
111
112 try
113 {
114 startHint = boost::lexical_cast<std::uint64_t>(value);
115 }
116 catch (boost::bad_lexical_cast&)
117 {
118 return RPC::invalid_field_error(jss::marker);
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)
127
128 if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
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 // LCOV_EXCL_START
146 UNREACHABLE("ripple::doAccountOffers : null SLE");
147 return false;
148 // LCOV_EXCL_STOP
149 }
150
151 if (++count == limit)
152 {
153 marker = sle->key();
154 nextHint = RPC::getStartHint(sle, accountID);
155 }
156
157 if (count <= limit && sle->getType() == ltOFFER)
158 {
159 offers.emplace_back(sle);
160 }
161
162 return true;
163 }))
164 {
166 }
167
168 // Both conditions need to be checked because marker is set on the limit-th
169 // item, but if there is no item on the limit + 1 iteration, then there is
170 // no need to return a marker.
171 if (count == limit + 1 && marker)
172 {
173 result[jss::limit] = limit;
174 result[jss::marker] =
175 to_string(*marker) + "," + std::to_string(nextHint);
176 }
177
178 for (auto const& offer : offers)
179 appendOfferJson(offer, jsonOffers);
180
182 return result;
183}
184
185} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
std::string getText() const override
Definition STAmount.cpp:683
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:503
T getline(T... args)
@ arrayValue
array value (ordered list)
Definition json_value.h:44
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
static LimitRange constexpr accountOffers
Limits for the account_offers command.
Json::Value invalid_field_error(std::string const &name)
Definition ErrorCodes.h:325
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition ErrorCodes.h:233
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition ErrorCodes.h:349
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.
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
Json::Value missing_field_error(std::string const &name)
Definition ErrorCodes.h:283
Charge const feeMediumBurdenRPC
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::uint64_t getQuality(uint256 const &uBase)
Definition Indexes.cpp:149
@ rpcACT_NOT_FOUND
Definition ErrorCodes.h:70
@ rpcACT_MALFORMED
Definition ErrorCodes.h:90
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:84
STAmount amountFromQuality(std::uint64_t rate)
Definition STAmount.cpp:984
Json::Value rpcError(int iError)
Definition RPCErr.cpp:31
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:684
Json::Value doAccountOffers(RPC::JsonContext &context)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
@ ltANY
A special type, matching any ledger entry type.
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Resource::Charge & loadType
Definition Context.h:42
T to_string(T... args)