mirror of
https://github.com/XRPLF/clio.git
synced 2026-08-23 13:40:52 +00:00
feat: Add DynamicMPT in account_mptoken_issuances (#2820)
Support DynamicMPT for the account_mptoken_issuances handler.
Related commit:
eed757e0c4
The original spec for `DynamicMPT` can be found here:
https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0094-dynamic-MPT
---------
Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
This commit is contained in:
@@ -56,6 +56,7 @@ AccountMPTokenIssuancesHandler::addMPTokenIssuance(
|
||||
{
|
||||
MPTokenIssuanceResponse issuance;
|
||||
|
||||
issuance.MPTokenIssuanceID = ripple::strHex(sle.key());
|
||||
issuance.issuer = ripple::to_string(account);
|
||||
issuance.sequence = sle.getFieldU32(ripple::sfSequence);
|
||||
auto const flags = sle.getFieldU32(ripple::sfFlags);
|
||||
@@ -73,6 +74,24 @@ AccountMPTokenIssuancesHandler::addMPTokenIssuance(
|
||||
setFlag(issuance.mptCanTransfer, ripple::lsfMPTCanTransfer);
|
||||
setFlag(issuance.mptCanClawback, ripple::lsfMPTCanClawback);
|
||||
|
||||
if (sle.isFieldPresent(ripple::sfMutableFlags)) {
|
||||
auto const mutableFlags = sle.getFieldU32(ripple::sfMutableFlags);
|
||||
|
||||
auto const setMutableFlag = [&](std::optional<bool>& field, std::uint32_t mask) {
|
||||
if ((mutableFlags & mask) != 0u)
|
||||
field = true;
|
||||
};
|
||||
|
||||
setMutableFlag(issuance.mptCanMutateCanLock, ripple::lsmfMPTCanMutateCanLock);
|
||||
setMutableFlag(issuance.mptCanMutateRequireAuth, ripple::lsmfMPTCanMutateRequireAuth);
|
||||
setMutableFlag(issuance.mptCanMutateCanEscrow, ripple::lsmfMPTCanMutateCanEscrow);
|
||||
setMutableFlag(issuance.mptCanMutateCanTrade, ripple::lsmfMPTCanMutateCanTrade);
|
||||
setMutableFlag(issuance.mptCanMutateCanTransfer, ripple::lsmfMPTCanMutateCanTransfer);
|
||||
setMutableFlag(issuance.mptCanMutateCanClawback, ripple::lsmfMPTCanMutateCanClawback);
|
||||
setMutableFlag(issuance.mptCanMutateMetadata, ripple::lsmfMPTCanMutateMetadata);
|
||||
setMutableFlag(issuance.mptCanMutateTransferFee, ripple::lsmfMPTCanMutateTransferFee);
|
||||
}
|
||||
|
||||
if (sle.isFieldPresent(ripple::sfTransferFee))
|
||||
issuance.transferFee = sle.getFieldU16(ripple::sfTransferFee);
|
||||
|
||||
@@ -201,6 +220,7 @@ tag_invoke(
|
||||
)
|
||||
{
|
||||
auto obj = boost::json::object{
|
||||
{JS(mpt_issuance_id), issuance.MPTokenIssuanceID},
|
||||
{JS(issuer), issuance.issuer},
|
||||
{JS(sequence), issuance.sequence},
|
||||
};
|
||||
@@ -227,6 +247,15 @@ tag_invoke(
|
||||
setIfPresent("mpt_can_transfer", issuance.mptCanTransfer);
|
||||
setIfPresent("mpt_can_clawback", issuance.mptCanClawback);
|
||||
|
||||
setIfPresent("mpt_can_mutate_can_lock", issuance.mptCanMutateCanLock);
|
||||
setIfPresent("mpt_can_mutate_require_auth", issuance.mptCanMutateRequireAuth);
|
||||
setIfPresent("mpt_can_mutate_can_escrow", issuance.mptCanMutateCanEscrow);
|
||||
setIfPresent("mpt_can_mutate_can_trade", issuance.mptCanMutateCanTrade);
|
||||
setIfPresent("mpt_can_mutate_can_transfer", issuance.mptCanMutateCanTransfer);
|
||||
setIfPresent("mpt_can_mutate_can_clawback", issuance.mptCanMutateCanClawback);
|
||||
setIfPresent("mpt_can_mutate_metadata", issuance.mptCanMutateMetadata);
|
||||
setIfPresent("mpt_can_mutate_transfer_fee", issuance.mptCanMutateTransferFee);
|
||||
|
||||
jv = std::move(obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
* @brief A struct to hold data for one MPTokenIssuance response.
|
||||
*/
|
||||
struct MPTokenIssuanceResponse {
|
||||
std::string MPTokenIssuanceID;
|
||||
std::string issuer;
|
||||
uint32_t sequence{};
|
||||
|
||||
@@ -80,6 +81,15 @@ public:
|
||||
std::optional<bool> mptCanTrade;
|
||||
std::optional<bool> mptCanTransfer;
|
||||
std::optional<bool> mptCanClawback;
|
||||
|
||||
std::optional<bool> mptCanMutateCanLock;
|
||||
std::optional<bool> mptCanMutateRequireAuth;
|
||||
std::optional<bool> mptCanMutateCanEscrow;
|
||||
std::optional<bool> mptCanMutateCanTrade;
|
||||
std::optional<bool> mptCanMutateCanTransfer;
|
||||
std::optional<bool> mptCanMutateCanClawback;
|
||||
std::optional<bool> mptCanMutateMetadata;
|
||||
std::optional<bool> mptCanMutateTransferFee;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,6 +54,7 @@ AccountMPTokensHandler::addMPToken(std::vector<MPTokenResponse>& mpts, ripple::S
|
||||
MPTokenResponse token{};
|
||||
auto const flags = sle.getFieldU32(ripple::sfFlags);
|
||||
|
||||
token.MPTokenID = ripple::strHex(sle.key());
|
||||
token.account = ripple::to_string(sle.getAccountID(ripple::sfAccount));
|
||||
token.MPTokenIssuanceID = ripple::strHex(sle.getFieldH192(ripple::sfMPTokenIssuanceID));
|
||||
token.MPTAmount = sle.getFieldU64(ripple::sfMPTAmount);
|
||||
@@ -170,6 +171,7 @@ void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, AccountMPTokensHandler::MPTokenResponse const& mptoken)
|
||||
{
|
||||
auto obj = boost::json::object{
|
||||
{"mpt_id", mptoken.MPTokenID},
|
||||
{JS(account), mptoken.account},
|
||||
{JS(mpt_issuance_id), mptoken.MPTokenIssuanceID},
|
||||
{JS(mpt_amount), mptoken.MPTAmount},
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
* @brief A struct to hold data for one MPToken response.
|
||||
*/
|
||||
struct MPTokenResponse {
|
||||
std::string MPTokenID;
|
||||
std::string account;
|
||||
std::string MPTokenIssuanceID;
|
||||
uint64_t MPTAmount{};
|
||||
|
||||
@@ -1452,7 +1452,8 @@ createMptIssuanceObject(
|
||||
std::optional<std::uint8_t> assetScale,
|
||||
std::optional<std::uint64_t> maxAmount,
|
||||
std::optional<std::uint64_t> lockedAmount,
|
||||
std::optional<std::string_view> domainId
|
||||
std::optional<std::string_view> domainId,
|
||||
std::optional<std::uint32_t> mutableFlags
|
||||
)
|
||||
{
|
||||
ripple::STObject mptIssuance(ripple::sfLedgerEntry);
|
||||
@@ -1479,6 +1480,8 @@ createMptIssuanceObject(
|
||||
}
|
||||
if (domainId.has_value())
|
||||
mptIssuance.setFieldH256(ripple::sfDomainID, ripple::uint256{*domainId});
|
||||
if (mutableFlags.has_value())
|
||||
mptIssuance.setFieldU32(ripple::sfMutableFlags, *mutableFlags);
|
||||
|
||||
return mptIssuance;
|
||||
}
|
||||
|
||||
@@ -461,7 +461,8 @@ createMptIssuanceObject(
|
||||
std::optional<std::uint8_t> assetScale = std::nullopt,
|
||||
std::optional<std::uint64_t> maxAmount = std::nullopt,
|
||||
std::optional<std::uint64_t> lockedAmount = std::nullopt,
|
||||
std::optional<std::string_view> domainId = std::nullopt
|
||||
std::optional<std::string_view> domainId = std::nullopt,
|
||||
std::optional<std::uint32_t> mutableFlags = std::nullopt
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
|
||||
@@ -62,6 +62,7 @@ constexpr auto kISSUANCE_INDEX2 = "B6DBAFC99223B42257915A63DFC6B0C032D4070F9A574
|
||||
constexpr uint64_t kISSUANCE1_MAX_AMOUNT = 10000;
|
||||
constexpr uint64_t kISSUANCE1_OUTSTANDING_AMOUNT = 5000;
|
||||
constexpr uint8_t kISSUANCE1_ASSET_SCALE = 2;
|
||||
constexpr uint16_t kISSUANCE1_TRANSFER_FEE = 10;
|
||||
|
||||
// unique values for issuance2
|
||||
constexpr uint64_t kISSUANCE2_MAX_AMOUNT = 20000;
|
||||
@@ -75,6 +76,7 @@ constexpr auto kISSUANCE2_DOMAIN_ID_HEX = "E6DBAFC99223B42257915A63DFC6B0C032D40
|
||||
// define expected JSON for mpt issuances
|
||||
auto const kISSUANCE_OUT1 = fmt::format(
|
||||
R"JSON({{
|
||||
"mpt_issuance_id": "{}",
|
||||
"issuer": "{}",
|
||||
"sequence": 1,
|
||||
"maximum_amount": {},
|
||||
@@ -85,6 +87,7 @@ auto const kISSUANCE_OUT1 = fmt::format(
|
||||
"mpt_require_auth": true,
|
||||
"mpt_can_transfer": true
|
||||
}})JSON",
|
||||
kISSUANCE_INDEX1,
|
||||
kACCOUNT,
|
||||
kISSUANCE1_MAX_AMOUNT,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
@@ -93,6 +96,7 @@ auto const kISSUANCE_OUT1 = fmt::format(
|
||||
|
||||
auto const kISSUANCE_OUT2 = fmt::format(
|
||||
R"JSON({{
|
||||
"mpt_issuance_id": "{}",
|
||||
"issuer": "{}",
|
||||
"sequence": 2,
|
||||
"maximum_amount": {},
|
||||
@@ -105,6 +109,7 @@ auto const kISSUANCE_OUT2 = fmt::format(
|
||||
"mpt_locked": true,
|
||||
"mpt_can_clawback": true
|
||||
}})JSON",
|
||||
kISSUANCE_INDEX2,
|
||||
kACCOUNT,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
@@ -293,7 +298,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, NonExistLedgerViaLedgerIntIndex)
|
||||
// ledger not found via hash (seq > max)
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LedgerSeqOutOfRangeByHash)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 31);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 31);
|
||||
EXPECT_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _)).WillOnce(Return(ledgerHeader));
|
||||
auto const input = json::parse(
|
||||
fmt::format(
|
||||
@@ -341,7 +346,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LedgerSeqOutOfRangeByIndex)
|
||||
// account not exist
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, NonExistAccount)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _)).WillOnce(Return(ledgerHeader));
|
||||
// fetch account object return empty
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).WillOnce(Return(std::optional<Blob>{}));
|
||||
@@ -369,13 +374,13 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, NonExistAccount)
|
||||
// fetch mptoken issuances via account successfully
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, DefaultParameters)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
// return non-empty account
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
// return two mptoken issuance objects
|
||||
@@ -385,33 +390,36 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, DefaultParameters)
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
// mocking mptoken issuance ledger objects
|
||||
std::vector<Blob> bbs;
|
||||
auto const issuance1 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
);
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const issuance2 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
);
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
bbs.push_back(issuance1.getSerializer().peekData());
|
||||
bbs.push_back(issuance2.getSerializer().peekData());
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
runSpawn([this](auto yield) {
|
||||
@@ -434,7 +442,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, DefaultParameters)
|
||||
kISSUANCE_OUT2
|
||||
);
|
||||
auto const input = json::parse(fmt::format(R"JSON({{"account": "{}"}})JSON", kACCOUNT));
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
@@ -445,22 +453,23 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, DefaultParameters)
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, UseLimit)
|
||||
{
|
||||
constexpr int kLIMIT = 20;
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
ON_CALL(*backend_, fetchLedgerBySequence).WillByDefault(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
std::vector<ripple::uint256> indexes;
|
||||
std::vector<Blob> bbs;
|
||||
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
indexes.emplace_back(kISSUANCE_INDEX1);
|
||||
auto const issuance = createMptIssuanceObject(kACCOUNT, i);
|
||||
bbs.push_back(issuance.getSerializer().peekData());
|
||||
}
|
||||
auto const indexes = std::vector<ripple::uint256>(50, ripple::uint256{kISSUANCE_INDEX1});
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(50);
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
v.push_back(createMptIssuanceObject(kACCOUNT, i).getSerializer().peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
|
||||
ripple::STObject ownerDir = createOwnerDirLedgerObject(indexes, kISSUANCE_INDEX1);
|
||||
ownerDir.setFieldU64(ripple::sfIndexNext, 99);
|
||||
@@ -482,7 +491,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, UseLimit)
|
||||
)
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
|
||||
@@ -531,27 +540,25 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MarkerOutput)
|
||||
{
|
||||
constexpr auto kNEXT_PAGE = 99;
|
||||
constexpr auto kLIMIT = 15;
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto ownerDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto ownerDir2Kk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const ownerDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const ownerDir2Kk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(3);
|
||||
|
||||
std::vector<ripple::uint256> indexes;
|
||||
indexes.reserve(10);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
indexes.emplace_back(kISSUANCE_INDEX1);
|
||||
}
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
bbs.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
bbs.push_back(createMptIssuanceObject(kACCOUNT, i).getSerializer().peekData());
|
||||
}
|
||||
auto const indexes = std::vector<ripple::uint256>(10, ripple::uint256{kISSUANCE_INDEX1});
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
v.push_back(createMptIssuanceObject(kACCOUNT, i).getSerializer().peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
// mock the first directory page
|
||||
@@ -577,7 +584,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MarkerOutput)
|
||||
kLIMIT
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
auto const& resultJson = (*output.result).as_object();
|
||||
@@ -594,21 +601,24 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MarkerInput)
|
||||
constexpr auto kNEXT_PAGE = 99;
|
||||
constexpr auto kLIMIT = 15;
|
||||
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto ownerDirKk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const ownerDirKk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(3);
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
std::vector<ripple::uint256> indexes;
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
indexes.emplace_back(kISSUANCE_INDEX1);
|
||||
bbs.push_back(createMptIssuanceObject(kACCOUNT, i).getSerializer().peekData());
|
||||
}
|
||||
auto const indexes = std::vector<ripple::uint256>(kLIMIT, ripple::uint256{kISSUANCE_INDEX1});
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
v.push_back(createMptIssuanceObject(kACCOUNT, i).getSerializer().peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
|
||||
ripple::STObject ownerDir = createOwnerDirLedgerObject(indexes, kISSUANCE_INDEX1);
|
||||
ownerDir.setFieldU64(ripple::sfIndexNext, 0);
|
||||
@@ -631,7 +641,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MarkerInput)
|
||||
kNEXT_PAGE
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
|
||||
@@ -643,47 +653,48 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MarkerInput)
|
||||
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitLessThanMin)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject(
|
||||
{ripple::uint256{kISSUANCE_INDEX1}, ripple::uint256{kISSUANCE_INDEX2}}, kISSUANCE_INDEX1
|
||||
);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
auto const issuance1 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
);
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const issuance2 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
);
|
||||
|
||||
bbs.push_back(issuance1.getSerializer().peekData());
|
||||
bbs.push_back(issuance2.getSerializer().peekData());
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
@@ -718,7 +729,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitLessThanMin)
|
||||
kISSUANCE_OUT2
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(correctOutput), *output.result);
|
||||
@@ -727,47 +738,48 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitLessThanMin)
|
||||
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitMoreThanMax)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject(
|
||||
{ripple::uint256{kISSUANCE_INDEX1}, ripple::uint256{kISSUANCE_INDEX2}}, kISSUANCE_INDEX1
|
||||
);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
auto const issuance1 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
);
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTrade | ripple::lsfMPTRequireAuth | ripple::lsfMPTCanTransfer | ripple::lsfMPTCanEscrow,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
std::nullopt,
|
||||
kISSUANCE1_ASSET_SCALE,
|
||||
kISSUANCE1_MAX_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const issuance2 = createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
);
|
||||
|
||||
bbs.push_back(issuance1.getSerializer().peekData());
|
||||
bbs.push_back(issuance2.getSerializer().peekData());
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
2,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTLocked | ripple::lsfMPTCanLock | ripple::lsfMPTCanClawback,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
kISSUANCE2_MAX_AMOUNT,
|
||||
kISSUANCE2_LOCKED_AMOUNT,
|
||||
kISSUANCE2_DOMAIN_ID_HEX
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
@@ -802,7 +814,7 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitMoreThanMax)
|
||||
kISSUANCE_OUT2
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(correctOutput), *output.result);
|
||||
@@ -811,17 +823,16 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, LimitMoreThanMax)
|
||||
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, EmptyResult)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject({}, kISSUANCE_INDEX1);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
runSpawn([this](auto yield) {
|
||||
auto const input = json::parse(
|
||||
@@ -832,9 +843,292 @@ TEST_F(RPCAccountMPTokenIssuancesHandlerTest, EmptyResult)
|
||||
kACCOUNT
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ((*output.result).as_object().at("mpt_issuances").as_array().size(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCAccountMPTokenIssuancesHandlerTest, MutableFlags)
|
||||
{
|
||||
uint32_t const mutableFlags1 = ripple::lsmfMPTCanMutateCanLock | ripple::lsmfMPTCanMutateRequireAuth |
|
||||
ripple::lsmfMPTCanMutateCanEscrow | ripple::lsmfMPTCanMutateCanTrade;
|
||||
|
||||
uint32_t const mutableFlags2 = ripple::lsmfMPTCanMutateCanTransfer | ripple::lsmfMPTCanMutateCanClawback |
|
||||
ripple::lsmfMPTCanMutateMetadata | ripple::lsmfMPTCanMutateTransferFee;
|
||||
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject(
|
||||
{ripple::uint256{kISSUANCE_INDEX1}, ripple::uint256{kISSUANCE_INDEX2}}, kISSUANCE_INDEX1
|
||||
);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
3,
|
||||
std::nullopt,
|
||||
ripple::lsfMPTCanTransfer,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE1_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
mutableFlags1
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
5,
|
||||
kISSUANCE2_METADATA,
|
||||
ripple::lsfMPTCanTransfer,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
mutableFlags2
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
runSpawn([this](auto yield) {
|
||||
auto const input = json::parse(
|
||||
fmt::format(
|
||||
R"JSON({{
|
||||
"account": "{}"
|
||||
}})JSON",
|
||||
kACCOUNT
|
||||
)
|
||||
);
|
||||
|
||||
auto const correctOutput = fmt::format(
|
||||
R"JSON({{
|
||||
"account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"ledger_index": 30,
|
||||
"validated": true,
|
||||
"limit": 200,
|
||||
"mpt_issuances": [
|
||||
{{
|
||||
"mpt_issuance_id": "{}",
|
||||
"issuer": "{}",
|
||||
"sequence": 3,
|
||||
"outstanding_amount": {},
|
||||
"transfer_fee": {},
|
||||
"mpt_can_transfer": true,
|
||||
"mpt_can_mutate_can_lock": true,
|
||||
"mpt_can_mutate_require_auth": true,
|
||||
"mpt_can_mutate_can_escrow": true,
|
||||
"mpt_can_mutate_can_trade": true
|
||||
}},
|
||||
{{
|
||||
"mpt_issuance_id": "{}",
|
||||
"issuer": "{}",
|
||||
"sequence": 5,
|
||||
"outstanding_amount": {},
|
||||
"transfer_fee": {},
|
||||
"mptoken_metadata": "{}",
|
||||
"mpt_can_transfer": true,
|
||||
"mpt_can_mutate_can_transfer": true,
|
||||
"mpt_can_mutate_can_clawback": true,
|
||||
"mpt_can_mutate_metadata": true,
|
||||
"mpt_can_mutate_transfer_fee": true
|
||||
}}
|
||||
]
|
||||
}})JSON",
|
||||
kACCOUNT,
|
||||
kLEDGER_HASH,
|
||||
kISSUANCE_INDEX1,
|
||||
kACCOUNT,
|
||||
kISSUANCE1_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE1_TRANSFER_FEE,
|
||||
kISSUANCE_INDEX2,
|
||||
kACCOUNT,
|
||||
kISSUANCE2_OUTSTANDING_AMOUNT,
|
||||
kISSUANCE2_TRANSFER_FEE,
|
||||
kISSUANCE2_METADATA_HEX
|
||||
);
|
||||
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(correctOutput), *output.result);
|
||||
});
|
||||
}
|
||||
|
||||
struct SingleFlagTest {
|
||||
std::string testName;
|
||||
uint32_t flag;
|
||||
std::string expectedJsonKey;
|
||||
};
|
||||
|
||||
struct AccountMPTokenIssuancesImmutableFlagsTest : RPCAccountMPTokenIssuancesHandlerTest,
|
||||
WithParamInterface<SingleFlagTest> {};
|
||||
|
||||
static auto
|
||||
generateSingleFlagTests()
|
||||
{
|
||||
return std::vector<SingleFlagTest>{
|
||||
{"Locked", ripple::lsfMPTLocked, "mpt_locked"},
|
||||
{"CanLock", ripple::lsfMPTCanLock, "mpt_can_lock"},
|
||||
{"RequireAuth", ripple::lsfMPTRequireAuth, "mpt_require_auth"},
|
||||
{"CanEscrow", ripple::lsfMPTCanEscrow, "mpt_can_escrow"},
|
||||
{"CanTrade", ripple::lsfMPTCanTrade, "mpt_can_trade"},
|
||||
{"CanTransfer", ripple::lsfMPTCanTransfer, "mpt_can_transfer"},
|
||||
{"CanClawback", ripple::lsfMPTCanClawback, "mpt_can_clawback"},
|
||||
};
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
RPCAccountMPTokenIssuancesImmutableFlagsGroup,
|
||||
AccountMPTokenIssuancesImmutableFlagsTest,
|
||||
ValuesIn(generateSingleFlagTests()),
|
||||
tests::util::kNAME_GENERATOR
|
||||
);
|
||||
|
||||
TEST_P(AccountMPTokenIssuancesImmutableFlagsTest, SingleFlag)
|
||||
{
|
||||
auto const testParams = GetParam();
|
||||
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject({ripple::uint256{kISSUANCE_INDEX1}}, kISSUANCE_INDEX1);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMptIssuanceObject(kACCOUNT, 1, std::nullopt, testParams.flag, 0).getSerializer().peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
runSpawn([this, &testParams](auto yield) {
|
||||
auto const input = json::parse(
|
||||
fmt::format(
|
||||
R"JSON({{
|
||||
"account": "{}"
|
||||
}})JSON",
|
||||
kACCOUNT
|
||||
)
|
||||
);
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_TRUE(output);
|
||||
auto const& resultJson = (*output.result).as_object();
|
||||
auto const& issuances = resultJson.at("mpt_issuances").as_array();
|
||||
ASSERT_EQ(issuances.size(), 1);
|
||||
|
||||
auto const& issuanceJson = issuances[0].as_object();
|
||||
EXPECT_TRUE(issuanceJson.contains(testParams.expectedJsonKey));
|
||||
EXPECT_EQ(issuanceJson.at(testParams.expectedJsonKey), true);
|
||||
});
|
||||
}
|
||||
|
||||
struct SingleMutableFlagTest {
|
||||
std::string testName;
|
||||
uint32_t mutableFlag;
|
||||
std::string expectedJsonKey;
|
||||
};
|
||||
|
||||
struct AccountMPTokenIssuancesMutableFlagsTest : RPCAccountMPTokenIssuancesHandlerTest,
|
||||
WithParamInterface<SingleMutableFlagTest> {};
|
||||
|
||||
static auto
|
||||
generateSingleMutableFlagTests()
|
||||
{
|
||||
return std::vector<SingleMutableFlagTest>{
|
||||
{"CanMutateCanLock", ripple::lsmfMPTCanMutateCanLock, "mpt_can_mutate_can_lock"},
|
||||
{"CanMutateRequireAuth", ripple::lsmfMPTCanMutateRequireAuth, "mpt_can_mutate_require_auth"},
|
||||
{"CanMutateCanEscrow", ripple::lsmfMPTCanMutateCanEscrow, "mpt_can_mutate_can_escrow"},
|
||||
{"CanMutateCanTrade", ripple::lsmfMPTCanMutateCanTrade, "mpt_can_mutate_can_trade"},
|
||||
{"CanMutateCanTransfer", ripple::lsmfMPTCanMutateCanTransfer, "mpt_can_mutate_can_transfer"},
|
||||
{"CanMutateCanClawback", ripple::lsmfMPTCanMutateCanClawback, "mpt_can_mutate_can_clawback"},
|
||||
{"CanMutateMetadata", ripple::lsmfMPTCanMutateMetadata, "mpt_can_mutate_metadata"},
|
||||
{"CanMutateTransferFee", ripple::lsmfMPTCanMutateTransferFee, "mpt_can_mutate_transfer_fee"},
|
||||
};
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
RPCAccountMPTokenIssuancesMutableFlagsGroup,
|
||||
AccountMPTokenIssuancesMutableFlagsTest,
|
||||
ValuesIn(generateSingleMutableFlagTests()),
|
||||
tests::util::kNAME_GENERATOR
|
||||
);
|
||||
|
||||
TEST_P(AccountMPTokenIssuancesMutableFlagsTest, SingleMutableFlag)
|
||||
{
|
||||
auto const testParams = GetParam();
|
||||
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject({ripple::uint256{kISSUANCE_INDEX1}}, kISSUANCE_INDEX1);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
auto const bbs = std::vector<Blob>{createMptIssuanceObject(
|
||||
kACCOUNT,
|
||||
1,
|
||||
std::nullopt,
|
||||
0,
|
||||
0,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
testParams.mutableFlag
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
runSpawn([this, &testParams](auto yield) {
|
||||
auto const input = json::parse(
|
||||
fmt::format(
|
||||
R"JSON({{
|
||||
"account": "{}"
|
||||
}})JSON",
|
||||
kACCOUNT
|
||||
)
|
||||
);
|
||||
auto const handler = AnyHandler{AccountMPTokenIssuancesHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_TRUE(output);
|
||||
auto const& resultJson = (*output.result).as_object();
|
||||
auto const& issuances = resultJson.at("mpt_issuances").as_array();
|
||||
ASSERT_EQ(issuances.size(), 1);
|
||||
|
||||
auto const& issuanceJson = issuances[0].as_object();
|
||||
EXPECT_TRUE(issuanceJson.contains(testParams.expectedJsonKey));
|
||||
EXPECT_EQ(issuanceJson.at(testParams.expectedJsonKey), true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,12 +64,14 @@ constexpr uint64_t kTOKEN2_AMOUNT = 250;
|
||||
// define expected JSON for mptokens
|
||||
auto const kTOKEN_OUT1 = fmt::format(
|
||||
R"JSON({{
|
||||
"mpt_id": "{}",
|
||||
"account": "{}",
|
||||
"mpt_issuance_id": "{}",
|
||||
"mpt_amount": {},
|
||||
"locked_amount": {},
|
||||
"mpt_locked": true
|
||||
}})JSON",
|
||||
kTOKEN_INDEX1,
|
||||
kACCOUNT,
|
||||
kISSUANCE_ID_HEX,
|
||||
kTOKEN1_AMOUNT,
|
||||
@@ -78,11 +80,13 @@ auto const kTOKEN_OUT1 = fmt::format(
|
||||
|
||||
auto const kTOKEN_OUT2 = fmt::format(
|
||||
R"JSON({{
|
||||
"mpt_id": "{}",
|
||||
"account": "{}",
|
||||
"mpt_issuance_id": "{}",
|
||||
"mpt_amount": {},
|
||||
"mpt_authorized": true
|
||||
}})JSON",
|
||||
kTOKEN_INDEX2,
|
||||
kACCOUNT,
|
||||
kISSUANCE_ID_HEX,
|
||||
kTOKEN2_AMOUNT
|
||||
@@ -262,7 +266,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, NonExistLedgerViaLedgerIntIndex)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, LedgerSeqOutOfRangeByHash)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 31);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 31);
|
||||
EXPECT_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const input = json::parse(
|
||||
@@ -311,7 +315,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, LedgerSeqOutOfRangeByIndex)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, NonExistAccount)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _)).WillOnce(Return(ledgerHeader));
|
||||
// fetch account object return empty
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).WillOnce(Return(std::optional<Blob>{}));
|
||||
@@ -339,29 +343,31 @@ TEST_F(RPCAccountMPTokensHandlerTest, NonExistAccount)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, DefaultParameters)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
ON_CALL(*backend_, fetchLedgerBySequence).WillByDefault(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir =
|
||||
createOwnerDirLedgerObject({ripple::uint256{kTOKEN_INDEX1}, ripple::uint256{kTOKEN_INDEX2}}, kTOKEN_INDEX1);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
auto const token1 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
);
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const token2 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
);
|
||||
|
||||
bbs.push_back(token1.getSerializer().peekData());
|
||||
bbs.push_back(token2.getSerializer().peekData());
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
@@ -385,7 +391,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, DefaultParameters)
|
||||
kTOKEN_OUT2
|
||||
);
|
||||
auto const input = json::parse(fmt::format(R"JSON({{"account": "{}"}})JSON", kACCOUNT));
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(expected), *output.result);
|
||||
@@ -395,22 +401,25 @@ TEST_F(RPCAccountMPTokensHandlerTest, DefaultParameters)
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, UseLimit)
|
||||
{
|
||||
constexpr int kLIMIT = 20;
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
ON_CALL(*backend_, fetchLedgerBySequence).WillByDefault(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
std::vector<ripple::uint256> indexes;
|
||||
std::vector<Blob> bbs;
|
||||
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
indexes.emplace_back(kTOKEN_INDEX1);
|
||||
auto const token = createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt);
|
||||
bbs.push_back(token.getSerializer().peekData());
|
||||
}
|
||||
auto const indexes = std::vector<ripple::uint256>(50, ripple::uint256{kTOKEN_INDEX1});
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(50);
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
v.push_back(createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt)
|
||||
.getSerializer()
|
||||
.peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
|
||||
ripple::STObject ownerDir = createOwnerDirLedgerObject(indexes, kTOKEN_INDEX1);
|
||||
ownerDir.setFieldU64(ripple::sfIndexNext, 99);
|
||||
@@ -432,7 +441,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, UseLimit)
|
||||
)
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
|
||||
@@ -454,7 +463,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, UseLimit)
|
||||
)
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ((*output.result).as_object().at("limit").as_uint64(), AccountMPTokensHandler::kLIMIT_MIN);
|
||||
@@ -472,7 +481,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, UseLimit)
|
||||
)
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ((*output.result).as_object().at("limit").as_uint64(), AccountMPTokensHandler::kLIMIT_MAX);
|
||||
@@ -483,22 +492,25 @@ TEST_F(RPCAccountMPTokensHandlerTest, MarkerOutput)
|
||||
{
|
||||
constexpr auto kNEXT_PAGE = 99;
|
||||
constexpr auto kLIMIT = 15;
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto ownerDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto ownerDir2Kk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const ownerDirKk = ripple::keylet::ownerDir(account).key;
|
||||
auto const ownerDir2Kk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
bbs.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
bbs.push_back(createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt)
|
||||
.getSerializer()
|
||||
.peekData());
|
||||
}
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
v.push_back(createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt)
|
||||
.getSerializer()
|
||||
.peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
std::vector<ripple::uint256> indexes1;
|
||||
@@ -528,7 +540,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, MarkerOutput)
|
||||
kLIMIT
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
auto const& resultJson = (*output.result).as_object();
|
||||
@@ -544,22 +556,25 @@ TEST_F(RPCAccountMPTokensHandlerTest, MarkerInput)
|
||||
constexpr auto kNEXT_PAGE = 99;
|
||||
constexpr auto kLIMIT = 15;
|
||||
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto ownerDirKk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
auto const ownerDirKk = ripple::keylet::page(ripple::keylet::ownerDir(account), kNEXT_PAGE).key;
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
std::vector<ripple::uint256> indexes;
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
indexes.emplace_back(kTOKEN_INDEX1);
|
||||
bbs.push_back(createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt)
|
||||
.getSerializer()
|
||||
.peekData());
|
||||
}
|
||||
auto const indexes = std::vector<ripple::uint256>(kLIMIT, ripple::uint256{kTOKEN_INDEX1});
|
||||
auto const bbs = [&]() {
|
||||
std::vector<Blob> v;
|
||||
v.reserve(kLIMIT);
|
||||
for (int i = 0; i < kLIMIT; ++i) {
|
||||
v.push_back(createMpTokenObject(kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), i, 0, std::nullopt)
|
||||
.getSerializer()
|
||||
.peekData());
|
||||
}
|
||||
return v;
|
||||
}();
|
||||
|
||||
ripple::STObject ownerDir = createOwnerDirLedgerObject(indexes, kTOKEN_INDEX1);
|
||||
ownerDir.setFieldU64(ripple::sfIndexNext, 0);
|
||||
@@ -583,7 +598,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, MarkerInput)
|
||||
kNEXT_PAGE
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
auto const& resultJson = (*output.result).as_object();
|
||||
@@ -594,29 +609,31 @@ TEST_F(RPCAccountMPTokensHandlerTest, MarkerInput)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, LimitLessThanMin)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir =
|
||||
createOwnerDirLedgerObject({ripple::uint256{kTOKEN_INDEX1}, ripple::uint256{kTOKEN_INDEX2}}, kTOKEN_INDEX1);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
auto const token1 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
);
|
||||
bbs.push_back(token1.getSerializer().peekData());
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const token2 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
);
|
||||
bbs.push_back(token2.getSerializer().peekData());
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
@@ -651,7 +668,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, LimitLessThanMin)
|
||||
kTOKEN_OUT2
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(correctOutput), *output.result);
|
||||
@@ -660,29 +677,31 @@ TEST_F(RPCAccountMPTokensHandlerTest, LimitLessThanMin)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, LimitMoreThanMax)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir =
|
||||
createOwnerDirLedgerObject({ripple::uint256{kTOKEN_INDEX1}, ripple::uint256{kTOKEN_INDEX2}}, kTOKEN_INDEX1);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
std::vector<Blob> bbs;
|
||||
auto const token1 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
);
|
||||
bbs.push_back(token1.getSerializer().peekData());
|
||||
auto const bbs = std::vector<Blob>{
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN1_AMOUNT, ripple::lsfMPTLocked, kTOKEN1_LOCKED_AMOUNT
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData(),
|
||||
|
||||
auto const token2 = createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
);
|
||||
bbs.push_back(token2.getSerializer().peekData());
|
||||
createMpTokenObject(
|
||||
kACCOUNT, ripple::uint192(kISSUANCE_ID_HEX), kTOKEN2_AMOUNT, ripple::lsfMPTAuthorized, std::nullopt
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()
|
||||
};
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObjects).WillOnce(Return(bbs));
|
||||
|
||||
@@ -717,7 +736,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, LimitMoreThanMax)
|
||||
kTOKEN_OUT2
|
||||
);
|
||||
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(json::parse(correctOutput), *output.result);
|
||||
@@ -726,17 +745,16 @@ TEST_F(RPCAccountMPTokensHandlerTest, LimitMoreThanMax)
|
||||
|
||||
TEST_F(RPCAccountMPTokensHandlerTest, EmptyResult)
|
||||
{
|
||||
auto ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 30);
|
||||
EXPECT_CALL(*backend_, fetchLedgerBySequence).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto account = getAccountIdWithString(kACCOUNT);
|
||||
auto accountKk = ripple::keylet::account(account).key;
|
||||
auto owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
ON_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillByDefault(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const accountKk = ripple::keylet::account(account).key;
|
||||
auto const owneDirKk = ripple::keylet::ownerDir(account).key;
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(accountKk, _, _)).WillOnce(Return(Blob{'f', 'a', 'k', 'e'}));
|
||||
|
||||
ripple::STObject const ownerDir = createOwnerDirLedgerObject({}, kTOKEN_INDEX1);
|
||||
ON_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillByDefault(Return(ownerDir.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject).Times(2);
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(owneDirKk, _, _)).WillOnce(Return(ownerDir.getSerializer().peekData()));
|
||||
|
||||
runSpawn([this](auto yield) {
|
||||
auto const input = json::parse(
|
||||
@@ -747,7 +765,7 @@ TEST_F(RPCAccountMPTokensHandlerTest, EmptyResult)
|
||||
kACCOUNT
|
||||
)
|
||||
);
|
||||
auto handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const handler = AnyHandler{AccountMPTokensHandler{this->backend_}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ((*output.result).as_object().at("mptokens").as_array().size(), 0);
|
||||
|
||||
Reference in New Issue
Block a user