mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Add RPC vault_info, remove RPC::supplementJson<ltVAULT>
This commit is contained in:
@@ -450,6 +450,7 @@ JSS(node_reads_hit); // out: GetCounts
|
||||
JSS(node_reads_total); // out: GetCounts
|
||||
JSS(node_reads_duration_us); // out: GetCounts
|
||||
JSS(node_size); // out: server_info
|
||||
JSS(nodes); // out: VaultInfo
|
||||
JSS(nodestore); // out: GetCounts
|
||||
JSS(node_writes); // out: GetCounts
|
||||
JSS(node_written_bytes); // out: GetCounts
|
||||
|
||||
@@ -802,19 +802,17 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
auto const vaultAccount = //
|
||||
[&env, key = keylet.key, this]() -> AccountID {
|
||||
Json::Value jvParams;
|
||||
jvParams[jss::ledger_index] = jss::validated;
|
||||
jvParams[jss::vault] = strHex(key);
|
||||
auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams));
|
||||
auto jvVault = env.rpc("vault_info", strHex(key));
|
||||
BEAST_EXPECT(
|
||||
jvVault[jss::result][jss::node][jss::SharesTotal] == "100");
|
||||
jvVault[jss::result][jss::nodes][0u][sfAssetsTotal] == "100");
|
||||
BEAST_EXPECT(
|
||||
jvVault[jss::result][jss::node][sfAssetsTotal.fieldName] ==
|
||||
jvVault[jss::result][jss::nodes][1u][sfOutstandingAmount] ==
|
||||
"100");
|
||||
|
||||
// Vault pseudo-account
|
||||
return parseBase58<AccountID>(
|
||||
jvVault[jss::result][jss::node][jss::Account].asString())
|
||||
jvVault[jss::result][jss::nodes][0u][jss::Account]
|
||||
.asString())
|
||||
.value();
|
||||
}();
|
||||
|
||||
@@ -843,15 +841,11 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
{
|
||||
testcase("nontransferable shares balance check");
|
||||
Json::Value jvParams;
|
||||
jvParams[jss::ledger_index] = jss::validated;
|
||||
jvParams[jss::vault] = strHex(keylet.key);
|
||||
auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams));
|
||||
|
||||
auto jvVault = env.rpc("vault_info", strHex(keylet.key));
|
||||
BEAST_EXPECT(
|
||||
jvVault[jss::result][jss::node][jss::SharesTotal] == "50");
|
||||
jvVault[jss::result][jss::nodes][0u][sfAssetsTotal] == "50");
|
||||
BEAST_EXPECT(
|
||||
jvVault[jss::result][jss::node][sfAssetsTotal.fieldName] ==
|
||||
jvVault[jss::result][jss::nodes][1u][sfOutstandingAmount] ==
|
||||
"50");
|
||||
}
|
||||
|
||||
@@ -1383,52 +1377,66 @@ class Vault_test : public beast::unit_test::suite
|
||||
}();
|
||||
|
||||
auto const check = [&, keylet = keylet, sle = sleVault, this](
|
||||
Json::Value const& node) {
|
||||
BEAST_EXPECT(node.isObject());
|
||||
Json::Value const& vault,
|
||||
Json::Value const& issuance = Json::nullValue) {
|
||||
BEAST_EXPECT(vault.isObject());
|
||||
|
||||
auto checkString =
|
||||
[&node](SField const& field, std::string expected) -> bool {
|
||||
constexpr auto checkString =
|
||||
[](auto& node, SField const& field, std::string v) -> bool {
|
||||
return node.isMember(field.fieldName) &&
|
||||
node[field.fieldName].isString() &&
|
||||
node[field.fieldName] == expected;
|
||||
node[field.fieldName] == v;
|
||||
};
|
||||
auto checkObject =
|
||||
[&node](SField const& field, Json::Value expected) -> bool {
|
||||
constexpr auto checkObject =
|
||||
[](auto& node, SField const& field, Json::Value v) -> bool {
|
||||
return node.isMember(field.fieldName) &&
|
||||
node[field.fieldName].isObject() &&
|
||||
node[field.fieldName] == expected;
|
||||
node[field.fieldName] == v;
|
||||
};
|
||||
auto checkInt = [&node](SField const& field, int expected) -> bool {
|
||||
constexpr auto checkInt =
|
||||
[](auto& node, SField const& field, int v) -> bool {
|
||||
return node.isMember(field.fieldName) &&
|
||||
((node[field.fieldName].isInt() &&
|
||||
node[field.fieldName] == Json::Int(expected)) ||
|
||||
node[field.fieldName] == Json::Int(v)) ||
|
||||
(node[field.fieldName].isUInt() &&
|
||||
node[field.fieldName] == Json::UInt(expected)));
|
||||
node[field.fieldName] == Json::UInt(v)));
|
||||
};
|
||||
|
||||
BEAST_EXPECT(node["LedgerEntryType"].asString() == "Vault");
|
||||
BEAST_EXPECT(node[jss::index].asString() == strHex(keylet.key));
|
||||
BEAST_EXPECT(checkInt(sfFlags, 0));
|
||||
BEAST_EXPECT(vault["LedgerEntryType"].asString() == "Vault");
|
||||
BEAST_EXPECT(vault[jss::index].asString() == strHex(keylet.key));
|
||||
BEAST_EXPECT(checkInt(vault, sfFlags, 0));
|
||||
// Ignore all other standard fields, this test doesn't care
|
||||
|
||||
BEAST_EXPECT(checkString(sfAccount, toBase58(sle->at(sfAccount))));
|
||||
BEAST_EXPECT(checkObject(sfAsset, to_json(sle->at(sfAsset))));
|
||||
BEAST_EXPECT(checkString(sfAssetsAvailable, "50"));
|
||||
BEAST_EXPECT(checkString(sfAssetsMaximum, "1000"));
|
||||
BEAST_EXPECT(checkString(sfAssetsTotal, "50"));
|
||||
BEAST_EXPECT(checkString(sfLossUnrealized, "0"));
|
||||
BEAST_EXPECT(
|
||||
checkString(sfShareMPTID, strHex(sle->at(sfShareMPTID))));
|
||||
BEAST_EXPECT(checkString(sfOwner, toBase58(owner.id())));
|
||||
BEAST_EXPECT(checkInt(sfSequence, sequence));
|
||||
checkString(vault, sfAccount, toBase58(sle->at(sfAccount))));
|
||||
BEAST_EXPECT(
|
||||
checkInt(sfWithdrawalPolicy, vaultStrategyFirstComeFirstServe));
|
||||
checkObject(vault, sfAsset, to_json(sle->at(sfAsset))));
|
||||
BEAST_EXPECT(checkString(vault, sfAssetsAvailable, "50"));
|
||||
BEAST_EXPECT(checkString(vault, sfAssetsMaximum, "1000"));
|
||||
BEAST_EXPECT(checkString(vault, sfAssetsTotal, "50"));
|
||||
BEAST_EXPECT(checkString(vault, sfLossUnrealized, "0"));
|
||||
|
||||
// This field is injected in RPC::supplementJson<ltVAULT>
|
||||
BEAST_EXPECT(
|
||||
node.isMember(jss::SharesTotal) &&
|
||||
node[jss::SharesTotal].isString() &&
|
||||
node[jss::SharesTotal] == "50");
|
||||
auto const strShareID = strHex(sle->at(sfShareMPTID));
|
||||
BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
|
||||
BEAST_EXPECT(checkString(vault, sfOwner, toBase58(owner.id())));
|
||||
BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
|
||||
BEAST_EXPECT(checkInt(
|
||||
vault, sfWithdrawalPolicy, vaultStrategyFirstComeFirstServe));
|
||||
|
||||
if (issuance.isObject())
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
issuance["LedgerEntryType"].asString() ==
|
||||
"MPTokenIssuance");
|
||||
BEAST_EXPECT(
|
||||
issuance[jss::mpt_issuance_id].asString() == strShareID);
|
||||
BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
|
||||
BEAST_EXPECT(checkInt(
|
||||
issuance,
|
||||
sfFlags,
|
||||
int(lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer)));
|
||||
BEAST_EXPECT(checkString(issuance, sfOutstandingAmount, "50"));
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
@@ -1537,6 +1545,74 @@ class Vault_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
|
||||
check(jv[jss::result][jss::state][0u]);
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info command line");
|
||||
Json::Value jv =
|
||||
env.rpc("vault_info", strHex(keylet.key), "validated");
|
||||
|
||||
BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::nodes));
|
||||
BEAST_EXPECT(jv[jss::result][jss::nodes].isArray());
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::directory));
|
||||
BEAST_EXPECT(jv[jss::result][jss::directory][jss::vault] == 0);
|
||||
BEAST_EXPECT(
|
||||
jv[jss::result][jss::directory][jss::mpt_issuance] == 1);
|
||||
check(
|
||||
jv[jss::result][jss::nodes][0u],
|
||||
jv[jss::result][jss::nodes][1u]);
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info json by owner and sequence");
|
||||
Json::Value jvParams;
|
||||
jvParams[jss::ledger_index] = jss::validated;
|
||||
jvParams[jss::vault][jss::owner] = owner.human();
|
||||
jvParams[jss::vault][jss::seq] = sequence;
|
||||
auto jv = env.rpc("json", "vault_info", to_string(jvParams));
|
||||
|
||||
BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::nodes));
|
||||
BEAST_EXPECT(jv[jss::result][jss::nodes].isArray());
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::directory));
|
||||
BEAST_EXPECT(jv[jss::result][jss::directory][jss::vault] == 0);
|
||||
BEAST_EXPECT(
|
||||
jv[jss::result][jss::directory][jss::mpt_issuance] == 1);
|
||||
check(
|
||||
jv[jss::result][jss::nodes][0u],
|
||||
jv[jss::result][jss::nodes][1u]);
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info command line invalid index");
|
||||
Json::Value jv = env.rpc("vault_info", "0", "validated");
|
||||
BEAST_EXPECT(jv[jss::error].asString() == "invalidParams");
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info json invalid index");
|
||||
Json::Value jvParams;
|
||||
jvParams[jss::ledger_index] = jss::validated;
|
||||
jvParams[jss::vault] = 0;
|
||||
auto jv = env.rpc("json", "vault_info", to_string(jvParams));
|
||||
BEAST_EXPECT(
|
||||
jv[jss::result][jss::error].asString() == "malformedRequest");
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info command line invalid index");
|
||||
Json::Value jv =
|
||||
env.rpc("vault_info", strHex(uint256(42)), "validated");
|
||||
BEAST_EXPECT(
|
||||
jv[jss::result][jss::error].asString() == "entryNotFound");
|
||||
}
|
||||
|
||||
{
|
||||
testcase("RPC vault_info command line invalid ledger");
|
||||
Json::Value jv = env.rpc("vault_info", strHex(keylet.key), "0");
|
||||
BEAST_EXPECT(
|
||||
jv[jss::result][jss::error].asString() == "lgrNotFound");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/core/LexicalCast.h>
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
#include <xrpl/json/to_string.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
@@ -862,6 +863,25 @@ private:
|
||||
return jvRequest;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
parseVault(Json::Value const& jvParams)
|
||||
{
|
||||
std::string strVaultID = jvParams[0u].asString();
|
||||
uint256 id = beast::zero;
|
||||
if (!id.parseHex(strVaultID))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
if (id == beast::zero)
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
|
||||
Json::Value jvRequest(Json::objectValue);
|
||||
jvRequest[jss::vault] = strVaultID;
|
||||
|
||||
if (jvParams.size() > 1)
|
||||
jvParseLedger(jvRequest, jvParams[1u].asString());
|
||||
|
||||
return jvRequest;
|
||||
}
|
||||
|
||||
// peer_reservations_add <public_key> [<name>]
|
||||
Json::Value
|
||||
parsePeerReservationsAdd(Json::Value const& jvParams)
|
||||
@@ -1208,6 +1228,7 @@ public:
|
||||
{"account_offers", &RPCParser::parseAccountItems, 1, 4},
|
||||
{"account_tx", &RPCParser::parseAccountTransactions, 1, 8},
|
||||
{"amm_info", &RPCParser::parseAsIs, 1, 2},
|
||||
{"vault_info", &RPCParser::parseVault, 1, 2},
|
||||
{"book_changes", &RPCParser::parseLedgerId, 1, 1},
|
||||
{"book_offers", &RPCParser::parseBookOffers, 2, 7},
|
||||
{"can_delete", &RPCParser::parseCanDelete, 0, 1},
|
||||
|
||||
@@ -93,6 +93,7 @@ Handler const handlerArray[]{
|
||||
{"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
|
||||
{"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
|
||||
{"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
|
||||
{"vault_info", byRef(&doVaultInfo), Role::USER, NO_CONDITION},
|
||||
{"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
|
||||
{"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
|
||||
{"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
|
||||
|
||||
@@ -149,26 +149,6 @@ isRelatedToAccount(
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
supplementJson<ltVAULT>(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
Json::Value& node)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
vault->getType() == ltVAULT,
|
||||
"ripple::RPC::supplementJson<ltVAULT> : matching type");
|
||||
|
||||
auto const share = vault->at(sfShareMPTID);
|
||||
auto const sleIssuance = view.read(keylet::mptIssuance(share));
|
||||
if (!sleIssuance)
|
||||
return;
|
||||
|
||||
node[jss::SharesTotal] =
|
||||
Number(sleIssuance->getFieldU64(sfOutstandingAmount));
|
||||
}
|
||||
|
||||
bool
|
||||
getAccountObjects(
|
||||
ReadView const& ledger,
|
||||
@@ -320,10 +300,7 @@ getAccountObjects(
|
||||
if (!typeFilter.has_value() ||
|
||||
typeMatchesFilter(typeFilter.value(), sleNode->getType()))
|
||||
{
|
||||
auto& entry =
|
||||
jvObjects.append(sleNode->getJson(JsonOptions::none));
|
||||
if (sleNode->getType() == ltVAULT)
|
||||
RPC::supplementJson<ltVAULT>(ledger, sleNode, entry);
|
||||
jvObjects.append(sleNode->getJson(JsonOptions::none));
|
||||
}
|
||||
|
||||
if (++i == mlimit)
|
||||
@@ -1163,5 +1140,37 @@ getLedgerByContext(RPC::JsonContext& context)
|
||||
return RPC::make_error(
|
||||
rpcNOT_READY, "findCreate failed to return an inbound ledger");
|
||||
}
|
||||
|
||||
std::optional<uint256>
|
||||
parseVault(Json::Value const& params, Json::Value& jvResult)
|
||||
{
|
||||
if (!params.isObject())
|
||||
{
|
||||
uint256 uNodeIndex;
|
||||
if (!uNodeIndex.parseHex(params.asString()))
|
||||
{
|
||||
jvResult[jss::error] = "malformedRequest";
|
||||
return std::nullopt;
|
||||
}
|
||||
return uNodeIndex;
|
||||
}
|
||||
|
||||
if (!params.isMember(jss::owner) || !params.isMember(jss::seq) ||
|
||||
!params[jss::seq].isIntegral())
|
||||
{
|
||||
jvResult[jss::error] = "malformedRequest";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto const id = parseBase58<AccountID>(params[jss::owner].asString());
|
||||
if (!id)
|
||||
{
|
||||
jvResult[jss::error] = "malformedOwner";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return keylet::vault(*id, params[jss::seq].asUInt()).key;
|
||||
}
|
||||
|
||||
} // namespace RPC
|
||||
} // namespace ripple
|
||||
|
||||
@@ -270,29 +270,12 @@ keypairForSignature(
|
||||
Json::Value& error,
|
||||
unsigned int apiVersion = apiVersionIfUnspecified);
|
||||
|
||||
/**
|
||||
* Supplement JSON of a ledger object with additional data read from a view
|
||||
*
|
||||
* To be specialized per ledger object type as needed; any specialization of
|
||||
* this function must be declared below and defined in RPCHelpers.cpp
|
||||
*
|
||||
* The general template is never used, hence it is only declared but not defined
|
||||
*/
|
||||
template <LedgerEntryType Type>
|
||||
inline void
|
||||
supplementJson(
|
||||
ReadView const&,
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
Json::Value&);
|
||||
|
||||
template <>
|
||||
void
|
||||
supplementJson<ltVAULT>(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
Json::Value& node);
|
||||
// Used by both VaultInfo and LedgerEntry
|
||||
std::optional<uint256>
|
||||
parseVault(Json::Value const& params, Json::Value& jvResult);
|
||||
|
||||
} // namespace RPC
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -166,6 +166,8 @@ Json::Value
|
||||
doValidatorListSites(RPC::JsonContext&);
|
||||
Json::Value
|
||||
doValidatorInfo(RPC::JsonContext&);
|
||||
Json::Value
|
||||
doVaultInfo(RPC::JsonContext&);
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -124,8 +124,6 @@ doLedgerData(RPC::JsonContext& context)
|
||||
{
|
||||
Json::Value& entry =
|
||||
nodes.append(sle->getJson(JsonOptions::none));
|
||||
if (sle->getType() == ltVAULT)
|
||||
RPC::supplementJson<ltVAULT>(*lpLedger, sle, entry);
|
||||
entry[jss::index] = to_string(sle->key());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,32 +856,7 @@ parsePermissionedDomains(Json::Value const& pd, Json::Value& jvResult)
|
||||
static std::optional<uint256>
|
||||
parseVault(Json::Value const& params, Json::Value& jvResult)
|
||||
{
|
||||
if (!params.isObject())
|
||||
{
|
||||
uint256 uNodeIndex;
|
||||
if (!uNodeIndex.parseHex(params.asString()))
|
||||
{
|
||||
jvResult[jss::error] = "malformedRequest";
|
||||
return std::nullopt;
|
||||
}
|
||||
return uNodeIndex;
|
||||
}
|
||||
|
||||
if (!params.isMember(jss::owner) || !params.isMember(jss::seq) ||
|
||||
!params[jss::seq].isIntegral())
|
||||
{
|
||||
jvResult[jss::error] = "malformedRequest";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto const id = parseBase58<AccountID>(params[jss::owner].asString());
|
||||
if (!id)
|
||||
{
|
||||
jvResult[jss::error] = "malformedOwner";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return keylet::vault(*id, params[jss::seq].asUInt()).key;
|
||||
return RPC::parseVault(params, jvResult);
|
||||
}
|
||||
|
||||
using FunctionType =
|
||||
@@ -1033,9 +1008,6 @@ doLedgerEntry(RPC::JsonContext& context)
|
||||
else
|
||||
{
|
||||
jvResult[jss::node] = sleNode->getJson(JsonOptions::none);
|
||||
if (sleNode->getType() == ltVAULT)
|
||||
RPC::supplementJson<ltVAULT>(
|
||||
*lpLedger, sleNode, jvResult[jss::node]);
|
||||
jvResult[jss::index] = to_string(uNodeIndex);
|
||||
}
|
||||
|
||||
|
||||
95
src/xrpld/rpc/handlers/VaultInfo.cpp
Normal file
95
src/xrpld/rpc/handlers/VaultInfo.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpld/rpc/Context.h>
|
||||
#include <xrpld/rpc/detail/RPCHelpers.h>
|
||||
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/protocol/serialize.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
Json::Value
|
||||
doVaultInfo(RPC::JsonContext& context)
|
||||
{
|
||||
std::shared_ptr<ReadView const> lpLedger;
|
||||
auto jvResult = RPC::lookupLedger(lpLedger, context);
|
||||
|
||||
if (!lpLedger)
|
||||
return jvResult;
|
||||
|
||||
auto const uNodeIndex =
|
||||
RPC::parseVault(context.params[jss::vault], jvResult)
|
||||
.value_or(beast::zero);
|
||||
if (uNodeIndex == beast::zero)
|
||||
{
|
||||
jvResult[jss::error] = "malformedRequest";
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
bool const isBinary = context.params[jss::binary].asBool();
|
||||
|
||||
auto const sleVault = lpLedger->read(keylet::vault(uNodeIndex));
|
||||
auto const sleIssuance = sleVault == nullptr //
|
||||
? nullptr
|
||||
: lpLedger->read(keylet::mptIssuance(sleVault->at(sfShareMPTID)));
|
||||
if (!sleVault || !sleIssuance)
|
||||
{
|
||||
jvResult[jss::error] = "entryNotFound";
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
Json::Value directory = Json::objectValue;
|
||||
// Some directory positions in nodes are hardcoded below, because the
|
||||
// order of writing these is hardcoded, but it may not stay like this
|
||||
// forever. If a given type can have any number of nodes, use an array
|
||||
// rather than a number
|
||||
directory[jss::vault] = 0;
|
||||
directory[jss::mpt_issuance] = 1;
|
||||
|
||||
Json::Value nodes = Json::arrayValue;
|
||||
if (!isBinary)
|
||||
{
|
||||
auto& vault = nodes.append(Json::objectValue);
|
||||
vault = sleVault->getJson(JsonOptions::none);
|
||||
|
||||
auto& issuance = nodes.append(Json::objectValue);
|
||||
issuance = sleIssuance->getJson(JsonOptions::none);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& vault = nodes.append(Json::objectValue);
|
||||
vault[jss::data] = serializeHex(*sleVault);
|
||||
vault[jss::index] = to_string(sleVault->key());
|
||||
|
||||
auto& issuance = nodes.append(Json::objectValue);
|
||||
issuance[jss::data] = serializeHex(*sleIssuance);
|
||||
issuance[jss::index] = to_string(sleIssuance->key());
|
||||
}
|
||||
|
||||
jvResult[jss::directory] = directory;
|
||||
jvResult[jss::nodes] = nodes;
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
Reference in New Issue
Block a user