Add account_offers paging (RIPD-344)

This commit is contained in:
Miguel Portilla
2014-09-11 13:13:26 -04:00
committed by Nik Bougalis
parent cd1bd18a49
commit d78f740250
2 changed files with 122 additions and 31 deletions

View File

@@ -801,7 +801,7 @@ public:
{ "account_currencies", &RPCParser::parseAccountCurrencies, 1, 2 },
{ "account_info", &RPCParser::parseAccountItems, 1, 2 },
{ "account_lines", &RPCParser::parseAccountLines, 1, 5 },
{ "account_offers", &RPCParser::parseAccountItems, 1, 2 },
{ "account_offers", &RPCParser::parseAccountItems, 1, 4 },
{ "account_tx", &RPCParser::parseAccountTransactions, 1, 8 },
{ "book_offers", &RPCParser::parseBookOffers, 2, 7 },
{ "connect", &RPCParser::parseConnect, 1, 2 },

View File

@@ -17,42 +17,34 @@
*/
//==============================================================================
#include <ripple/rpc/impl/Tuning.h>
namespace ripple {
static void offerAdder (Json::Value& jvLines, SLE::ref offer)
{
if (offer->getType () == ltOFFER)
{
Json::Value& obj = jvLines.append (Json::objectValue);
offer->getFieldAmount (sfTakerPays).setJson (obj[jss::taker_pays]);
offer->getFieldAmount (sfTakerGets).setJson (obj[jss::taker_gets]);
obj[jss::seq] = offer->getFieldU32 (sfSequence);
obj[jss::flags] = offer->getFieldU32 (sfFlags);
}
}
// {
// account: <account>|<account_public_key>
// account_index: <number> // optional, defaults to 0.
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// limit: integer // optional
// marker: opaque // optional, resume previous query
// }
Json::Value doAccountOffers (RPC::Context& context)
{
auto const& params (context.params_);
Ledger::pointer ledger;
Json::Value result
= RPC::lookupLedger (context.params_, ledger, context.netOps_);
Json::Value result (RPC::lookupLedger (params, ledger, context.netOps_));
if (! ledger)
return result;
if (!context.params_.isMember (jss::account))
if (! params.isMember (jss::account))
return RPC::missing_field_error ("account");
std::string strIdent = context.params_[jss::account].asString ();
bool bIndex = context.params_.isMember (jss::account_index);
int iIndex = bIndex ? context.params_[jss::account_index].asUInt () : 0;
std::string strIdent (params[jss::account].asString ());
bool bIndex (params.isMember (jss::account_index));
int iIndex (bIndex ? params[jss::account_index].asUInt () : 0);
RippleAddress raAccount;
@@ -72,14 +64,113 @@ Json::Value doAccountOffers (RPC::Context& context)
if (! ledger->hasAccount (raAccount))
return rpcError (rpcACT_NOT_FOUND);
Json::Value& jvsOffers = (result[jss::offers] = Json::arrayValue);
auto adder = std::bind (
&offerAdder,
std::ref (jvsOffers),
std::placeholders::_1);
ledger->visitAccountItems (raAccount.getAccountID (), adder);
context.loadType_ = Resource::feeMediumBurdenRPC;
unsigned int limit;
if (params.isMember (jss::limit))
{
limit = std::max (RPC::Tuning::minOffersPerRequest,
std::min (params[jss::limit].asUInt (),
RPC::Tuning::maxOffersPerRequest));
}
else
{
limit = RPC::Tuning::defaultOffersPerRequest;
}
uint256 const rootIndex (Ledger::getOwnerDirIndex (raAccount.getAccountID ()));
std::uint32_t resumeSeq;
uint256 currentIndex;
bool resume (true);
if (params.isMember (jss::marker))
{
Json::Value const& marker (params[jss::marker]);
if (! marker.isObject () || marker.size () != 2 ||
! marker.isMember (jss::seq) || ! marker[jss::seq].isIntegral () ||
! marker.isMember (jss::account_index) ||
! marker[jss::account_index].isString ())
{
return rpcError (rpcACT_MALFORMED);
}
resumeSeq = marker[jss::seq].asUInt ();
currentIndex = Ledger::getDirNodeIndex (rootIndex,
uintFromHex (marker[jss::account_index].asString ()));
resume = false;
}
else
{
currentIndex = rootIndex;
}
Json::Value& jvsOffers(result[jss::offers] = Json::arrayValue);
unsigned int i (0);
bool process (true);
while (process)
{
SLE::pointer ownerDir (ledger->getSLEi (currentIndex));
if (!ownerDir || ownerDir->getType () != ltDIR_NODE)
break;
for (auto const& node : ownerDir->getFieldV256 (sfIndexes).peekValue ())
{
SLE::ref offer (ledger->getSLEi (node));
if (offer->getType () == ltOFFER)
{
std::uint32_t const seq (offer->getFieldU32 (sfSequence));
if (!resume && resumeSeq == seq)
resume = true;
if (resume)
{
if (i < limit)
{
Json::Value& obj (jvsOffers.append (Json::objectValue));
offer->getFieldAmount (sfTakerPays).setJson (
obj[jss::taker_pays]);
offer->getFieldAmount (sfTakerGets).setJson (
obj[jss::taker_gets]);
obj[jss::seq] = seq;
obj[jss::flags] = offer->getFieldU32 (sfFlags);
++i;
}
else
{
result[jss::limit] = limit;
Json::Value& marker (result[jss::marker] = Json::objectValue);
marker[jss::seq] = seq;
marker[jss::account_index] = strHex(
ownerDir->getFieldU64 (sfIndexPrevious));
process = false;
break;
}
}
}
}
if (process)
{
std::uint64_t const uNodeNext(ownerDir->getFieldU64(sfIndexNext));
if (!uNodeNext)
break;
currentIndex = Ledger::getDirNodeIndex(rootIndex, uNodeNext);
}
}
if (!resume)
return rpcError (rpcACT_MALFORMED);
context.loadType_ = Resource::feeMediumBurdenRPC;
return result;
}