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/ledger/ReadView.h>
21#include <xrpld/ledger/View.h>
22#include <xrpld/rpc/Context.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
24#include <xrpld/rpc/detail/Tuning.h>
25#include <xrpl/json/json_value.h>
26#include <xrpl/protocol/ErrorCodes.h>
27#include <xrpl/protocol/RPCErr.h>
28#include <xrpl/protocol/jss.h>
29#include <xrpl/resource/Fees.h>
30
31namespace ripple {
32
33void
35{
36 STAmount dirRate =
37 amountFromQuality(getQuality(offer->getFieldH256(sfBookDirectory)));
38 Json::Value& obj(offers.append(Json::objectValue));
39 offer->getFieldAmount(sfTakerPays).setJson(obj[jss::taker_pays]);
40 offer->getFieldAmount(sfTakerGets).setJson(obj[jss::taker_gets]);
41 obj[jss::seq] = offer->getFieldU32(sfSequence);
42 obj[jss::flags] = offer->getFieldU32(sfFlags);
43 obj[jss::quality] = dirRate.getText();
44 if (offer->isFieldPresent(sfExpiration))
45 obj[jss::expiration] = offer->getFieldU32(sfExpiration);
46};
47
48// {
49// account: <account>
50// ledger_hash : <ledger>
51// ledger_index : <ledger_index>
52// limit: integer // optional
53// marker: opaque // optional, resume previous query
54// }
57{
58 auto const& params(context.params);
59 if (!params.isMember(jss::account))
60 return RPC::missing_field_error(jss::account);
61
62 if (!params[jss::account].isString())
63 return RPC::invalid_field_error(jss::account);
64
66 auto result = RPC::lookupLedger(ledger, context);
67 if (!ledger)
68 return result;
69
70 auto id = parseBase58<AccountID>(params[jss::account].asString());
71 if (!id)
72 {
74 return result;
75 }
76 auto const accountID{std::move(id.value())};
77
78 // Get info on account.
79 result[jss::account] = toBase58(accountID);
80
81 if (!ledger->exists(keylet::account(accountID)))
83
84 unsigned int limit;
85 if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context))
86 return *err;
87
88 if (limit == 0)
89 return RPC::invalid_field_error(jss::limit);
90
91 Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
93 uint256 startAfter = beast::zero;
94 std::uint64_t startHint = 0;
95
96 if (params.isMember(jss::marker))
97 {
98 if (!params[jss::marker].isString())
99 return RPC::expected_field_error(jss::marker, "string");
100
101 // Marker is composed of a comma separated index and start hint. The
102 // former will be read as hex, and the latter using boost lexical cast.
103 std::stringstream marker(params[jss::marker].asString());
104 std::string value;
105 if (!std::getline(marker, value, ','))
106 return RPC::invalid_field_error(jss::marker);
107
108 if (!startAfter.parseHex(value))
109 return RPC::invalid_field_error(jss::marker);
110
111 if (!std::getline(marker, value, ','))
112 return RPC::invalid_field_error(jss::marker);
113
114 try
115 {
116 startHint = boost::lexical_cast<std::uint64_t>(value);
117 }
118 catch (boost::bad_lexical_cast&)
119 {
120 return RPC::invalid_field_error(jss::marker);
121 }
122
123 // We then must check if the object pointed to by the marker is actually
124 // owned by the account in the request.
125 auto const sle = ledger->read({ltANY, startAfter});
126
127 if (!sle)
129
130 if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
132 }
133
134 auto count = 0;
135 std::optional<uint256> marker = {};
136 std::uint64_t nextHint = 0;
137 if (!forEachItemAfter(
138 *ledger,
139 accountID,
140 startAfter,
141 startHint,
142 limit + 1,
143 [&offers, &count, &marker, &limit, &nextHint, &accountID](
144 std::shared_ptr<SLE const> const& sle) {
145 if (!sle)
146 {
147 UNREACHABLE("ripple::doAccountOffers : null SLE");
148 return false;
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:148
std::string getText() const override
Definition: STAmount.cpp:547
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:43
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
static LimitRange constexpr accountOffers
Limits for the account_offers command.
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:315
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:114
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:223
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:339
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:621
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:97
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:273
Charge const feeMediumBurdenRPC
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:175
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:140
@ 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:854
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:31
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.
Definition: LedgerFormats.h:78
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:571
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Resource::Charge & loadType
Definition: Context.h:41
Json::Value params
Definition: Context.h:62
T to_string(T... args)