mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-24 07:30:30 +00:00
fix: address PR review feedback
This commit is contained in:
@@ -57,6 +57,32 @@ public:
|
||||
{
|
||||
return this->tx_->at(sfVaultID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfMemoData (soeOPTIONAL)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_VL::type::value_type>
|
||||
getMemoData() const
|
||||
{
|
||||
if (hasMemoData())
|
||||
{
|
||||
return this->tx_->at(sfMemoData);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfMemoData is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasMemoData() const
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfMemoData);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -112,6 +138,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfMemoData (soeOPTIONAL)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
VaultDeleteBuilder&
|
||||
setMemoData(std::decay_t<typename SF_VL::type::value_type> const& value)
|
||||
{
|
||||
object_[sfMemoData] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the VaultDelete wrapper.
|
||||
* @param publicKey The public key for signing.
|
||||
|
||||
@@ -32,7 +32,7 @@ VaultCreate::checkExtraFeatures(PreflightContext const& ctx)
|
||||
std::uint32_t
|
||||
VaultCreate::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.rules.enabled(fixLendingProtocolV1_1))
|
||||
if (ctx.rules.enabled(featureLendingProtocolV1_1))
|
||||
return tfVaultCreateMask;
|
||||
|
||||
return tfVaultCreateMask | tfVaultOwnerCanBlockDeposit;
|
||||
@@ -193,7 +193,8 @@ VaultCreate::doApply()
|
||||
if (tx.isFlag(tfVaultPrivate))
|
||||
vault->setFlag(lsfVaultPrivate);
|
||||
|
||||
if (view().rules().enabled(fixLendingProtocolV1_1) && tx.isFlag(tfVaultOwnerCanBlockDeposit))
|
||||
if (view().rules().enabled(featureLendingProtocolV1_1) &&
|
||||
tx.isFlag(tfVaultOwnerCanBlockDeposit))
|
||||
vault->setFlag(lsfVaultOwnerCanBlockDeposit);
|
||||
|
||||
vault->at(sfSequence) = sequence;
|
||||
|
||||
@@ -77,7 +77,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
if (ctx.view.rules().enabled(fixLendingProtocolV1_1))
|
||||
if (ctx.view.rules().enabled(featureLendingProtocolV1_1))
|
||||
{
|
||||
// Perform these checks early to avoid unnecessary processing
|
||||
|
||||
@@ -85,7 +85,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
|
||||
if (isVaultInsolvent(vault, sleShareIssuance))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "VaultDeposit: Vault is insolvent, deposits are not allowed";
|
||||
return tecNO_PERMISSION;
|
||||
return tecLOCKED;
|
||||
}
|
||||
|
||||
if (vault->isFlag(lsfVaultDepositBlocked))
|
||||
|
||||
@@ -23,7 +23,7 @@ VaultSet::checkExtraFeatures(PreflightContext const& ctx)
|
||||
std::uint32_t
|
||||
VaultSet::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.rules.enabled(fixLendingProtocolV1_1))
|
||||
if (ctx.rules.enabled(featureLendingProtocolV1_1))
|
||||
return tfVaultSetMask;
|
||||
|
||||
// Add tfVaultDepositBlock and tfVaultDepositUnblock flags to indicate they are disabled
|
||||
@@ -36,6 +36,8 @@ isValidVaultUpdate(PreflightContext const& ctx)
|
||||
auto const atLeastOneFieldPresent = ctx.tx.isFieldPresent(sfDomainID) ||
|
||||
ctx.tx.isFieldPresent(sfAssetsMaximum) || ctx.tx.isFieldPresent(sfData);
|
||||
|
||||
// Mask of valid, non-universal flags: any bit set here means the
|
||||
// transaction is requesting a meaningful flag change.
|
||||
auto const expectedFlags = ~(VaultSet::getFlagsMask(ctx) | tfUniversal);
|
||||
|
||||
return atLeastOneFieldPresent || (ctx.tx.getFlags() & expectedFlags);
|
||||
@@ -134,7 +136,7 @@ VaultSet::preclaim(PreclaimContext const& ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.view.rules().enabled(fixLendingProtocolV1_1))
|
||||
if (ctx.view.rules().enabled(featureLendingProtocolV1_1))
|
||||
{
|
||||
// The Vault is not configured to support deposit blocking
|
||||
if (!vault->isFlag(lsfVaultOwnerCanBlockDeposit) &&
|
||||
@@ -214,7 +216,7 @@ VaultSet::doApply()
|
||||
view().update(sleIssuance);
|
||||
}
|
||||
|
||||
if (view().rules().enabled(fixLendingProtocolV1_1))
|
||||
if (view().rules().enabled(featureLendingProtocolV1_1))
|
||||
{
|
||||
if (tx.isFlag(tfVaultDepositBlock))
|
||||
vault->setFlag(lsfVaultDepositBlocked);
|
||||
|
||||
@@ -669,11 +669,11 @@ class Vault_test : public beast::unit_test::suite
|
||||
env(tx, ter{temINVALID_FLAG});
|
||||
|
||||
{
|
||||
env.disableFeature(fixLendingProtocolV1_1);
|
||||
env.disableFeature(featureLendingProtocolV1_1);
|
||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||
tx[sfFlags] = tfVaultOwnerCanBlockDeposit;
|
||||
env(tx, ter{temINVALID_FLAG});
|
||||
env.enableFeature(fixLendingProtocolV1_1);
|
||||
env.enableFeature(featureLendingProtocolV1_1);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1067,18 +1067,18 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
testCase(
|
||||
[&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) {
|
||||
testcase("set flags fail without fixLendingProtocolV1_1");
|
||||
testcase("set flags fail without featureLendingProtocolV1_1");
|
||||
|
||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||
|
||||
{
|
||||
env.disableFeature(fixLendingProtocolV1_1);
|
||||
env.disableFeature(featureLendingProtocolV1_1);
|
||||
env(vault.set({.owner = owner, .id = keylet.key, .flags = tfVaultDepositBlock}),
|
||||
ter(temINVALID_FLAG));
|
||||
env(vault.set(
|
||||
{.owner = owner, .id = keylet.key, .flags = tfVaultDepositUnblock}),
|
||||
ter(temINVALID_FLAG));
|
||||
env.enableFeature(fixLendingProtocolV1_1);
|
||||
env.enableFeature(featureLendingProtocolV1_1);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2371,7 +2371,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const tx = vault.deposit(
|
||||
{.depositor = depositor, .id = vaultKeylet.key, .amount = depositAmount});
|
||||
env(tx, ter{tesSUCCESS}, THISLINE);
|
||||
env(tx, ter{tesSUCCESS});
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -2383,7 +2383,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
using namespace loanBroker;
|
||||
using namespace loan;
|
||||
|
||||
env(set(owner, vaultKeylet.key), THISLINE);
|
||||
env(set(owner, vaultKeylet.key));
|
||||
env.close();
|
||||
|
||||
// Create a simple Loan for the full amount of Vault assets
|
||||
@@ -2393,11 +2393,10 @@ class Vault_test : public beast::unit_test::suite
|
||||
paymentTotal(1),
|
||||
sig(sfCounterpartySignature, owner),
|
||||
fee(env.current()->fees().base * 2),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close(std::chrono::seconds{120 + 60});
|
||||
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS), THISLINE);
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const sleVault = env.le(vaultKeylet);
|
||||
@@ -2424,7 +2423,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const tx = vault.deposit(
|
||||
{.depositor = depositor, .id = vaultKeylet.key, .amount = asset(20)});
|
||||
env(tx, ter{tecNO_PERMISSION}, THISLINE);
|
||||
env(tx, ter{tecNO_PERMISSION});
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -2440,14 +2439,13 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
.amount = share(0)}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
{
|
||||
env(loan::del(owner, loanKeylet.key), ter(tesSUCCESS), THISLINE);
|
||||
env(loanBroker::del(owner, brokerKeylet.key), ter(tesSUCCESS), THISLINE);
|
||||
env(loan::del(owner, loanKeylet.key), ter(tesSUCCESS));
|
||||
env(loanBroker::del(owner, brokerKeylet.key), ter(tesSUCCESS));
|
||||
env(vault.del({.owner = owner, .id = vaultKeylet.key}));
|
||||
env.close();
|
||||
}
|
||||
@@ -3173,7 +3171,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const tx = vault.deposit(
|
||||
{.depositor = issuer, .id = vaultKeylet.key, .amount = depositAmount});
|
||||
env(tx, ter{tesSUCCESS}, THISLINE);
|
||||
env(tx, ter{tesSUCCESS});
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -3185,7 +3183,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
using namespace loanBroker;
|
||||
using namespace loan;
|
||||
|
||||
env(set(owner, vaultKeylet.key), ter{tesSUCCESS}, THISLINE);
|
||||
env(set(owner, vaultKeylet.key), ter{tesSUCCESS});
|
||||
env.close();
|
||||
|
||||
// Create a simple Loan for the full amount of Vault assets
|
||||
@@ -3195,11 +3193,10 @@ class Vault_test : public beast::unit_test::suite
|
||||
paymentTotal(1),
|
||||
sig(sfCounterpartySignature, owner),
|
||||
fee(env.current()->fees().base * 2),
|
||||
ter{tesSUCCESS},
|
||||
THISLINE);
|
||||
ter{tesSUCCESS});
|
||||
env.close(std::chrono::seconds{120 + 60});
|
||||
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS), THISLINE);
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const sleVault = env.le(vaultKeylet);
|
||||
@@ -3226,7 +3223,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const tx = vault.deposit(
|
||||
{.depositor = issuer, .id = vaultKeylet.key, .amount = asset(20)});
|
||||
env(tx, ter{tecNO_PERMISSION}, THISLINE);
|
||||
env(tx, ter{tecNO_PERMISSION});
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -3242,14 +3239,13 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = issuer,
|
||||
.amount = share(0)}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
{
|
||||
env(loan::del(owner, loanKeylet.key), ter(tesSUCCESS), THISLINE);
|
||||
env(loanBroker::del(owner, brokerKeylet.key), ter(tesSUCCESS), THISLINE);
|
||||
env(loan::del(owner, loanKeylet.key), ter(tesSUCCESS));
|
||||
env(loanBroker::del(owner, brokerKeylet.key), ter(tesSUCCESS));
|
||||
env(vault.del({.owner = owner, .id = vaultKeylet.key}));
|
||||
env.close();
|
||||
}
|
||||
@@ -5585,30 +5581,28 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
auto const blockVault = [&](TER expectedTer, Keylet const& keylet) {
|
||||
env(vault.set({.owner = owner, .id = keylet.key, .flags = tfVaultDepositBlock}),
|
||||
ter(expectedTer),
|
||||
THISLINE);
|
||||
ter(expectedTer));
|
||||
};
|
||||
|
||||
auto const unblockVault = [&](TER expectedTer, Keylet const& keylet) {
|
||||
env(vault.set({.owner = owner, .id = keylet.key, .flags = tfVaultDepositUnblock}),
|
||||
ter(expectedTer),
|
||||
THISLINE);
|
||||
ter(expectedTer));
|
||||
};
|
||||
|
||||
// Blocking Vault with the amendment disabled fails
|
||||
{
|
||||
testcase(prefix + "block/unblock fails when amendment is disabled");
|
||||
|
||||
env.disableFeature(fixLendingProtocolV1_1);
|
||||
env.disableFeature(featureLendingProtocolV1_1);
|
||||
auto const [tx, keylet] = vault.create(
|
||||
{.owner = owner, .asset = asset, .flags = tfVaultOwnerCanBlockDeposit});
|
||||
env(tx, ter(temINVALID_FLAG), THISLINE);
|
||||
env(tx, ter(temINVALID_FLAG));
|
||||
env.close();
|
||||
|
||||
blockVault(temINVALID_FLAG, keylet);
|
||||
unblockVault(temINVALID_FLAG, keylet);
|
||||
|
||||
env.enableFeature(fixLendingProtocolV1_1);
|
||||
env.enableFeature(featureLendingProtocolV1_1);
|
||||
}
|
||||
|
||||
// Block Vault deposits fails if the vault is not configured to allow blocking deposits
|
||||
@@ -5621,7 +5615,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
blockVault(tecNO_PERMISSION, keylet);
|
||||
unblockVault(tecNO_PERMISSION, keylet);
|
||||
|
||||
env(vault.del({.owner = owner, .id = keylet.key}), ter(tesSUCCESS), THISLINE);
|
||||
env(vault.del({.owner = owner, .id = keylet.key}), ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -5638,15 +5632,13 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env(vault.deposit({
|
||||
.depositor = other,
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
blockVault(tesSUCCESS, keylet);
|
||||
|
||||
@@ -5656,8 +5648,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
|
||||
// Other accounts are also blocked from depositing to the vault
|
||||
env(vault.deposit({
|
||||
@@ -5665,8 +5656,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
|
||||
// Block vault withdrawal works as normal
|
||||
env(vault.withdraw({
|
||||
@@ -5674,16 +5664,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
env(vault.withdraw({
|
||||
.depositor = other,
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
unblockVault(tesSUCCESS, keylet);
|
||||
|
||||
@@ -5692,16 +5680,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
env(vault.deposit({
|
||||
.depositor = other,
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
// Withdraw to keep the vault empty
|
||||
env(vault.withdraw({
|
||||
@@ -5709,30 +5695,26 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
env(vault.withdraw({
|
||||
.depositor = other,
|
||||
.id = keylet.key,
|
||||
.amount = XRP(10'000),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
}
|
||||
|
||||
{
|
||||
testcase(prefix + "block/unblock fails when caller is not owner");
|
||||
|
||||
env(vault.set({.owner = other, .id = keylet.key, .flags = tfVaultDepositBlock}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
|
||||
blockVault(tesSUCCESS, keylet);
|
||||
|
||||
env(vault.set({.owner = other, .id = keylet.key, .flags = tfVaultDepositUnblock}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
|
||||
unblockVault(tesSUCCESS, keylet);
|
||||
}
|
||||
@@ -5772,7 +5754,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 disabled");
|
||||
env.disableFeature(featureLendingProtocolV1_1);
|
||||
delTx[sfMemoData] = strHex(std::string(maxDataPayloadLength, 'A'));
|
||||
env(delTx, ter(temDISABLED), THISLINE);
|
||||
env(delTx, ter(temDISABLED));
|
||||
env.close();
|
||||
env.enableFeature(featureLendingProtocolV1_1);
|
||||
}
|
||||
@@ -5781,7 +5763,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data too large");
|
||||
delTx[sfMemoData] = strHex(std::string(maxDataPayloadLength + 1, 'A'));
|
||||
env(delTx, ter(temMALFORMED), THISLINE);
|
||||
env(delTx, ter(temMALFORMED));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -5789,7 +5771,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data empty");
|
||||
delTx[sfMemoData] = strHex(std::string(0, 'A'));
|
||||
env(delTx, ter(temMALFORMED), THISLINE);
|
||||
env(delTx, ter(temMALFORMED));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -5797,12 +5779,12 @@ class Vault_test : public beast::unit_test::suite
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data valid");
|
||||
PrettyAsset const xrpAsset = xrpIssue();
|
||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpAsset});
|
||||
env(tx, ter(tesSUCCESS), THISLINE);
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
// Recreate the transaction as the vault keylet changed
|
||||
auto delTx = vault.del({.owner = owner, .id = keylet.key});
|
||||
delTx[sfMemoData] = strHex(std::string(maxDataPayloadLength, 'A'));
|
||||
env(delTx, ter(tesSUCCESS), THISLINE);
|
||||
env(delTx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ TEST(TransactionsVaultDeleteTests, BuilderSettersRoundTrip)
|
||||
|
||||
// Transaction-specific field values
|
||||
auto const vaultIDValue = canonical_UINT256();
|
||||
auto const memoDataValue = canonical_VL();
|
||||
|
||||
VaultDeleteBuilder builder{
|
||||
accountValue,
|
||||
@@ -39,6 +40,7 @@ TEST(TransactionsVaultDeleteTests, BuilderSettersRoundTrip)
|
||||
};
|
||||
|
||||
// Set optional fields
|
||||
builder.setMemoData(memoDataValue);
|
||||
|
||||
auto tx = builder.build(publicKey, secretKey);
|
||||
|
||||
@@ -62,6 +64,14 @@ TEST(TransactionsVaultDeleteTests, BuilderSettersRoundTrip)
|
||||
}
|
||||
|
||||
// Verify optional fields
|
||||
{
|
||||
auto const& expected = memoDataValue;
|
||||
auto const actualOpt = tx.getMemoData();
|
||||
ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfMemoData should be present";
|
||||
expectEqualField(expected, *actualOpt, "sfMemoData");
|
||||
EXPECT_TRUE(tx.hasMemoData());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 2 & 4) Start from an STTx, construct a builder from it, build a new wrapper,
|
||||
@@ -79,6 +89,7 @@ TEST(TransactionsVaultDeleteTests, BuilderFromStTxRoundTrip)
|
||||
|
||||
// Transaction-specific field values
|
||||
auto const vaultIDValue = canonical_UINT256();
|
||||
auto const memoDataValue = canonical_VL();
|
||||
|
||||
// Build an initial transaction
|
||||
VaultDeleteBuilder initialBuilder{
|
||||
@@ -88,6 +99,7 @@ TEST(TransactionsVaultDeleteTests, BuilderFromStTxRoundTrip)
|
||||
feeValue
|
||||
};
|
||||
|
||||
initialBuilder.setMemoData(memoDataValue);
|
||||
|
||||
auto initialTx = initialBuilder.build(publicKey, secretKey);
|
||||
|
||||
@@ -112,6 +124,13 @@ TEST(TransactionsVaultDeleteTests, BuilderFromStTxRoundTrip)
|
||||
}
|
||||
|
||||
// Verify optional fields
|
||||
{
|
||||
auto const& expected = memoDataValue;
|
||||
auto const actualOpt = rebuiltTx.getMemoData();
|
||||
ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfMemoData should be present";
|
||||
expectEqualField(expected, *actualOpt, "sfMemoData");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 3) Verify wrapper throws when constructed from wrong transaction type.
|
||||
@@ -142,5 +161,35 @@ TEST(TransactionsVaultDeleteTests, BuilderThrowsOnWrongTxType)
|
||||
EXPECT_THROW(VaultDeleteBuilder{wrongTx.getSTTx()}, std::runtime_error);
|
||||
}
|
||||
|
||||
// 5) Build with only required fields and verify optional fields return nullopt.
|
||||
TEST(TransactionsVaultDeleteTests, OptionalFieldsReturnNullopt)
|
||||
{
|
||||
// Generate a deterministic keypair for signing
|
||||
auto const [publicKey, secretKey] =
|
||||
generateKeyPair(KeyType::secp256k1, generateSeed("testVaultDeleteNullopt"));
|
||||
|
||||
// Common transaction fields
|
||||
auto const accountValue = calcAccountID(publicKey);
|
||||
std::uint32_t const sequenceValue = 3;
|
||||
auto const feeValue = canonical_AMOUNT();
|
||||
|
||||
// Transaction-specific required field values
|
||||
auto const vaultIDValue = canonical_UINT256();
|
||||
|
||||
VaultDeleteBuilder builder{
|
||||
accountValue,
|
||||
vaultIDValue,
|
||||
sequenceValue,
|
||||
feeValue
|
||||
};
|
||||
|
||||
// Do NOT set optional fields
|
||||
|
||||
auto tx = builder.build(publicKey, secretKey);
|
||||
|
||||
// Verify optional fields are not present
|
||||
EXPECT_FALSE(tx.hasMemoData());
|
||||
EXPECT_FALSE(tx.getMemoData().has_value());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user