Skip to content

Commit 0dae3cb

Browse files
committed
compile
1 parent a97d549 commit 0dae3cb

File tree

12 files changed

+271
-18
lines changed

12 files changed

+271
-18
lines changed

src/data/BackendInterface.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ class BackendInterface {
322322
boost::asio::yield_context yield
323323
) const = 0;
324324

325+
virtual MPTHoldersAndCursor
326+
fetchMPTHolders(
327+
ripple::uint192 const& mptID,
328+
std::uint32_t const limit,
329+
std::optional<ripple::AccountID> const& cursorIn,
330+
std::uint32_t const ledgerSequence,
331+
boost::asio::yield_context yield)const = 0;
332+
325333
/**
326334
* @brief Fetches a specific ledger object.
327335
*
@@ -549,6 +557,9 @@ class BackendInterface {
549557
virtual void
550558
writeNFTTransactions(std::vector<NFTTransactionsData> const& data) = 0;
551559

560+
virtual void
561+
writeMPTHolders(std::vector<std::pair<ripple::uint192, ripple::AccountID>>&& data) = 0;
562+
552563
/**
553564
* @brief Write a new successor.
554565
*

src/data/CassandraBackend.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,14 +532,14 @@ class BasicCassandraBackend : public BackendInterface {
532532

533533
MPTHoldersAndCursor
534534
fetchMPTHolders(
535-
ripple::uint192 const& mpt_id,
535+
ripple::uint192 const& mptID,
536536
std::uint32_t const limit,
537537
std::optional<ripple::AccountID> const& cursorIn,
538538
std::uint32_t const ledgerSequence,
539539
boost::asio::yield_context yield)const override
540540
{
541541

542-
auto const holderEntries = executor_.read(yield, schema_->selectMPTHolders, mpt_id, cursorIn.value_or(ripple::AccountID(0)), Limit{limit});
542+
auto const holderEntries = executor_.read(yield, schema_->selectMPTHolders, mptID, cursorIn.value_or(ripple::AccountID(0)), Limit{limit});
543543

544544
auto const& holderResults = holderEntries.value();
545545
if (not holderResults.hasRows())
@@ -552,7 +552,7 @@ class BasicCassandraBackend : public BackendInterface {
552552
std::optional<ripple::AccountID> cursor;
553553
for (auto const [holder] : extract<ripple::AccountID>(holderResults))
554554
{
555-
mptKeys.push_back(ripple::getMptID(mpt_id, holder));
555+
mptKeys.push_back(ripple::keylet::mptoken(mptID, holder).key);
556556
cursor = holder;
557557
}
558558

@@ -569,9 +569,9 @@ class BasicCassandraBackend : public BackendInterface {
569569
}
570570

571571
if (mptKeys.size() == limit)
572-
return {filteredMpt, cusor};
572+
return {filteredMpt, cursor};
573573

574-
return {filteredMpt, {}}
574+
return {filteredMpt, {}};
575575
}
576576

577577
std::optional<Blob>

src/data/cassandra/impl/Statement.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ class Statement : public ManagedObject<CassStatement> {
103103
using UintByteTupleType = std::tuple<uint32_t, ripple::uint256>;
104104
using ByteVectorType = std::vector<ripple::uint256>;
105105

106-
if constexpr (std::is_same_v<DecayedType, ripple::uint256>) {
106+
if constexpr (std::is_same_v<DecayedType, ripple::uint256> || std::is_same_v<DecayedType, ripple::uint192>) {
107107
auto const rc = bindBytes(value.data(), value.size());
108-
throwErrorIfNeeded(rc, "Bind ripple::uint256");
109-
} else if constexpr (std::is_same_v<DecayedType, ripple::AccountID>) {
108+
throwErrorIfNeeded(rc, "Bind ripple::base_uint");
109+
}
110+
else if constexpr (std::is_same_v<DecayedType, ripple::AccountID>) {
110111
auto const rc = bindBytes(value.data(), value.size());
111112
throwErrorIfNeeded(rc, "Bind ripple::AccountID");
112113
} else if constexpr (std::is_same_v<DecayedType, UCharVectorType>) {

src/etl/MPTHelpers.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,17 @@
2929

3030
namespace etl {
3131

32-
std::optional<std::pair<ripple::uint192, ripple::AccountID>>
33-
getMPTokenAuthorize(ripple::TxMeta const& txMeta, ripple::STTx const& sttx){
32+
static std::optional<std::pair<ripple::uint192, ripple::AccountID>>
33+
getMPTokenAuthorize(ripple::TxMeta const& txMeta){
3434
for (ripple::STObject const& node : txMeta.getNodes())
3535
{
3636
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltMPTOKEN)
3737
continue;
3838

39-
if (node.getFName() == ripple::sfCreatedNode)
40-
return std::make_pair(node[ripple::sfMPTokenIssuanceID], node[ripple::sfAccount]);
39+
if (node.getFName() == ripple::sfCreatedNode){
40+
auto const& newMPT = node.peekAtField(ripple::sfNewFields).downcast<ripple::STObject>();
41+
return std::make_pair(newMPT[ripple::sfMPTokenIssuanceID], newMPT[ripple::sfAccount]);
42+
}
4143
}
4244
return {};
4345
}
@@ -48,11 +50,11 @@ getMPTHolderFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx){
4850
|| sttx.getTxnType()!= ripple::TxType::ttMPTOKEN_AUTHORIZE)
4951
return {};
5052

51-
return getMPTokenAuthorize(txMeta, sttx);
53+
return getMPTokenAuthorize(txMeta);
5254
}
5355

5456
std::optional<std::pair<ripple::uint192, ripple::AccountID>>
55-
getMPTHolderFromObj(std::uint32_t const seq, std::string const& key, std::string const& blob){
57+
getMPTHolderFromObj(std::string const& key, std::string const& blob){
5658
ripple::STLedgerEntry const sle =
5759
ripple::STLedgerEntry(ripple::SerialIter{blob.data(), blob.size()}, ripple::uint256::fromVoid(key.data()));
5860

src/etl/MPTHelpers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ getMPTHolderFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
4646
* @return The CFTIssuance and issuer pair as a optional
4747
*/
4848
std::optional<std::pair<ripple::uint192, ripple::AccountID>>
49-
getMPTHolderFromObj(std::uint32_t const seq, std::string const& key, std::string const& blob);
49+
getMPTHolderFromObj(std::string const& key, std::string const& blob);
5050

5151

5252
} // namespace etl

src/etl/impl/AsyncData.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "data/BackendInterface.h"
2323
#include "etl/NFTHelpers.h"
24+
#include "etl/MPTHelpers.h"
2425
#include "util/Assert.h"
2526
#include "util/log/Logger.h"
2627

@@ -140,7 +141,7 @@ class AsyncCallData {
140141
lastKey_ = obj.key();
141142
backend.writeNFTs(getNFTDataFromObj(request_.ledger().sequence(), obj.key(), obj.data()));
142143

143-
auto const maybeMPTHolder = getMPTHolderFromObj(request_.ledger().sequence(), obj.key(), obj.data());
144+
auto const maybeMPTHolder = getMPTHolderFromObj(obj.key(), obj.data());
144145
if(maybeMPTHolder)
145146
backend.writeMPTHolders({*maybeMPTHolder});
146147

src/etl/impl/LedgerLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class LedgerLoader {
247247
backend_->writeAccountTransactions(std::move(insertTxResult.accountTxData));
248248
backend_->writeNFTs(insertTxResult.nfTokensData);
249249
backend_->writeNFTTransactions(insertTxResult.nfTokenTxData);
250-
backend_->writeMPTHolders(insertTxResult.mptHoldersData);
250+
backend_->writeMPTHolders(std::move(insertTxResult.mptHoldersData));
251251
}
252252

253253
backend_->finishWrites(sequence);

src/etl/impl/Transformer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class Transformer {
201201
backend_->writeAccountTransactions(std::move(insertTxResultOp->accountTxData));
202202
backend_->writeNFTs(insertTxResultOp->nfTokensData);
203203
backend_->writeNFTTransactions(insertTxResultOp->nfTokenTxData);
204-
backend_->writeMPTHolders(insertTxResultOp->mptHoldersData);
204+
backend_->writeMPTHolders(std::move(insertTxResultOp->mptHoldersData));
205205

206206
auto [success, duration] =
207207
::util::timed<std::chrono::duration<double>>([&]() { return backend_->finishWrites(lgrInfo.seq); });

src/rpc/common/impl/HandlerProvider.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "rpc/handlers/LedgerData.h"
4141
#include "rpc/handlers/LedgerEntry.h"
4242
#include "rpc/handlers/LedgerRange.h"
43+
#include "rpc/handlers/MPTHolders.h"
4344
#include "rpc/handlers/NFTBuyOffers.h"
4445
#include "rpc/handlers/NFTHistory.h"
4546
#include "rpc/handlers/NFTInfo.h"
@@ -87,6 +88,7 @@ ProductionHandlerProvider::ProductionHandlerProvider(
8788
{"ledger_data", {LedgerDataHandler{backend}}},
8889
{"ledger_entry", {LedgerEntryHandler{backend}}},
8990
{"ledger_range", {LedgerRangeHandler{backend}}},
91+
{"mpt_holders", {MPTHoldersHandler{backend}, true}}, //clio only
9092
{"nfts_by_issuer", {NFTsByIssuerHandler{backend}, true}}, // clio only
9193
{"nft_history", {NFTHistoryHandler{backend}, true}}, // clio only
9294
{"nft_buy_offers", {NFTBuyOffersHandler{backend}}},

src/rpc/handlers/MPTHolders.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
//------------------------------------------------------------------------------
2+
/*
3+
This file is part of clio: https://github.com/XRPLF/clio
4+
Copyright (c) 2023, the clio developers.
5+
6+
Permission to use, copy, modify, and 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 "rpc/handlers/MPTHolders.h"
21+
22+
#include "rpc/Errors.h"
23+
#include "rpc/JS.h"
24+
#include "rpc/RPCHelpers.h"
25+
#include "rpc/common/Types.h"
26+
27+
#include <boost/json/conversion.hpp>
28+
#include <boost/json/object.hpp>
29+
#include <boost/json/value.hpp>
30+
#include <ripple/basics/base_uint.h>
31+
#include <ripple/basics/strHex.h>
32+
#include <ripple/protocol/AccountID.h>
33+
#include <ripple/protocol/ErrorCodes.h>
34+
#include <ripple/protocol/Indexes.h>
35+
#include <ripple/protocol/LedgerHeader.h>
36+
#include <ripple/protocol/jss.h>
37+
#include <ripple/protocol/nft.h>
38+
39+
#include <optional>
40+
#include <string>
41+
#include <variant>
42+
43+
using namespace ripple;
44+
45+
namespace rpc {
46+
47+
MPTHoldersHandler::Result
48+
MPTHoldersHandler::process(MPTHoldersHandler::Input input, Context const& ctx) const
49+
{
50+
auto const range = sharedPtrBackend_->fetchLedgerRange();
51+
auto const lgrInfoOrStatus = getLedgerInfoFromHashOrSeq(
52+
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
53+
);
54+
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
55+
return Error{*status};
56+
57+
auto const lgrInfo = std::get<LedgerInfo>(lgrInfoOrStatus);
58+
59+
auto const limit = input.limit.value_or(MPTHoldersHandler::LIMIT_DEFAULT);
60+
61+
auto const mptID = ripple::uint192{input.mptID.c_str()};
62+
63+
std::optional<ripple::AccountID> cursor;
64+
if (input.marker)
65+
cursor = ripple::AccountID{input.marker->c_str()};
66+
67+
auto const dbResponse =
68+
sharedPtrBackend_->fetchMPTHolders(mptID, limit, cursor, lgrInfo.seq, ctx.yield);
69+
70+
auto output = MPTHoldersHandler::Output{};
71+
72+
output.mptID = to_string(mptID);
73+
output.limit = limit;
74+
output.ledgerIndex = lgrInfo.seq;
75+
76+
boost::json::array mpts;
77+
for (auto const& mpt : dbResponse.mptokens) {
78+
ripple::STLedgerEntry sle{ripple::SerialIter{mpt.data(), mpt.size()}, keylet::mptIssuance(mptID).key};
79+
boost::json::object mptJson;
80+
81+
mptJson["mpt_amount"] = std::to_string(sle[ripple::sfMPTAmount]);
82+
mptJson[JS(flags)] = sle[ripple::sfFlags];
83+
mptJson[JS(account)] = toBase58(sle.getAccountID(ripple::sfAccount));
84+
85+
if(sle[~ripple::sfLockedAmount])
86+
mptJson["locked_amount"] = std::to_string(sle[~ripple::sfLockedAmount].value_or(0));
87+
88+
output.mpts.push_back(mptJson);
89+
}
90+
91+
if (dbResponse.cursor.has_value())
92+
output.marker = strHex(*dbResponse.cursor);
93+
94+
return output;
95+
}
96+
97+
void
98+
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, MPTHoldersHandler::Output const& output)
99+
{
100+
jv = {
101+
{JS(mpt_issuance_id), output.mptID},
102+
{JS(limit), output.limit},
103+
{JS(ledger_index), output.ledgerIndex},
104+
{"mpts", output.mpts},
105+
{JS(validated), output.validated},
106+
};
107+
108+
if (output.marker.has_value())
109+
jv.as_object()[JS(marker)] = *(output.marker);
110+
}
111+
112+
MPTHoldersHandler::Input
113+
tag_invoke(boost::json::value_to_tag<MPTHoldersHandler::Input>, boost::json::value const& jv)
114+
{
115+
auto const& jsonObject = jv.as_object();
116+
MPTHoldersHandler::Input input;
117+
118+
input.mptID = jsonObject.at(JS(mpt_issuance_id)).as_string().c_str();
119+
120+
if (jsonObject.contains(JS(ledger_hash)))
121+
input.ledgerHash = jsonObject.at(JS(ledger_hash)).as_string().c_str();
122+
123+
if (jsonObject.contains(JS(ledger_index))) {
124+
if (!jsonObject.at(JS(ledger_index)).is_string()) {
125+
input.ledgerIndex = jsonObject.at(JS(ledger_index)).as_int64();
126+
} else if (jsonObject.at(JS(ledger_index)).as_string() != "validated") {
127+
input.ledgerIndex = std::stoi(jsonObject.at(JS(ledger_index)).as_string().c_str());
128+
}
129+
}
130+
131+
if (jsonObject.contains(JS(limit)))
132+
input.limit = jsonObject.at(JS(limit)).as_int64();
133+
134+
if (jsonObject.contains(JS(marker)))
135+
input.marker = jsonObject.at(JS(marker)).as_string().c_str();
136+
137+
return input;
138+
}
139+
} // namespace rpc

0 commit comments

Comments
 (0)