xrpld
Loading...
Searching...
No Matches
TestHelpers.cpp
1#include <test/jtx/TestHelpers.h>
2
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/balance.h> // IWYU pragma: keep
7#include <test/jtx/envconfig.h>
8#include <test/jtx/mpt.h>
9#include <test/jtx/offer.h>
10#include <test/jtx/owners.h>
11#include <test/jtx/rate.h>
12#include <test/jtx/trust.h>
13
14#include <xrpld/core/Config.h>
15#include <xrpld/rpc/RPCHandler.h>
16#include <xrpld/rpc/Role.h>
17
18#include <xrpl/basics/Number.h>
19#include <xrpl/basics/Slice.h>
20#include <xrpl/basics/base_uint.h>
21#include <xrpl/basics/chrono.h>
22#include <xrpl/basics/contract.h>
23#include <xrpl/basics/strHex.h>
24#include <xrpl/beast/unit_test/suite.h>
25#include <xrpl/beast/utility/instrumentation.h>
26#include <xrpl/core/Job.h>
27#include <xrpl/core/ServiceRegistry.h>
28#include <xrpl/json/json_value.h>
29#include <xrpl/json/to_string.h>
30#include <xrpl/ledger/ReadView.h>
31#include <xrpl/ledger/helpers/DirectoryHelpers.h>
32#include <xrpl/protocol/AccountID.h>
33#include <xrpl/protocol/ApiVersion.h>
34#include <xrpl/protocol/Book.h>
35#include <xrpl/protocol/Indexes.h>
36#include <xrpl/protocol/Issue.h>
37#include <xrpl/protocol/LedgerFormats.h>
38#include <xrpl/protocol/MPTIssue.h>
39#include <xrpl/protocol/PathAsset.h>
40#include <xrpl/protocol/PublicKey.h>
41#include <xrpl/protocol/Quality.h>
42#include <xrpl/protocol/SField.h>
43#include <xrpl/protocol/STAmount.h>
44#include <xrpl/protocol/STParsedJSON.h>
45#include <xrpl/protocol/STPathSet.h>
46#include <xrpl/protocol/SeqProxy.h>
47#include <xrpl/protocol/UintTypes.h>
48#include <xrpl/protocol/XRPAmount.h>
49#include <xrpl/protocol/jss.h>
50#include <xrpl/resource/Charge.h>
51#include <xrpl/resource/Consumer.h>
52#include <xrpl/resource/Fees.h>
53#include <xrpl/tx/paths/detail/Steps.h>
54
55#include <algorithm>
56#include <chrono>
57#include <cstddef>
58#include <cstdint>
59#include <memory>
60#include <optional>
61#include <stdexcept>
62#include <tuple>
63#include <utility>
64#include <variant>
65#include <vector>
66
67namespace xrpl::test::jtx {
68
69// Functions used in debugging
70json::Value
71getAccountOffers(Env& env, AccountID const& acct, bool current)
72{
73 json::Value jv;
74 jv[jss::account] = to_string(acct);
75 return env.rpc("json", "account_offers", to_string(jv))[jss::result];
76}
77
79getAccountLines(Env& env, AccountID const& acctId)
80{
81 json::Value jv;
82 jv[jss::account] = to_string(acctId);
83 return env.rpc("json", "account_lines", to_string(jv))[jss::result];
84}
85
86bool
87checkArraySize(json::Value const& val, unsigned int size)
88{
89 return val.isArray() && val.size() == size;
90}
91
93ownerCount(Env const& env, Account const& account)
94{
95 return env.ownerCount(account);
96}
97
99sponsoredOwnerCount(Env const& env, Account const& account)
100{
101 return env.sponsoredOwnerCount(account);
102}
103
105sponsoringOwnerCount(Env const& env, Account const& account)
106{
107 return env.sponsoringOwnerCount(account);
108}
109
111sponsoringAccountCount(Env const& env, Account const& account)
112{
113 return env.sponsoringAccountCount(account);
114}
115
116/* Path finding */
117/******************************************************************************/
118void
119stpathAppendOne(STPath& st, Account const& account)
120{
121 st.pushBack(STPathElement({account.id(), std::nullopt, std::nullopt}));
122}
123
124void
126{
127 st.pushBack(pe);
128}
129
130bool
131equal(STAmount const& sa1, STAmount const& sa2)
132{
133 return sa1 == sa2 && sa1.getIssuer() == sa2.getIssuer();
134}
135
136static void
138 json::Value& jv,
139 PathAsset const& srcAsset,
140 std::optional<AccountID> const& srcIssuer)
141{
143 [&]<typename TAsset>(TAsset const& asset) {
145 {
146 jv[jss::currency] = to_string(asset);
147 if (srcIssuer)
148 jv[jss::issuer] = to_string(*srcIssuer);
149 }
150 else
151 {
152 if (srcIssuer)
153 Throw<std::runtime_error>("MPT source_currencies can't have issuer");
154 jv[jss::mpt_issuance_id] = to_string(asset);
155 }
156 },
157 srcAsset.value());
158}
159
161rpf(jtx::Account const& src,
162 jtx::Account const& dst,
163 STAmount const& dstAmount,
164 std::optional<STAmount> const& sendMax,
165 std::optional<PathAsset> const& srcAsset,
166 std::optional<AccountID> const& srcIssuer)
167{
169 jv[jss::command] = "ripple_path_find";
170 jv[jss::source_account] = toBase58(src);
171 jv[jss::destination_account] = toBase58(dst);
172 jv[jss::destination_amount] = dstAmount.getJson(JsonOptions::Values::None);
173 if (sendMax)
174 jv[jss::send_max] = sendMax->getJson(JsonOptions::Values::None);
175 if (srcAsset)
176 {
177 auto& sc = jv[jss::source_currencies] = json::ValueType::Array;
179 addSourceAsset(j, *srcAsset, srcIssuer);
180 sc.append(j);
181 }
182
183 return jv;
184}
185
188{
189 // These tests were originally written with search parameters that are
190 // different from the current defaults. This function creates an env
191 // with the search parameters that the tests were written for.
192 using namespace jtx;
193 return Env(suite, envconfig([](std::unique_ptr<Config> cfg) {
194 cfg->pathSearchOld = 7;
195 cfg->pathSearch = 7;
196 cfg->pathSearchMax = 10;
197 return cfg;
198 }));
199}
200
203 jtx::Env& env,
204 jtx::Account const& src,
205 jtx::Account const& dst,
206 STAmount const& saDstAmount,
207 std::optional<STAmount> const& saSendMax,
208 std::optional<PathAsset> const& srcAsset,
209 std::optional<AccountID> const& srcIssuer,
210 std::optional<uint256> const& domain)
211{
212 using namespace jtx;
213
214 auto& app = env.app();
217
218 rpc::JsonContext context{
219 {.j = env.journal,
220 .app = app,
221 .loadType = loadType,
222 .netOps = app.getOPs(),
223 .ledgerMaster = app.getLedgerMaster(),
224 .consumer = c,
225 .role = Role::USER,
226 .coro = {},
227 .infoSub = {},
228 .apiVersion = rpc::kApiVersionIfUnspecified},
229 {},
230 {}};
231
233 params[jss::command] = "ripple_path_find";
234 params[jss::source_account] = toBase58(src);
235 params[jss::destination_account] = toBase58(dst);
236 params[jss::destination_amount] = saDstAmount.getJson(JsonOptions::Values::None);
237 if (saSendMax)
238 params[jss::send_max] = saSendMax->getJson(JsonOptions::Values::None);
239
240 if (srcAsset)
241 {
242 auto& sc = params[jss::source_currencies] = json::ValueType::Array;
244 addSourceAsset(j, *srcAsset, srcIssuer);
245 sc.append(j);
246 }
247
248 if (domain)
249 params[jss::domain] = to_string(*domain);
250
251 json::Value result;
252 Gate g;
253 app.getJobQueue().postCoro(JtClient, "RPC-Client", [&](auto const& coro) {
254 context.params = std::move(params);
255 context.coro = coro;
256 rpc::doCommand(context, result);
257 g.signal();
258 });
259
260 using namespace std::chrono_literals;
261 using namespace beast::unit_test;
262 g.waitFor(5s);
263 return result;
264}
265
268 jtx::Env& env,
269 jtx::Account const& src,
270 jtx::Account const& dst,
271 STAmount const& saDstAmount,
272 std::optional<STAmount> const& saSendMax,
273 std::optional<PathAsset> const& srcAsset,
274 std::optional<AccountID> const& srcIssuer,
275 std::optional<uint256> const& domain)
276{
277 json::Value result =
278 findPathsRequest(env, src, dst, saDstAmount, saSendMax, srcAsset, srcIssuer, domain);
279 if (result.isMember(jss::error))
281
282 STAmount da;
283 if (result.isMember(jss::destination_amount))
284 da = amountFromJson(sfGeneric, result[jss::destination_amount]);
285
286 STAmount sa;
287 STPathSet paths;
288 if (result.isMember(jss::alternatives))
289 {
290 auto const& alts = result[jss::alternatives];
291 if (alts.size() > 0)
292 {
293 auto const& path = alts[0u];
294
295 if (path.isMember(jss::source_amount))
296 sa = amountFromJson(sfGeneric, path[jss::source_amount]);
297
298 if (path.isMember(jss::destination_amount))
299 da = amountFromJson(sfGeneric, path[jss::destination_amount]);
300
301 if (path.isMember(jss::paths_computed))
302 {
303 json::Value p;
304 p["Paths"] = path[jss::paths_computed];
305 STParsedJSONObject po("generic", p);
306 if (po.object)
307 paths = po.object->getFieldPathSet(sfPaths);
308 }
309 }
310 }
311
312 return std::make_tuple(std::move(paths), std::move(sa), std::move(da));
313}
314
317 jtx::Env& env,
318 jtx::Account const& src,
319 jtx::Account const& dst,
320 STAmount const& saDstAmount,
321 std::optional<STAmount> const& saSendMax,
322 std::optional<STPathElement> const& srcElement,
323 std::optional<AccountID> const& srcIssuer,
324 std::optional<uint256> const& domain)
325{
326 // srcElement is optional but is expected to always be present
327 XRPL_ASSERT(
328 srcElement.has_value(), "xrpl::test::jtx::findPathsByElement::srcElement : nullptr");
329
330 return findPaths(
331 env,
332 src,
333 dst,
334 saDstAmount,
335 saSendMax,
336 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
337 srcElement->getPathAsset(),
338 srcIssuer,
339 domain);
340}
341
342/******************************************************************************/
343
345txFee(Env const& env, std::uint16_t n)
346{
347 return env.current()->fees().base * n;
348}
349
351xrpMinusFee(Env const& env, std::int64_t xrpAmount)
352{
353 auto feeDrops = env.current()->fees().base;
354 return drops(kJtxDropsPerXrp * xrpAmount - feeDrops);
355};
356
357[[nodiscard]] bool
358expectHolding(Env& env, AccountID const& account, STAmount const& value, bool defaultLimits)
359{
360 if (auto const sle = env.le(keylet::trustLine(account, value.get<Issue>())))
361 {
362 Issue const issue = value.get<Issue>();
363 bool const accountLow = account < issue.account;
364
365 bool expectDefaultTrustLine = true;
366 if (defaultLimits)
367 {
368 STAmount low{issue};
369 STAmount high{issue};
370
371 low.get<Issue>().account = accountLow ? account : issue.account;
372 high.get<Issue>().account = accountLow ? issue.account : account;
373
374 expectDefaultTrustLine =
375 sle->getFieldAmount(sfLowLimit) == low && sle->getFieldAmount(sfHighLimit) == high;
376 }
377
378 auto amount = sle->getFieldAmount(sfBalance);
379 amount.get<Issue>().account = value.getIssuer();
380 if (!accountLow)
381 amount.negate();
382 return amount == value && expectDefaultTrustLine;
383 }
384 return false;
385}
386
387[[nodiscard]] bool
388expectHolding(Env& env, AccountID const& account, None const&, Issue const& issue)
389{
390 return !env.le(keylet::trustLine(account, issue));
391}
392
393[[nodiscard]] bool
394expectHolding(Env& env, AccountID const& account, None const&, MPTIssue const& mptIssue)
395{
396 return !env.le(keylet::mptoken(mptIssue.getMptID(), account));
397}
398
399[[nodiscard]] bool
400expectHolding(Env& env, AccountID const& account, None const& value)
401{
402 return std::visit(
403 [&](auto const& issue) { return expectHolding(env, account, value, issue); },
404 value.asset.value());
405}
406
407[[nodiscard]] bool
408expectMPT(Env& env, AccountID const& account, STAmount const& value)
409{
410 auto const mptIssuanceID = keylet::mptokenIssuance(value.asset().get<MPTIssue>());
411 auto const mptToken = env.le(keylet::mptoken(mptIssuanceID.key, account));
412 return mptToken && (*mptToken)[sfMPTAmount] == value.mpt().value();
413}
414
415[[nodiscard]] bool
417 Env& env,
418 AccountID const& account,
419 std::uint16_t size,
420 std::vector<Amounts> const& toMatch)
421{
422 std::uint16_t cnt = 0;
423 std::uint16_t matched = 0;
424 forEachItem(*env.current(), account, [&](SLE::const_ref sle) {
425 if (!sle)
426 return false;
427 if (sle->getType() == ltOFFER)
428 {
429 ++cnt;
430 if (std::ranges::find_if(toMatch, [&](auto const& a) {
431 return a.in == sle->getFieldAmount(sfTakerPays) &&
432 a.out == sle->getFieldAmount(sfTakerGets);
433 }) != toMatch.end())
434 ++matched;
435 }
436 return true;
437 });
438 return size == cnt && ((toMatch.empty() && size != 0) || (matched == toMatch.size()));
439}
440
442ledgerEntryRoot(Env& env, Account const& acct)
443{
444 json::Value jvParams;
445 jvParams[jss::ledger_index] = "current";
446 jvParams[jss::account_root] = acct.human();
447 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
448}
449
451ledgerEntryState(Env& env, Account const& acctA, Account const& acctB, std::string const& currency)
452{
453 json::Value jvParams;
454 jvParams[jss::ledger_index] = "current";
455 jvParams[jss::ripple_state][jss::currency] = currency;
456 jvParams[jss::ripple_state][jss::accounts] = json::ValueType::Array;
457 jvParams[jss::ripple_state][jss::accounts].append(acctA.human());
458 jvParams[jss::ripple_state][jss::accounts].append(acctB.human());
459 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
460}
461
464{
465 json::Value jvParams;
466 jvParams[jss::offer][jss::account] = acct.human();
467 jvParams[jss::offer][jss::seq] = offerSeq;
468 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
469}
470
472ledgerEntryMPT(jtx::Env& env, jtx::Account const& acct, MPTID const& mptID)
473{
474 json::Value jvParams;
475 jvParams[jss::mptoken][jss::account] = acct.human();
476 jvParams[jss::mptoken][jss::mpt_issuance_id] = to_string(mptID);
477 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
478}
479
481getBookOffers(jtx::Env& env, Asset const& takerPays, Asset const& takerGets)
482{
483 json::Value jvbp;
484 jvbp[jss::ledger_index] = "current";
485 takerPays.setJson(jvbp[jss::taker_pays]);
486 takerGets.setJson(jvbp[jss::taker_gets]);
487 return env.rpc("json", "book_offers", to_string(jvbp))[jss::result];
488}
489
491accountBalance(Env& env, Account const& acct)
492{
493 auto const jrr = ledgerEntryRoot(env, acct);
494 return jrr[jss::node][sfBalance.fieldName];
495}
496
497[[nodiscard]] bool
498expectLedgerEntryRoot(Env& env, Account const& acct, STAmount const& expectedValue)
499{
500 return accountBalance(env, acct) == to_string(expectedValue.xrp());
501}
502
503/* Payment Channel */
504/******************************************************************************/
505namespace paychan {
506
509 AccountID const& account,
510 AccountID const& to,
511 STAmount const& amount,
512 NetClock::duration const& settleDelay,
513 PublicKey const& pk,
514 std::optional<NetClock::time_point> const& cancelAfter,
515 std::optional<std::uint32_t> const& dstTag)
516{
517 json::Value jv;
518 jv[jss::TransactionType] = jss::PaymentChannelCreate;
519 jv[jss::Account] = to_string(account);
520 jv[jss::Destination] = to_string(to);
521 jv[jss::Amount] = amount.getJson(JsonOptions::Values::None);
522 jv[jss::SettleDelay] = settleDelay.count();
523 jv[sfPublicKey.fieldName] = strHex(pk.slice());
524 if (cancelAfter)
525 jv[sfCancelAfter.fieldName] = cancelAfter->time_since_epoch().count();
526 if (dstTag)
527 jv[sfDestinationTag.fieldName] = *dstTag;
528 return jv;
529}
530
533 AccountID const& account,
534 uint256 const& channel,
535 STAmount const& amount,
536 std::optional<NetClock::time_point> const& expiration)
537{
538 json::Value jv;
539 jv[jss::TransactionType] = jss::PaymentChannelFund;
540 jv[jss::Account] = to_string(account);
541 jv[sfChannel.fieldName] = to_string(channel);
542 jv[jss::Amount] = amount.getJson(JsonOptions::Values::None);
543 if (expiration)
544 jv[sfExpiration.fieldName] = expiration->time_since_epoch().count();
545 return jv;
546}
547
550 AccountID const& account,
551 uint256 const& channel,
552 std::optional<STAmount> const& balance,
553 std::optional<STAmount> const& amount,
554 std::optional<Slice> const& signature,
555 std::optional<PublicKey> const& pk)
556{
557 json::Value jv;
558 jv[jss::TransactionType] = jss::PaymentChannelClaim;
559 jv[jss::Account] = to_string(account);
560 jv["Channel"] = to_string(channel);
561 if (amount)
562 jv[jss::Amount] = amount->getJson(JsonOptions::Values::None);
563 if (balance)
564 jv["Balance"] = balance->getJson(JsonOptions::Values::None);
565 if (signature)
566 jv["Signature"] = strHex(*signature);
567 if (pk)
568 jv["PublicKey"] = strHex(pk->slice());
569 return jv;
570}
571
573channel(AccountID const& account, AccountID const& dst, std::uint32_t seqProxyValue)
574{
575 auto const seqProxy = SeqProxy::rawSequence(seqProxyValue);
576 auto const k = keylet::payChannel(account, dst, seqProxy);
577 return k.key;
578}
579
581channelBalance(ReadView const& view, uint256 const& chan)
582{
583 auto const slep = view.read({ltPAYCHAN, chan});
584 if (!slep)
585 return XRPAmount{-1};
586 return (*slep)[sfBalance];
587}
588
589bool
590channelExists(ReadView const& view, uint256 const& chan)
591{
592 auto const slep = view.read({ltPAYCHAN, chan});
593 return bool(slep);
594}
595
596} // namespace paychan
597
598/* Crossing Limits */
599/******************************************************************************/
600
601void
602nOffers(Env& env, std::size_t n, Account const& account, STAmount const& in, STAmount const& out)
603{
604 auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount);
605 for (std::size_t i = 0; i < n; i++)
606 {
607 env(offer(account, in, out));
608 env.close();
609 }
610 env.require(Owners(account, ownerCount + n));
611}
612
613/* Pay Strand */
614/***************************************************************/
615
616// Currency path element
618cpe(PathAsset const& pa)
619{
620 return pa.visit(
621 [](Currency const& currency) {
623 },
624 [](MPTID const& mpt) {
626 });
627};
628
629// All path element
631allPathElements(AccountID const& a, Asset const& asset)
632{
633 return STPathElement(a, asset, asset.getIssuer());
634};
635
637ipe(Asset const& asset)
638{
639 return asset.visit(
640 [](Issue const& issue) {
641 return STPathElement(
643 xrpAccount(),
644 issue.currency,
645 issue.account);
646 },
647 [](MPTIssue const& issue) {
648 return STPathElement(
650 xrpAccount(),
651 issue.getMptID(),
652 issue.getIssuer());
653 });
654};
655
656// Issuer path element
658iape(AccountID const& account)
659{
661};
662
663// Account path element
669
670bool
672{
673 if (!s1)
674 return false;
675 return test::directStepEqual(*s1, dsi.src, dsi.dst, dsi.currency);
676}
677
678bool
680{
681 if (!s1)
682 return false;
683 return test::mptEndpointStepEqual(*s1, dsi.src, dsi.dst, dsi.mptid);
684}
685
686bool
688{
689 if (!s1)
690 return false;
691 return test::xrpEndpointStepEqual(*s1, xrpStepInfo.acc);
692}
693
694bool
696{
697 if (!s1)
698 return false;
699 return bookStepEqual(*s1, bsi);
700}
701
702namespace detail {
703
704IOU
706{
707 auto const iou = args.issuer[args.token];
708 if (args.transferFee != 0)
709 {
710 auto const tfee = 1. + (static_cast<double>(args.transferFee) / 100'000);
711 args.env(rate(args.issuer, tfee));
712 }
713 for (auto const& account : args.holders)
714 {
715 args.env(trust(account, iou(args.limit.value_or(1'000))));
716 }
717 return iou;
718}
719
720MPT
722{
723 using namespace jtx;
724 if (args.limit)
725 {
726 MPT const mpt = MPTTester(
727 {.env = args.env,
728 .issuer = args.issuer,
729 .holders = args.holders,
730 .transferFee = args.transferFee,
731 .maxAmt = args.limit});
732 return mpt;
733 }
734
735 MPT const mpt = MPTTester(
736 {.env = args.env,
737 .issuer = args.issuer,
738 .holders = args.holders,
739 .transferFee = args.transferFee});
740 return mpt;
741}
742
743} // namespace detail
744
745/* LoanBroker */
746/******************************************************************************/
747
748namespace loan_broker {
749
751set(AccountID const& account, uint256 const& vaultId, uint32_t flags)
752{
753 json::Value jv;
754 jv[sfTransactionType] = jss::LoanBrokerSet;
755 jv[sfAccount] = to_string(account);
756 jv[sfVaultID] = to_string(vaultId);
757 jv[sfFlags] = flags;
758 return jv;
759}
760
762del(AccountID const& account, uint256 const& brokerID, uint32_t flags)
763{
764 json::Value jv;
765 jv[sfTransactionType] = jss::LoanBrokerDelete;
766 jv[sfAccount] = to_string(account);
767 jv[sfLoanBrokerID] = to_string(brokerID);
768 jv[sfFlags] = flags;
769 return jv;
770}
771
774 AccountID const& account,
775 uint256 const& brokerID,
776 STAmount const& amount,
777 uint32_t flags)
778{
779 json::Value jv;
780 jv[sfTransactionType] = jss::LoanBrokerCoverDeposit;
781 jv[sfAccount] = to_string(account);
782 jv[sfLoanBrokerID] = to_string(brokerID);
783 jv[sfAmount] = amount.getJson(JsonOptions::Values::None);
784 jv[sfFlags] = flags;
785 return jv;
786}
787
790 AccountID const& account,
791 uint256 const& brokerID,
792 STAmount const& amount,
793 uint32_t flags)
794{
795 json::Value jv;
796 jv[sfTransactionType] = jss::LoanBrokerCoverWithdraw;
797 jv[sfAccount] = to_string(account);
798 jv[sfLoanBrokerID] = to_string(brokerID);
799 jv[sfAmount] = amount.getJson(JsonOptions::Values::None);
800 jv[sfFlags] = flags;
801 return jv;
802}
803
806{
807 json::Value jv;
808 jv[sfTransactionType] = jss::LoanBrokerCoverClawback;
809 jv[sfAccount] = to_string(account);
810 jv[sfFlags] = flags;
811 return jv;
812}
813
814} // namespace loan_broker
815
816/* Loan */
817/******************************************************************************/
818namespace loan {
819
821set(AccountID const& account,
822 uint256 const& loanBrokerID,
823 Number principalRequested,
824 std::uint32_t flags)
825{
826 json::Value jv;
827 jv[sfTransactionType] = jss::LoanSet;
828 jv[sfAccount] = to_string(account);
829 jv[sfLoanBrokerID] = to_string(loanBrokerID);
830 jv[sfPrincipalRequested] = to_string(principalRequested);
831 jv[sfFlags] = flags;
832 return jv;
833}
834
836manage(AccountID const& account, uint256 const& loanID, std::uint32_t flags)
837{
838 json::Value jv;
839 jv[sfTransactionType] = jss::LoanManage;
840 jv[sfAccount] = to_string(account);
841 jv[sfLoanID] = to_string(loanID);
842 jv[sfFlags] = flags;
843 return jv;
844}
845
847del(AccountID const& account, uint256 const& loanID, std::uint32_t flags)
848{
849 json::Value jv;
850 jv[sfTransactionType] = jss::LoanDelete;
851 jv[sfAccount] = to_string(account);
852 jv[sfLoanID] = to_string(loanID);
853 jv[sfFlags] = flags;
854 return jv;
855}
856
858pay(AccountID const& account, uint256 const& loanID, STAmount const& amount, std::uint32_t flags)
859{
860 json::Value jv;
861 jv[sfTransactionType] = jss::LoanPay;
862 jv[sfAccount] = to_string(account);
863 jv[sfLoanID] = to_string(loanID);
864 jv[sfAmount] = amount.getJson();
865 jv[sfFlags] = flags;
866 return jv;
867}
868
869} // namespace loan
870} // namespace xrpl::test::jtx
A testsuite class.
Definition suite.h:52
Represents a JSON value.
Definition json_value.h:117
bool isArray() const
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
bool isMember(char const *key) const
Return true if the object has a member named key.
void setJson(json::Value &jv) const
Definition Asset.cpp:33
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
Definition Asset.h:117
AccountID const & getIssuer() const
Definition Asset.cpp:21
Specifies an order book.
Definition Book.h:28
A currency issued by an account.
Definition Issue.h:18
Currency currency
Definition Issue.h:20
AccountID account
Definition Issue.h:21
AccountID const & getIssuer() const
Definition Issue.h:30
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:43
std::chrono::duration< rep, period > duration
Definition chrono.h:47
Number is a floating point type that can represent a wide range of values.
Definition Number.h:351
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
Definition PathAsset.h:50
constexpr std::variant< Currency, MPTID > const & value() const
Definition PathAsset.h:91
A public key.
Definition PublicKey.h:53
Slice slice() const noexcept
Definition PublicKey.h:115
A view into a ledger.
Definition ReadView.h:41
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
constexpr TIss const & get() const
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
Definition STAmount.cpp:734
AccountID const & getIssuer() const
Definition STAmount.h:516
XRPAmount xrp() const
Definition STAmount.cpp:271
std::shared_ptr< STLedgerEntry const > const & const_ref
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
void pushBack(STPathElement const &e)
Definition STPathSet.h:451
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:62
A consumption charge.
Definition Charge.h:13
An endpoint that consumes resources.
Definition Consumer.h:20
Immutable cryptographic account descriptor.
Definition jtx/Account.h:21
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
Definition Env.h:161
Application & app()
Definition Env.h:300
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:133
std::uint32_t sponsoringAccountCount(Account const &account) const
Return the number of sponsoring accounts owned by an account.
Definition Env.cpp:293
std::uint32_t sponsoringOwnerCount(Account const &account) const
Return the number of sponsoring objects owned by an account.
Definition Env.cpp:284
SLE::const_pointer le(Account const &account) const
Return an account root.
Definition Env.cpp:311
std::uint32_t ownerCount(Account const &account) const
Return the number of objects owned by an account.
Definition Env.cpp:266
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:1056
std::uint32_t sponsoredOwnerCount(Account const &account) const
Return the number of sponsored objects owned by an account.
Definition Env.cpp:275
beast::Journal const journal
Definition Env.h:204
void require(Args const &... args)
Check a set of requirements.
Definition Env.h:764
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:377
bool waitFor(std::chrono::duration< Rep, Period > const &relTime)
Converts to IOU Issue or STAmount.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
Definition mpt.h:447
Converts to MPT Issue or STAmount.
Match the number of items in the account's owner directory.
Definition owners.h:55
T is_same_v
T make_tuple(T... args)
@ Array
array value (ordered list)
Definition json_value.h:28
@ Object
object value (collection of name/value pairs).
Definition json_value.h:29
Keylet payChannel(AccountID const &src, AccountID const &dst, SeqProxy const &seq) noexcept
A PaymentChannel.
Definition Indexes.cpp:394
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:543
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Definition Indexes.cpp:537
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:253
Charge const kFeeReferenceRpc
static constexpr auto kApiVersionIfUnspecified
Definition ApiVersion.h:44
Status doCommand(rpc::JsonContext &context, json::Value &result)
Execute an RPC command and store the results in a json::Value.
MPT issueHelperMPT(IssuerArgs const &args)
IOU issueHelperIOU(IssuerArgs const &args)
json::Value set(AccountID const &account, uint256 const &vaultId, uint32_t flags)
json::Value coverDeposit(AccountID const &account, uint256 const &brokerID, STAmount const &amount, uint32_t flags)
json::Value coverClawback(AccountID const &account, std::uint32_t flags)
json::Value coverWithdraw(AccountID const &account, uint256 const &brokerID, STAmount const &amount, uint32_t flags)
json::Value del(AccountID const &account, uint256 const &brokerID, uint32_t flags)
json::Value set(AccountID const &account, uint256 const &loanBrokerID, Number principalRequested, std::uint32_t flags)
json::Value manage(AccountID const &account, uint256 const &loanID, std::uint32_t flags)
json::Value del(AccountID const &account, uint256 const &loanID, std::uint32_t flags)
json::Value pay(AccountID const &account, uint256 const &loanID, STAmount const &amount, std::uint32_t flags)
json::Value fund(AccountID const &account, uint256 const &channel, STAmount const &amount, std::optional< NetClock::time_point > const &expiration)
STAmount channelBalance(ReadView const &view, uint256 const &chan)
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)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
json::Value claim(AccountID const &account, uint256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
bool channelExists(ReadView const &view, uint256 const &chan)
void nOffers(Env &env, std::size_t n, Account const &account, STAmount const &in, STAmount const &out)
json::Value findPathsRequest(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax, std::optional< PathAsset > const &srcAsset, std::optional< AccountID > const &srcIssuer, std::optional< uint256 > const &domain)
jtx::Env pathTestEnv(beast::unit_test::Suite &suite)
json::Value ledgerEntryMPT(jtx::Env &env, jtx::Account const &acct, MPTID const &mptID)
bool expectLedgerEntryRoot(Env &env, Account const &acct, STAmount const &expectedValue)
bool expectMPT(Env &env, AccountID const &account, STAmount const &value)
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
STPathElement allPathElements(AccountID const &a, Asset const &asset)
bool expectHolding(Env &env, AccountID const &account, STAmount const &value, bool defaultLimits)
static void addSourceAsset(json::Value &jv, PathAsset const &srcAsset, std::optional< AccountID > const &srcIssuer)
constexpr XRPAmount kJtxDropsPerXrp
json::Value getBookOffers(jtx::Env &env, Asset const &takerPays, Asset const &takerGets)
std::uint32_t sponsoringAccountCount(Env const &env, Account const &account)
std::uint32_t ownerCount(Env const &env, Account const &account)
XRPAmount txFee(Env const &env, std::uint16_t n)
std::tuple< STPathSet, STAmount, STAmount > findPaths(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax, std::optional< PathAsset > const &srcAsset, std::optional< AccountID > const &srcIssuer, std::optional< uint256 > const &domain)
json::Value rpf(jtx::Account const &src, jtx::Account const &dst, STAmount const &dstAmount, std::optional< STAmount > const &sendMax, std::optional< PathAsset > const &srcAsset, std::optional< AccountID > const &srcIssuer)
std::uint32_t sponsoringOwnerCount(Env const &env, Account const &account)
STPathElement cpe(PathAsset const &pa)
std::tuple< STPathSet, STAmount, STAmount > findPathsByElement(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax, std::optional< STPathElement > const &srcElement, std::optional< AccountID > const &srcIssuer, std::optional< uint256 > const &domain)
STPathElement ipe(Asset const &asset)
json::Value ledgerEntryState(Env &env, Account const &acctA, Account const &acctB, std::string const &currency)
bool equal(STAmount const &sa1, STAmount const &sa2)
STPathElement iape(AccountID const &account)
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition offer.cpp:14
std::uint32_t sponsoredOwnerCount(Env const &env, Account const &account)
json::Value ledgerEntryRoot(Env &env, Account const &acct)
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:37
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:18
void stpathAppendOne(STPath &st, Account const &account)
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value accountBalance(Env &env, Account const &acct)
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition rate.cpp:15
json::Value getAccountLines(Env &env, AccountID const &acctId)
bool checkArraySize(json::Value const &val, unsigned int size)
json::Value ledgerEntryOffer(jtx::Env &env, jtx::Account const &acct, std::uint32_t offerSeq)
STPathElement ape(AccountID const &a)
json::Value getAccountOffers(Env &env, AccountID const &acct, bool current)
bool bookStepEqual(Step const &step, xrpl::Book const &book)
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool mptEndpointStepEqual(Step const &step, AccountID const &src, AccountID const &dst, MPTID const &mptid)
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
constexpr XRPAmount
Convert XRP to drops (integral types).
Definition TxTest.h:54
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:13
SField const sfGeneric
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:42
Currency const & xrpCurrency()
XRP currency.
Definition UintTypes.cpp:99
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
@ USER
Definition Role.h:27
@ JtClient
Definition Job.h:31
BaseUInt< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
Definition UintTypes.h:54
STAmount amountFromJson(SField const &name, json::Value const &v)
Definition STAmount.cpp:916
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(SLE::const_ref)> const &f)
Iterate all items in the given directory.
AccountID const & xrpAccount()
Compute AccountID from public key.
BaseUInt< 256 > uint256
Definition base_uint.h:580
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
T has_value(T... args)
std::shared_ptr< JobQueue::Coro > coro
Definition Context.h:35
json::Value params
Definition Context.h:51
std::optional< std::uint64_t > limit
std::vector< jtx::Account > holders
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...
T value_or(T... args)
T visit(T... args)