1#include <test/jtx/Account.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/SignerUtils.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/acctdelete.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/batch.h>
9#include <test/jtx/check.h>
10#include <test/jtx/delegate.h>
11#include <test/jtx/envconfig.h>
12#include <test/jtx/fee.h>
13#include <test/jtx/flags.h>
14#include <test/jtx/mpt.h>
15#include <test/jtx/multisign.h>
16#include <test/jtx/noop.h>
17#include <test/jtx/offer.h>
18#include <test/jtx/pay.h>
19#include <test/jtx/regkey.h>
20#include <test/jtx/seq.h>
21#include <test/jtx/sig.h>
22#include <test/jtx/tags.h>
23#include <test/jtx/ter.h>
24#include <test/jtx/ticket.h>
25#include <test/jtx/trust.h>
26#include <test/jtx/txflags.h>
27#include <test/jtx/utility.h>
28#include <test/jtx/vault.h>
30#include <xrpld/app/misc/Transaction.h>
31#include <xrpld/app/misc/TxQ.h>
33#include <xrpl/basics/base_uint.h>
34#include <xrpl/basics/strHex.h>
35#include <xrpl/beast/unit_test/suite.h>
36#include <xrpl/beast/utility/Journal.h>
37#include <xrpl/config/BasicConfig.h>
38#include <xrpl/config/Constants.h>
39#include <xrpl/core/HashRouter.h>
40#include <xrpl/json/json_value.h>
41#include <xrpl/json/to_string.h>
42#include <xrpl/ledger/ApplyView.h>
43#include <xrpl/ledger/OpenView.h>
44#include <xrpl/protocol/AccountID.h>
45#include <xrpl/protocol/Batch.h>
46#include <xrpl/protocol/Feature.h>
47#include <xrpl/protocol/Indexes.h>
48#include <xrpl/protocol/Issue.h>
49#include <xrpl/protocol/KeyType.h>
50#include <xrpl/protocol/MPTIssue.h>
51#include <xrpl/protocol/Protocol.h>
52#include <xrpl/protocol/SField.h>
53#include <xrpl/protocol/STParsedJSON.h>
54#include <xrpl/protocol/STTx.h>
55#include <xrpl/protocol/SecretKey.h>
56#include <xrpl/protocol/SeqProxy.h>
57#include <xrpl/protocol/Serializer.h>
58#include <xrpl/protocol/Sign.h>
59#include <xrpl/protocol/TER.h>
60#include <xrpl/protocol/TxFlags.h>
61#include <xrpl/protocol/TxFormats.h>
62#include <xrpl/protocol/Units.h>
63#include <xrpl/protocol/XRPAmount.h>
64#include <xrpl/protocol/jss.h>
65#include <xrpl/server/NetworkOPs.h>
66#include <xrpl/tx/Transactor.h>
67#include <xrpl/tx/apply.h>
68#include <xrpl/tx/transactors/payment/Payment.h>
69#include <xrpl/tx/transactors/system/Batch.h>
103 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
105 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
115 params[jss::ledger_index] = env.
closed()->seq();
116 params[jss::transactions] =
true;
117 params[jss::expand] =
true;
125 auto const transactions = jrr[jss::result][jss::ledger][jss::transactions];
130 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
131 BEAST_EXPECT(txn.isMember(jss::metaData));
133 BEAST_EXPECT(txn[sfTransactionType.jsonName] == ledgerResult.txType);
134 BEAST_EXPECT(meta[sfTransactionResult.jsonName] == ledgerResult.result);
135 if (ledgerResult.batchID)
139 *ledgerResult.batchID,
142 ledgerResult.result);
147 template <
typename... Args>
154 auto const ids = batchTxn.stx->getBatchTransactionIDs();
157 for (
auto const&
id : ids)
159 TxID const batchID = batchTxn.stx->getTransactionID();
183 for (
auto const& [k, v] : extraTxQ)
194 auto const& view = *env.
current();
205 for (
bool const withBatch : {
true,
false})
207 testcase <<
"enabled: Batch " << (withBatch ?
"enabled" :
"disabled");
209 auto const amend = withBatch ? features : features - featureBatchV1_1;
211 Env env{*
this, amend};
213 auto const alice =
Account(
"alice");
214 auto const bob =
Account(
"bob");
215 auto const carol =
Account(
"carol");
216 env.
fund(
XRP(10000), alice, bob, carol);
221 auto const seq = env.
seq(alice);
254 Env env{*
this, features};
256 auto const alice =
Account(
"alice");
257 auto const bob =
Account(
"bob");
258 auto const carol =
Account(
"carol");
259 env.
fund(
XRP(10000), alice, bob, carol);
271 auto const seq = env.
seq(alice);
279 auto const seq = env.
seq(alice);
287 auto const seq = env.
seq(alice);
290 Txflags(tfAllOrNothing | tfOnlyOne),
297 auto const seq = env.
seq(alice);
305 auto const seq = env.
seq(alice);
316 auto const seq = env.
seq(alice);
335 auto const seq = env.
seq(alice);
348 auto const seq = env.
seq(alice);
361 auto const seq = env.
seq(alice);
375 auto const seq = env.
seq(alice);
377 auto jt = env.
jt(
pay(alice, bob,
XRP(1)));
387 auto const seq = env.
seq(alice);
389 auto tx1 =
pay(alice, bob,
XRP(1));
392 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] = alice.human();
393 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfSigningPubKey.jsonName] =
395 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfTxnSignature.jsonName] =
"DEADBEEF";
406 auto const seq = env.
seq(alice);
409 tx1[jss::SigningPubKey] =
strHex(alice.pk());
421 auto const seq = env.
seq(alice);
442 Env disabledEnv{*
this, features - featureBatchV1_1};
443 disabledEnv.
fund(
XRP(10000), alice, bob);
449 disabledEnv.
current()->rules(),
468 auto const seq = env.
seq(alice);
481 auto const seq = env.
seq(alice);
484 tx1[jss::Fee] =
"-1";
494 auto const seq = env.
seq(alice);
497 tx1[jss::Fee] =
"1.5";
504 fail(
"Expected parse_error for fractional fee");
515 auto const seq = env.
seq(alice);
518 tx1[jss::Sequence] = seq + 1;
529 auto const seq = env.
seq(alice);
540 auto const seq = env.
seq(alice);
551 auto const seq = env.
seq(alice);
562 auto const seq = env.
seq(alice);
575 auto const seq = env.
seq(alice);
587 auto const seq = env.
seq(alice);
599 auto const seq = env.
seq(alice);
612 auto const seq = env.
seq(alice);
624 auto const seq = env.
seq(alice);
636 auto const seq = env.
seq(alice);
637 auto const bobSeq = env.
seq(bob);
647 jt.stx->getAccountID(sfAccount),
648 jt.stx->getSeqProxy().value(),
650 jt.stx->getBatchTransactionIDs());
653 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfAccount.jsonName] =
655 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfSigningPubKey.jsonName] =
657 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
666 auto const seq = env.
seq(alice);
689 Env env{*
this, features};
691 auto const alice =
Account(
"alice");
692 auto const bob =
Account(
"bob");
693 auto const carol =
Account(
"carol");
694 auto const dave =
Account(
"dave");
695 auto const elsa =
Account(
"elsa");
696 auto const frank =
Account(
"frank");
697 auto const phantom =
Account(
"phantom");
700 env.
fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
708 auto const seq = env.
seq(alice);
723 auto const seq = env.
seq(alice);
733 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
736 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
741 auto const seq = env.
seq(alice);
753 auto const seq = env.
seq(alice);
758 batch::Msig(bob, {carol, Account(
"dave", KeyType::Ed25519)}),
766 env(
fset(elsa, asfDisableMaster),
Sig(elsa));
767 auto const seq = env.
seq(alice);
779 auto const seq = env.
seq(alice);
791 auto const seq = env.
seq(alice);
805 auto const seq = env.seq(alice);
809 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
810 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
811 batch::Msig(bob, {carol, Reg{dave, davo}}),
818 auto const seq = env.seq(alice);
821 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
822 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
823 batch::Msig(bob, {carol}),
830 auto const seq = env.seq(alice);
833 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
834 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
835 batch::Msig(bob, {carol, dave}),
842 auto const seq = env.seq(alice);
845 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
846 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
847 batch::Msig(bob, {carol, dave}),
858 auto const ledSeq = env.current()->seq();
859 auto const seq = env.seq(alice);
862 batch::Inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
863 batch::Inner(
noop(phantom), ledSeq),
864 batch::Sig(
Reg{phantom, carol}),
871 auto const ledSeq = env.current()->seq();
872 auto const seq = env.seq(alice);
875 batch::Inner(
pay(alice, bob,
XRP(1000)), seq + 1),
876 batch::Inner(
noop(bob), ledSeq),
877 batch::Sig(
Reg{bob, carol}),
885 auto const seq = env.seq(alice);
888 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
889 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
890 batch::Sig(
Reg{bob, carol}),
897 auto const seq = env.seq(alice);
900 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
901 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
910 env(
fset(bob, asfDisableMaster),
Sig(bob));
911 auto const seq = env.seq(alice);
914 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
915 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
930 Env env{*
this, features};
932 auto const alice =
Account(
"alice");
933 auto const bob =
Account(
"bob");
935 env.
fund(
XRP(10000), alice, bob);
943 auto const seq = env.
seq(alice);
945 tx1.removeMember(field);
954 return jt.
stx ==
nullptr;
963 BEAST_EXPECT(batchCtorFails(jss::TransactionType));
965 BEAST_EXPECT(batchCtorFails(jss::Account));
967 BEAST_EXPECT(batchCtorFails(jss::Sequence));
969 BEAST_EXPECT(batchCtorFails(jss::Fee));
971 BEAST_EXPECT(batchCtorFails(jss::SigningPubKey));
976 STAmount const mptAmt{issue, UINT64_C(100)};
979 auto const seq = env.
seq(alice);
982 tx1[jss::TransactionType] = jss::OfferCreate;
983 tx1[jss::Account] = alice.human();
997 auto const seq = env.
seq(alice);
999 auto tx1 =
pay(alice, bob,
XRP(10));
1000 auto& ma = tx1[
"Memos"];
1001 auto& mi = ma[ma.size()];
1002 auto& m = mi[
"Memo"];
1006 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
1022 Env env{*
this, features};
1024 auto const alice =
Account(
"alice");
1025 auto const bob =
Account(
"bob");
1026 auto const gw =
Account(
"gw");
1027 auto const usd = gw[
"USD"];
1029 env.
fund(
XRP(10000), alice, bob, gw);
1031 env.
trust(usd(1000), alice, bob);
1032 env(
pay(gw, alice, usd(100)));
1033 env(
pay(gw, bob, usd(100)));
1041 auto const preAliceSeq = env.
seq(alice);
1042 auto const preAlice = env.
balance(alice);
1043 auto const preAliceUSD = env.
balance(alice, usd.issue());
1044 auto const preBobSeq = env.
seq(bob);
1045 auto const preBob = env.
balance(bob);
1046 auto const preBobUSD = env.
balance(bob, usd.issue());
1052 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1062 .result =
"tesSUCCESS",
1064 .batchID = std::nullopt},
1077 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1078 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1079 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1080 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1081 BEAST_EXPECT(env.
balance(bob) == preBob);
1082 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1087 auto const preAliceSeq = env.
seq(alice);
1088 auto const preAlice = env.
balance(alice);
1089 auto const preAliceUSD = env.
balance(alice, usd.issue());
1090 auto const preBobSeq = env.
seq(bob);
1091 auto const preBob = env.
balance(bob);
1092 auto const preBobUSD = env.
balance(bob, usd.issue());
1098 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1108 .result =
"tesSUCCESS",
1110 .batchID = std::nullopt},
1123 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1124 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1125 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1126 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1127 BEAST_EXPECT(env.
balance(bob) == preBob);
1128 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1133 auto const preAliceSeq = env.
seq(alice);
1134 auto const preAlice = env.
balance(alice);
1135 auto const preAliceUSD = env.
balance(alice, usd.issue());
1136 auto const preBobSeq = env.
seq(bob);
1137 auto const preBob = env.
balance(bob);
1138 auto const preBobUSD = env.
balance(bob, usd.issue());
1144 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1154 .result =
"tesSUCCESS",
1156 .batchID = std::nullopt},
1169 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1170 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1171 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1172 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1173 BEAST_EXPECT(env.
balance(bob) == preBob);
1174 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1179 auto const preAliceSeq = env.
seq(alice);
1180 auto const preAlice = env.
balance(alice);
1181 auto const preAliceUSD = env.
balance(alice, usd.issue());
1182 auto const preBobSeq = env.
seq(bob);
1183 auto const preBob = env.
balance(bob);
1184 auto const preBobUSD = env.
balance(bob, usd.issue());
1190 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1200 .result =
"tesSUCCESS",
1202 .batchID = std::nullopt},
1215 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1216 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1217 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1218 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1219 BEAST_EXPECT(env.
balance(bob) == preBob);
1220 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1225 auto const preAliceSeq = env.
seq(alice);
1226 auto const preAlice = env.
balance(alice);
1227 auto const preAliceUSD = env.
balance(alice, usd.issue());
1228 auto const preBobSeq = env.
seq(bob);
1229 auto const preBob = env.
balance(bob);
1230 auto const preBobUSD = env.
balance(bob, usd.issue());
1236 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1246 .result =
"tesSUCCESS",
1248 .batchID = std::nullopt},
1261 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1262 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1263 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1264 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1265 BEAST_EXPECT(env.
balance(bob) == preBob);
1266 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1280 Env env{*
this, features};
1282 auto const alice =
Account(
"alice");
1283 auto const bob =
Account(
"bob");
1284 env.
fund(
XRP(10000), alice, bob);
1292 auto const aliceSeq = env.
seq(alice);
1293 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1302 Env env{*
this, features};
1304 auto const alice =
Account(
"alice");
1305 auto const bob =
Account(
"bob");
1306 auto const carol =
Account(
"carol");
1307 env.
fund(
XRP(10000), alice, bob, carol);
1313 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1318 auto const aliceSeq = env.
seq(alice);
1319 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1329 Env env{*
this, features};
1331 auto const alice =
Account(
"alice");
1332 auto const bob =
Account(
"bob");
1333 auto const carol =
Account(
"carol");
1334 env.
fund(
XRP(10000), alice, bob, carol);
1340 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1345 auto const aliceSeq = env.
seq(alice);
1346 auto const bobSeq = env.
seq(bob);
1347 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1358 Env env{*
this, features};
1360 auto const alice =
Account(
"alice");
1361 auto const bob =
Account(
"bob");
1362 auto const carol =
Account(
"carol");
1363 env.
fund(
XRP(10000), alice, bob, carol);
1369 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1372 env(
signers(bob, 2, {{alice, 1}, {carol, 1}}));
1377 auto const aliceSeq = env.
seq(alice);
1378 auto const bobSeq = env.
seq(bob);
1379 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1390 Env env{*
this, features};
1392 auto const alice =
Account(
"alice");
1393 auto const bob =
Account(
"bob");
1394 env.
fund(
XRP(10000), alice, bob);
1402 auto const aliceSeq = env.
seq(alice);
1403 auto const bobSeq = env.
seq(bob);
1404 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1414 Env env{*
this, features};
1416 auto const alice =
Account(
"alice");
1417 auto const bob =
Account(
"bob");
1418 auto const gw =
Account(
"gw");
1419 auto const usd = gw[
"USD"];
1421 env.
fund(
XRP(10000), alice, bob, gw);
1423 auto const ammCreate = [&alice](
STAmount const& amount,
STAmount const& amount2) {
1425 jv[jss::Account] = alice.human();
1428 jv[jss::TradingFee] = 0;
1429 jv[jss::TransactionType] = jss::AMMCreate;
1434 auto const seq = env.
seq(alice);
1435 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
1453 Env env{*
this, features};
1455 auto const alice =
Account(
"alice");
1456 auto const bob =
Account(
"bob");
1457 env.
fund(
XRP(10000), alice, bob);
1461 auto const aliceSeq = env.
seq(alice);
1462 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1480 Env env{*
this, features};
1482 auto const alice =
Account(
"alice");
1483 auto const bob =
Account(
"bob");
1484 env.
fund(
XRP(10000), alice, bob);
1488 auto const aliceSeq = env.
seq(alice);
1490 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1501 BEAST_EXPECT(jt.stx ==
nullptr);
1509 Env env{*
this, features};
1511 auto const alice =
Account(
"alice");
1512 auto const bob =
Account(
"bob");
1513 env.
fund(
XRP(10000), alice, bob);
1516 auto const aliceSeq = env.
seq(alice);
1522 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1538 BEAST_EXPECT(threw);
1550 Env env{*
this, features};
1552 auto const alice =
Account(
"alice");
1553 auto const bob =
Account(
"bob");
1554 env.
fund(
XRP(10000), alice, bob);
1560 auto const aliceSeq = env.
seq(alice);
1562 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1573 Env env{*
this, features};
1575 auto const alice =
Account(
"alice");
1576 auto const bob =
Account(
"bob");
1577 env.
fund(
XRP(10000), alice, bob);
1581 auto const aliceSeq = env.
seq(alice);
1583 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1591 return result.applied;
1597 auto const [
valid, reason] =
1600 BEAST_EXPECT(reason ==
"BatchSigners array exceeds max entries.");
1612 Env env{*
this, features};
1614 auto const alice =
Account(
"alice");
1615 auto const bob =
Account(
"bob");
1616 auto const gw =
Account(
"gw");
1617 auto const usd = gw[
"USD"];
1618 env.
fund(
XRP(10000), alice, bob, gw);
1623 auto const preAlice = env.
balance(alice);
1624 auto const preBob = env.
balance(bob);
1627 auto const seq = env.
seq(alice);
1639 .result =
"tesSUCCESS",
1641 .batchID = std::nullopt},
1643 .txType =
"Payment",
1644 .result =
"tesSUCCESS",
1646 .batchID = batchID},
1648 .txType =
"Payment",
1649 .result =
"tesSUCCESS",
1651 .batchID = batchID},
1656 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1659 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
1660 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
1665 auto const preAlice = env.
balance(alice);
1666 auto const preBob = env.
balance(bob);
1669 auto const seq = env.
seq(alice);
1683 .result =
"tesSUCCESS",
1685 .batchID = std::nullopt},
1690 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1693 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1694 BEAST_EXPECT(env.
balance(bob) == preBob);
1699 auto const preAlice = env.
balance(alice);
1700 auto const preBob = env.
balance(bob);
1703 auto const seq = env.
seq(alice);
1716 .result =
"tesSUCCESS",
1718 .batchID = std::nullopt},
1723 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1726 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1727 BEAST_EXPECT(env.
balance(bob) == preBob);
1732 auto const preAlice = env.
balance(alice);
1733 auto const preBob = env.
balance(bob);
1736 auto const seq = env.
seq(alice);
1749 .result =
"tesSUCCESS",
1751 .batchID = std::nullopt},
1756 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1759 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1760 BEAST_EXPECT(env.
balance(bob) == preBob);
1772 Env env{*
this, features};
1774 auto const alice =
Account(
"alice");
1775 auto const bob =
Account(
"bob");
1776 auto const carol =
Account(
"carol");
1777 auto const dave =
Account(
"dave");
1778 auto const gw =
Account(
"gw");
1779 auto const usd = gw[
"USD"];
1780 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
1785 auto const preAlice = env.
balance(alice);
1786 auto const preBob = env.
balance(bob);
1789 auto const seq = env.
seq(alice);
1805 .result =
"tesSUCCESS",
1807 .batchID = std::nullopt},
1809 .txType =
"Payment",
1810 .result =
"tecUNFUNDED_PAYMENT",
1812 .batchID = batchID},
1814 .txType =
"Payment",
1815 .result =
"tecUNFUNDED_PAYMENT",
1817 .batchID = batchID},
1819 .txType =
"Payment",
1820 .result =
"tecUNFUNDED_PAYMENT",
1822 .batchID = batchID},
1827 BEAST_EXPECT(env.
seq(alice) == seq + 4);
1830 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1831 BEAST_EXPECT(env.
balance(bob) == preBob);
1836 auto const preAlice = env.
balance(alice);
1837 auto const preBob = env.
balance(bob);
1840 auto const seq = env.
seq(alice);
1854 .result =
"tesSUCCESS",
1856 .batchID = std::nullopt},
1858 .txType =
"Payment",
1859 .result =
"tecUNFUNDED_PAYMENT",
1861 .batchID = batchID},
1863 .txType =
"Payment",
1864 .result =
"tesSUCCESS",
1866 .batchID = batchID},
1871 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1874 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1875 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1880 auto const preAlice = env.
balance(alice);
1881 auto const preBob = env.
balance(bob);
1884 auto const seq = env.
seq(alice);
1898 .result =
"tesSUCCESS",
1900 .batchID = std::nullopt},
1902 .txType =
"Payment",
1903 .result =
"tesSUCCESS",
1905 .batchID = batchID},
1910 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1913 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1914 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1919 auto const preAlice = env.
balance(alice);
1920 auto const preBob = env.
balance(bob);
1923 auto const seq = env.
seq(alice);
1937 .result =
"tesSUCCESS",
1939 .batchID = std::nullopt},
1941 .txType =
"Payment",
1942 .result =
"tesSUCCESS",
1944 .batchID = batchID},
1949 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1952 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1953 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1958 auto const preAlice = env.
balance(alice);
1959 auto const preBob = env.
balance(bob);
1962 auto const seq = env.
seq(alice);
1976 .result =
"tesSUCCESS",
1978 .batchID = std::nullopt},
1980 .txType =
"Payment",
1981 .result =
"tesSUCCESS",
1983 .batchID = batchID},
1988 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1991 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1992 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1997 auto const preAlice = env.
balance(alice);
1998 auto const preBob = env.
balance(bob);
1999 auto const preCarol = env.
balance(carol);
2000 auto const seq = env.
seq(alice);
2008 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 1),
2010 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 2),
2012 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
2021 .result =
"tesSUCCESS",
2023 .batchID = std::nullopt},
2025 .txType =
"OfferCreate",
2026 .result =
"tecKILLED",
2028 .batchID = batchID},
2030 .txType =
"OfferCreate",
2031 .result =
"tecKILLED",
2033 .batchID = batchID},
2035 .txType =
"OfferCreate",
2036 .result =
"tecKILLED",
2038 .batchID = batchID},
2040 .txType =
"Payment",
2041 .result =
"tesSUCCESS",
2043 .batchID = batchID},
2047 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(100) - batchFee);
2048 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2049 BEAST_EXPECT(env.
balance(carol) == preCarol);
2061 Env env{*
this, features};
2063 auto const alice =
Account(
"alice");
2064 auto const bob =
Account(
"bob");
2065 auto const carol =
Account(
"carol");
2066 auto const dave =
Account(
"dave");
2067 auto const gw =
Account(
"gw");
2068 auto const usd = gw[
"USD"];
2069 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
2074 auto const preAlice = env.
balance(alice);
2075 auto const preBob = env.
balance(bob);
2078 auto const seq = env.
seq(alice);
2093 .result =
"tesSUCCESS",
2095 .batchID = std::nullopt},
2097 .txType =
"Payment",
2098 .result =
"tecUNFUNDED_PAYMENT",
2100 .batchID = batchID},
2105 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2108 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
2109 BEAST_EXPECT(env.
balance(bob) == preBob);
2114 auto const preAlice = env.
balance(alice);
2115 auto const preBob = env.
balance(bob);
2118 auto const seq = env.
seq(alice);
2132 .result =
"tesSUCCESS",
2134 .batchID = std::nullopt},
2136 .txType =
"Payment",
2137 .result =
"tesSUCCESS",
2139 .batchID = batchID},
2141 .txType =
"Payment",
2142 .result =
"tesSUCCESS",
2144 .batchID = batchID},
2146 .txType =
"Payment",
2147 .result =
"tesSUCCESS",
2149 .batchID = batchID},
2151 .txType =
"Payment",
2152 .result =
"tesSUCCESS",
2154 .batchID = batchID},
2159 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2162 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee);
2163 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10));
2168 auto const preAlice = env.
balance(alice);
2169 auto const preBob = env.
balance(bob);
2172 auto const seq = env.
seq(alice);
2187 .result =
"tesSUCCESS",
2189 .batchID = std::nullopt},
2191 .txType =
"Payment",
2192 .result =
"tesSUCCESS",
2194 .batchID = batchID},
2196 .txType =
"Payment",
2197 .result =
"tesSUCCESS",
2199 .batchID = batchID},
2201 .txType =
"Payment",
2202 .result =
"tecUNFUNDED_PAYMENT",
2204 .batchID = batchID},
2209 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2212 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2213 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2218 auto const preAlice = env.
balance(alice);
2219 auto const preBob = env.
balance(bob);
2222 auto const seq = env.
seq(alice);
2237 .result =
"tesSUCCESS",
2239 .batchID = std::nullopt},
2241 .txType =
"Payment",
2242 .result =
"tesSUCCESS",
2244 .batchID = batchID},
2246 .txType =
"Payment",
2247 .result =
"tesSUCCESS",
2249 .batchID = batchID},
2254 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2257 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2258 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2263 auto const preAlice = env.
balance(alice);
2264 auto const preBob = env.
balance(bob);
2267 auto const seq = env.
seq(alice);
2282 .result =
"tesSUCCESS",
2284 .batchID = std::nullopt},
2286 .txType =
"Payment",
2287 .result =
"tesSUCCESS",
2289 .batchID = batchID},
2291 .txType =
"Payment",
2292 .result =
"tesSUCCESS",
2294 .batchID = batchID},
2299 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2302 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2303 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2308 auto const preAlice = env.
balance(alice);
2309 auto const preBob = env.
balance(bob);
2310 auto const preCarol = env.
balance(carol);
2311 auto const seq = env.
seq(alice);
2320 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
2327 .result =
"tesSUCCESS",
2329 .batchID = std::nullopt},
2331 .txType =
"Payment",
2332 .result =
"tesSUCCESS",
2334 .batchID = batchID},
2336 .txType =
"Payment",
2337 .result =
"tesSUCCESS",
2339 .batchID = batchID},
2341 .txType =
"OfferCreate",
2342 .result =
"tecKILLED",
2344 .batchID = batchID},
2348 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2349 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2350 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2362 Env env{*
this, features};
2364 auto const alice =
Account(
"alice");
2365 auto const bob =
Account(
"bob");
2366 auto const carol =
Account(
"carol");
2367 auto const gw =
Account(
"gw");
2368 auto const usd = gw[
"USD"];
2369 env.
fund(
XRP(10000), alice, bob, carol, gw);
2374 auto const preAlice = env.
balance(alice);
2375 auto const preBob = env.
balance(bob);
2378 auto const seq = env.
seq(alice);
2394 .result =
"tesSUCCESS",
2396 .batchID = std::nullopt},
2398 .txType =
"Payment",
2399 .result =
"tesSUCCESS",
2401 .batchID = batchID},
2403 .txType =
"Payment",
2404 .result =
"tecUNFUNDED_PAYMENT",
2406 .batchID = batchID},
2408 .txType =
"Payment",
2409 .result =
"tecUNFUNDED_PAYMENT",
2411 .batchID = batchID},
2413 .txType =
"Payment",
2414 .result =
"tesSUCCESS",
2416 .batchID = batchID},
2421 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2424 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(4) - batchFee);
2425 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(4));
2430 auto const preAlice = env.
balance(alice);
2431 auto const preBob = env.
balance(bob);
2434 auto const seq = env.
seq(alice);
2449 .result =
"tesSUCCESS",
2451 .batchID = std::nullopt},
2453 .txType =
"Payment",
2454 .result =
"tesSUCCESS",
2456 .batchID = batchID},
2458 .txType =
"Payment",
2459 .result =
"tesSUCCESS",
2461 .batchID = batchID},
2463 .txType =
"Payment",
2464 .result =
"tecUNFUNDED_PAYMENT",
2466 .batchID = batchID},
2468 .txType =
"Payment",
2469 .result =
"tesSUCCESS",
2471 .batchID = batchID},
2476 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2479 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(6) - batchFee);
2480 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2485 auto const preAlice = env.
balance(alice);
2486 auto const preBob = env.
balance(bob);
2489 auto const seq = env.
seq(alice);
2504 .result =
"tesSUCCESS",
2506 .batchID = std::nullopt},
2508 .txType =
"Payment",
2509 .result =
"tesSUCCESS",
2511 .batchID = batchID},
2513 .txType =
"Payment",
2514 .result =
"tesSUCCESS",
2516 .batchID = batchID},
2518 .txType =
"Payment",
2519 .result =
"tesSUCCESS",
2521 .batchID = batchID},
2526 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2529 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2530 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2535 auto const preAlice = env.
balance(alice);
2536 auto const preBob = env.
balance(bob);
2539 auto const seq = env.
seq(alice);
2554 .result =
"tesSUCCESS",
2556 .batchID = std::nullopt},
2558 .txType =
"Payment",
2559 .result =
"tesSUCCESS",
2561 .batchID = batchID},
2563 .txType =
"Payment",
2564 .result =
"tesSUCCESS",
2566 .batchID = batchID},
2568 .txType =
"Payment",
2569 .result =
"tesSUCCESS",
2571 .batchID = batchID},
2576 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2579 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2580 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2585 auto const preAlice = env.
balance(alice);
2586 auto const preBob = env.
balance(bob);
2587 auto const preCarol = env.
balance(carol);
2588 auto const seq = env.
seq(alice);
2597 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3));
2603 .result =
"tesSUCCESS",
2605 .batchID = std::nullopt},
2607 .txType =
"Payment",
2608 .result =
"tesSUCCESS",
2610 .batchID = batchID},
2612 .txType =
"Payment",
2613 .result =
"tesSUCCESS",
2615 .batchID = batchID},
2617 .txType =
"OfferCreate",
2618 .result =
"tecKILLED",
2620 .batchID = batchID},
2624 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2625 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2626 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2634 std::string(
"inner submit rpc: batch ") + (withBatch ?
"enabled" :
"disabled") +
": ";
2636 auto const amend = withBatch ? features : features - featureBatchV1_1;
2641 Env env{*
this, amend};
2642 if (!BEAST_EXPECT(amend[featureBatchV1_1] == withBatch))
2645 auto const alice =
Account(
"alice");
2646 auto const bob =
Account(
"bob");
2648 env.
fund(
XRP(10000), alice, bob);
2658 jrr[jss::status] ==
"error" && jrr[jss::error] ==
"invalidTransaction" &&
2659 jrr[jss::error_exception] ==
2660 "fails local checks: Batch inner transactions are never "
2661 "considered validly signed.",
2675 txn[sfTxnSignature] =
"DEADBEEF";
2679 submitAndValidate(
"TxnSignature set", s.
slice(), __LINE__);
2689 txn[sfSigningPubKey] =
strHex(alice.pk());
2693 submitAndValidate(
"SigningPubKey set", s.
slice(), __LINE__);
2707 submitAndValidate(
"Signers set", s.
slice(), __LINE__);
2713 auto const jt = env.
jt(txn.getTxn());
2718 submitAndValidate(
"Fully signed", s.
slice(), __LINE__);
2731 submitAndValidate(
"No signing fields set", s.
slice(), __LINE__);
2740 STTx const amendTx(ttAMENDMENT, [seq = env.
closed()->header().seq + 1](
auto& obj) {
2741 obj.setAccountID(sfAccount, AccountID());
2742 obj.setFieldH256(sfAmendment, featureBatchV1_1);
2743 obj.setFieldU32(sfLedgerSequence, seq);
2744 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
2750 submitAndValidate(
"Pseudo-transaction", s.
slice(), __LINE__);
2757 for (
bool const withBatch : {
true,
false})
2771 Env env{*
this, features};
2773 auto const alice =
Account(
"alice");
2774 auto const bob =
Account(
"bob");
2779 auto const preAlice = env.
balance(alice);
2780 auto const ledSeq = env.
current()->seq();
2781 auto const seq = env.
seq(alice);
2795 .result =
"tesSUCCESS",
2797 .batchID = std::nullopt},
2799 .txType =
"Payment",
2800 .result =
"tesSUCCESS",
2802 .batchID = batchID},
2804 .txType =
"AccountSet",
2805 .result =
"tesSUCCESS",
2807 .batchID = batchID},
2812 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2815 BEAST_EXPECT(env.
seq(bob) == ledSeq + 1);
2818 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - batchFee);
2829 Env env{*
this, features};
2831 auto const alice =
Account(
"alice");
2832 auto const gw =
Account(
"gw");
2833 auto const carol =
Account(
"carol");
2834 auto const usd = gw[
"USD"];
2835 env.
fund(
XRP(10000), alice, gw);
2839 env(
trust(alice, usd(100000)));
2840 env(
pay(gw, alice, usd(10000)));
2841 env(
offer(gw, usd(2000),
XRP(2000)));
2844 auto const seq = env.
seq(alice);
2847 auto pp =
pay(alice, carol,
XRP(1000));
2849 pp[jss::Flags] = tfPartialPayment;
2858 BEAST_EXPECT(!env.
le(carol));
2875 Env env{*
this, features};
2877 auto const alice =
Account(
"alice");
2880 auto const unfunded =
Account(
"aaa");
2881 auto const carol =
Account(
"carol");
2882 env.
fund(
XRP(10000), alice, carol);
2886 BEAST_EXPECT(unfunded.id() < carol.id());
2888 auto const seq = env.
seq(alice);
2889 auto const ledSeq = env.
current()->seq();
2900 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
2917 Env env{*
this, features};
2919 auto const alice =
Account(
"alice");
2920 auto const bob =
Account(
"bob");
2921 env.
fund(
XRP(10000), alice, bob);
2924 auto const preAlice = env.
balance(alice);
2925 auto const preBob = env.
balance(bob);
2927 auto const seq = env.
seq(alice);
2931 tx1[sfDomain] =
strHex(domain);
2943 .result =
"tesSUCCESS",
2945 .batchID = std::nullopt},
2947 .txType =
"AccountSet",
2948 .result =
"tesSUCCESS",
2950 .batchID = batchID},
2952 .txType =
"Payment",
2953 .result =
"tesSUCCESS",
2955 .batchID = batchID},
2961 BEAST_EXPECT(sle->getFieldVL(sfDomain) ==
Blob(domain.
begin(), domain.
end()));
2964 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2967 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
2968 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
2981 Env env{*
this, features};
2983 auto const alice =
Account(
"alice");
2984 auto const bob =
Account(
"bob");
2985 env.
fund(
XRP(10000), alice, bob);
2989 for (
int i = 0; i < 5; ++i)
2992 auto const preAlice = env.
balance(alice);
2993 auto const preBob = env.
balance(bob);
2995 auto const seq = env.
seq(alice);
3010 .result =
"tesSUCCESS",
3012 .batchID = std::nullopt},
3014 .txType =
"Payment",
3015 .result =
"tesSUCCESS",
3017 .batchID = batchID},
3019 .txType =
"AccountDelete",
3020 .result =
"tesSUCCESS",
3022 .batchID = batchID},
3028 BEAST_EXPECT(env.
balance(bob) == preBob + (preAlice - batchFee));
3033 Env env{*
this, features};
3035 auto const alice =
Account(
"alice");
3036 auto const bob =
Account(
"bob");
3037 env.
fund(
XRP(10000), alice, bob);
3041 for (
int i = 0; i < 5; ++i)
3044 auto const preAlice = env.
balance(alice);
3045 auto const preBob = env.
balance(bob);
3047 env.
trust(bob[
"USD"](1000), alice);
3050 auto const seq = env.
seq(alice);
3065 .result =
"tesSUCCESS",
3067 .batchID = std::nullopt},
3069 .txType =
"Payment",
3070 .result =
"tesSUCCESS",
3072 .batchID = batchID},
3074 .txType =
"AccountDelete",
3075 .result =
"tecHAS_OBLIGATIONS",
3077 .batchID = batchID},
3079 .txType =
"Payment",
3080 .result =
"tesSUCCESS",
3082 .batchID = batchID},
3088 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3093 Env env{*
this, features};
3095 auto const alice =
Account(
"alice");
3096 auto const bob =
Account(
"bob");
3097 env.
fund(
XRP(10000), alice, bob);
3101 for (
int i = 0; i < 5; ++i)
3104 auto const preAlice = env.
balance(alice);
3105 auto const preBob = env.
balance(bob);
3107 auto const seq = env.
seq(alice);
3122 .result =
"tesSUCCESS",
3124 .batchID = std::nullopt},
3130 BEAST_EXPECT(env.
balance(bob) == preBob);
3139 bool const lendingBatchEnabled = features[featureLendingProtocolV1_2];
3143 Env env{*
this, features};
3145 Account const issuer{
"issuer"};
3148 Account const lender{
"lender"};
3150 Account const borrower{
"borrower"};
3160 Vault const vault{env};
3162 auto const deposit = asset(50'000);
3163 auto const debtMaximumValue = asset(25'000).value();
3164 auto const coverDepositValue = asset(1000).value();
3170 auto [tx, vaultKeylet, subscriptionDate] =
3171 vault.createClosedEnded({.owner = lender, .asset = asset});
3174 BEAST_EXPECT(env.
le(vaultKeylet));
3176 env(vault.deposit({.depositor = lender, .id = vaultKeylet.key, .amount = deposit}));
3180 vault.closePastSubscription(subscriptionDate);
3182 auto const brokerKeylet =
3187 env(
set(lender, vaultKeylet.key),
3189 kDebtMaximum(debtMaximumValue),
3193 env(coverDeposit(lender, brokerKeylet.key, coverDepositValue));
3199 using namespace loan;
3200 using namespace std::chrono_literals;
3202 auto const lenderSeq = env.
seq(lender);
3210 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3213 set(lender, brokerKeylet.key, asset(1000).value()),
3215 Sig(sfCounterpartySignature, borrower),
3221 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3228 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3231 set(lender, brokerKeylet.key, asset(1000).value()),
3238 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3245 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3248 set(lender, brokerKeylet.key, asset(1000).value()),
3250 kCounterparty(borrower.
id()),
3256 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3267 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3270 set(lender, brokerKeylet.key, asset(1000).value()),
3271 kCounterparty(borrower.
id()),
3283 STAmount{asset, asset(500).value()}),
3288 BEAST_EXPECT(!env.
le(loanKeylet));
3289 auto const brokerSleBefore = env.
le(brokerKeylet);
3290 if (!BEAST_EXPECT(brokerSleBefore))
3292 auto const coverAvailableBefore = brokerSleBefore->at(sfCoverAvailable);
3293 auto const coverDepositAmount = asset(100).value();
3298 auto const lenderSeq = env.
seq(lender);
3303 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3306 set(lender, brokerKeylet.key, asset(1000).value()),
3307 kCounterparty(borrower.
id()),
3318 BEAST_EXPECT(
static_cast<bool>(env.
le(loanKeylet)) == lendingBatchEnabled);
3319 if (
auto const brokerSle = env.
le(brokerKeylet); BEAST_EXPECT(brokerSle))
3321 auto const expectedCover = lendingBatchEnabled
3322 ? coverAvailableBefore + coverDepositAmount
3323 : coverAvailableBefore;
3324 BEAST_EXPECT(brokerSle->at(sfCoverAvailable) == expectedCover);
3337 auto const checkVaultBatch = [
this](
FeatureBitset amendments) {
3338 bool const lendingBatchEnabled = amendments[featureLendingProtocolV1_2];
3339 Env env{*
this, amendments};
3342 Account const lender{
"lender"};
3343 env.
fund(
XRP(100'000), payer, lender);
3346 Vault const vault{env};
3347 auto [
create, vaultKeylet] = vault.create({.owner = lender, .asset =
xrpIssue()});
3349 auto const payerSeq = env.
seq(payer);
3350 auto const lenderSeq = env.
seq(lender);
3355 batch::outer(payer, payerSeq, batchFee, tfAllOrNothing),
3359 {.depositor = lender, .id = vaultKeylet.key, .amount = XRP(1'000)}),
3364 BEAST_EXPECT(
static_cast<bool>(env.
le(vaultKeylet)) == lendingBatchEnabled);
3367 checkVaultBatch(features - featureLendingProtocolV1_2);
3368 checkVaultBatch(features);
3374 testcase(
"object create w/ sequence");
3379 Env env{*
this, features};
3381 auto const alice =
Account(
"alice");
3382 auto const bob =
Account(
"bob");
3383 auto const gw =
Account(
"gw");
3384 auto const usd = gw[
"USD"];
3386 env.
fund(
XRP(10000), alice, bob, gw);
3389 env.
trust(usd(1000), alice, bob);
3390 env(
pay(gw, alice, usd(100)));
3391 env(
pay(gw, bob, usd(100)));
3396 auto const aliceSeq = env.
seq(alice);
3397 auto const bobSeq = env.
seq(bob);
3398 auto const preAlice = env.
balance(alice);
3399 auto const preBob = env.
balance(bob);
3400 auto const preAliceUSD = env.
balance(alice, usd.issue());
3401 auto const preBobUSD = env.
balance(bob, usd.issue());
3408 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3417 .result =
"tesSUCCESS",
3419 .batchID = std::nullopt},
3421 .txType =
"CheckCreate",
3422 .result =
"tesSUCCESS",
3424 .batchID = batchID},
3426 .txType =
"CheckCash",
3427 .result =
"tesSUCCESS",
3429 .batchID = batchID},
3434 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3437 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3440 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3441 BEAST_EXPECT(env.
balance(bob) == preBob);
3444 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3445 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3450 env(
fset(alice, asfRequireDest));
3453 auto const aliceSeq = env.
seq(alice);
3454 auto const bobSeq = env.
seq(bob);
3455 auto const preAlice = env.
balance(alice);
3456 auto const preBob = env.
balance(bob);
3457 auto const preAliceUSD = env.
balance(alice, usd.issue());
3458 auto const preBobUSD = env.
balance(bob, usd.issue());
3465 batch::outer(alice, aliceSeq, batchFee, tfIndependent),
3475 .result =
"tesSUCCESS",
3477 .batchID = std::nullopt},
3479 .txType =
"CheckCreate",
3480 .result =
"tecDST_TAG_NEEDED",
3482 .batchID = batchID},
3484 .txType =
"CheckCash",
3485 .result =
"tecNO_ENTRY",
3487 .batchID = batchID},
3492 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3495 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3498 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3499 BEAST_EXPECT(env.
balance(bob) == preBob);
3502 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
3503 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
3510 testcase(
"object create w/ ticket");
3515 Env env{*
this, features};
3517 auto const alice =
Account(
"alice");
3518 auto const bob =
Account(
"bob");
3519 auto const gw =
Account(
"gw");
3520 auto const usd = gw[
"USD"];
3522 env.
fund(
XRP(10000), alice, bob, gw);
3525 env.
trust(usd(1000), alice, bob);
3526 env(
pay(gw, alice, usd(100)));
3527 env(
pay(gw, bob, usd(100)));
3530 auto const aliceSeq = env.
seq(alice);
3531 auto const bobSeq = env.
seq(bob);
3532 auto const preAlice = env.
balance(alice);
3533 auto const preBob = env.
balance(bob);
3534 auto const preAliceUSD = env.
balance(alice, usd.issue());
3535 auto const preBobUSD = env.
balance(bob, usd.issue());
3542 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3552 .result =
"tesSUCCESS",
3554 .batchID = std::nullopt},
3556 .txType =
"TicketCreate",
3557 .result =
"tesSUCCESS",
3559 .batchID = batchID},
3561 .txType =
"CheckCreate",
3562 .result =
"tesSUCCESS",
3564 .batchID = batchID},
3566 .txType =
"CheckCash",
3567 .result =
"tesSUCCESS",
3569 .batchID = batchID},
3573 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3574 BEAST_EXPECT(env.
seq(bob) == bobSeq + 10 + 1);
3575 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3576 BEAST_EXPECT(env.
balance(bob) == preBob);
3577 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3578 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3584 testcase(
"object create w/ 3rd party");
3589 Env env{*
this, features};
3591 auto const alice =
Account(
"alice");
3592 auto const bob =
Account(
"bob");
3593 auto const carol =
Account(
"carol");
3594 auto const gw =
Account(
"gw");
3595 auto const usd = gw[
"USD"];
3597 env.
fund(
XRP(10000), alice, bob, carol, gw);
3600 env.
trust(usd(1000), alice, bob);
3601 env(
pay(gw, alice, usd(100)));
3602 env(
pay(gw, bob, usd(100)));
3605 auto const aliceSeq = env.
seq(alice);
3606 auto const bobSeq = env.
seq(bob);
3607 auto const carolSeq = env.
seq(carol);
3608 auto const preAlice = env.
balance(alice);
3609 auto const preBob = env.
balance(bob);
3610 auto const preCarol = env.
balance(carol);
3611 auto const preAliceUSD = env.
balance(alice, usd.issue());
3612 auto const preBobUSD = env.
balance(bob, usd.issue());
3619 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3628 .result =
"tesSUCCESS",
3630 .batchID = std::nullopt},
3632 .txType =
"CheckCreate",
3633 .result =
"tesSUCCESS",
3635 .batchID = batchID},
3637 .txType =
"CheckCash",
3638 .result =
"tesSUCCESS",
3640 .batchID = batchID},
3644 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3645 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3646 BEAST_EXPECT(env.
seq(carol) == carolSeq + 1);
3647 BEAST_EXPECT(env.
balance(alice) == preAlice);
3648 BEAST_EXPECT(env.
balance(bob) == preBob);
3649 BEAST_EXPECT(env.
balance(carol) == preCarol - batchFee);
3650 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3651 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3663 Env env{*
this, features};
3665 auto const alice =
Account(
"alice");
3666 auto const bob =
Account(
"bob");
3668 env.
fund(
XRP(10000), alice, bob);
3675 auto const aliceSeq = env.
seq(alice);
3676 auto const preAlice = env.
balance(alice);
3677 auto const preBob = env.
balance(bob);
3692 .result =
"tesSUCCESS",
3694 .batchID = std::nullopt},
3696 .txType =
"Payment",
3697 .result =
"tesSUCCESS",
3699 .batchID = batchID},
3701 .txType =
"Payment",
3702 .result =
"tesSUCCESS",
3704 .batchID = batchID},
3710 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
3711 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
3713 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3714 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3715 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3724 Env env{*
this, features};
3726 auto const alice =
Account(
"alice");
3727 auto const bob =
Account(
"bob");
3729 env.
fund(
XRP(10000), alice, bob);
3736 auto const aliceSeq = env.
seq(alice);
3737 auto const preAlice = env.
balance(alice);
3738 auto const preBob = env.
balance(bob);
3744 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3752 .result =
"tesSUCCESS",
3754 .batchID = std::nullopt},
3756 .txType =
"Payment",
3757 .result =
"tesSUCCESS",
3759 .batchID = batchID},
3761 .txType =
"Payment",
3762 .result =
"tesSUCCESS",
3764 .batchID = batchID},
3770 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3771 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3773 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3774 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3775 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3784 Env env{*
this, features};
3786 auto const alice =
Account(
"alice");
3787 auto const bob =
Account(
"bob");
3789 env.
fund(
XRP(10000), alice, bob);
3796 auto const aliceSeq = env.
seq(alice);
3797 auto const preAlice = env.
balance(alice);
3798 auto const preBob = env.
balance(bob);
3813 .result =
"tesSUCCESS",
3815 .batchID = std::nullopt},
3817 .txType =
"Payment",
3818 .result =
"tesSUCCESS",
3820 .batchID = batchID},
3822 .txType =
"Payment",
3823 .result =
"tesSUCCESS",
3825 .batchID = batchID},
3831 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3832 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3834 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3835 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3836 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3848 auto const alice =
Account(
"alice");
3849 auto const bob =
Account(
"bob");
3850 auto const carol =
Account(
"carol");
3859 Env env{*
this, features};
3860 env.
fund(
XRP(10000), alice, bob, carol);
3863 auto const aliceSeq = env.
seq(alice);
3864 auto const carolSeq = env.
seq(carol);
3867 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 2));
3868 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3876 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3886 .result =
"tesSUCCESS",
3888 .batchID = std::nullopt},
3890 .txType =
"Payment",
3891 .result =
"tesSUCCESS",
3893 .batchID = batchID},
3895 .txType =
"Payment",
3896 .result =
"tesSUCCESS",
3898 .batchID = batchID},
3908 .txType =
"AccountSet",
3909 .result =
"tesSUCCESS",
3910 .txHash = noopTxnID,
3911 .batchID = std::nullopt},
3922 Env env{*
this, features};
3923 env.
fund(
XRP(10000), alice, bob);
3926 auto const aliceSeq = env.
seq(alice);
3929 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3937 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3946 .result =
"tesSUCCESS",
3948 .batchID = std::nullopt},
3950 .txType =
"Payment",
3951 .result =
"tesSUCCESS",
3953 .batchID = batchID},
3955 .txType =
"Payment",
3956 .result =
"tesSUCCESS",
3958 .batchID = batchID},
3976 Env env{*
this, features};
3977 env.
fund(
XRP(10000), alice, bob);
3980 auto const aliceSeq = env.
seq(alice);
3985 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3989 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3997 .result =
"tesSUCCESS",
3999 .batchID = std::nullopt},
4001 .txType =
"Payment",
4002 .result =
"tesSUCCESS",
4004 .batchID = batchID},
4006 .txType =
"Payment",
4007 .result =
"tesSUCCESS",
4009 .batchID = batchID},
4024 Env env{*
this, features};
4025 env.
fund(
XRP(10000), alice, bob, carol);
4028 auto const aliceSeq = env.
seq(alice);
4029 auto const carolSeq = env.
seq(carol);
4036 batch::outer(carol, carolSeq + 1, batchFee, tfAllOrNothing),
4042 auto const noopTxn = env.
jt(
noop(carol),
Seq(carolSeq));
4043 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
4050 .txType =
"AccountSet",
4051 .result =
"tesSUCCESS",
4052 .txHash = noopTxnID,
4053 .batchID = std::nullopt},
4056 .result =
"tesSUCCESS",
4058 .batchID = std::nullopt},
4060 .txType =
"Payment",
4061 .result =
"tesSUCCESS",
4063 .batchID = batchID},
4065 .txType =
"Payment",
4066 .result =
"tesSUCCESS",
4068 .batchID = batchID},
4090 auto const alice =
Account(
"alice");
4091 auto const bob =
Account(
"bob");
4098 Env env{*
this, features};
4099 env.
fund(
XRP(10000), alice, bob);
4106 auto const aliceSeq = env.
seq(alice);
4127 .result =
"tesSUCCESS",
4129 .batchID = std::nullopt},
4131 .txType =
"Payment",
4132 .result =
"tesSUCCESS",
4134 .batchID = batchID},
4136 .txType =
"Payment",
4137 .result =
"tesSUCCESS",
4139 .batchID = batchID},
4157 Env env{*
this, features};
4158 env.
fund(
XRP(10000), alice, bob);
4165 auto const aliceSeq = env.
seq(alice);
4186 .result =
"tesSUCCESS",
4188 .batchID = std::nullopt},
4190 .txType =
"Payment",
4191 .result =
"tesSUCCESS",
4193 .batchID = batchID},
4195 .txType =
"Payment",
4196 .result =
"tesSUCCESS",
4198 .batchID = batchID},
4220 auto const alice =
Account(
"alice");
4221 auto const bob =
Account(
"bob");
4230 Env env{*
this, features};
4231 env.
fund(
XRP(10000), alice, bob);
4238 auto const aliceSeq = env.
seq(alice);
4243 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4261 .result =
"tesSUCCESS",
4263 .batchID = std::nullopt},
4265 .txType =
"CheckCreate",
4266 .result =
"tesSUCCESS",
4268 .batchID = batchID},
4270 .txType =
"Payment",
4271 .result =
"tesSUCCESS",
4273 .batchID = batchID},
4275 .txType =
"CheckCash",
4276 .result =
"tesSUCCESS",
4278 .batchID = std::nullopt},
4293 Env env{*
this, features};
4294 env.
fund(
XRP(10000), alice, bob);
4301 auto const aliceSeq = env.
seq(alice);
4302 auto const bobSeq = env.
seq(bob);
4307 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4325 .txType =
"CheckCreate",
4326 .result =
"tesSUCCESS",
4328 .batchID = std::nullopt},
4331 .result =
"tesSUCCESS",
4333 .batchID = std::nullopt},
4335 .txType =
"CheckCash",
4336 .result =
"tesSUCCESS",
4338 .batchID = batchID},
4340 .txType =
"Payment",
4341 .result =
"tesSUCCESS",
4343 .batchID = batchID},
4356 Env env{*
this, features};
4357 env.
fund(
XRP(10000), alice, bob);
4364 auto const aliceSeq = env.
seq(alice);
4379 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4387 .result =
"tesSUCCESS",
4389 .batchID = std::nullopt},
4391 .txType =
"CheckCreate",
4392 .result =
"tesSUCCESS",
4394 .batchID = batchID},
4396 .txType =
"Payment",
4397 .result =
"tesSUCCESS",
4399 .batchID = batchID},
4401 .txType =
"CheckCash",
4402 .result =
"tesSUCCESS",
4404 .batchID = std::nullopt},
4414 testcase(
"pseudo txn with tfInnerBatchTxn");
4419 Env env{*
this, features};
4421 auto const alice =
Account(
"alice");
4422 auto const bob =
Account(
"bob");
4423 env.
fund(
XRP(10000), alice, bob);
4426 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
4427 obj.setAccountID(sfAccount,
AccountID());
4428 obj.setFieldH256(sfAmendment,
UInt256(2));
4429 obj.setFieldU32(sfLedgerSequence, env.
seq(alice));
4436 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
4440 return result.applied;
4458 Env env{*
this, features};
4461 auto const alice =
Account(
"alice");
4462 auto const bob =
Account(
"bob");
4464 env.
fund(
XRP(10000), alice, bob);
4470 auto const aliceSeq = env.
seq(alice);
4471 auto const preAlice = env.
balance(alice);
4472 auto const preBob = env.
balance(bob);
4473 auto const bobSeq = env.
seq(bob);
4476 auto const payTxn1 = env.
jt(
pay(alice, bob,
XRP(10)),
Seq(aliceSeq));
4477 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
4485 batch::outer(alice, aliceSeq + 1, batchFee, tfAllOrNothing),
4491 auto const payTxn2 = env.
jt(
pay(bob, alice,
XRP(5)),
Seq(bobSeq + 1));
4492 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
4498 .txType =
"Payment",
4499 .result =
"tesSUCCESS",
4500 .txHash = payTxn1ID,
4501 .batchID = std::nullopt},
4504 .result =
"tesSUCCESS",
4506 .batchID = std::nullopt},
4508 .txType =
"Payment",
4509 .result =
"tesSUCCESS",
4511 .batchID = batchID},
4513 .txType =
"Payment",
4514 .result =
"tesSUCCESS",
4516 .batchID = batchID},
4525 .txType =
"Payment",
4526 .result =
"tesSUCCESS",
4527 .txHash = payTxn2ID,
4528 .batchID = std::nullopt},
4534 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 3);
4537 BEAST_EXPECT(env.
seq(bob) == bobSeq + 2);
4540 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
4541 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10) - baseFee);
4564 auto alice =
Account(
"alice");
4566 auto carol =
Account(
"carol");
4570 env.
close(env.
now() + 5s, 10000ms);
4572 env.
close(env.
now() + 5s, 10000ms);
4583 auto const aliceSeq = env.
seq(alice);
4584 auto const bobSeq = env.
seq(bob);
4589 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4615 auto alice =
Account(
"alice");
4617 auto carol =
Account(
"carol");
4621 env.
close(env.
now() + 5s, 10000ms);
4623 env.
close(env.
now() + 5s, 10000ms);
4630 auto const aliceSeq = env.
seq(alice);
4631 auto const bobSeq = env.
seq(bob);
4636 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4660 auto alice =
Account(
"alice");
4664 env.
close(env.
now() + 5s, 10000ms);
4672 auto const aliceSeq = env.
seq(alice);
4681 auto const bobSeq = env.
seq(bob);
4683 env(
batch::outer(alice, aliceSeq + 2, batchFee, tfAllOrNothing),
4704 auto alice =
Account(
"alice");
4706 env.
fund(
XRP(10000), alice, bob);
4714 return jt.stx->getTransactionID();
4725 return transaction->getID();
4746 testcase(
"batch delegate consent");
4763 Env env{*
this, features};
4765 auto const alice =
Account(
"alice");
4766 auto const bob =
Account(
"bob");
4767 auto const mallory =
Account(
"mallory");
4768 env.
fund(
XRP(10000), alice, bob, mallory);
4774 auto const preMallory = env.
balance(mallory);
4777 auto const seq = env.
seq(alice);
4780 inner[jss::Delegate] = bob.human();
4783 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4790 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4804 Env env{*
this, features};
4806 auto const alice =
Account(
"alice");
4807 auto const bob =
Account(
"bob");
4808 auto const mallory =
Account(
"mallory");
4809 env.
fund(
XRP(10000), alice, bob, mallory);
4812 auto const preMallory = env.
balance(mallory);
4815 auto const seq = env.
seq(alice);
4818 inner[jss::Delegate] = bob.human();
4820 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4826 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4832 Env env{*
this, features};
4834 auto const alice =
Account(
"alice");
4835 auto const bob =
Account(
"bob");
4836 auto const mallory =
Account(
"mallory");
4837 env.
fund(
XRP(10000), alice, bob, mallory);
4840 auto const preMallory = env.
balance(mallory);
4843 auto const seq = env.
seq(alice);
4846 inner[jss::Delegate] = bob.human();
4848 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4855 BEAST_EXPECT(env.
balance(mallory) == preMallory +
XRP(1000));
4861 Env env{*
this, features};
4863 auto const alice =
Account(
"alice");
4864 auto const bob =
Account(
"bob");
4865 auto const carol =
Account(
"carol");
4866 env.
fund(
XRP(10000), alice, bob, carol);
4872 auto const preAlice = env.
balance(alice);
4875 auto const aliceSeq = env.
seq(alice);
4876 auto const bobSeq = env.
seq(bob);
4879 inner[jss::Delegate] = carol.human();
4882 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4888 BEAST_EXPECT(env.
balance(alice) == preAlice);
4894 Env env{*
this, features};
4896 auto const alice =
Account(
"alice");
4897 auto const bob =
Account(
"bob");
4898 auto const carol =
Account(
"carol");
4899 auto const mallory =
Account(
"mallory");
4900 env.
fund(
XRP(10000), alice, bob, carol, mallory);
4906 auto const preMallory = env.
balance(mallory);
4909 auto const seq = env.
seq(alice);
4912 inner[jss::Delegate] = bob.human();
4915 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4922 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4928 Env env{*
this, features};
4930 auto const alice =
Account(
"alice");
4931 auto const bob =
Account(
"bob");
4932 env.
fund(
XRP(10000), alice, bob);
4939 auto const preBob = env.
balance(bob);
4942 auto const aliceSeq = env.
seq(alice);
4943 auto const bobSeq = env.
seq(bob);
4946 inner[jss::Delegate] = alice.human();
4948 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4955 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
4963 Env env{*
this, features};
4965 auto const alice =
Account(
"alice");
4966 auto const bob =
Account(
"bob");
4967 auto const carol =
Account(
"carol");
4968 env.
fund(
XRP(10000), alice, bob, carol);
4974 auto const preAlice = env.
balance(alice);
4977 auto const aliceSeq = env.
seq(alice);
4978 auto const bobSeq = env.
seq(bob);
4981 inner[jss::Delegate] = carol.human();
4984 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4991 BEAST_EXPECT(env.
balance(alice) == preAlice);
4999 Env env{*
this, features};
5001 auto const alice =
Account(
"alice");
5002 auto const bob =
Account(
"bob");
5003 auto const mallory =
Account(
"mallory");
5004 env.
fund(
XRP(10000), alice, bob, mallory);
5010 auto const preMallory = env.
balance(mallory);
5013 auto const seq = env.
seq(bob);
5016 inner2[jss::Delegate] = alice.human();
5032 .result =
"tesSUCCESS",
5034 .batchID = std::nullopt},
5036 .txType =
"Payment",
5037 .result =
"tesSUCCESS",
5039 .batchID = batchID},
5041 .txType =
"Payment",
5042 .result =
"tesSUCCESS",
5044 .batchID = batchID},
5049 BEAST_EXPECT(env.
balance(mallory) == preMallory +
XRP(1000));
5059 Env env{*
this, features};
5061 auto const alice =
Account(
"alice");
5062 auto const bob =
Account(
"bob");
5063 auto const mallory =
Account(
"mallory");
5064 env.
fund(
XRP(10000), alice, bob, mallory);
5070 auto const preMallory = env.
balance(mallory);
5073 auto const seq = env.
seq(bob);
5078 inner2[jss::Delegate] = alice.human();
5095 .result =
"tesSUCCESS",
5097 .batchID = std::nullopt},
5099 .txType =
"DelegateSet",
5100 .result =
"tesSUCCESS",
5102 .batchID = batchID},
5108 BEAST_EXPECT(env.
balance(mallory) == preMallory);
5109 BEAST_EXPECT(env.
rpc(
"tx", txIDs[1])[jss::result][jss::error] ==
"txnNotFound");
5123 Env env{*
this, features};
5125 auto const alice =
Account(
"alice");
5126 auto const bob =
Account(
"bob");
5127 auto const gw =
Account(
"gw");
5128 auto const usd = gw[
"USD"];
5129 env.
fund(
XRP(10000), alice, bob, gw);
5135 auto const preAlice = env.
balance(alice);
5136 auto const preBob = env.
balance(bob);
5139 auto const seq = env.
seq(alice);
5142 tx[jss::Delegate] = bob.human();
5157 .result =
"tesSUCCESS",
5159 .batchID = std::nullopt},
5161 .txType =
"Payment",
5162 .result =
"tesSUCCESS",
5164 .batchID = batchID},
5166 .txType =
"Payment",
5167 .result =
"tesSUCCESS",
5169 .batchID = batchID},
5174 BEAST_EXPECT(env.
seq(alice) == seq + 3);
5177 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
5178 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
5183 Env env{*
this, features};
5185 auto const alice =
Account(
"alice");
5186 auto const bob =
Account(
"bob");
5187 auto const carol =
Account(
"carol");
5188 auto const gw =
Account(
"gw");
5189 auto const usd = gw[
"USD"];
5190 env.
fund(
XRP(10000), alice, bob, carol, gw);
5196 auto const preAlice = env.
balance(alice);
5197 auto const preBob = env.
balance(bob);
5198 auto const preCarol = env.
balance(carol);
5201 auto const aliceSeq = env.
seq(alice);
5202 auto const bobSeq = env.
seq(bob);
5205 tx[jss::Delegate] = carol.human();
5211 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
5220 .result =
"tesSUCCESS",
5222 .batchID = std::nullopt},
5224 .txType =
"Payment",
5225 .result =
"tesSUCCESS",
5227 .batchID = batchID},
5229 .txType =
"Payment",
5230 .result =
"tesSUCCESS",
5232 .batchID = batchID},
5236 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
5237 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5238 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
5239 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
5242 BEAST_EXPECT(env.
balance(carol) == preCarol);
5249 Env env{*
this, features};
5251 auto const alice =
Account(
"alice");
5252 auto const bob =
Account(
"bob");
5253 auto const gw =
Account(
"gw");
5254 auto const usd = gw[
"USD"];
5255 env.
fund(
XRP(10000), alice, bob, gw);
5261 auto const preAlice = env.
balance(alice);
5262 auto const preBob = env.
balance(bob);
5265 auto const seq = env.
seq(alice);
5269 tx[sfDomain.jsonName] =
strHex(domain);
5270 tx[jss::Delegate] = bob.human();
5285 .result =
"tesSUCCESS",
5287 .batchID = std::nullopt},
5289 .txType =
"AccountSet",
5290 .result =
"tesSUCCESS",
5292 .batchID = batchID},
5294 .txType =
"Payment",
5295 .result =
"tesSUCCESS",
5297 .batchID = batchID},
5302 BEAST_EXPECT(env.
seq(alice) == seq + 3);
5305 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(2) - batchFee);
5306 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(2));
5313 Env env{*
this, features};
5316 env.
fund(
XRP(100000), alice, bob);
5320 MPTTester mpt(env, alice, {.fund =
false});
5322 mpt.create({.flags = tfMPTCanLock});
5326 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
5329 auto const seq = env.
seq(alice);
5333 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
5334 jv1[sfAccount] = alice.
human();
5335 jv1[sfDelegate] = bob.
human();
5336 jv1[sfSequence] = seq + 1;
5337 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
5338 jv1[sfFlags] = tfMPTLock;
5341 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
5342 jv2[sfAccount] = alice.
human();
5343 jv2[sfDelegate] = bob.
human();
5344 jv2[sfSequence] = seq + 2;
5345 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
5346 jv2[sfFlags] = tfMPTUnlock;
5362 .result =
"tesSUCCESS",
5364 .batchID = std::nullopt},
5366 .txType =
"MPTokenIssuanceSet",
5367 .result =
"tesSUCCESS",
5369 .batchID = batchID},
5371 .txType =
"MPTokenIssuanceSet",
5372 .result =
"tesSUCCESS",
5374 .batchID = batchID},
5383 Env env{*
this, features};
5387 env.
fund(
XRP(10000), gw, alice, bob);
5388 env(
fset(gw, asfRequireAuth));
5390 env(
trust(alice, gw[
"USD"](50)));
5393 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
5396 auto const seq = env.
seq(gw);
5399 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetfAuth);
5400 jv1[sfDelegate] = bob.
human();
5401 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
5402 jv2[sfDelegate] = bob.
human();
5418 .result =
"tesSUCCESS",
5420 .batchID = std::nullopt},
5422 .txType =
"TrustSet",
5423 .result =
"tesSUCCESS",
5425 .batchID = batchID},
5427 .txType =
"TrustSet",
5428 .result =
"tesSUCCESS",
5430 .batchID = batchID},
5437 Env env{*
this, features};
5441 env.
fund(
XRP(10000), gw, alice, bob);
5442 env(
fset(gw, asfRequireAuth));
5444 env(
trust(alice, gw[
"USD"](50)));
5447 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
5450 auto const seq = env.
seq(gw);
5453 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
5454 jv1[sfDelegate] = bob.
human();
5455 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfClearFreeze);
5456 jv2[sfDelegate] = bob.
human();
5473 .result =
"tesSUCCESS",
5475 .batchID = std::nullopt},
5477 .txType =
"TrustSet",
5478 .result =
"tesSUCCESS",
5480 .batchID = batchID},
5486 BEAST_EXPECT(env.
rpc(
"tx", txIDs[1])[jss::result][jss::error] ==
"txnNotFound");
5498 using namespace jtx;
5499 Env env(*
this, features);
5502 env.
fund(
XRP(10000), alice, bob);
5507 auto const baseFee = env.
current()->fees().base;
5508 auto const aliceSeq = env.
seq(alice);
5513 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5516 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5517 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
5518 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5519 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
5520 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5521 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5522 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5527 auto const baseFee = env.
current()->fees().base;
5528 auto const aliceSeq = env.
seq(alice);
5529 env(
fset(bob, asfRequireDest));
5534 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5537 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5538 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
5539 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5540 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
5541 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5542 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5543 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5548 auto const baseFee = env.
current()->fees().base;
5549 auto const aliceSeq = env.
seq(alice);
5554 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5557 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5558 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq);
5559 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5560 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
5561 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5562 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5563 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5570 using namespace jtx;
5571 Env env(*
this, features);
5575 env.
fund(
XRP(10000), alice, bob, carol);
5587 auto const seq = env.
seq(alice);
5593 BEAST_EXPECT(
jtx.stx ==
nullptr);
5599 auto const seq = env.
seq(alice);
5614 BEAST_EXPECT(
jtx.stx ==
nullptr);
5619 auto const seq = env.
seq(alice);
5629 BEAST_EXPECT(txBaseFee == env.
current()->fees().base);
5634 auto const seq = env.
seq(alice);
5641 BEAST_EXPECT(txBaseFee == batchFee);
5648 testcase(
"standalone tx with tfInnerBatchTxn rejected");
5657 Env env{*
this, features};
5659 auto const alice =
Account(
"alice");
5660 auto const bob =
Account(
"bob");
5661 env.
fund(
XRP(10000), alice, bob);
5675 STTx const stx =
STTx(ttPAYMENT, [&](
auto& obj) {
5676 obj.setAccountID(sfAccount, alice.id());
5677 obj.setAccountID(sfDestination, bob.id());
5678 obj.setFieldAmount(sfAmount,
XRP(1));
5679 obj.setFieldAmount(sfFee,
XRP(0));
5680 obj.setFieldU32(sfSequence, env.
seq(alice));
5686 BEAST_EXPECT(!result.applied);
5702 Env env{*
this, features};
5704 auto const alice =
Account(
"alice");
5705 auto const bob =
Account(
"bob");
5706 auto const carol =
Account(
"carol");
5707 auto const eve =
Account(
"eve");
5708 env.
fund(
XRP(10000), alice, bob, carol, eve);
5711 auto const preCarol = env.
balance(carol);
5712 auto const bobSeq = env.
seq(bob);
5713 auto const carolSeq = env.
seq(carol);
5715 auto const aliceSeq = env.
seq(alice);
5723 auto const capturedSigners = jt1.
jv[sfBatchSigners.jsonName];
5727 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5728 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5736 jt2.
jv[sfBatchSigners.jsonName] = capturedSigners;
5740 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5741 BEAST_EXPECT(env.
balance(carol) == preCarol);
5747 Env env{*
this, features};
5749 auto const alice =
Account(
"alice");
5750 auto const bob =
Account(
"bob");
5751 auto const carol =
Account(
"carol");
5752 env.
fund(
XRP(10000), alice, bob, carol);
5755 auto const preCarol = env.
balance(carol);
5756 auto const bobSeq = env.
seq(bob);
5757 auto const carolSeq = env.
seq(carol);
5759 auto const aliceSeq1 = env.
seq(alice);
5767 auto const capturedSigners = jt1.
jv[sfBatchSigners.jsonName];
5771 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5772 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5780 jt2.
jv[sfBatchSigners.jsonName] = capturedSigners;
5784 BEAST_EXPECT(env.
balance(carol) == preCarol);
5785 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5791 Env env{*
this, features};
5793 auto const alice =
Account(
"alice");
5794 auto const bob =
Account(
"bob");
5795 auto const carol =
Account(
"carol");
5796 auto const dave =
Account(
"dave");
5797 auto const elsa =
Account(
"elsa");
5798 env.
fund(
XRP(10000), alice, bob, carol, dave, elsa);
5801 env(
signers(bob, 2, {{dave, 1}, {elsa, 1}}));
5803 env(
signers(carol, 2, {{dave, 1}, {elsa, 1}}));
5806 auto const seq = env.
seq(alice);
5815 auto const bobSignerEntry = jt1.
jv[sfBatchSigners.jsonName][0u];
5820 auto const seq2 = env.
seq(alice);
5828 carolSigner[sfBatchSigner.jsonName][jss::Account] = carol.human();
5829 carolSigner[sfBatchSigner.jsonName][jss::SigningPubKey] =
"";
5830 carolSigner[sfBatchSigner.jsonName][sfSigners.jsonName] =
5831 bobSignerEntry[sfBatchSigner.jsonName][sfSigners.jsonName];
5833 jt2.jv[sfBatchSigners.jsonName][0u] = carolSigner;
5842 testcase(
"unsorted batch signers");
5846 Env env{*
this, features};
5848 auto const alice =
Account(
"alice");
5849 auto const bob =
Account(
"bob");
5850 auto const carol =
Account(
"carol");
5851 env.
fund(
XRP(10000), alice, bob, carol);
5854 auto const seq = env.
seq(alice);
5855 auto const bobSeq = env.
seq(bob);
5856 auto const carolSeq = env.
seq(carol);
5865 auto const s0 = jt.
jv[sfBatchSigners.jsonName][0u];
5866 auto const s1 = jt.jv[sfBatchSigners.jsonName][1u];
5867 jt.jv[sfBatchSigners.jsonName][0u] = s1;
5868 jt.jv[sfBatchSigners.jsonName][1u] = s0;
5877 testcase(
"batch signature caching");
5887 auto buildValidBatch = [](
Env& env) {
5888 auto const alice =
Account(
"alice");
5889 auto const bob =
Account(
"bob");
5890 auto const seq = env.seq(alice);
5901 Env env{*
this, features};
5905 auto jt = buildValidBatch(env);
5906 auto const txid = jt.stx->getTransactionID();
5917 Env env{*
this, features};
5921 auto jt = buildValidBatch(env);
5922 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
5929 Env env{*
this, features};
5933 auto jt = buildValidBatch(env);
5934 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
A generic endpoint for log messages.
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
Lightweight wrapper to tag static string.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
bool setFlags(UInt256 const &key, HashRouterFlags flags)
Set the flags on a hash.
HashRouterFlags getFlags(UInt256 const &key)
virtual void submitTransaction(std::shared_ptr< STTx const > const &)=0
virtual void processTransaction(std::shared_ptr< Transaction > &transaction, bool bUnlimited, bool bLocal, FailHard failType)=0
Process transactions as they arrive from the network or which are submitted by clients.
bool modify(ModifyType const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
UInt256 getTransactionID() const
json::Value getJson(JsonOptions options) const override
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Slice slice() const noexcept
virtual NetworkOPs & getOPs()=0
virtual OpenLedger & getOpenLedger()=0
virtual HashRouter & getHashRouter()=0
An immutable linear range of bytes.
static NotTEC invokePreflight(PreflightContext const &ctx)
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
void testOpenLedger(FeatureBitset features)
void testLendingAmendment(FeatureBitset features)
void testBatchDelegateConsent(FeatureBitset features)
void testTicketsOpenLedger(FeatureBitset features)
static json::Value getLastLedger(jtx::Env &env)
void run() override
Runs the suite.
void testBadRawTxn(FeatureBitset features)
void testObjectsOpenLedger(FeatureBitset features)
void testStandaloneInnerBatchFlag(FeatureBitset features)
void testSequenceOpenLedger(FeatureBitset features)
void testEnable(FeatureBitset features)
void testPreflight(FeatureBitset features)
void testObjectCreate3rdParty(FeatureBitset features)
static UInt256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
void testIndependent(FeatureBitset features)
void doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
void testBatchDelegate(FeatureBitset features)
void testBadSequence(FeatureBitset features)
void testTickets(FeatureBitset features)
void testAccountSet(FeatureBitset features)
std::pair< std::vector< std::string >, std::string > submitBatch(jtx::Env &env, TER const &result, Args &&... args)
void testPreclaim(FeatureBitset features)
void testBatchTxQueue(FeatureBitset features)
static auto openLedgerFee(jtx::Env &env, XRPAmount const &batchFee)
void testAllOrNothing(FeatureBitset features)
void testCheckAllSignatures(FeatureBitset features)
void testValidateRPCResponse(FeatureBitset features)
void testWithFeats(FeatureBitset features)
void testBatchCalculateBaseFee(FeatureBitset features)
void testLoan(FeatureBitset features)
void testOuterBinding(FeatureBitset features)
void testBatchNetworkOps(FeatureBitset features)
static json::Value getTxByIndex(json::Value const &jrr, int const index)
void testObjectCreateTicket(FeatureBitset features)
void testInnerSubmitRPC(FeatureBitset features)
void validateClosedLedger(jtx::Env &env, std::vector< TestLedgerData > const &ledgerResults)
void testCalculateBaseFee(FeatureBitset features)
void testAccountActivation(FeatureBitset features)
void testUntilFailure(FeatureBitset features)
void testObjectCreateSequence(FeatureBitset features)
void testOnlyOne(FeatureBitset features)
static std::unique_ptr< Config > makeSmallQueueConfig(std::map< std::string, std::string > extraTxQ={}, std::map< std::string, std::string > extraVoting={})
void testAccountDelete(FeatureBitset features)
void testUnsortedBatchSigners(FeatureBitset features)
void testPseudoTxn(FeatureBitset features)
void testBadOuterFee(FeatureBitset features)
void testBatchSigCache(FeatureBitset features)
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
SLE::const_pointer le(Account const &account) const
Return an account root.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
ParseFailureGuard getParseFailureGuard(bool b)
Gets an RAII guard to set and restore the parse failure flag.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
JTx jtnofill(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
void memoize(Account const &account)
Associate AccountID with account.
beast::Journal const journal
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
Set a multisignature on a JTx.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Adds an inner Batch transaction to a JTx and autofills it.
Sets a nested multi-signature for a Batch transaction on a JTx.
Sets the Batch transaction signers on a JTx.
Set a ticket sequence on a JTx.
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet check(AccountID const &id, SeqProxy const &seq) noexcept
A Check.
Keylet loanBroker(AccountID const &owner, SeqProxy const &seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet loan(UInt256 const &loanBrokerID, SeqProxy const &loanSeq) noexcept
void validateInnerTxn(Env &env, std::string const &batchID, std::string const &txHash, std::string const &txType, std::string const &result, std::source_location const &loc=std::source_location::current())
Expect an inner Batch transaction to be recorded with the given type and result, and with ParentBatch...
json::Value outer(jtx::Account const &account, uint32_t seq, STAmount const &fee, std::uint32_t flags)
Build an outer Batch transaction JSON object.
XRPAmount calcBatchFee(jtx::Env const &env, uint32_t const &numSigners, uint32_t const &txns=0)
Calculate the expected outer Batch transaction fee.
json::Value cash(jtx::Account const &dest, UInt256 const &checkId, STAmount const &amount)
Cash a check requiring that a specific amount be delivered.
json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
Deposit preauthorize operations.
json::Value coverDeposit(AccountID const &account, UInt256 const &brokerID, STAmount const &amount, uint32_t flags)
json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
void checkMetrics(Suite &test, jtx::Env &env, std::size_t expectedCount, std::optional< std::size_t > expectedMaxCount, std::size_t expectedInLedger, std::size_t expectedPerLedger, std::uint64_t expectedMinFeeLevel=kBaseFeeLevel.fee(), std::uint64_t expectedMedFeeLevel=kMinEscalationFeeLevel.fee(), std::source_location const location=std::source_location::current())
FeatureBitset testableAmendments()
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
void incLgrSeqForAccDel(jtx::Env &env, jtx::Account const &acc, std::uint32_t margin=0)
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
constexpr FlagValue tfInnerBatchTxn
constexpr std::size_t kMaxBatchSigners
The maximum number of batch signers.
@ SigBad
Signature is bad.
ApplyResult apply(ServiceRegistry ®istry, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
std::string strHex(FwdIt begin, FwdIt end)
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules)
Checks transaction signature and local checks.
constexpr TenthBips32 percentageToTenthBips(std::uint32_t percentage)
constexpr std::size_t kMaxBatchTxCount
The maximum number of transactions that can be in a batch.
constexpr HashRouterFlags kSfSiggood
UInt256 TxID
A transaction identifier.
XRPAmount toDrops(FeeLevel< T > const &level, XRPAmount baseFee)
TenthBips< std::uint32_t > TenthBips32
TenthBips< std::uint16_t > TenthBips16
std::string to_string(BaseUInt< Bits, Tag > const &a)
bool passesLocalChecks(STTx const &tx, std::string &)
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
MPTID makeMptID(std::uint32_t const sequence, AccountID const &account)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
TERSubset< CanCvtToTER > TER
std::vector< unsigned char > Blob
Storage for linear binary data.
void serializeBatch(Serializer &msg, AccountID const &outerAccount, std::uint32_t outerSeqValue, std::uint32_t const &flags, std::vector< UInt256 > const &txids)
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
constexpr bool any(HashRouterFlags flags)
static constexpr auto kMinLedgersToComputeSizeLimit
static constexpr auto kRetrySequencePercent
static constexpr auto kMaxLedgerCountsToStore
static constexpr auto kMinimumQueueSize
static constexpr auto kNormalConsensusIncreasePercent
static constexpr auto kLedgersInQueue
static constexpr auto kMinimumTxnInLedgerStandalone
State information when preflighting a tx.
static constexpr auto kTransactionQueue
std::optional< std::string > batchID
Execution context for applying a JSON transaction.
std::shared_ptr< STTx const > stx
Set the sequence number on a JTx.