rippled
Loading...
Searching...
No Matches
SetFeeTests.cpp
1// Auto-generated unit tests for transaction SetFee
2
3
4#include <gtest/gtest.h>
5
6#include <protocol_autogen/TestHelpers.h>
7
8#include <xrpl/protocol/SecretKey.h>
9#include <xrpl/protocol/Seed.h>
10#include <xrpl/protocol/STTx.h>
11#include <xrpl/protocol_autogen/transactions/SetFee.h>
12#include <xrpl/protocol_autogen/transactions/AccountSet.h>
13
14#include <string>
15
16namespace xrpl::transactions {
17
18// 1 & 4) Set fields via builder setters, build, then read them back via
19// wrapper getters. After build(), validate() should succeed.
20TEST(TransactionsSetFeeTests, BuilderSettersRoundTrip)
21{
22 // Generate a deterministic keypair for signing
23 auto const [publicKey, secretKey] =
25
26 // Common transaction fields
27 auto const accountValue = calcAccountID(publicKey);
28 std::uint32_t const sequenceValue = 1;
29 auto const feeValue = canonical_AMOUNT();
30
31 // Transaction-specific field values
32 auto const ledgerSequenceValue = canonical_UINT32();
33 auto const baseFeeValue = canonical_UINT64();
34 auto const referenceFeeUnitsValue = canonical_UINT32();
35 auto const reserveBaseValue = canonical_UINT32();
36 auto const reserveIncrementValue = canonical_UINT32();
37 auto const baseFeeDropsValue = canonical_AMOUNT();
38 auto const reserveBaseDropsValue = canonical_AMOUNT();
39 auto const reserveIncrementDropsValue = canonical_AMOUNT();
40
41 SetFeeBuilder builder{
42 accountValue,
43 sequenceValue,
44 feeValue
45 };
46
47 // Set optional fields
48 builder.setLedgerSequence(ledgerSequenceValue);
49 builder.setBaseFee(baseFeeValue);
50 builder.setReferenceFeeUnits(referenceFeeUnitsValue);
51 builder.setReserveBase(reserveBaseValue);
52 builder.setReserveIncrement(reserveIncrementValue);
53 builder.setBaseFeeDrops(baseFeeDropsValue);
54 builder.setReserveBaseDrops(reserveBaseDropsValue);
55 builder.setReserveIncrementDrops(reserveIncrementDropsValue);
56
57 auto tx = builder.build(publicKey, secretKey);
58
59 std::string reason;
60 EXPECT_TRUE(tx.validate(reason)) << reason;
61
62 // Verify signing was applied
63 EXPECT_FALSE(tx.getSigningPubKey().empty());
64 EXPECT_TRUE(tx.hasTxnSignature());
65
66 // Verify common fields
67 EXPECT_EQ(tx.getAccount(), accountValue);
68 EXPECT_EQ(tx.getSequence(), sequenceValue);
69 EXPECT_EQ(tx.getFee(), feeValue);
70
71 // Verify required fields
72 // Verify optional fields
73 {
74 auto const& expected = ledgerSequenceValue;
75 auto const actualOpt = tx.getLedgerSequence();
76 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfLedgerSequence should be present";
77 expectEqualField(expected, *actualOpt, "sfLedgerSequence");
78 EXPECT_TRUE(tx.hasLedgerSequence());
79 }
80
81 {
82 auto const& expected = baseFeeValue;
83 auto const actualOpt = tx.getBaseFee();
84 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFee should be present";
85 expectEqualField(expected, *actualOpt, "sfBaseFee");
86 EXPECT_TRUE(tx.hasBaseFee());
87 }
88
89 {
90 auto const& expected = referenceFeeUnitsValue;
91 auto const actualOpt = tx.getReferenceFeeUnits();
92 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReferenceFeeUnits should be present";
93 expectEqualField(expected, *actualOpt, "sfReferenceFeeUnits");
94 EXPECT_TRUE(tx.hasReferenceFeeUnits());
95 }
96
97 {
98 auto const& expected = reserveBaseValue;
99 auto const actualOpt = tx.getReserveBase();
100 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBase should be present";
101 expectEqualField(expected, *actualOpt, "sfReserveBase");
102 EXPECT_TRUE(tx.hasReserveBase());
103 }
104
105 {
106 auto const& expected = reserveIncrementValue;
107 auto const actualOpt = tx.getReserveIncrement();
108 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrement should be present";
109 expectEqualField(expected, *actualOpt, "sfReserveIncrement");
110 EXPECT_TRUE(tx.hasReserveIncrement());
111 }
112
113 {
114 auto const& expected = baseFeeDropsValue;
115 auto const actualOpt = tx.getBaseFeeDrops();
116 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFeeDrops should be present";
117 expectEqualField(expected, *actualOpt, "sfBaseFeeDrops");
118 EXPECT_TRUE(tx.hasBaseFeeDrops());
119 }
120
121 {
122 auto const& expected = reserveBaseDropsValue;
123 auto const actualOpt = tx.getReserveBaseDrops();
124 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBaseDrops should be present";
125 expectEqualField(expected, *actualOpt, "sfReserveBaseDrops");
126 EXPECT_TRUE(tx.hasReserveBaseDrops());
127 }
128
129 {
130 auto const& expected = reserveIncrementDropsValue;
131 auto const actualOpt = tx.getReserveIncrementDrops();
132 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrementDrops should be present";
133 expectEqualField(expected, *actualOpt, "sfReserveIncrementDrops");
134 EXPECT_TRUE(tx.hasReserveIncrementDrops());
135 }
136
137}
138
139// 2 & 4) Start from an STTx, construct a builder from it, build a new wrapper,
140// and verify all fields match.
141TEST(TransactionsSetFeeTests, BuilderFromStTxRoundTrip)
142{
143 // Generate a deterministic keypair for signing
144 auto const [publicKey, secretKey] =
145 generateKeyPair(KeyType::secp256k1, generateSeed("testSetFeeFromTx"));
146
147 // Common transaction fields
148 auto const accountValue = calcAccountID(publicKey);
149 std::uint32_t const sequenceValue = 2;
150 auto const feeValue = canonical_AMOUNT();
151
152 // Transaction-specific field values
153 auto const ledgerSequenceValue = canonical_UINT32();
154 auto const baseFeeValue = canonical_UINT64();
155 auto const referenceFeeUnitsValue = canonical_UINT32();
156 auto const reserveBaseValue = canonical_UINT32();
157 auto const reserveIncrementValue = canonical_UINT32();
158 auto const baseFeeDropsValue = canonical_AMOUNT();
159 auto const reserveBaseDropsValue = canonical_AMOUNT();
160 auto const reserveIncrementDropsValue = canonical_AMOUNT();
161
162 // Build an initial transaction
163 SetFeeBuilder initialBuilder{
164 accountValue,
165 sequenceValue,
166 feeValue
167 };
168
169 initialBuilder.setLedgerSequence(ledgerSequenceValue);
170 initialBuilder.setBaseFee(baseFeeValue);
171 initialBuilder.setReferenceFeeUnits(referenceFeeUnitsValue);
172 initialBuilder.setReserveBase(reserveBaseValue);
173 initialBuilder.setReserveIncrement(reserveIncrementValue);
174 initialBuilder.setBaseFeeDrops(baseFeeDropsValue);
175 initialBuilder.setReserveBaseDrops(reserveBaseDropsValue);
176 initialBuilder.setReserveIncrementDrops(reserveIncrementDropsValue);
177
178 auto initialTx = initialBuilder.build(publicKey, secretKey);
179
180 // Create builder from existing STTx
181 SetFeeBuilder builderFromTx{initialTx.getSTTx()};
182
183 auto rebuiltTx = builderFromTx.build(publicKey, secretKey);
184
185 std::string reason;
186 EXPECT_TRUE(rebuiltTx.validate(reason)) << reason;
187
188 // Verify common fields
189 EXPECT_EQ(rebuiltTx.getAccount(), accountValue);
190 EXPECT_EQ(rebuiltTx.getSequence(), sequenceValue);
191 EXPECT_EQ(rebuiltTx.getFee(), feeValue);
192
193 // Verify required fields
194 // Verify optional fields
195 {
196 auto const& expected = ledgerSequenceValue;
197 auto const actualOpt = rebuiltTx.getLedgerSequence();
198 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfLedgerSequence should be present";
199 expectEqualField(expected, *actualOpt, "sfLedgerSequence");
200 }
201
202 {
203 auto const& expected = baseFeeValue;
204 auto const actualOpt = rebuiltTx.getBaseFee();
205 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFee should be present";
206 expectEqualField(expected, *actualOpt, "sfBaseFee");
207 }
208
209 {
210 auto const& expected = referenceFeeUnitsValue;
211 auto const actualOpt = rebuiltTx.getReferenceFeeUnits();
212 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReferenceFeeUnits should be present";
213 expectEqualField(expected, *actualOpt, "sfReferenceFeeUnits");
214 }
215
216 {
217 auto const& expected = reserveBaseValue;
218 auto const actualOpt = rebuiltTx.getReserveBase();
219 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBase should be present";
220 expectEqualField(expected, *actualOpt, "sfReserveBase");
221 }
222
223 {
224 auto const& expected = reserveIncrementValue;
225 auto const actualOpt = rebuiltTx.getReserveIncrement();
226 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrement should be present";
227 expectEqualField(expected, *actualOpt, "sfReserveIncrement");
228 }
229
230 {
231 auto const& expected = baseFeeDropsValue;
232 auto const actualOpt = rebuiltTx.getBaseFeeDrops();
233 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFeeDrops should be present";
234 expectEqualField(expected, *actualOpt, "sfBaseFeeDrops");
235 }
236
237 {
238 auto const& expected = reserveBaseDropsValue;
239 auto const actualOpt = rebuiltTx.getReserveBaseDrops();
240 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBaseDrops should be present";
241 expectEqualField(expected, *actualOpt, "sfReserveBaseDrops");
242 }
243
244 {
245 auto const& expected = reserveIncrementDropsValue;
246 auto const actualOpt = rebuiltTx.getReserveIncrementDrops();
247 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrementDrops should be present";
248 expectEqualField(expected, *actualOpt, "sfReserveIncrementDrops");
249 }
250
251}
252
253// 3) Verify wrapper throws when constructed from wrong transaction type.
254TEST(TransactionsSetFeeTests, WrapperThrowsOnWrongTxType)
255{
256 // Build a valid transaction of a different type
257 auto const [pk, sk] =
259 auto const account = calcAccountID(pk);
260
261 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
262 auto wrongTx = wrongBuilder.build(pk, sk);
263
264 EXPECT_THROW(SetFee{wrongTx.getSTTx()}, std::runtime_error);
265}
266
267// 4) Verify builder throws when constructed from wrong transaction type.
268TEST(TransactionsSetFeeTests, BuilderThrowsOnWrongTxType)
269{
270 // Build a valid transaction of a different type
271 auto const [pk, sk] =
272 generateKeyPair(KeyType::secp256k1, generateSeed("testWrongTypeBuilder"));
273 auto const account = calcAccountID(pk);
274
275 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
276 auto wrongTx = wrongBuilder.build(pk, sk);
277
278 EXPECT_THROW(SetFeeBuilder{wrongTx.getSTTx()}, std::runtime_error);
279}
280
281// 5) Build with only required fields and verify optional fields return nullopt.
282TEST(TransactionsSetFeeTests, OptionalFieldsReturnNullopt)
283{
284 // Generate a deterministic keypair for signing
285 auto const [publicKey, secretKey] =
286 generateKeyPair(KeyType::secp256k1, generateSeed("testSetFeeNullopt"));
287
288 // Common transaction fields
289 auto const accountValue = calcAccountID(publicKey);
290 std::uint32_t const sequenceValue = 3;
291 auto const feeValue = canonical_AMOUNT();
292
293 // Transaction-specific required field values
294
295 SetFeeBuilder builder{
296 accountValue,
297 sequenceValue,
298 feeValue
299 };
300
301 // Do NOT set optional fields
302
303 auto tx = builder.build(publicKey, secretKey);
304
305 // Verify optional fields are not present
306 EXPECT_FALSE(tx.hasLedgerSequence());
307 EXPECT_FALSE(tx.getLedgerSequence().has_value());
308 EXPECT_FALSE(tx.hasBaseFee());
309 EXPECT_FALSE(tx.getBaseFee().has_value());
310 EXPECT_FALSE(tx.hasReferenceFeeUnits());
311 EXPECT_FALSE(tx.getReferenceFeeUnits().has_value());
312 EXPECT_FALSE(tx.hasReserveBase());
313 EXPECT_FALSE(tx.getReserveBase().has_value());
314 EXPECT_FALSE(tx.hasReserveIncrement());
315 EXPECT_FALSE(tx.getReserveIncrement().has_value());
316 EXPECT_FALSE(tx.hasBaseFeeDrops());
317 EXPECT_FALSE(tx.getBaseFeeDrops().has_value());
318 EXPECT_FALSE(tx.hasReserveBaseDrops());
319 EXPECT_FALSE(tx.getReserveBaseDrops().has_value());
320 EXPECT_FALSE(tx.hasReserveIncrementDrops());
321 EXPECT_FALSE(tx.getReserveIncrementDrops().has_value());
322}
323
324}
Builder for SetFee transactions.
Definition SetFee.h:267
SetFee build(PublicKey const &publicKey, SecretKey const &secretKey)
Build and return the SetFee wrapper.
Definition SetFee.h:394
Transaction: SetFee.
Definition SetFee.h:30
std::shared_ptr< STTx const > getSTTx() const
Get the underlying STTx object.
TEST(TransactionsAccountDeleteTests, BuilderSettersRoundTrip)
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:57
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
AccountID calcAccountID(PublicKey const &pk)
void expectEqualField(T const &expected, T const &actual, char const *fieldName)