From d7f3a62db606fed7a7f3e93718eadf196ffe38a0 Mon Sep 17 00:00:00 2001 From: intelliot Date: Fri, 1 Sep 2023 22:54:46 +0000 Subject: [PATCH] deploy: b014b79d88baefe546c3113099581c6c8ee29df6 --- AMMCreate_8cpp_source.html | 182 +- AMMCreate_8h_source.html | 2 +- AMMDelete_8cpp_source.html | 2 +- AMMDeposit_8cpp_source.html | 2 +- AMMExtended__test_8cpp_source.html | 12 +- AMMInfo_8cpp_source.html | 313 +- AMMInfo__test_8cpp_source.html | 334 +- AMMUtils_8cpp_source.html | 238 +- AMMUtils_8h_source.html | 6 +- AMMWithdraw_8cpp_source.html | 2 +- AMM_8cpp_source.html | 1259 +++--- AMM_8h_source.html | 566 +-- AMM__test_8cpp_source.html | 26 +- AcceptedLedgerTx_8cpp_source.html | 2 +- AccountLinesRPC__test_8cpp_source.html | 4 +- AccountObjects__test_8cpp_source.html | 1672 ++++---- CashCheck_8cpp_source.html | 2 +- Clawback_8cpp_source.html | 2 +- CreateOffer_8cpp_source.html | 4 +- DeleteAccount_8cpp_source.html | 12 +- DirectStep_8cpp_source.html | 2 +- InvariantCheck_8cpp_source.html | 2 +- JSONRPC__test_8cpp_source.html | 4 +- LedgerCleaner_8cpp_source.html | 2 +- LedgerFormats_8cpp_source.html | 31 +- LedgerFormats_8h_source.html | 2 +- LedgerMaster_8cpp_source.html | 2 +- LedgerToJson_8cpp_source.html | 2 +- NFTokenAcceptOffer_8cpp_source.html | 2 +- NetworkOPs_8cpp_source.html | 4 +- OfferStream_8cpp_source.html | 4 +- Path__test_8cpp_source.html | 2 +- PaymentSandbox__test_8cpp_source.html | 4 +- RPCHelpers_8cpp_source.html | 2 +- STInteger_8cpp_source.html | 2 +- STLedgerEntry_8cpp_source.html | 2 +- STParsedJSON_8cpp_source.html | 2 +- Taker_8cpp_source.html | 2 +- View_8cpp_source.html | 139 +- View_8h_source.html | 661 ++-- View__test_8cpp_source.html | 4 +- classripple_1_1AMMCreate.html | 2 +- classripple_1_1LedgerFormats.html | 2 +- classripple_1_1test_1_1AMMInfo__test.html | 8 +- ...ipple_1_1test_1_1AccountObjects__test.html | 12 +- ...sripple_1_1test_1_1jtx_1_1AMM-members.html | 4 +- classripple_1_1test_1_1jtx_1_1AMM.html | 116 +- functions.html | 2 +- functions_e.html | 2 +- functions_func.html | 2 +- functions_func_e.html | 2 +- jss_8h_source.html | 1089 ++--- namespacemembers_c.html | 2 +- namespacemembers_e.html | 13 +- namespacemembers_enum.html | 3 + namespacemembers_func_c.html | 2 +- namespacemembers_o.html | 2 +- namespacemembers_s.html | 29 +- namespacemembers_type.html | 3 + namespaceripple.html | 94 +- namespaceripple_1_1jss.html | 1234 +++--- namespaceripple_1_1test.html | 2 +- namespaceripple_1_1test_1_1jtx_1_1amm.html | 4 +- search/all_1.js | 2 +- search/all_10.js | 1240 +++--- search/all_11.js | 98 +- search/all_12.js | 1352 +++---- search/all_13.js | 2967 +++++++------- search/all_14.js | 3488 ++++++++--------- search/all_15.js | 708 ++-- search/all_16.js | 508 +-- search/all_17.js | 480 +-- search/all_18.js | 146 +- search/all_19.js | 16 +- search/all_1a.js | 18 +- search/all_1b.js | 720 ++-- search/all_3.js | 2 +- search/all_5.js | 321 +- search/all_6.js | 994 ++--- search/all_7.js | 1344 +++---- search/all_8.js | 392 +- search/all_9.js | 1624 ++++---- search/all_a.js | 228 +- search/all_b.js | 112 +- search/all_c.js | 962 ++--- search/all_d.js | 1974 +++++----- search/all_e.js | 662 ++-- search/all_f.js | 694 ++-- search/classes_0.js | 4 +- search/classes_1.js | 432 +- search/classes_10.js | 268 +- search/classes_11.js | 24 +- search/classes_12.js | 258 +- search/classes_13.js | 674 ++-- search/classes_14.js | 302 +- search/classes_15.js | 408 +- search/classes_16.js | 252 +- search/classes_17.js | 144 +- search/classes_18.js | 36 +- search/classes_19.js | 4 +- search/classes_1a.js | 10 +- search/classes_2.js | 228 +- search/classes_3.js | 432 +- search/classes_4.js | 202 +- search/classes_5.js | 176 +- search/classes_6.js | 156 +- search/classes_7.js | 56 +- search/classes_8.js | 80 +- search/classes_9.js | 410 +- search/classes_a.js | 46 +- search/classes_b.js | 32 +- search/classes_c.js | 218 +- search/classes_d.js | 274 +- search/classes_e.js | 172 +- search/classes_f.js | 184 +- search/enums_0.js | 12 +- search/enums_1.js | 20 +- search/enums_10.js | 31 +- search/enums_11.js | 34 +- search/enums_12.js | 10 +- search/enums_13.js | 8 +- search/enums_14.js | 6 +- search/enums_2.js | 8 +- search/enums_3.js | 10 +- search/enums_4.js | 8 +- search/enums_5.js | 4 +- search/enums_6.js | 4 +- search/enums_7.js | 4 +- search/enums_8.js | 4 +- search/enums_9.js | 14 +- search/enums_a.js | 4 +- search/enums_b.js | 6 +- search/enums_c.js | 8 +- search/enums_d.js | 18 +- search/enums_e.js | 2 +- search/enums_f.js | 10 +- search/enumvalues_0.js | 48 +- search/enumvalues_1.js | 46 +- search/enumvalues_10.js | 4 +- search/enumvalues_11.js | 176 +- search/enumvalues_12.js | 178 +- search/enumvalues_13.js | 490 +-- search/enumvalues_14.js | 28 +- search/enumvalues_15.js | 12 +- search/enumvalues_16.js | 18 +- search/enumvalues_17.js | 18 +- search/enumvalues_18.js | 2 +- search/enumvalues_2.js | 52 +- search/enumvalues_3.js | 56 +- search/enumvalues_4.js | 26 +- search/enumvalues_5.js | 36 +- search/enumvalues_6.js | 44 +- search/enumvalues_7.js | 24 +- search/enumvalues_8.js | 34 +- search/enumvalues_9.js | 96 +- search/enumvalues_a.js | 28 +- search/enumvalues_b.js | 170 +- search/enumvalues_c.js | 46 +- search/enumvalues_d.js | 66 +- search/enumvalues_e.js | 38 +- search/enumvalues_f.js | 42 +- search/files_0.js | 8 +- search/files_1.js | 4 +- search/files_10.js | 8 +- search/files_2.js | 68 +- search/files_3.js | 2 +- search/files_4.js | 4 +- search/files_5.js | 10 +- search/files_6.js | 14 +- search/files_7.js | 6 +- search/files_8.js | 8 +- search/files_9.js | 4 +- search/files_a.js | 4 +- search/files_b.js | 2 +- search/files_c.js | 8 +- search/files_d.js | 26 +- search/files_e.js | 10 +- search/files_f.js | 6 +- search/functions_0.js | 2 +- search/functions_1.js | 808 ++-- search/functions_10.js | 744 ++-- search/functions_11.js | 50 +- search/functions_12.js | 612 +-- search/functions_13.js | 1390 +++---- search/functions_14.js | 2376 +++++------ search/functions_15.js | 242 +- search/functions_16.js | 176 +- search/functions_17.js | 304 +- search/functions_18.js | 82 +- search/functions_19.js | 2 +- search/functions_1a.js | 10 +- search/functions_1b.js | 720 ++-- search/functions_2.js | 306 +- search/functions_3.js | 944 ++--- search/functions_4.js | 756 ++-- search/functions_5.js | 330 +- search/functions_6.js | 544 +-- search/functions_7.js | 1228 +++--- search/functions_8.js | 186 +- search/functions_9.js | 872 ++--- search/functions_a.js | 50 +- search/functions_b.js | 34 +- search/functions_c.js | 368 +- search/functions_d.js | 630 +-- search/functions_e.js | 324 +- search/functions_f.js | 436 +-- search/groups_0.js | 2 +- search/namespaces_0.js | 24 +- search/namespaces_1.js | 4 +- search/namespaces_2.js | 2 +- search/namespaces_3.js | 82 +- search/namespaces_4.js | 24 +- search/pages_0.js | 2 +- search/pages_1.js | 4 +- search/pages_10.js | 2 +- search/pages_2.js | 10 +- search/pages_3.js | 6 +- search/pages_4.js | 2 +- search/pages_5.js | 4 +- search/pages_6.js | 6 +- search/pages_7.js | 2 +- search/pages_8.js | 4 +- search/pages_9.js | 4 +- search/pages_a.js | 2 +- search/pages_b.js | 4 +- search/pages_c.js | 6 +- search/pages_d.js | 16 +- search/pages_e.js | 8 +- search/pages_f.js | 2 +- search/related_0.js | 8 +- search/related_1.js | 16 +- search/related_2.js | 4 +- search/related_3.js | 6 +- search/related_4.js | 2 +- search/related_5.js | 6 +- search/related_6.js | 18 +- search/related_7.js | 18 +- search/related_8.js | 34 +- search/related_9.js | 6 +- search/related_a.js | 12 +- search/related_b.js | 12 +- search/related_c.js | 4 +- search/related_d.js | 6 +- search/typedefs_0.js | 50 +- search/typedefs_1.js | 28 +- search/typedefs_10.js | 2 +- search/typedefs_11.js | 54 +- search/typedefs_12.js | 158 +- search/typedefs_13.js | 84 +- search/typedefs_14.js | 16 +- search/typedefs_15.js | 14 +- search/typedefs_16.js | 10 +- search/typedefs_17.js | 2 +- search/typedefs_18.js | 2 +- search/typedefs_2.js | 62 +- search/typedefs_3.js | 28 +- search/typedefs_4.js | 37 +- search/typedefs_5.js | 20 +- search/typedefs_6.js | 2 +- search/typedefs_7.js | 38 +- search/typedefs_8.js | 52 +- search/typedefs_9.js | 6 +- search/typedefs_a.js | 14 +- search/typedefs_b.js | 54 +- search/typedefs_c.js | 58 +- search/typedefs_d.js | 22 +- search/typedefs_e.js | 20 +- search/typedefs_f.js | 56 +- search/variables_0.js | 374 +- search/variables_1.js | 162 +- search/variables_10.js | 42 +- search/variables_11.js | 330 +- search/variables_12.js | 968 ++--- search/variables_13.js | 418 +- search/variables_14.js | 72 +- search/variables_15.js | 130 +- search/variables_16.js | 96 +- search/variables_17.js | 20 +- search/variables_18.js | 6 +- search/variables_19.js | 4 +- search/variables_2.js | 344 +- search/variables_3.js | 236 +- search/variables_4.js | 122 +- search/variables_5.js | 372 +- search/variables_6.js | 58 +- search/variables_7.js | 106 +- search/variables_8.js | 398 +- search/variables_9.js | 50 +- search/variables_a.js | 26 +- search/variables_b.js | 296 +- search/variables_c.js | 1132 +++--- search/variables_d.js | 202 +- search/variables_e.js | 100 +- search/variables_f.js | 312 +- 294 files changed, 29706 insertions(+), 29336 deletions(-) diff --git a/AMMCreate_8cpp_source.html b/AMMCreate_8cpp_source.html index 0a79d41dbb8..d11a874fb3e 100644 --- a/AMMCreate_8cpp_source.html +++ b/AMMCreate_8cpp_source.html @@ -350,92 +350,107 @@
279  // AMM creator gets the auction slot and the voting slot.
280  initializeFeeAuctionVote(
281  ctx_.view(), ammSle, account_, lptIss, ctx_.tx[sfTradingFee]);
-
282  sb.insert(ammSle);
-
283 
-
284  // Send LPT to LP.
-
285  auto res = accountSend(sb, *ammAccount, account_, lpTokens, ctx_.journal);
-
286  if (res != tesSUCCESS)
-
287  {
-
288  JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens;
-
289  return {res, false};
+
282 
+
283  // Add owner directory to link the root account and AMM object.
+
284  if (auto const page = sb.dirInsert(
+
285  keylet::ownerDir(*ammAccount),
+
286  ammSle->key(),
+
287  describeOwnerDir(*ammAccount)))
+
288  {
+
289  ammSle->setFieldU64(sfOwnerNode, *page);
290  }
-
291 
-
292  auto sendAndTrustSet = [&](STAmount const& amount) -> TER {
-
293  if (auto const res = accountSend(
-
294  sb,
-
295  account_,
-
296  *ammAccount,
-
297  amount,
-
298  ctx_.journal,
-
299  WaiveTransferFee::Yes))
-
300  return res;
-
301  // Set AMM flag on AMM trustline
-
302  if (!isXRP(amount))
-
303  {
-
304  if (SLE::pointer sleRippleState =
-
305  sb.peek(keylet::line(*ammAccount, amount.issue()));
-
306  !sleRippleState)
-
307  return tecINTERNAL;
-
308  else
-
309  {
-
310  auto const flags = sleRippleState->getFlags();
-
311  sleRippleState->setFieldU32(sfFlags, flags | lsfAMMNode);
-
312  sb.update(sleRippleState);
-
313  }
-
314  }
-
315  return tesSUCCESS;
-
316  };
-
317 
-
318  // Send asset1.
-
319  res = sendAndTrustSet(amount);
-
320  if (res != tesSUCCESS)
-
321  {
-
322  JLOG(j_.debug()) << "AMM Instance: failed to send " << amount;
-
323  return {res, false};
-
324  }
-
325 
-
326  // Send asset2.
-
327  res = sendAndTrustSet(amount2);
-
328  if (res != tesSUCCESS)
-
329  {
-
330  JLOG(j_.debug()) << "AMM Instance: failed to send " << amount2;
-
331  return {res, false};
-
332  }
-
333 
-
334  JLOG(j_.debug()) << "AMM Instance: success " << *ammAccount << " "
-
335  << ammKeylet.key << " " << lpTokens << " " << amount << " "
-
336  << amount2;
-
337  auto addOrderBook =
-
338  [&](Issue const& issueIn, Issue const& issueOut, std::uint64_t uRate) {
-
339  Book const book{issueIn, issueOut};
-
340  auto const dir = keylet::quality(keylet::book(book), uRate);
-
341  if (auto const bookExisted = static_cast<bool>(sb.read(dir));
-
342  !bookExisted)
-
343  ctx_.app.getOrderBookDB().addOrderBook(book);
-
344  };
-
345  addOrderBook(amount.issue(), amount2.issue(), getRate(amount2, amount));
-
346  addOrderBook(amount2.issue(), amount.issue(), getRate(amount, amount2));
+
291  else
+
292  {
+
293  JLOG(j_.debug()) << "AMM Instance: failed to insert owner dir";
+
294  return {tecDIR_FULL, false};
+
295  }
+
296  sb.insert(ammSle);
+
297 
+
298  // Send LPT to LP.
+
299  auto res = accountSend(sb, *ammAccount, account_, lpTokens, ctx_.journal);
+
300  if (res != tesSUCCESS)
+
301  {
+
302  JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens;
+
303  return {res, false};
+
304  }
+
305 
+
306  auto sendAndTrustSet = [&](STAmount const& amount) -> TER {
+
307  if (auto const res = accountSend(
+
308  sb,
+
309  account_,
+
310  *ammAccount,
+
311  amount,
+
312  ctx_.journal,
+
313  WaiveTransferFee::Yes))
+
314  return res;
+
315  // Set AMM flag on AMM trustline
+
316  if (!isXRP(amount))
+
317  {
+
318  if (SLE::pointer sleRippleState =
+
319  sb.peek(keylet::line(*ammAccount, amount.issue()));
+
320  !sleRippleState)
+
321  return tecINTERNAL;
+
322  else
+
323  {
+
324  auto const flags = sleRippleState->getFlags();
+
325  sleRippleState->setFieldU32(sfFlags, flags | lsfAMMNode);
+
326  sb.update(sleRippleState);
+
327  }
+
328  }
+
329  return tesSUCCESS;
+
330  };
+
331 
+
332  // Send asset1.
+
333  res = sendAndTrustSet(amount);
+
334  if (res != tesSUCCESS)
+
335  {
+
336  JLOG(j_.debug()) << "AMM Instance: failed to send " << amount;
+
337  return {res, false};
+
338  }
+
339 
+
340  // Send asset2.
+
341  res = sendAndTrustSet(amount2);
+
342  if (res != tesSUCCESS)
+
343  {
+
344  JLOG(j_.debug()) << "AMM Instance: failed to send " << amount2;
+
345  return {res, false};
+
346  }
347 
-
348  return {res, res == tesSUCCESS};
-
349 }
-
350 
-
351 TER
-
352 AMMCreate::doApply()
-
353 {
-
354  // This is the ledger view that we work against. Transactions are applied
-
355  // as we go on processing transactions.
-
356  Sandbox sb(&ctx_.view());
-
357 
-
358  auto const result = applyCreate(ctx_, sb, account_, j_);
-
359  if (result.second)
-
360  sb.apply(ctx_.rawView());
+
348  JLOG(j_.debug()) << "AMM Instance: success " << *ammAccount << " "
+
349  << ammKeylet.key << " " << lpTokens << " " << amount << " "
+
350  << amount2;
+
351  auto addOrderBook =
+
352  [&](Issue const& issueIn, Issue const& issueOut, std::uint64_t uRate) {
+
353  Book const book{issueIn, issueOut};
+
354  auto const dir = keylet::quality(keylet::book(book), uRate);
+
355  if (auto const bookExisted = static_cast<bool>(sb.read(dir));
+
356  !bookExisted)
+
357  ctx_.app.getOrderBookDB().addOrderBook(book);
+
358  };
+
359  addOrderBook(amount.issue(), amount2.issue(), getRate(amount2, amount));
+
360  addOrderBook(amount2.issue(), amount.issue(), getRate(amount, amount2));
361 
-
362  return result.first;
+
362  return {res, res == tesSUCCESS};
363 }
364 
-
365 } // namespace ripple
+
365 TER
+
366 AMMCreate::doApply()
+
367 {
+
368  // This is the ledger view that we work against. Transactions are applied
+
369  // as we go on processing transactions.
+
370  Sandbox sb(&ctx_.view());
+
371 
+
372  auto const result = applyCreate(ctx_, sb, account_, j_);
+
373  if (result.second)
+
374  sb.apply(ctx_.rawView());
+
375 
+
376  return result.first;
+
377 }
+
378 
+
379 } // namespace ripple
-
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:272
+
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:304
+
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:283
@ tecFROZEN
Definition: TER.h:273
virtual OrderBookDB & getOrderBookDB()=0
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:130
@@ -447,12 +462,14 @@
ReadView const & view
Definition: Transactor.h:56
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition: AMMCreate.cpp:82
+
const SF_UINT64 sfOwnerNode
TER accountSend(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
Definition: View.cpp:1142
const beast::Journal j
Definition: Transactor.h:60
static std::pair< TER, bool > applyCreate(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Definition: AMMCreate.cpp:205
@ lsfDisableMaster
Issue const & issue() const
Definition: STAmount.h:347
const SF_AMOUNT sfAmount2
+
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition: View.cpp:748
const SF_AMOUNT sfAmount
const beast::Journal j_
Definition: Transactor.h:89
bool isTesSuccess(TER x)
Definition: TER.h:608
@@ -486,6 +503,7 @@
XRPAmount increment
Definition: protocol/Fees.h:36
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition: STAmount.cpp:495
static TER preclaim(PreclaimContext const &ctx)
Definition: AMMCreate.cpp:89
+
uint256 key
Definition: Keylet.h:40
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
@ temINVALID_FLAG
Definition: TER.h:109
@ temBAD_AMM_TOKENS
Definition: TER.h:127
@@ -500,7 +518,7 @@
@ tecAMM_INVALID_TOKENS
Definition: TER.h:301
Discardable, editable view to a ledger.
Definition: Sandbox.h:34
-
TER doApply() override
Attempt to create the AMM instance.
Definition: AMMCreate.cpp:352
+
TER doApply() override
Attempt to create the AMM instance.
Definition: AMMCreate.cpp:366
TERSubset< CanCvtToTER > TER
Definition: TER.h:579
Definition: STAmount.h:45
Stream error() const
Definition: Journal.h:333
@@ -520,6 +538,7 @@
ApplyView & view()
Definition: ApplyContext.h:54
Definition: STIssue.h:31
STTx const & tx
Definition: Transactor.h:58
+
@ tecDIR_FULL
Definition: TER.h:257
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:52
void insert(std::shared_ptr< SLE > const &sle) override
Insert a new state SLE.
A view into a ledger.
Definition: ReadView.h:54
@@ -542,6 +561,7 @@
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Definition: Indexes.cpp:229
STTx const & tx
Definition: Transactor.h:35
State information when preflighting a tx.
Definition: Transactor.h:31
+
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition: ApplyView.h:306
const Rules rules
Definition: Transactor.h:36
constexpr std::uint32_t tfUniversalMask
Definition: TxFlags.h:60
@ tesSUCCESS
Definition: TER.h:225
diff --git a/AMMCreate_8h_source.html b/AMMCreate_8h_source.html index b2a684cc067..a58bd18bce2 100644 --- a/AMMCreate_8h_source.html +++ b/AMMCreate_8h_source.html @@ -130,7 +130,7 @@
static TER preclaim(PreclaimContext const &ctx)
Definition: AMMCreate.cpp:89
ConsequencesFactoryType
Definition: Transactor.h:101
Definition: TER.h:351
-
TER doApply() override
Attempt to create the AMM instance.
Definition: AMMCreate.cpp:352
+
TER doApply() override
Attempt to create the AMM instance.
Definition: AMMCreate.cpp:366
Definition: STTx.h:45
State information when applying a tx.
Definition: ApplyContext.h:35
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:52
diff --git a/AMMDelete_8cpp_source.html b/AMMDelete_8cpp_source.html index c87201d1a96..fae65b6e58c 100644 --- a/AMMDelete_8cpp_source.html +++ b/AMMDelete_8cpp_source.html @@ -182,7 +182,7 @@
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
@ temDISABLED
Definition: TER.h:112
@ terNO_AMM
Definition: TER.h:210
-
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:229
+
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:234
TER doApply() override
Definition: AMMDelete.cpp:69
ApplyContext & ctx_
Definition: Transactor.h:88
Stream debug() const
Definition: Journal.h:315
diff --git a/AMMDeposit_8cpp_source.html b/AMMDeposit_8cpp_source.html index 74e4e6419c2..9b71065a803 100644 --- a/AMMDeposit_8cpp_source.html +++ b/AMMDeposit_8cpp_source.html @@ -904,7 +904,7 @@
904 } // namespace ripple
std::pair< TER, STAmount > singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)
Single asset deposit (Asset1In, LPTokens) by the tokens.
Definition: AMMDeposit.cpp:752
-
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:272
+
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:283
@ tecFROZEN
Definition: TER.h:273
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:130
@ tecUNFUNDED_AMM
Definition: TER.h:298
diff --git a/AMMExtended__test_8cpp_source.html b/AMMExtended__test_8cpp_source.html index 1c97ae5d329..1d90fbffb7c 100644 --- a/AMMExtended__test_8cpp_source.html +++ b/AMMExtended__test_8cpp_source.html @@ -3996,7 +3996,7 @@
void receive_max()
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
bool same(STPathSet const &st1, Args const &... args)
Definition: TestHelpers.h:133
-
AccountID const & ammAccount() const
Definition: AMM.h:251
+
AccountID const & ammAccount() const
Definition: AMM.h:255
void testPayStrand()
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
void testRIPD1373(FeatureBitset features)
@@ -4021,7 +4021,7 @@
Check a set of conditions.
Definition: require.h:63
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
Definition: TestHelpers.cpp:93
void testCurrencyConversionInParts(FeatureBitset features)
-
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:734
+
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:746
void path_find_consume_all()
const jtx::Account gw
Definition: AMMTest.h:64
const uint256 featureMultiSignReserve
@@ -4043,7 +4043,7 @@
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, ripple, 2)
void testFlow()
bool empty() const
Definition: STPathSet.h:503
-
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Definition: AMM.cpp:193
+
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Definition: AMM.cpp:203
void via_offers_via_gateway()
@ tecKILLED
Definition: TER.h:286
void test_convert_all_of_an_asset(FeatureBitset features)
@@ -4079,7 +4079,7 @@
void path_find_01()
Definition: STAmount.h:45
bool isOffer(jtx::Env &env, jtx::Account const &account, STAmount const &takerPays, STAmount const &takerGets)
An offer exists.
Definition: PathSet.h:71
-
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:722
+
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:734
Add a path.
Definition: paths.h:55
jtx::Env pathTestEnv()
Definition: AMMTest.cpp:159
FeatureBitset supported_amendments()
Definition: Env.h:71
@@ -4090,7 +4090,7 @@
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
void testSellWithFillOrKill(FeatureBitset features)
constexpr std::uint32_t tfFillOrKill
Definition: TxFlags.h:96
-
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:274
+
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:284
Set the fee on a JTx.
Definition: fee.h:35
const uint256 fix1578
bool equal(std::unique_ptr< Step > const &s1, DirectStepInfo const &dsi)
@@ -4100,7 +4100,7 @@
constexpr std::uint32_t tfSell
Definition: TxFlags.h:97
Match set account flags.
Definition: flags.h:111
const jtx::IOU EUR
Definition: AMMTest.h:69
-
IOUAmount tokens() const
Definition: AMM.h:263
+
IOUAmount tokens() const
Definition: AMM.h:267
@ tecNO_LINE
Definition: TER.h:271
void testPayment(FeatureBitset features)
constexpr std::uint32_t tfSetfAuth
Definition: TxFlags.h:109
diff --git a/AMMInfo_8cpp_source.html b/AMMInfo_8cpp_source.html index 604e5a23543..fff9565f504 100644 --- a/AMMInfo_8cpp_source.html +++ b/AMMInfo_8cpp_source.html @@ -145,147 +145,193 @@
74 {
75  auto const& params(context.params);
76  Json::Value result;
-
77  std::optional<AccountID> accountID;
-
78 
-
79  Issue issue1;
-
80  Issue issue2;
-
81 
-
82  if (!params.isMember(jss::asset) || !params.isMember(jss::asset2))
-
83  {
-
84  RPC::inject_error(rpcINVALID_PARAMS, result);
-
85  return result;
-
86  }
-
87 
-
88  if (auto const i = getIssue(params[jss::asset], context.j); !i)
-
89  {
-
90  RPC::inject_error(i.error(), result);
-
91  return result;
-
92  }
-
93  else
-
94  issue1 = *i;
-
95  if (auto const i = getIssue(params[jss::asset2], context.j); !i)
-
96  {
-
97  RPC::inject_error(i.error(), result);
-
98  return result;
-
99  }
-
100  else
-
101  issue2 = *i;
-
102 
-
103  std::shared_ptr<ReadView const> ledger;
-
104  result = RPC::lookupLedger(ledger, context);
-
105  if (!ledger)
-
106  return result;
-
107 
-
108  if (params.isMember(jss::account))
-
109  {
-
110  accountID = getAccount(params[jss::account], result);
-
111  if (!accountID || !ledger->read(keylet::account(*accountID)))
-
112  {
-
113  RPC::inject_error(rpcACT_MALFORMED, result);
-
114  return result;
-
115  }
-
116  }
+
77 
+
78  std::shared_ptr<ReadView const> ledger;
+
79  result = RPC::lookupLedger(ledger, context);
+
80  if (!ledger)
+
81  return result;
+
82 
+
83  struct ValuesFromContextParams
+
84  {
+
85  std::optional<AccountID> accountID;
+
86  Issue issue1;
+
87  Issue issue2;
+
88  std::shared_ptr<SLE const> amm;
+
89  };
+
90 
+
91  auto getValuesFromContextParams =
+
92  [&]() -> Expected<ValuesFromContextParams, error_code_i> {
+
93  std::optional<AccountID> accountID;
+
94  std::optional<Issue> issue1;
+
95  std::optional<Issue> issue2;
+
96  std::optional<uint256> ammID;
+
97 
+
98  if ((params.isMember(jss::asset) != params.isMember(jss::asset2)) ||
+
99  (params.isMember(jss::asset) == params.isMember(jss::amm_account)))
+
100  return Unexpected(rpcINVALID_PARAMS);
+
101 
+
102  if (params.isMember(jss::asset))
+
103  {
+
104  if (auto const i = getIssue(params[jss::asset], context.j))
+
105  issue1 = *i;
+
106  else
+
107  return Unexpected(i.error());
+
108  }
+
109 
+
110  if (params.isMember(jss::asset2))
+
111  {
+
112  if (auto const i = getIssue(params[jss::asset2], context.j))
+
113  issue2 = *i;
+
114  else
+
115  return Unexpected(i.error());
+
116  }
117 
-
118  auto const ammKeylet = keylet::amm(issue1, issue2);
-
119  auto const amm = ledger->read(ammKeylet);
-
120  if (!amm)
-
121  return rpcError(rpcACT_NOT_FOUND);
-
122 
-
123  auto const ammAccountID = amm->getAccountID(sfAccount);
-
124 
-
125  // provide funds if frozen, specify asset_frozen flag
-
126  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
-
127  *ledger,
-
128  ammAccountID,
-
129  issue1,
-
130  issue2,
-
131  FreezeHandling::fhIGNORE_FREEZE,
-
132  context.j);
-
133  auto const lptAMMBalance = accountID
-
134  ? ammLPHolds(*ledger, *amm, *accountID, context.j)
-
135  : (*amm)[sfLPTokenBalance];
-
136 
-
137  Json::Value ammResult;
-
138  asset1Balance.setJson(ammResult[jss::amount]);
-
139  asset2Balance.setJson(ammResult[jss::amount2]);
-
140  lptAMMBalance.setJson(ammResult[jss::lp_token]);
-
141  ammResult[jss::trading_fee] = (*amm)[sfTradingFee];
-
142  ammResult[jss::account] = to_string(ammAccountID);
-
143  Json::Value voteSlots(Json::arrayValue);
-
144  if (amm->isFieldPresent(sfVoteSlots))
-
145  {
-
146  for (auto const& voteEntry : amm->getFieldArray(sfVoteSlots))
-
147  {
-
148  Json::Value vote;
-
149  vote[jss::account] = to_string(voteEntry.getAccountID(sfAccount));
-
150  vote[jss::trading_fee] = voteEntry[sfTradingFee];
-
151  vote[jss::vote_weight] = voteEntry[sfVoteWeight];
-
152  voteSlots.append(std::move(vote));
+
118  if (params.isMember(jss::amm_account))
+
119  {
+
120  auto const id = getAccount(params[jss::amm_account], result);
+
121  if (!id)
+
122  return Unexpected(rpcACT_MALFORMED);
+
123  auto const sle = ledger->read(keylet::account(*id));
+
124  if (!sle)
+
125  return Unexpected(rpcACT_MALFORMED);
+
126  ammID = sle->getFieldH256(sfAMMID);
+
127  }
+
128 
+
129  assert(
+
130  (issue1.has_value() == issue2.has_value()) &&
+
131  (issue1.has_value() != ammID.has_value()));
+
132 
+
133  if (params.isMember(jss::account))
+
134  {
+
135  accountID = getAccount(params[jss::account], result);
+
136  if (!accountID || !ledger->read(keylet::account(*accountID)))
+
137  return Unexpected(rpcACT_MALFORMED);
+
138  }
+
139 
+
140  auto const ammKeylet = [&]() {
+
141  if (issue1 && issue2)
+
142  return keylet::amm(*issue1, *issue2);
+
143  assert(ammID);
+
144  return keylet::amm(*ammID);
+
145  }();
+
146  auto const amm = ledger->read(ammKeylet);
+
147  if (!amm)
+
148  return Unexpected(rpcACT_NOT_FOUND);
+
149  if (!issue1 && !issue2)
+
150  {
+
151  issue1 = (*amm)[sfAsset];
+
152  issue2 = (*amm)[sfAsset2];
153  }
-
154  }
-
155  if (voteSlots.size() > 0)
-
156  ammResult[jss::vote_slots] = std::move(voteSlots);
-
157  if (amm->isFieldPresent(sfAuctionSlot))
-
158  {
-
159  auto const& auctionSlot =
-
160  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
-
161  if (auctionSlot.isFieldPresent(sfAccount))
-
162  {
-
163  Json::Value auction;
-
164  auto const timeSlot = ammAuctionTimeSlot(
-
165  ledger->info().parentCloseTime.time_since_epoch().count(),
-
166  auctionSlot);
-
167  auction[jss::time_interval] =
-
168  timeSlot ? *timeSlot : AUCTION_SLOT_TIME_INTERVALS;
-
169  auctionSlot[sfPrice].setJson(auction[jss::price]);
-
170  auction[jss::discounted_fee] = auctionSlot[sfDiscountedFee];
-
171  auction[jss::account] =
-
172  to_string(auctionSlot.getAccountID(sfAccount));
-
173  auction[jss::expiration] = to_iso8601(NetClock::time_point{
-
174  NetClock::duration{auctionSlot[sfExpiration]}});
-
175  if (auctionSlot.isFieldPresent(sfAuthAccounts))
-
176  {
-
177  Json::Value auth;
-
178  for (auto const& acct :
-
179  auctionSlot.getFieldArray(sfAuthAccounts))
-
180  {
-
181  Json::Value jv;
-
182  jv[jss::account] = to_string(acct.getAccountID(sfAccount));
-
183  auth.append(jv);
-
184  }
-
185  auction[jss::auth_accounts] = auth;
-
186  }
-
187  ammResult[jss::auction_slot] = std::move(auction);
-
188  }
-
189  }
-
190 
-
191  if (!isXRP(asset1Balance))
-
192  ammResult[jss::asset_frozen] =
-
193  isFrozen(*ledger, ammAccountID, issue1.currency, issue1.account);
-
194  if (!isXRP(asset2Balance))
-
195  ammResult[jss::asset2_frozen] =
-
196  isFrozen(*ledger, ammAccountID, issue2.currency, issue2.account);
-
197 
-
198  result[jss::amm] = std::move(ammResult);
-
199  if (!result.isMember(jss::ledger_index) &&
-
200  !result.isMember(jss::ledger_hash))
-
201  result[jss::ledger_current_index] = ledger->info().seq;
-
202  result[jss::validated] =
-
203  RPC::isValidated(context.ledgerMaster, *ledger, context.app);
-
204 
-
205  return result;
-
206 }
-
207 
-
208 } // namespace ripple
+
154 
+
155  return ValuesFromContextParams{
+
156  accountID, *issue1, *issue2, std::move(amm)};
+
157  };
+
158 
+
159  auto const r = getValuesFromContextParams();
+
160  if (!r)
+
161  {
+
162  RPC::inject_error(r.error(), result);
+
163  return result;
+
164  }
+
165 
+
166  auto const& [accountID, issue1, issue2, amm] = *r;
+
167 
+
168  auto const ammAccountID = amm->getAccountID(sfAccount);
+
169 
+
170  // provide funds if frozen, specify asset_frozen flag
+
171  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
+
172  *ledger,
+
173  ammAccountID,
+
174  issue1,
+
175  issue2,
+
176  FreezeHandling::fhIGNORE_FREEZE,
+
177  context.j);
+
178  auto const lptAMMBalance = accountID
+
179  ? ammLPHolds(*ledger, *amm, *accountID, context.j)
+
180  : (*amm)[sfLPTokenBalance];
+
181 
+
182  Json::Value ammResult;
+
183  asset1Balance.setJson(ammResult[jss::amount]);
+
184  asset2Balance.setJson(ammResult[jss::amount2]);
+
185  lptAMMBalance.setJson(ammResult[jss::lp_token]);
+
186  ammResult[jss::trading_fee] = (*amm)[sfTradingFee];
+
187  ammResult[jss::account] = to_string(ammAccountID);
+
188  Json::Value voteSlots(Json::arrayValue);
+
189  if (amm->isFieldPresent(sfVoteSlots))
+
190  {
+
191  for (auto const& voteEntry : amm->getFieldArray(sfVoteSlots))
+
192  {
+
193  Json::Value vote;
+
194  vote[jss::account] = to_string(voteEntry.getAccountID(sfAccount));
+
195  vote[jss::trading_fee] = voteEntry[sfTradingFee];
+
196  vote[jss::vote_weight] = voteEntry[sfVoteWeight];
+
197  voteSlots.append(std::move(vote));
+
198  }
+
199  }
+
200  if (voteSlots.size() > 0)
+
201  ammResult[jss::vote_slots] = std::move(voteSlots);
+
202  if (amm->isFieldPresent(sfAuctionSlot))
+
203  {
+
204  auto const& auctionSlot =
+
205  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
+
206  if (auctionSlot.isFieldPresent(sfAccount))
+
207  {
+
208  Json::Value auction;
+
209  auto const timeSlot = ammAuctionTimeSlot(
+
210  ledger->info().parentCloseTime.time_since_epoch().count(),
+
211  auctionSlot);
+
212  auction[jss::time_interval] =
+
213  timeSlot ? *timeSlot : AUCTION_SLOT_TIME_INTERVALS;
+
214  auctionSlot[sfPrice].setJson(auction[jss::price]);
+
215  auction[jss::discounted_fee] = auctionSlot[sfDiscountedFee];
+
216  auction[jss::account] =
+
217  to_string(auctionSlot.getAccountID(sfAccount));
+
218  auction[jss::expiration] = to_iso8601(NetClock::time_point{
+
219  NetClock::duration{auctionSlot[sfExpiration]}});
+
220  if (auctionSlot.isFieldPresent(sfAuthAccounts))
+
221  {
+
222  Json::Value auth;
+
223  for (auto const& acct :
+
224  auctionSlot.getFieldArray(sfAuthAccounts))
+
225  {
+
226  Json::Value jv;
+
227  jv[jss::account] = to_string(acct.getAccountID(sfAccount));
+
228  auth.append(jv);
+
229  }
+
230  auction[jss::auth_accounts] = auth;
+
231  }
+
232  ammResult[jss::auction_slot] = std::move(auction);
+
233  }
+
234  }
+
235 
+
236  if (!isXRP(asset1Balance))
+
237  ammResult[jss::asset_frozen] =
+
238  isFrozen(*ledger, ammAccountID, issue1.currency, issue1.account);
+
239  if (!isXRP(asset2Balance))
+
240  ammResult[jss::asset2_frozen] =
+
241  isFrozen(*ledger, ammAccountID, issue2.currency, issue2.account);
+
242 
+
243  result[jss::amm] = std::move(ammResult);
+
244  if (!result.isMember(jss::ledger_index) &&
+
245  !result.isMember(jss::ledger_hash))
+
246  result[jss::ledger_current_index] = ledger->info().seq;
+
247  result[jss::validated] =
+
248  RPC::isValidated(context.ledgerMaster, *ledger, context.app);
+
249 
+
250  return result;
+
251 }
+
252 
+
253 } // namespace ripple
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
+
T has_value(T... args)
Definition: Context.h:53
const SF_UINT16 sfDiscountedFee
A currency issued by an account.
Definition: Issue.h:35
+
const SF_ISSUE sfAsset
STL class.
STL class.
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
-
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
constexpr std::uint16_t AUCTION_SLOT_TIME_INTERVALS
Definition: AMMCore.h:35
const SField sfVoteSlots
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
@@ -294,7 +340,6 @@
Unexpected(E(&)[N]) -> Unexpected< E const * >
LedgerMaster & ledgerMaster
Definition: Context.h:45
-
Currency currency
Definition: Issue.h:38
LedgerIndex seq
Definition: LedgerHeader.h:41
const SF_AMOUNT sfPrice
const SF_UINT32 sfVoteWeight
@@ -309,6 +354,8 @@
T time_since_epoch(T... args)
NetClock::time_point parentCloseTime
Definition: LedgerHeader.h:42
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
+
const SF_ISSUE sfAsset2
+
Definition: Expected.h:132
Issue getIssue(T const &amt)
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
const SField sfAuthAccounts
@@ -321,6 +368,7 @@
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
A generic endpoint for log messages.
Definition: Journal.h:58
Issue issueFromJson(Json::Value const &v)
Definition: Issue.cpp:77
+
const SF_UINT256 sfAMMID
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
std::optional< AccountID > getAccount(Json::Value const &v, Json::Value &result)
Definition: AMMInfo.cpp:32
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition: AMMInfo.cpp:73
@@ -339,7 +387,6 @@
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:214
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:203
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:87
-
AccountID account
Definition: Issue.h:39
T what(T... args)
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition: AMMCore.cpp:107
Represents a JSON value.
Definition: json_value.h:145
diff --git a/AMMInfo__test_8cpp_source.html b/AMMInfo__test_8cpp_source.html index 180ee246765..652086e484e 100644 --- a/AMMInfo__test_8cpp_source.html +++ b/AMMInfo__test_8cpp_source.html @@ -113,186 +113,250 @@
42  Account const gw("gw");
43  auto const USD = gw["USD"];
44  auto const jv =
-
45  ammAlice.ammRpcInfo({}, {}, {{USD.issue(), USD.issue()}});
+
45  ammAlice.ammRpcInfo({}, {}, USD.issue(), USD.issue());
46  BEAST_EXPECT(jv[jss::error_message] == "Account not found.");
47  });
48 
49  // Invalid LP account id
50  testAMM([&](AMM& ammAlice, Env&) {
51  Account bogie("bogie");
-
52  auto const jv = ammAlice.ammRpcInfo(bogie.id());
+
52  auto const jv = ammAlice.ammRpcInfo(bogie.id());
53  BEAST_EXPECT(jv[jss::error_message] == "Account malformed.");
54  });
-
55  }
-
56 
-
57  void
-
58  testSimpleRpc()
-
59  {
-
60  testcase("RPC simple");
-
61 
-
62  using namespace jtx;
-
63  testAMM([&](AMM& ammAlice, Env&) {
-
64  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
-
65  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
-
66  });
-
67  }
-
68 
-
69  void
-
70  testVoteAndBid()
-
71  {
-
72  testcase("Vote and Bid");
-
73 
-
74  using namespace jtx;
-
75  testAMM([&](AMM& ammAlice, Env& env) {
-
76  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
-
77  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
-
78  std::unordered_map<std::string, std::uint16_t> votes;
-
79  votes.insert({alice.human(), 0});
-
80  for (int i = 0; i < 7; ++i)
-
81  {
-
82  Account a(std::to_string(i));
-
83  votes.insert({a.human(), 50 * (i + 1)});
-
84  fund(env, gw, {a}, {USD(10000)}, Fund::Acct);
-
85  ammAlice.deposit(a, 10000000);
-
86  ammAlice.vote(a, 50 * (i + 1));
-
87  }
-
88  BEAST_EXPECT(ammAlice.expectTradingFee(175));
-
89  Account ed("ed");
-
90  Account bill("bill");
-
91  env.fund(XRP(1000), bob, ed, bill);
-
92  ammAlice.bid(alice, 100, std::nullopt, {carol, bob, ed, bill});
-
93  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
-
94  XRP(80000), USD(80000), IOUAmount{79994400}));
-
95  std::unordered_set<std::string> authAccounts = {
-
96  carol.human(), bob.human(), ed.human(), bill.human()};
-
97  auto const ammInfo = ammAlice.ammRpcInfo();
-
98  auto const& amm = ammInfo[jss::amm];
-
99  try
-
100  {
-
101  // votes
-
102  auto const voteSlots = amm[jss::vote_slots];
-
103  for (std::uint8_t i = 0; i < 8; ++i)
-
104  {
-
105  if (!BEAST_EXPECT(
-
106  votes[voteSlots[i][jss::account].asString()] ==
-
107  voteSlots[i][jss::trading_fee].asUInt() &&
-
108  voteSlots[i][jss::vote_weight].asUInt() == 12500))
-
109  return;
-
110  votes.erase(voteSlots[i][jss::account].asString());
-
111  }
-
112  if (!BEAST_EXPECT(votes.empty()))
-
113  return;
+
55 
+
56  // Invalid parameters
+
57  testAMM([&](AMM& ammAlice, Env&) {
+
58  std::vector<std::tuple<
+
59  std::optional<Issue>,
+
60  std::optional<Issue>,
+
61  std::optional<AccountID>,
+
62  bool>>
+
63  vals = {
+
64  {xrpIssue(), std::nullopt, std::nullopt, false},
+
65  {std::nullopt, USD.issue(), std::nullopt, false},
+
66  {xrpIssue(), std::nullopt, ammAlice.ammAccount(), false},
+
67  {std::nullopt, USD.issue(), ammAlice.ammAccount(), false},
+
68  {xrpIssue(), USD.issue(), ammAlice.ammAccount(), false},
+
69  {std::nullopt, std::nullopt, std::nullopt, true}};
+
70  for (auto const& [iss1, iss2, acct, ignoreParams] : vals)
+
71  {
+
72  auto const jv = ammAlice.ammRpcInfo(
+
73  std::nullopt, std::nullopt, iss1, iss2, acct, ignoreParams);
+
74  BEAST_EXPECT(jv[jss::error_message] == "Invalid parameters.");
+
75  }
+
76  });
+
77 
+
78  // Invalid AMM account id
+
79  testAMM([&](AMM& ammAlice, Env&) {
+
80  Account bogie("bogie");
+
81  auto const jv = ammAlice.ammRpcInfo(
+
82  std::nullopt,
+
83  std::nullopt,
+
84  std::nullopt,
+
85  std::nullopt,
+
86  bogie.id());
+
87  BEAST_EXPECT(jv[jss::error_message] == "Account malformed.");
+
88  });
+
89  }
+
90 
+
91  void
+
92  testSimpleRpc()
+
93  {
+
94  testcase("RPC simple");
+
95 
+
96  using namespace jtx;
+
97  testAMM([&](AMM& ammAlice, Env&) {
+
98  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
+
99  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
+
100  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
+
101  XRP(10000),
+
102  USD(10000),
+
103  IOUAmount{10000000, 0},
+
104  std::nullopt,
+
105  std::nullopt,
+
106  ammAlice.ammAccount()));
+
107  });
+
108  }
+
109 
+
110  void
+
111  testVoteAndBid()
+
112  {
+
113  testcase("Vote and Bid");
114 
-
115  // bid
-
116  auto const auctionSlot = amm[jss::auction_slot];
-
117  for (std::uint8_t i = 0; i < 4; ++i)
-
118  {
-
119  if (!BEAST_EXPECT(authAccounts.contains(
-
120  auctionSlot[jss::auth_accounts][i][jss::account]
-
121  .asString())))
-
122  return;
-
123  authAccounts.erase(
-
124  auctionSlot[jss::auth_accounts][i][jss::account]
-
125  .asString());
-
126  }
-
127  if (!BEAST_EXPECT(authAccounts.empty()))
-
128  return;
-
129  BEAST_EXPECT(
-
130  auctionSlot[jss::account].asString() == alice.human() &&
-
131  auctionSlot[jss::discounted_fee].asUInt() == 17 &&
-
132  auctionSlot[jss::price][jss::value].asString() == "5600" &&
-
133  auctionSlot[jss::price][jss::currency].asString() ==
-
134  to_string(ammAlice.lptIssue().currency) &&
-
135  auctionSlot[jss::price][jss::issuer].asString() ==
-
136  to_string(ammAlice.lptIssue().account));
-
137  }
-
138  catch (std::exception const& e)
-
139  {
-
140  fail(e.what(), __FILE__, __LINE__);
-
141  }
-
142  });
-
143  }
-
144 
-
145  void
-
146  testFreeze()
-
147  {
-
148  using namespace jtx;
-
149  testAMM([&](AMM& ammAlice, Env& env) {
-
150  env(fset(gw, asfGlobalFreeze));
-
151  env.close();
-
152  auto test = [&](bool freeze) {
-
153  auto const info = ammAlice.ammRpcInfo();
-
154  BEAST_EXPECT(
-
155  info[jss::amm][jss::asset2_frozen].asBool() == freeze);
-
156  };
-
157  test(true);
-
158  env(fclear(gw, asfGlobalFreeze));
-
159  env.close();
-
160  test(false);
-
161  });
-
162  }
-
163 
-
164  void
-
165  run() override
-
166  {
-
167  testErrors();
-
168  testSimpleRpc();
-
169  testVoteAndBid();
-
170  testFreeze();
-
171  }
-
172 };
-
173 
-
174 BEAST_DEFINE_TESTSUITE(AMMInfo, app, ripple);
-
175 
-
176 } // namespace test
-
177 } // namespace ripple
+
115  using namespace jtx;
+
116  testAMM([&](AMM& ammAlice, Env& env) {
+
117  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
+
118  XRP(10000), USD(10000), IOUAmount{10000000, 0}));
+
119  std::unordered_map<std::string, std::uint16_t> votes;
+
120  votes.insert({alice.human(), 0});
+
121  for (int i = 0; i < 7; ++i)
+
122  {
+
123  Account a(std::to_string(i));
+
124  votes.insert({a.human(), 50 * (i + 1)});
+
125  fund(env, gw, {a}, {USD(10000)}, Fund::Acct);
+
126  ammAlice.deposit(a, 10000000);
+
127  ammAlice.vote(a, 50 * (i + 1));
+
128  }
+
129  BEAST_EXPECT(ammAlice.expectTradingFee(175));
+
130  Account ed("ed");
+
131  Account bill("bill");
+
132  env.fund(XRP(1000), bob, ed, bill);
+
133  ammAlice.bid(alice, 100, std::nullopt, {carol, bob, ed, bill});
+
134  BEAST_EXPECT(ammAlice.expectAmmRpcInfo(
+
135  XRP(80000),
+
136  USD(80000),
+
137  IOUAmount{79994400},
+
138  std::nullopt,
+
139  std::nullopt,
+
140  ammAlice.ammAccount()));
+
141  for (auto i = 0; i < 2; ++i)
+
142  {
+
143  std::unordered_set<std::string> authAccounts = {
+
144  carol.human(), bob.human(), ed.human(), bill.human()};
+
145  auto const ammInfo = i ? ammAlice.ammRpcInfo()
+
146  : ammAlice.ammRpcInfo(
+
147  std::nullopt,
+
148  std::nullopt,
+
149  std::nullopt,
+
150  std::nullopt,
+
151  ammAlice.ammAccount());
+
152  auto const& amm = ammInfo[jss::amm];
+
153  try
+
154  {
+
155  // votes
+
156  auto const voteSlots = amm[jss::vote_slots];
+
157  auto votesCopy = votes;
+
158  for (std::uint8_t i = 0; i < 8; ++i)
+
159  {
+
160  if (!BEAST_EXPECT(
+
161  votes[voteSlots[i][jss::account].asString()] ==
+
162  voteSlots[i][jss::trading_fee].asUInt() &&
+
163  voteSlots[i][jss::vote_weight].asUInt() ==
+
164  12500))
+
165  return;
+
166  votes.erase(voteSlots[i][jss::account].asString());
+
167  }
+
168  if (!BEAST_EXPECT(votes.empty()))
+
169  return;
+
170  votes = votesCopy;
+
171 
+
172  // bid
+
173  auto const auctionSlot = amm[jss::auction_slot];
+
174  for (std::uint8_t i = 0; i < 4; ++i)
+
175  {
+
176  if (!BEAST_EXPECT(authAccounts.contains(
+
177  auctionSlot[jss::auth_accounts][i][jss::account]
+
178  .asString())))
+
179  return;
+
180  authAccounts.erase(
+
181  auctionSlot[jss::auth_accounts][i][jss::account]
+
182  .asString());
+
183  }
+
184  if (!BEAST_EXPECT(authAccounts.empty()))
+
185  return;
+
186  BEAST_EXPECT(
+
187  auctionSlot[jss::account].asString() == alice.human() &&
+
188  auctionSlot[jss::discounted_fee].asUInt() == 17 &&
+
189  auctionSlot[jss::price][jss::value].asString() ==
+
190  "5600" &&
+
191  auctionSlot[jss::price][jss::currency].asString() ==
+
192  to_string(ammAlice.lptIssue().currency) &&
+
193  auctionSlot[jss::price][jss::issuer].asString() ==
+
194  to_string(ammAlice.lptIssue().account));
+
195  }
+
196  catch (std::exception const& e)
+
197  {
+
198  fail(e.what(), __FILE__, __LINE__);
+
199  }
+
200  }
+
201  });
+
202  }
+
203 
+
204  void
+
205  testFreeze()
+
206  {
+
207  using namespace jtx;
+
208  testAMM([&](AMM& ammAlice, Env& env) {
+
209  env(fset(gw, asfGlobalFreeze));
+
210  env.close();
+
211  auto test = [&](bool freeze) {
+
212  auto const info = ammAlice.ammRpcInfo();
+
213  BEAST_EXPECT(
+
214  info[jss::amm][jss::asset2_frozen].asBool() == freeze);
+
215  };
+
216  test(true);
+
217  env(fclear(gw, asfGlobalFreeze));
+
218  env.close();
+
219  test(false);
+
220  });
+
221  }
+
222 
+
223  void
+
224  run() override
+
225  {
+
226  testErrors();
+
227  testSimpleRpc();
+
228  testVoteAndBid();
+
229  testFreeze();
+
230  }
+
231 };
+
232 
+
233 BEAST_DEFINE_TESTSUITE(AMMInfo, app, ripple);
+
234 
+
235 } // namespace test
+
236 } // namespace ripple
const jtx::IOU USD
Definition: AMMTest.h:68
void testErrors()
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
STL class.
+
AccountID const & ammAccount() const
Definition: AMM.h:255
STL class.
-
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< std::pair< Issue, Issue >> tokens=std::nullopt) const
Send amm_info RPC command.
Definition: AMM.cpp:136
+
STL class.
Currency currency
Definition: Issue.h:38
-
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:566
+
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:578
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:113
const jtx::Account gw
Definition: AMMTest.h:64
const jtx::Account carol
Definition: AMMTest.h:65
-
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:371
+
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:383
const jtx::Account alice
Definition: AMMTest.h:66
+
Issue issue() const
Definition: amount.h:303
-
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:587
+
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:599
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
Convenience class to test AMM functionality.
Definition: AMM.h:62
@ freeze
T contains(T... args)
AccountID id() const
Returns the Account ID.
Definition: Account.h:106
+
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< Issue > issue1=std::nullopt, std::optional< Issue > issue2=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt, bool ignoreParams=false) const
Send amm_info RPC command.
Definition: AMM.cpp:136
+
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledger_index=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt) const
Definition: AMM.cpp:300
const jtx::Account bob
Definition: AMMTest.h:67
Definition: AMMTest.h:61
-
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledger_index=std::nullopt) const
Definition: AMM.cpp:290
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
T to_string(T... args)
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
T erase(T... args)
-
void testVoteAndBid()
-
void run() override
+
void testVoteAndBid()
+
void run() override
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
-
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:274
+
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:284
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T insert(T... args)
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Definition: AMMTest.cpp:35
T empty(T... args)
+
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition: Issue.h:105
constexpr std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:80
-
void testFreeze()
+
void testFreeze()
+
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Immutable cryptographic account descriptor.
Definition: Account.h:37
-
void testSimpleRpc()
+
void testSimpleRpc()
void testAMM(std::function< void(jtx::AMM &, jtx::Env &)> &&cb, std::optional< std::pair< STAmount, STAmount >> const &pool=std::nullopt, std::uint16_t tfee=0, std::optional< jtx::ter > const &ter=std::nullopt, std::optional< FeatureBitset > const &features=std::nullopt)
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
Definition: AMMTest.cpp:101
-
Issue lptIssue() const
Definition: AMM.h:257
+
Issue lptIssue() const
Definition: AMM.h:261
A transaction testing environment.
Definition: Env.h:117
AccountID account
Definition: Issue.h:39
T what(T... args)
diff --git a/AMMUtils_8cpp_source.html b/AMMUtils_8cpp_source.html index 3582c757ae4..12c35f725b2 100644 --- a/AMMUtils_8cpp_source.html +++ b/AMMUtils_8cpp_source.html @@ -266,118 +266,129 @@
195  std::uint16_t maxTrustlinesToDelete,
196  beast::Journal j)
197 {
-
198  return cleanupOnAccountDelete(
+
198  return cleanupOnAccountDelete(
199  sb,
200  keylet::ownerDir(ammAccountID),
201  [&](LedgerEntryType nodeType,
202  uint256 const&,
-
203  std::shared_ptr<SLE>& sleItem) -> TER {
-
204  // Should only have the trustlines
-
205  if (nodeType != LedgerEntryType::ltRIPPLE_STATE)
-
206  {
-
207  JLOG(j.error())
-
208  << "deleteAMMTrustLines: deleting non-trustline "
-
209  << nodeType;
-
210  return tecINTERNAL;
-
211  }
-
212 
-
213  // Trustlines must have zero balance
-
214  if (sleItem->getFieldAmount(sfBalance) != beast::zero)
-
215  {
-
216  JLOG(j.error())
-
217  << "deleteAMMTrustLines: deleting trustline with "
-
218  "non-zero balance.";
-
219  return tecINTERNAL;
-
220  }
-
221 
-
222  return deleteAMMTrustLine(sb, sleItem, ammAccountID, j);
-
223  },
-
224  j,
-
225  maxTrustlinesToDelete);
-
226 }
-
227 
-
228 TER
-
229 deleteAMMAccount(
-
230  Sandbox& sb,
-
231  Issue const& asset,
-
232  Issue const& asset2,
-
233  beast::Journal j)
-
234 {
-
235  auto ammSle = sb.peek(keylet::amm(asset, asset2));
-
236  if (!ammSle)
-
237  {
-
238  JLOG(j.error()) << "deleteAMMAccount: AMM object does not exist "
-
239  << asset << " " << asset2;
-
240  return tecINTERNAL;
-
241  }
-
242 
-
243  auto const ammAccountID = (*ammSle)[sfAccount];
-
244  auto sleAMMRoot = sb.peek(keylet::account(ammAccountID));
-
245  if (!sleAMMRoot)
-
246  {
-
247  JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist "
-
248  << to_string(ammAccountID);
-
249  return tecINTERNAL;
-
250  }
-
251 
-
252  if (auto const ter =
-
253  deleteAMMTrustLines(sb, ammAccountID, maxDeletableAMMTrustLines, j);
-
254  ter != tesSUCCESS)
-
255  return ter;
+
203  std::shared_ptr<SLE>& sleItem) -> std::pair<TER, SkipEntry> {
+
204  // Skip AMM
+
205  if (nodeType == LedgerEntryType::ltAMM)
+
206  return {tesSUCCESS, SkipEntry::Yes};
+
207  // Should only have the trustlines
+
208  if (nodeType != LedgerEntryType::ltRIPPLE_STATE)
+
209  {
+
210  JLOG(j.error())
+
211  << "deleteAMMTrustLines: deleting non-trustline "
+
212  << nodeType;
+
213  return {tecINTERNAL, SkipEntry::No};
+
214  }
+
215 
+
216  // Trustlines must have zero balance
+
217  if (sleItem->getFieldAmount(sfBalance) != beast::zero)
+
218  {
+
219  JLOG(j.error())
+
220  << "deleteAMMTrustLines: deleting trustline with "
+
221  "non-zero balance.";
+
222  return {tecINTERNAL, SkipEntry::No};
+
223  }
+
224 
+
225  return {
+
226  deleteAMMTrustLine(sb, sleItem, ammAccountID, j),
+
227  SkipEntry::No};
+
228  },
+
229  j,
+
230  maxTrustlinesToDelete);
+
231 }
+
232 
+
233 TER
+
234 deleteAMMAccount(
+
235  Sandbox& sb,
+
236  Issue const& asset,
+
237  Issue const& asset2,
+
238  beast::Journal j)
+
239 {
+
240  auto ammSle = sb.peek(keylet::amm(asset, asset2));
+
241  if (!ammSle)
+
242  {
+
243  JLOG(j.error()) << "deleteAMMAccount: AMM object does not exist "
+
244  << asset << " " << asset2;
+
245  return tecINTERNAL;
+
246  }
+
247 
+
248  auto const ammAccountID = (*ammSle)[sfAccount];
+
249  auto sleAMMRoot = sb.peek(keylet::account(ammAccountID));
+
250  if (!sleAMMRoot)
+
251  {
+
252  JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist "
+
253  << to_string(ammAccountID);
+
254  return tecINTERNAL;
+
255  }
256 
-
257  auto const ownerDirKeylet = keylet::ownerDir(ammAccountID);
-
258  if (sb.exists(ownerDirKeylet) && !sb.emptyDirDelete(ownerDirKeylet))
-
259  {
-
260  JLOG(j.error()) << "deleteAMMAccount: cannot delete root dir node of "
-
261  << toBase58(ammAccountID);
-
262  return tecINTERNAL;
-
263  }
-
264 
-
265  sb.erase(ammSle);
-
266  sb.erase(sleAMMRoot);
-
267 
-
268  return tesSUCCESS;
-
269 }
-
270 
-
271 void
-
272 initializeFeeAuctionVote(
-
273  ApplyView& view,
-
274  std::shared_ptr<SLE>& ammSle,
-
275  AccountID const& account,
-
276  Issue const& lptIssue,
-
277  std::uint16_t tfee)
-
278 {
-
279  // AMM creator gets the voting slot.
-
280  STArray voteSlots;
-
281  STObject voteEntry{sfVoteEntry};
-
282  if (tfee != 0)
-
283  voteEntry.setFieldU16(sfTradingFee, tfee);
-
284  voteEntry.setFieldU32(sfVoteWeight, VOTE_WEIGHT_SCALE_FACTOR);
-
285  voteEntry.setAccountID(sfAccount, account);
-
286  voteSlots.push_back(voteEntry);
-
287  ammSle->setFieldArray(sfVoteSlots, voteSlots);
-
288  // AMM creator gets the auction slot for free.
-
289  auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
-
290  auctionSlot.setAccountID(sfAccount, account);
-
291  // current + sec in 24h
-
292  auto const expiration = std::chrono::duration_cast<std::chrono::seconds>(
-
293  view.info().parentCloseTime.time_since_epoch())
-
294  .count() +
-
295  TOTAL_TIME_SLOT_SECS;
-
296  auctionSlot.setFieldU32(sfExpiration, expiration);
-
297  auctionSlot.setFieldAmount(sfPrice, STAmount{lptIssue, 0});
-
298  // Set the fee
-
299  if (tfee != 0)
-
300  ammSle->setFieldU16(sfTradingFee, tfee);
-
301  else if (ammSle->isFieldPresent(sfTradingFee))
-
302  ammSle->makeFieldAbsent(sfTradingFee);
-
303  if (auto const dfee = tfee / AUCTION_SLOT_DISCOUNTED_FEE_FRACTION)
-
304  auctionSlot.setFieldU16(sfDiscountedFee, dfee);
-
305  else if (auctionSlot.isFieldPresent(sfDiscountedFee))
-
306  auctionSlot.makeFieldAbsent(sfDiscountedFee);
-
307 }
-
308 
-
309 } // namespace ripple
+
257  if (auto const ter =
+
258  deleteAMMTrustLines(sb, ammAccountID, maxDeletableAMMTrustLines, j);
+
259  ter != tesSUCCESS)
+
260  return ter;
+
261 
+
262  auto const ownerDirKeylet = keylet::ownerDir(ammAccountID);
+
263  if (!sb.dirRemove(
+
264  ownerDirKeylet, (*ammSle)[sfOwnerNode], ammSle->key(), false))
+
265  {
+
266  JLOG(j.error()) << "deleteAMMAccount: failed to remove dir link";
+
267  return tecINTERNAL;
+
268  }
+
269  if (sb.exists(ownerDirKeylet) && !sb.emptyDirDelete(ownerDirKeylet))
+
270  {
+
271  JLOG(j.error()) << "deleteAMMAccount: cannot delete root dir node of "
+
272  << toBase58(ammAccountID);
+
273  return tecINTERNAL;
+
274  }
+
275 
+
276  sb.erase(ammSle);
+
277  sb.erase(sleAMMRoot);
+
278 
+
279  return tesSUCCESS;
+
280 }
+
281 
+
282 void
+
283 initializeFeeAuctionVote(
+
284  ApplyView& view,
+
285  std::shared_ptr<SLE>& ammSle,
+
286  AccountID const& account,
+
287  Issue const& lptIssue,
+
288  std::uint16_t tfee)
+
289 {
+
290  // AMM creator gets the voting slot.
+
291  STArray voteSlots;
+
292  STObject voteEntry{sfVoteEntry};
+
293  if (tfee != 0)
+
294  voteEntry.setFieldU16(sfTradingFee, tfee);
+
295  voteEntry.setFieldU32(sfVoteWeight, VOTE_WEIGHT_SCALE_FACTOR);
+
296  voteEntry.setAccountID(sfAccount, account);
+
297  voteSlots.push_back(voteEntry);
+
298  ammSle->setFieldArray(sfVoteSlots, voteSlots);
+
299  // AMM creator gets the auction slot for free.
+
300  auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
+
301  auctionSlot.setAccountID(sfAccount, account);
+
302  // current + sec in 24h
+
303  auto const expiration = std::chrono::duration_cast<std::chrono::seconds>(
+
304  view.info().parentCloseTime.time_since_epoch())
+
305  .count() +
+
306  TOTAL_TIME_SLOT_SECS;
+
307  auctionSlot.setFieldU32(sfExpiration, expiration);
+
308  auctionSlot.setFieldAmount(sfPrice, STAmount{lptIssue, 0});
+
309  // Set the fee
+
310  if (tfee != 0)
+
311  ammSle->setFieldU16(sfTradingFee, tfee);
+
312  else if (ammSle->isFieldPresent(sfTradingFee))
+
313  ammSle->makeFieldAbsent(sfTradingFee);
+
314  if (auto const dfee = tfee / AUCTION_SLOT_DISCOUNTED_FEE_FRACTION)
+
315  auctionSlot.setFieldU16(sfDiscountedFee, dfee);
+
316  else if (auctionSlot.isFieldPresent(sfDiscountedFee))
+
317  auctionSlot.makeFieldAbsent(sfDiscountedFee);
+
318 }
+
319 
+
320 } // namespace ripple
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
const STBase & peekAtField(SField const &field) const
Definition: STObject.cpp:373
@@ -385,7 +396,7 @@
void setAccountID(SField const &field, AccountID const &)
Definition: STObject.cpp:689
void negate()
Definition: STAmount.h:402
bool issues(DebtDirection dir)
Definition: Steps.h:50
-
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:272
+
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:283
T make_tuple(T... args)
const SF_UINT16 sfDiscountedFee
void makeFieldAbsent(SField const &field)
Definition: STObject.cpp:514
@@ -393,6 +404,7 @@
A currency issued by an account.
Definition: Issue.h:35
const SF_ISSUE sfAsset
STL class.
+
const SF_UINT64 sfOwnerNode
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:653
constexpr std::uint32_t VOTE_WEIGHT_SCALE_FACTOR
Definition: AMMCore.h:45
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition: AMMUtils.cpp:45
@@ -411,7 +423,7 @@
void push_back(STObject const &object)
Definition: STArray.h:212
constexpr std::uint16_t maxDeletableAMMTrustLines
The maximum number of trustlines to delete as part of AMM account deletion cleanup.
Definition: Protocol.h:101
TER deleteAMMTrustLine(ApplyView &view, std::shared_ptr< SLE > sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
Definition: View.cpp:1607
-
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:78
+
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:79
const SF_AMOUNT sfPrice
const SF_UINT32 sfVoteWeight
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
@@ -419,15 +431,16 @@
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:134
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:29
const SF_UINT32 sfExpiration
+
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
Definition: ApplyView.cpp:189
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
T time_since_epoch(T... args)
NetClock::time_point parentCloseTime
Definition: LedgerHeader.h:42
+
@ Yes
const SF_ISSUE sfAsset2
void setFieldArray(SField const &field, STArray const &v)
Definition: STObject.cpp:725
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:589
@ tecAMM_INVALID_TOKENS
Definition: TER.h:301
-
const SField sfAuthAccounts
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
Definition: AMMUtils.cpp:138
Definition: STArray.h:28
@@ -442,6 +455,7 @@
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue >> const &pair=std::nullopt)
Definition: AMMCore.cpp:79
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition: Indexes.cpp:194
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
+
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, EntryDeleter const &deleter, beast::Journal j, std::optional< uint16_t > maxNodesToDelete)
Definition: View.cpp:1531
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
Definition: STObject.h:52
A view into a ledger.
Definition: ReadView.h:54
@@ -450,11 +464,11 @@
constexpr std::uint32_t TOTAL_TIME_SLOT_SECS
Definition: AMMCore.h:34
LedgerEntryType
Identifiers for on-ledger objects.
Definition: LedgerFormats.h:53
bool emptyDirDelete(Keylet const &directory)
Remove the specified directory, if it is empty.
Definition: ApplyView.cpp:125
-
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, std::function< TER(LedgerEntryType, uint256 const &, std::shared_ptr< SLE > &)> deleter, beast::Journal j, std::optional< uint16_t > maxNodesToDelete)
Definition: View.cpp:1531
static TER deleteAMMTrustLines(Sandbox &sb, AccountID const &ammAccountID, std::uint16_t maxTrustlinesToDelete, beast::Journal j)
Definition: AMMUtils.cpp:192
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:428
-
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:229
+
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:234
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
+
@ No
const SF_AMOUNT sfBalance
Stream debug() const
Definition: Journal.h:315
diff --git a/AMMUtils_8h_source.html b/AMMUtils_8h_source.html index dc6d81e607e..a9646cc8763 100644 --- a/AMMUtils_8h_source.html +++ b/AMMUtils_8h_source.html @@ -169,12 +169,12 @@
117 
118 #endif // RIPPLE_APP_MISC_AMMUTILS_H_INLCUDED
-
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:272
+
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:283
STL class.
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition: AMMUtils.cpp:45
STLedgerEntry SLE
Definition: Application.h:66
-
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:78
+
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:79
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:29
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
Definition: AMMUtils.cpp:138
@@ -183,7 +183,7 @@
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
-
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:229
+
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:234
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
STAmount ammAccountHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue)
Returns total amount held by AMM for the given token.
Definition: AMMUtils.cpp:166
diff --git a/AMMWithdraw_8cpp_source.html b/AMMWithdraw_8cpp_source.html index df8f287d510..0c1252f9ff6 100644 --- a/AMMWithdraw_8cpp_source.html +++ b/AMMWithdraw_8cpp_source.html @@ -905,7 +905,7 @@
const SF_UINT32 sfFlags
@ terNO_AMM
Definition: TER.h:210
constexpr std::uint32_t tfTwoAsset
Definition: TxFlags.h:171
-
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:229
+
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:234
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
std::pair< TER, STAmount > withdraw(Sandbox &view, AccountID const &ammAccount, STAmount const &amountWithdraw, STAmount const &amountBalance, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Withdraw requested assets and token from AMM into LP account.
ApplyContext & ctx_
Definition: Transactor.h:88
diff --git a/AMM_8cpp_source.html b/AMM_8cpp_source.html index 942b5ca1f44..4be34b3078d 100644 --- a/AMM_8cpp_source.html +++ b/AMM_8cpp_source.html @@ -204,632 +204,644 @@
133 }
134 
135 Json::Value
-
136 AMM::ammRpcInfo(
+
136 AMM::ammRpcInfo(
137  std::optional<AccountID> const& account,
138  std::optional<std::string> const& ledgerIndex,
-
139  std::optional<std::pair<Issue, Issue>> tokens) const
-
140 {
-
141  Json::Value jv;
-
142  if (account)
-
143  jv[jss::account] = to_string(*account);
-
144  if (ledgerIndex)
-
145  jv[jss::ledger_index] = *ledgerIndex;
-
146  if (tokens)
-
147  {
-
148  jv[jss::asset] =
-
149  STIssue(sfAsset, tokens->first).getJson(JsonOptions::none);
-
150  jv[jss::asset2] =
-
151  STIssue(sfAsset2, tokens->second).getJson(JsonOptions::none);
-
152  }
-
153  else
-
154  {
-
155  jv[jss::asset] =
-
156  STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
-
157  jv[jss::asset2] =
-
158  STIssue(sfAsset2, asset2_.issue()).getJson(JsonOptions::none);
-
159  }
-
160  auto jr = env_.rpc("json", "amm_info", to_string(jv));
-
161  if (jr.isObject() && jr.isMember(jss::result) &&
-
162  jr[jss::result].isMember(jss::status))
-
163  return jr[jss::result];
-
164  return Json::nullValue;
-
165 }
-
166 
-
167 std::tuple<STAmount, STAmount, STAmount>
-
168 AMM::balances(
-
169  Issue const& issue1,
-
170  Issue const& issue2,
-
171  std::optional<AccountID> const& account) const
-
172 {
-
173  if (auto const amm =
-
174  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
-
175  {
-
176  auto const ammAccountID = amm->getAccountID(sfAccount);
-
177  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
-
178  *env_.current(),
-
179  ammAccountID,
-
180  issue1,
-
181  issue2,
-
182  FreezeHandling::fhIGNORE_FREEZE,
-
183  env_.journal);
-
184  auto const lptAMMBalance = account
-
185  ? ammLPHolds(*env_.current(), *amm, *account, env_.journal)
-
186  : amm->getFieldAmount(sfLPTokenBalance);
-
187  return {asset1Balance, asset2Balance, lptAMMBalance};
-
188  }
-
189  return {STAmount{}, STAmount{}, STAmount{}};
-
190 }
-
191 
-
192 bool
-
193 AMM::expectBalances(
-
194  STAmount const& asset1,
-
195  STAmount const& asset2,
-
196  IOUAmount const& lpt,
-
197  std::optional<AccountID> const& account) const
-
198 {
-
199  auto const [asset1Balance, asset2Balance, lptAMMBalance] =
-
200  balances(asset1.issue(), asset2.issue(), account);
-
201  return asset1 == asset1Balance && asset2 == asset2Balance &&
-
202  lptAMMBalance == STAmount{lpt, lptIssue_};
-
203  return false;
-
204 }
-
205 
-
206 IOUAmount
-
207 AMM::getLPTokensBalance(std::optional<AccountID> const& account) const
+
139  std::optional<Issue> issue1,
+
140  std::optional<Issue> issue2,
+
141  std::optional<AccountID> const& ammAccount,
+
142  bool ignoreParams) const
+
143 {
+
144  Json::Value jv;
+
145  if (account)
+
146  jv[jss::account] = to_string(*account);
+
147  if (ledgerIndex)
+
148  jv[jss::ledger_index] = *ledgerIndex;
+
149  if (!ignoreParams)
+
150  {
+
151  if (issue1 || issue2)
+
152  {
+
153  if (issue1)
+
154  jv[jss::asset] =
+
155  STIssue(sfAsset, *issue1).getJson(JsonOptions::none);
+
156  if (issue2)
+
157  jv[jss::asset2] =
+
158  STIssue(sfAsset2, *issue2).getJson(JsonOptions::none);
+
159  }
+
160  else if (!ammAccount)
+
161  {
+
162  jv[jss::asset] =
+
163  STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
+
164  jv[jss::asset2] =
+
165  STIssue(sfAsset2, asset2_.issue()).getJson(JsonOptions::none);
+
166  }
+
167  if (ammAccount)
+
168  jv[jss::amm_account] = to_string(*ammAccount);
+
169  }
+
170  auto jr = env_.rpc("json", "amm_info", to_string(jv));
+
171  if (jr.isObject() && jr.isMember(jss::result) &&
+
172  jr[jss::result].isMember(jss::status))
+
173  return jr[jss::result];
+
174  return Json::nullValue;
+
175 }
+
176 
+
177 std::tuple<STAmount, STAmount, STAmount>
+
178 AMM::balances(
+
179  Issue const& issue1,
+
180  Issue const& issue2,
+
181  std::optional<AccountID> const& account) const
+
182 {
+
183  if (auto const amm =
+
184  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
+
185  {
+
186  auto const ammAccountID = amm->getAccountID(sfAccount);
+
187  auto const [asset1Balance, asset2Balance] = ammPoolHolds(
+
188  *env_.current(),
+
189  ammAccountID,
+
190  issue1,
+
191  issue2,
+
192  FreezeHandling::fhIGNORE_FREEZE,
+
193  env_.journal);
+
194  auto const lptAMMBalance = account
+
195  ? ammLPHolds(*env_.current(), *amm, *account, env_.journal)
+
196  : amm->getFieldAmount(sfLPTokenBalance);
+
197  return {asset1Balance, asset2Balance, lptAMMBalance};
+
198  }
+
199  return {STAmount{}, STAmount{}, STAmount{}};
+
200 }
+
201 
+
202 bool
+
203 AMM::expectBalances(
+
204  STAmount const& asset1,
+
205  STAmount const& asset2,
+
206  IOUAmount const& lpt,
+
207  std::optional<AccountID> const& account) const
208 {
-
209  if (account)
-
210  return accountHolds(
-
211  *env_.current(),
-
212  *account,
-
213  lptIssue_,
-
214  FreezeHandling::fhZERO_IF_FROZEN,
-
215  env_.journal)
-
216  .iou();
-
217  if (auto const amm =
-
218  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
-
219  return amm->getFieldAmount(sfLPTokenBalance).iou();
-
220  return IOUAmount{0};
-
221 }
-
222 
-
223 bool
-
224 AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
-
225 {
-
226  if (auto const amm =
-
227  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
-
228  {
-
229  auto const lptAMMBalance =
-
230  ammLPHolds(*env_.current(), *amm, account, env_.journal);
-
231  return lptAMMBalance == STAmount{expTokens, lptIssue_};
-
232  }
-
233  return false;
-
234 }
-
235 
-
236 bool
-
237 AMM::expectAuctionSlot(
-
238  std::uint32_t fee,
-
239  std::optional<std::uint8_t> timeSlot,
-
240  IOUAmount expectedPrice) const
-
241 {
-
242  return expectAuctionSlot([&](std::uint32_t slotFee,
-
243  std::optional<std::uint8_t> slotInterval,
-
244  IOUAmount const& slotPrice,
-
245  auto const&) {
-
246  return slotFee == fee &&
-
247  // Auction slot might be expired, in which case slotInterval is
-
248  // 0
-
249  ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) &&
-
250  slotPrice == expectedPrice;
-
251  });
-
252 }
-
253 
-
254 bool
-
255 AMM::expectAuctionSlot(std::vector<AccountID> const& authAccounts) const
-
256 {
-
257  return expectAuctionSlot([&](std::uint32_t,
-
258  std::optional<std::uint8_t>,
-
259  IOUAmount const&,
-
260  STArray const& accounts) {
-
261  for (auto const& account : accounts)
-
262  {
-
263  if (std::find(
-
264  authAccounts.cbegin(),
-
265  authAccounts.cend(),
-
266  account.getAccountID(sfAccount)) == authAccounts.end())
-
267  return false;
-
268  }
-
269  return true;
-
270  });
-
271 }
-
272 
-
273 bool
-
274 AMM::expectTradingFee(std::uint16_t fee) const
-
275 {
-
276  auto const amm =
-
277  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()));
-
278  return amm && (*amm)[sfTradingFee] == fee;
-
279 }
-
280 
-
281 bool
-
282 AMM::ammExists() const
-
283 {
-
284  return env_.current()->read(keylet::account(ammAccount_)) != nullptr &&
-
285  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) !=
-
286  nullptr;
-
287 }
-
288 
-
289 bool
-
290 AMM::expectAmmRpcInfo(
-
291  STAmount const& asset1,
-
292  STAmount const& asset2,
-
293  IOUAmount const& balance,
-
294  std::optional<AccountID> const& account,
-
295  std::optional<std::string> const& ledger_index) const
-
296 {
-
297  auto const jv = ammRpcInfo(account, ledger_index);
-
298  return expectAmmInfo(asset1, asset2, balance, jv);
-
299 }
-
300 
-
301 bool
-
302 AMM::expectAmmInfo(
-
303  STAmount const& asset1,
-
304  STAmount const& asset2,
-
305  IOUAmount const& balance,
-
306  Json::Value const& jvres) const
+
209  auto const [asset1Balance, asset2Balance, lptAMMBalance] =
+
210  balances(asset1.issue(), asset2.issue(), account);
+
211  return asset1 == asset1Balance && asset2 == asset2Balance &&
+
212  lptAMMBalance == STAmount{lpt, lptIssue_};
+
213  return false;
+
214 }
+
215 
+
216 IOUAmount
+
217 AMM::getLPTokensBalance(std::optional<AccountID> const& account) const
+
218 {
+
219  if (account)
+
220  return accountHolds(
+
221  *env_.current(),
+
222  *account,
+
223  lptIssue_,
+
224  FreezeHandling::fhZERO_IF_FROZEN,
+
225  env_.journal)
+
226  .iou();
+
227  if (auto const amm =
+
228  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
+
229  return amm->getFieldAmount(sfLPTokenBalance).iou();
+
230  return IOUAmount{0};
+
231 }
+
232 
+
233 bool
+
234 AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
+
235 {
+
236  if (auto const amm =
+
237  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
+
238  {
+
239  auto const lptAMMBalance =
+
240  ammLPHolds(*env_.current(), *amm, account, env_.journal);
+
241  return lptAMMBalance == STAmount{expTokens, lptIssue_};
+
242  }
+
243  return false;
+
244 }
+
245 
+
246 bool
+
247 AMM::expectAuctionSlot(
+
248  std::uint32_t fee,
+
249  std::optional<std::uint8_t> timeSlot,
+
250  IOUAmount expectedPrice) const
+
251 {
+
252  return expectAuctionSlot([&](std::uint32_t slotFee,
+
253  std::optional<std::uint8_t> slotInterval,
+
254  IOUAmount const& slotPrice,
+
255  auto const&) {
+
256  return slotFee == fee &&
+
257  // Auction slot might be expired, in which case slotInterval is
+
258  // 0
+
259  ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) &&
+
260  slotPrice == expectedPrice;
+
261  });
+
262 }
+
263 
+
264 bool
+
265 AMM::expectAuctionSlot(std::vector<AccountID> const& authAccounts) const
+
266 {
+
267  return expectAuctionSlot([&](std::uint32_t,
+
268  std::optional<std::uint8_t>,
+
269  IOUAmount const&,
+
270  STArray const& accounts) {
+
271  for (auto const& account : accounts)
+
272  {
+
273  if (std::find(
+
274  authAccounts.cbegin(),
+
275  authAccounts.cend(),
+
276  account.getAccountID(sfAccount)) == authAccounts.end())
+
277  return false;
+
278  }
+
279  return true;
+
280  });
+
281 }
+
282 
+
283 bool
+
284 AMM::expectTradingFee(std::uint16_t fee) const
+
285 {
+
286  auto const amm =
+
287  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()));
+
288  return amm && (*amm)[sfTradingFee] == fee;
+
289 }
+
290 
+
291 bool
+
292 AMM::ammExists() const
+
293 {
+
294  return env_.current()->read(keylet::account(ammAccount_)) != nullptr &&
+
295  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) !=
+
296  nullptr;
+
297 }
+
298 
+
299 bool
+
300 AMM::expectAmmRpcInfo(
+
301  STAmount const& asset1,
+
302  STAmount const& asset2,
+
303  IOUAmount const& balance,
+
304  std::optional<AccountID> const& account,
+
305  std::optional<std::string> const& ledger_index,
+
306  std::optional<AccountID> const& ammAccount) const
307 {
-
308  if (!jvres.isMember(jss::amm))
-
309  return false;
-
310  auto const& jv = jvres[jss::amm];
-
311  if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) ||
-
312  !jv.isMember(jss::lp_token))
-
313  return false;
-
314  STAmount asset1Info;
-
315  if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount]))
-
316  return false;
-
317  STAmount asset2Info;
-
318  if (!amountFromJsonNoThrow(asset2Info, jv[jss::amount2]))
-
319  return false;
-
320  STAmount lptBalance;
-
321  if (!amountFromJsonNoThrow(lptBalance, jv[jss::lp_token]))
-
322  return false;
-
323  // ammRpcInfo returns unordered assets
-
324  if (asset1Info.issue() != asset1.issue())
-
325  std::swap(asset1Info, asset2Info);
-
326  return asset1 == asset1Info && asset2 == asset2Info &&
-
327  lptBalance == STAmount{balance, lptIssue_};
-
328 }
-
329 
-
330 void
-
331 AMM::setTokens(
-
332  Json::Value& jv,
-
333  std::optional<std::pair<Issue, Issue>> const& assets)
-
334 {
-
335  if (assets)
-
336  {
-
337  jv[jss::Asset] =
-
338  STIssue(sfAsset, assets->first).getJson(JsonOptions::none);
-
339  jv[jss::Asset2] =
-
340  STIssue(sfAsset, assets->second).getJson(JsonOptions::none);
-
341  }
-
342  else
-
343  {
-
344  jv[jss::Asset] =
-
345  STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
-
346  jv[jss::Asset2] =
-
347  STIssue(sfAsset, asset2_.issue()).getJson(JsonOptions::none);
-
348  }
-
349 }
-
350 
-
351 IOUAmount
-
352 AMM::deposit(
-
353  std::optional<Account> const& account,
-
354  Json::Value& jv,
-
355  std::optional<std::pair<Issue, Issue>> const& assets,
-
356  std::optional<jtx::seq> const& seq,
-
357  std::optional<ter> const& ter)
-
358 {
-
359  auto const& acct = account ? *account : creatorAccount_;
-
360  auto const lpTokens = getLPTokensBalance(acct);
-
361  jv[jss::Account] = acct.human();
-
362  setTokens(jv, assets);
-
363  jv[jss::TransactionType] = jss::AMMDeposit;
-
364  if (fee_ != 0)
-
365  jv[jss::Fee] = std::to_string(fee_);
-
366  submit(jv, seq, ter);
-
367  return getLPTokensBalance(acct) - lpTokens;
-
368 }
-
369 
-
370 IOUAmount
-
371 AMM::deposit(
-
372  std::optional<Account> const& account,
-
373  LPToken tokens,
-
374  std::optional<STAmount> const& asset1In,
-
375  std::optional<std::uint32_t> const& flags,
-
376  std::optional<ter> const& ter)
-
377 {
-
378  return deposit(
-
379  account,
-
380  tokens,
-
381  asset1In,
-
382  std::nullopt,
-
383  std::nullopt,
-
384  flags,
-
385  std::nullopt,
-
386  std::nullopt,
-
387  std::nullopt,
-
388  ter);
-
389 }
-
390 
-
391 IOUAmount
-
392 AMM::deposit(
-
393  std::optional<Account> const& account,
-
394  STAmount const& asset1In,
-
395  std::optional<STAmount> const& asset2In,
-
396  std::optional<STAmount> const& maxEP,
-
397  std::optional<std::uint32_t> const& flags,
-
398  std::optional<ter> const& ter)
-
399 {
-
400  assert(!(asset2In && maxEP));
-
401  return deposit(
-
402  account,
-
403  std::nullopt,
-
404  asset1In,
-
405  asset2In,
-
406  maxEP,
-
407  flags,
-
408  std::nullopt,
-
409  std::nullopt,
-
410  std::nullopt,
-
411  ter);
-
412 }
-
413 
-
414 IOUAmount
-
415 AMM::deposit(
-
416  std::optional<Account> const& account,
-
417  std::optional<LPToken> tokens,
-
418  std::optional<STAmount> const& asset1In,
-
419  std::optional<STAmount> const& asset2In,
-
420  std::optional<STAmount> const& maxEP,
-
421  std::optional<std::uint32_t> const& flags,
-
422  std::optional<std::pair<Issue, Issue>> const& assets,
-
423  std::optional<jtx::seq> const& seq,
-
424  std::optional<std::uint16_t> const& tfee,
-
425  std::optional<ter> const& ter)
-
426 {
-
427  Json::Value jv;
-
428  if (tokens)
-
429  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenOut]);
-
430  if (asset1In)
-
431  asset1In->setJson(jv[jss::Amount]);
-
432  if (asset2In)
-
433  asset2In->setJson(jv[jss::Amount2]);
-
434  if (maxEP)
-
435  maxEP->setJson(jv[jss::EPrice]);
-
436  if (tfee)
-
437  jv[jss::TradingFee] = *tfee;
-
438  std::uint32_t jvflags = 0;
-
439  if (flags)
-
440  jvflags = *flags;
-
441  // If including asset1In and asset2In or tokens as
-
442  // deposit min amounts then must set the flags
-
443  // explicitly instead of relying on this logic.
-
444  if (!(jvflags & tfDepositSubTx))
-
445  {
-
446  if (tokens && !asset1In)
-
447  jvflags |= tfLPToken;
-
448  else if (tokens && asset1In)
-
449  jvflags |= tfOneAssetLPToken;
-
450  else if (asset1In && asset2In)
-
451  jvflags |= tfTwoAsset;
-
452  else if (maxEP && asset1In)
-
453  jvflags |= tfLimitLPToken;
-
454  else if (asset1In)
-
455  jvflags |= tfSingleAsset;
-
456  }
-
457  jv[jss::Flags] = jvflags;
-
458  return deposit(account, jv, assets, seq, ter);
-
459 }
-
460 
-
461 IOUAmount
-
462 AMM::withdraw(
-
463  std::optional<Account> const& account,
-
464  Json::Value& jv,
-
465  std::optional<jtx::seq> const& seq,
-
466  std::optional<std::pair<Issue, Issue>> const& assets,
-
467  std::optional<ter> const& ter)
-
468 {
-
469  auto const& acct = account ? *account : creatorAccount_;
-
470  auto const lpTokens = getLPTokensBalance(acct);
-
471  jv[jss::Account] = acct.human();
-
472  setTokens(jv, assets);
-
473  jv[jss::TransactionType] = jss::AMMWithdraw;
-
474  if (fee_ != 0)
-
475  jv[jss::Fee] = std::to_string(fee_);
-
476  submit(jv, seq, ter);
-
477  return lpTokens - getLPTokensBalance(acct);
-
478 }
-
479 
-
480 IOUAmount
-
481 AMM::withdraw(
-
482  std::optional<Account> const& account,
-
483  std::optional<LPToken> const& tokens,
-
484  std::optional<STAmount> const& asset1Out,
-
485  std::optional<std::uint32_t> const& flags,
-
486  std::optional<ter> const& ter)
-
487 {
-
488  return withdraw(
-
489  account,
-
490  tokens,
-
491  asset1Out,
-
492  std::nullopt,
-
493  std::nullopt,
-
494  flags,
-
495  std::nullopt,
-
496  std::nullopt,
-
497  ter);
-
498 }
-
499 
-
500 IOUAmount
-
501 AMM::withdraw(
-
502  std::optional<Account> const& account,
-
503  STAmount const& asset1Out,
-
504  std::optional<STAmount> const& asset2Out,
-
505  std::optional<IOUAmount> const& maxEP,
-
506  std::optional<ter> const& ter)
-
507 {
-
508  assert(!(asset2Out && maxEP));
-
509  return withdraw(
-
510  account,
-
511  std::nullopt,
-
512  asset1Out,
-
513  asset2Out,
-
514  maxEP,
-
515  std::nullopt,
-
516  std::nullopt,
-
517  std::nullopt,
-
518  ter);
-
519 }
-
520 
-
521 IOUAmount
-
522 AMM::withdraw(
-
523  std::optional<Account> const& account,
-
524  std::optional<LPToken> const& tokens,
-
525  std::optional<STAmount> const& asset1Out,
-
526  std::optional<STAmount> const& asset2Out,
-
527  std::optional<IOUAmount> const& maxEP,
-
528  std::optional<std::uint32_t> const& flags,
-
529  std::optional<std::pair<Issue, Issue>> const& assets,
-
530  std::optional<jtx::seq> const& seq,
-
531  std::optional<ter> const& ter)
-
532 {
-
533  Json::Value jv;
-
534  if (tokens)
-
535  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenIn]);
-
536  if (asset1Out)
-
537  asset1Out->setJson(jv[jss::Amount]);
-
538  if (asset2Out)
-
539  asset2Out->setJson(jv[jss::Amount2]);
-
540  if (maxEP)
-
541  {
-
542  STAmount const saMaxEP{*maxEP, lptIssue_};
-
543  saMaxEP.setJson(jv[jss::EPrice]);
-
544  }
-
545  std::uint32_t jvflags = 0;
-
546  if (flags)
-
547  jvflags = *flags;
-
548  if (!(jvflags & tfWithdrawSubTx))
-
549  {
-
550  if (tokens && !asset1Out)
-
551  jvflags |= tfLPToken;
-
552  else if (asset1Out && asset2Out)
-
553  jvflags |= tfTwoAsset;
-
554  else if (tokens && asset1Out)
-
555  jvflags |= tfOneAssetLPToken;
-
556  else if (asset1Out && maxEP)
-
557  jvflags |= tfLimitLPToken;
-
558  else if (asset1Out)
-
559  jvflags |= tfSingleAsset;
-
560  }
-
561  jv[jss::Flags] = jvflags;
-
562  return withdraw(account, jv, seq, assets, ter);
-
563 }
-
564 
-
565 void
-
566 AMM::vote(
-
567  std::optional<Account> const& account,
-
568  std::uint32_t feeVal,
-
569  std::optional<std::uint32_t> const& flags,
-
570  std::optional<jtx::seq> const& seq,
-
571  std::optional<std::pair<Issue, Issue>> const& assets,
-
572  std::optional<ter> const& ter)
-
573 {
-
574  Json::Value jv;
-
575  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
-
576  setTokens(jv, assets);
-
577  jv[jss::TradingFee] = feeVal;
-
578  jv[jss::TransactionType] = jss::AMMVote;
-
579  if (flags)
-
580  jv[jss::Flags] = *flags;
-
581  if (fee_ != 0)
-
582  jv[jss::Fee] = std::to_string(fee_);
-
583  submit(jv, seq, ter);
-
584 }
-
585 
-
586 void
-
587 AMM::bid(
-
588  std::optional<Account> const& account,
-
589  std::optional<std::variant<int, IOUAmount, STAmount>> const& bidMin,
-
590  std::optional<std::variant<int, IOUAmount, STAmount>> const& bidMax,
-
591  std::vector<Account> const& authAccounts,
-
592  std::optional<std::uint32_t> const& flags,
-
593  std::optional<jtx::seq> const& seq,
-
594  std::optional<std::pair<Issue, Issue>> const& assets,
-
595  std::optional<ter> const& ter)
-
596 {
-
597  if (auto const amm =
-
598  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
-
599  {
-
600  if (amm->isFieldPresent(sfAuctionSlot))
-
601  {
-
602  auto const& auctionSlot =
-
603  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
-
604  lastPurchasePrice_ = auctionSlot[sfPrice].iou();
-
605  }
-
606  }
-
607  bidMin_ = std::nullopt;
-
608  bidMax_ = std::nullopt;
-
609 
-
610  Json::Value jv;
-
611  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
-
612  setTokens(jv, assets);
-
613  auto getBid = [&](auto const& bid) {
-
614  if (std::holds_alternative<int>(bid))
-
615  return STAmount{lptIssue_, std::get<int>(bid)};
-
616  else if (std::holds_alternative<IOUAmount>(bid))
-
617  return toSTAmount(std::get<IOUAmount>(bid), lptIssue_);
-
618  else
-
619  return std::get<STAmount>(bid);
-
620  };
-
621  if (bidMin)
-
622  {
-
623  STAmount saTokens = getBid(*bidMin);
-
624  saTokens.setJson(jv[jss::BidMin]);
-
625  bidMin_ = saTokens.iou();
-
626  }
-
627  if (bidMax)
-
628  {
-
629  STAmount saTokens = getBid(*bidMax);
-
630  saTokens.setJson(jv[jss::BidMax]);
-
631  bidMax_ = saTokens.iou();
-
632  }
-
633  if (authAccounts.size() > 0)
+
308  auto const jv = ammRpcInfo(
+
309  account, ledger_index, std::nullopt, std::nullopt, ammAccount);
+
310  return expectAmmInfo(asset1, asset2, balance, jv);
+
311 }
+
312 
+
313 bool
+
314 AMM::expectAmmInfo(
+
315  STAmount const& asset1,
+
316  STAmount const& asset2,
+
317  IOUAmount const& balance,
+
318  Json::Value const& jvres) const
+
319 {
+
320  if (!jvres.isMember(jss::amm))
+
321  return false;
+
322  auto const& jv = jvres[jss::amm];
+
323  if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) ||
+
324  !jv.isMember(jss::lp_token))
+
325  return false;
+
326  STAmount asset1Info;
+
327  if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount]))
+
328  return false;
+
329  STAmount asset2Info;
+
330  if (!amountFromJsonNoThrow(asset2Info, jv[jss::amount2]))
+
331  return false;
+
332  STAmount lptBalance;
+
333  if (!amountFromJsonNoThrow(lptBalance, jv[jss::lp_token]))
+
334  return false;
+
335  // ammRpcInfo returns unordered assets
+
336  if (asset1Info.issue() != asset1.issue())
+
337  std::swap(asset1Info, asset2Info);
+
338  return asset1 == asset1Info && asset2 == asset2Info &&
+
339  lptBalance == STAmount{balance, lptIssue_};
+
340 }
+
341 
+
342 void
+
343 AMM::setTokens(
+
344  Json::Value& jv,
+
345  std::optional<std::pair<Issue, Issue>> const& assets)
+
346 {
+
347  if (assets)
+
348  {
+
349  jv[jss::Asset] =
+
350  STIssue(sfAsset, assets->first).getJson(JsonOptions::none);
+
351  jv[jss::Asset2] =
+
352  STIssue(sfAsset, assets->second).getJson(JsonOptions::none);
+
353  }
+
354  else
+
355  {
+
356  jv[jss::Asset] =
+
357  STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none);
+
358  jv[jss::Asset2] =
+
359  STIssue(sfAsset, asset2_.issue()).getJson(JsonOptions::none);
+
360  }
+
361 }
+
362 
+
363 IOUAmount
+
364 AMM::deposit(
+
365  std::optional<Account> const& account,
+
366  Json::Value& jv,
+
367  std::optional<std::pair<Issue, Issue>> const& assets,
+
368  std::optional<jtx::seq> const& seq,
+
369  std::optional<ter> const& ter)
+
370 {
+
371  auto const& acct = account ? *account : creatorAccount_;
+
372  auto const lpTokens = getLPTokensBalance(acct);
+
373  jv[jss::Account] = acct.human();
+
374  setTokens(jv, assets);
+
375  jv[jss::TransactionType] = jss::AMMDeposit;
+
376  if (fee_ != 0)
+
377  jv[jss::Fee] = std::to_string(fee_);
+
378  submit(jv, seq, ter);
+
379  return getLPTokensBalance(acct) - lpTokens;
+
380 }
+
381 
+
382 IOUAmount
+
383 AMM::deposit(
+
384  std::optional<Account> const& account,
+
385  LPToken tokens,
+
386  std::optional<STAmount> const& asset1In,
+
387  std::optional<std::uint32_t> const& flags,
+
388  std::optional<ter> const& ter)
+
389 {
+
390  return deposit(
+
391  account,
+
392  tokens,
+
393  asset1In,
+
394  std::nullopt,
+
395  std::nullopt,
+
396  flags,
+
397  std::nullopt,
+
398  std::nullopt,
+
399  std::nullopt,
+
400  ter);
+
401 }
+
402 
+
403 IOUAmount
+
404 AMM::deposit(
+
405  std::optional<Account> const& account,
+
406  STAmount const& asset1In,
+
407  std::optional<STAmount> const& asset2In,
+
408  std::optional<STAmount> const& maxEP,
+
409  std::optional<std::uint32_t> const& flags,
+
410  std::optional<ter> const& ter)
+
411 {
+
412  assert(!(asset2In && maxEP));
+
413  return deposit(
+
414  account,
+
415  std::nullopt,
+
416  asset1In,
+
417  asset2In,
+
418  maxEP,
+
419  flags,
+
420  std::nullopt,
+
421  std::nullopt,
+
422  std::nullopt,
+
423  ter);
+
424 }
+
425 
+
426 IOUAmount
+
427 AMM::deposit(
+
428  std::optional<Account> const& account,
+
429  std::optional<LPToken> tokens,
+
430  std::optional<STAmount> const& asset1In,
+
431  std::optional<STAmount> const& asset2In,
+
432  std::optional<STAmount> const& maxEP,
+
433  std::optional<std::uint32_t> const& flags,
+
434  std::optional<std::pair<Issue, Issue>> const& assets,
+
435  std::optional<jtx::seq> const& seq,
+
436  std::optional<std::uint16_t> const& tfee,
+
437  std::optional<ter> const& ter)
+
438 {
+
439  Json::Value jv;
+
440  if (tokens)
+
441  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenOut]);
+
442  if (asset1In)
+
443  asset1In->setJson(jv[jss::Amount]);
+
444  if (asset2In)
+
445  asset2In->setJson(jv[jss::Amount2]);
+
446  if (maxEP)
+
447  maxEP->setJson(jv[jss::EPrice]);
+
448  if (tfee)
+
449  jv[jss::TradingFee] = *tfee;
+
450  std::uint32_t jvflags = 0;
+
451  if (flags)
+
452  jvflags = *flags;
+
453  // If including asset1In and asset2In or tokens as
+
454  // deposit min amounts then must set the flags
+
455  // explicitly instead of relying on this logic.
+
456  if (!(jvflags & tfDepositSubTx))
+
457  {
+
458  if (tokens && !asset1In)
+
459  jvflags |= tfLPToken;
+
460  else if (tokens && asset1In)
+
461  jvflags |= tfOneAssetLPToken;
+
462  else if (asset1In && asset2In)
+
463  jvflags |= tfTwoAsset;
+
464  else if (maxEP && asset1In)
+
465  jvflags |= tfLimitLPToken;
+
466  else if (asset1In)
+
467  jvflags |= tfSingleAsset;
+
468  }
+
469  jv[jss::Flags] = jvflags;
+
470  return deposit(account, jv, assets, seq, ter);
+
471 }
+
472 
+
473 IOUAmount
+
474 AMM::withdraw(
+
475  std::optional<Account> const& account,
+
476  Json::Value& jv,
+
477  std::optional<jtx::seq> const& seq,
+
478  std::optional<std::pair<Issue, Issue>> const& assets,
+
479  std::optional<ter> const& ter)
+
480 {
+
481  auto const& acct = account ? *account : creatorAccount_;
+
482  auto const lpTokens = getLPTokensBalance(acct);
+
483  jv[jss::Account] = acct.human();
+
484  setTokens(jv, assets);
+
485  jv[jss::TransactionType] = jss::AMMWithdraw;
+
486  if (fee_ != 0)
+
487  jv[jss::Fee] = std::to_string(fee_);
+
488  submit(jv, seq, ter);
+
489  return lpTokens - getLPTokensBalance(acct);
+
490 }
+
491 
+
492 IOUAmount
+
493 AMM::withdraw(
+
494  std::optional<Account> const& account,
+
495  std::optional<LPToken> const& tokens,
+
496  std::optional<STAmount> const& asset1Out,
+
497  std::optional<std::uint32_t> const& flags,
+
498  std::optional<ter> const& ter)
+
499 {
+
500  return withdraw(
+
501  account,
+
502  tokens,
+
503  asset1Out,
+
504  std::nullopt,
+
505  std::nullopt,
+
506  flags,
+
507  std::nullopt,
+
508  std::nullopt,
+
509  ter);
+
510 }
+
511 
+
512 IOUAmount
+
513 AMM::withdraw(
+
514  std::optional<Account> const& account,
+
515  STAmount const& asset1Out,
+
516  std::optional<STAmount> const& asset2Out,
+
517  std::optional<IOUAmount> const& maxEP,
+
518  std::optional<ter> const& ter)
+
519 {
+
520  assert(!(asset2Out && maxEP));
+
521  return withdraw(
+
522  account,
+
523  std::nullopt,
+
524  asset1Out,
+
525  asset2Out,
+
526  maxEP,
+
527  std::nullopt,
+
528  std::nullopt,
+
529  std::nullopt,
+
530  ter);
+
531 }
+
532 
+
533 IOUAmount
+
534 AMM::withdraw(
+
535  std::optional<Account> const& account,
+
536  std::optional<LPToken> const& tokens,
+
537  std::optional<STAmount> const& asset1Out,
+
538  std::optional<STAmount> const& asset2Out,
+
539  std::optional<IOUAmount> const& maxEP,
+
540  std::optional<std::uint32_t> const& flags,
+
541  std::optional<std::pair<Issue, Issue>> const& assets,
+
542  std::optional<jtx::seq> const& seq,
+
543  std::optional<ter> const& ter)
+
544 {
+
545  Json::Value jv;
+
546  if (tokens)
+
547  tokens->tokens(lptIssue_).setJson(jv[jss::LPTokenIn]);
+
548  if (asset1Out)
+
549  asset1Out->setJson(jv[jss::Amount]);
+
550  if (asset2Out)
+
551  asset2Out->setJson(jv[jss::Amount2]);
+
552  if (maxEP)
+
553  {
+
554  STAmount const saMaxEP{*maxEP, lptIssue_};
+
555  saMaxEP.setJson(jv[jss::EPrice]);
+
556  }
+
557  std::uint32_t jvflags = 0;
+
558  if (flags)
+
559  jvflags = *flags;
+
560  if (!(jvflags & tfWithdrawSubTx))
+
561  {
+
562  if (tokens && !asset1Out)
+
563  jvflags |= tfLPToken;
+
564  else if (asset1Out && asset2Out)
+
565  jvflags |= tfTwoAsset;
+
566  else if (tokens && asset1Out)
+
567  jvflags |= tfOneAssetLPToken;
+
568  else if (asset1Out && maxEP)
+
569  jvflags |= tfLimitLPToken;
+
570  else if (asset1Out)
+
571  jvflags |= tfSingleAsset;
+
572  }
+
573  jv[jss::Flags] = jvflags;
+
574  return withdraw(account, jv, seq, assets, ter);
+
575 }
+
576 
+
577 void
+
578 AMM::vote(
+
579  std::optional<Account> const& account,
+
580  std::uint32_t feeVal,
+
581  std::optional<std::uint32_t> const& flags,
+
582  std::optional<jtx::seq> const& seq,
+
583  std::optional<std::pair<Issue, Issue>> const& assets,
+
584  std::optional<ter> const& ter)
+
585 {
+
586  Json::Value jv;
+
587  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
+
588  setTokens(jv, assets);
+
589  jv[jss::TradingFee] = feeVal;
+
590  jv[jss::TransactionType] = jss::AMMVote;
+
591  if (flags)
+
592  jv[jss::Flags] = *flags;
+
593  if (fee_ != 0)
+
594  jv[jss::Fee] = std::to_string(fee_);
+
595  submit(jv, seq, ter);
+
596 }
+
597 
+
598 void
+
599 AMM::bid(
+
600  std::optional<Account> const& account,
+
601  std::optional<std::variant<int, IOUAmount, STAmount>> const& bidMin,
+
602  std::optional<std::variant<int, IOUAmount, STAmount>> const& bidMax,
+
603  std::vector<Account> const& authAccounts,
+
604  std::optional<std::uint32_t> const& flags,
+
605  std::optional<jtx::seq> const& seq,
+
606  std::optional<std::pair<Issue, Issue>> const& assets,
+
607  std::optional<ter> const& ter)
+
608 {
+
609  if (auto const amm =
+
610  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())))
+
611  {
+
612  if (amm->isFieldPresent(sfAuctionSlot))
+
613  {
+
614  auto const& auctionSlot =
+
615  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
+
616  lastPurchasePrice_ = auctionSlot[sfPrice].iou();
+
617  }
+
618  }
+
619  bidMin_ = std::nullopt;
+
620  bidMax_ = std::nullopt;
+
621 
+
622  Json::Value jv;
+
623  jv[jss::Account] = account ? account->human() : creatorAccount_.human();
+
624  setTokens(jv, assets);
+
625  auto getBid = [&](auto const& bid) {
+
626  if (std::holds_alternative<int>(bid))
+
627  return STAmount{lptIssue_, std::get<int>(bid)};
+
628  else if (std::holds_alternative<IOUAmount>(bid))
+
629  return toSTAmount(std::get<IOUAmount>(bid), lptIssue_);
+
630  else
+
631  return std::get<STAmount>(bid);
+
632  };
+
633  if (bidMin)
634  {
-
635  Json::Value accounts(Json::arrayValue);
-
636  for (auto const& account : authAccounts)
-
637  {
-
638  Json::Value acct;
-
639  Json::Value authAcct;
-
640  acct[jss::Account] = account.human();
-
641  authAcct[jss::AuthAccount] = acct;
-
642  accounts.append(authAcct);
-
643  }
-
644  jv[jss::AuthAccounts] = accounts;
-
645  }
-
646  if (flags)
-
647  jv[jss::Flags] = *flags;
-
648  jv[jss::TransactionType] = jss::AMMBid;
-
649  if (fee_ != 0)
-
650  jv[jss::Fee] = std::to_string(fee_);
-
651  submit(jv, seq, ter);
-
652 }
-
653 
-
654 void
-
655 AMM::submit(
-
656  Json::Value const& jv,
-
657  std::optional<jtx::seq> const& seq,
-
658  std::optional<ter> const& ter)
-
659 {
-
660  if (log_)
-
661  std::cout << jv.toStyledString();
-
662  if (msig_)
-
663  {
-
664  if (seq && ter)
-
665  env_(jv, *msig_, *seq, *ter);
-
666  else if (seq)
-
667  env_(jv, *msig_, *seq);
-
668  else if (ter)
-
669  env_(jv, *msig_, *ter);
-
670  else
-
671  env_(jv, *msig_);
-
672  }
-
673  else if (seq && ter)
-
674  env_(jv, *seq, *ter);
-
675  else if (seq)
-
676  env_(jv, *seq);
-
677  else if (ter)
-
678  env_(jv, *ter);
-
679  else
-
680  env_(jv);
-
681  if (doClose_)
-
682  env_.close();
-
683 }
-
684 
-
685 bool
-
686 AMM::expectAuctionSlot(auto&& cb) const
-
687 {
-
688  if (auto const amm =
-
689  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()));
-
690  amm && amm->isFieldPresent(sfAuctionSlot))
-
691  {
-
692  auto const& auctionSlot =
-
693  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
-
694  if (auctionSlot.isFieldPresent(sfAccount))
-
695  {
-
696  auto const slotFee = auctionSlot[sfDiscountedFee];
-
697  auto const slotInterval = ammAuctionTimeSlot(
-
698  env_.app().timeKeeper().now().time_since_epoch().count(),
-
699  auctionSlot);
-
700  auto const slotPrice = auctionSlot[sfPrice].iou();
-
701  auto const authAccounts = auctionSlot.getFieldArray(sfAuthAccounts);
-
702  return cb(slotFee, slotInterval, slotPrice, authAccounts);
-
703  }
-
704  }
-
705  return false;
-
706 }
-
707 
-
708 void
-
709 AMM::ammDelete(AccountID const& deleter, std::optional<ter> const& ter)
-
710 {
-
711  Json::Value jv;
-
712  jv[jss::Account] = to_string(deleter);
-
713  setTokens(jv);
-
714  jv[jss::TransactionType] = jss::AMMDelete;
-
715  if (fee_ != 0)
-
716  jv[jss::Fee] = std::to_string(fee_);
-
717  submit(jv, std::nullopt, ter);
+
635  STAmount saTokens = getBid(*bidMin);
+
636  saTokens.setJson(jv[jss::BidMin]);
+
637  bidMin_ = saTokens.iou();
+
638  }
+
639  if (bidMax)
+
640  {
+
641  STAmount saTokens = getBid(*bidMax);
+
642  saTokens.setJson(jv[jss::BidMax]);
+
643  bidMax_ = saTokens.iou();
+
644  }
+
645  if (authAccounts.size() > 0)
+
646  {
+
647  Json::Value accounts(Json::arrayValue);
+
648  for (auto const& account : authAccounts)
+
649  {
+
650  Json::Value acct;
+
651  Json::Value authAcct;
+
652  acct[jss::Account] = account.human();
+
653  authAcct[jss::AuthAccount] = acct;
+
654  accounts.append(authAcct);
+
655  }
+
656  jv[jss::AuthAccounts] = accounts;
+
657  }
+
658  if (flags)
+
659  jv[jss::Flags] = *flags;
+
660  jv[jss::TransactionType] = jss::AMMBid;
+
661  if (fee_ != 0)
+
662  jv[jss::Fee] = std::to_string(fee_);
+
663  submit(jv, seq, ter);
+
664 }
+
665 
+
666 void
+
667 AMM::submit(
+
668  Json::Value const& jv,
+
669  std::optional<jtx::seq> const& seq,
+
670  std::optional<ter> const& ter)
+
671 {
+
672  if (log_)
+
673  std::cout << jv.toStyledString();
+
674  if (msig_)
+
675  {
+
676  if (seq && ter)
+
677  env_(jv, *msig_, *seq, *ter);
+
678  else if (seq)
+
679  env_(jv, *msig_, *seq);
+
680  else if (ter)
+
681  env_(jv, *msig_, *ter);
+
682  else
+
683  env_(jv, *msig_);
+
684  }
+
685  else if (seq && ter)
+
686  env_(jv, *seq, *ter);
+
687  else if (seq)
+
688  env_(jv, *seq);
+
689  else if (ter)
+
690  env_(jv, *ter);
+
691  else
+
692  env_(jv);
+
693  if (doClose_)
+
694  env_.close();
+
695 }
+
696 
+
697 bool
+
698 AMM::expectAuctionSlot(auto&& cb) const
+
699 {
+
700  if (auto const amm =
+
701  env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()));
+
702  amm && amm->isFieldPresent(sfAuctionSlot))
+
703  {
+
704  auto const& auctionSlot =
+
705  static_cast<STObject const&>(amm->peekAtField(sfAuctionSlot));
+
706  if (auctionSlot.isFieldPresent(sfAccount))
+
707  {
+
708  auto const slotFee = auctionSlot[sfDiscountedFee];
+
709  auto const slotInterval = ammAuctionTimeSlot(
+
710  env_.app().timeKeeper().now().time_since_epoch().count(),
+
711  auctionSlot);
+
712  auto const slotPrice = auctionSlot[sfPrice].iou();
+
713  auto const authAccounts = auctionSlot.getFieldArray(sfAuthAccounts);
+
714  return cb(slotFee, slotInterval, slotPrice, authAccounts);
+
715  }
+
716  }
+
717  return false;
718 }
719 
-
720 namespace amm {
-
721 Json::Value
-
722 trust(AccountID const& account, STAmount const& amount, std::uint32_t flags)
-
723 {
-
724  if (isXRP(amount))
-
725  Throw<std::runtime_error>("trust() requires IOU");
-
726  Json::Value jv;
-
727  jv[jss::Account] = to_string(account);
-
728  jv[jss::LimitAmount] = amount.getJson(JsonOptions::none);
-
729  jv[jss::TransactionType] = jss::TrustSet;
-
730  jv[jss::Flags] = flags;
-
731  return jv;
-
732 }
+
720 void
+
721 AMM::ammDelete(AccountID const& deleter, std::optional<ter> const& ter)
+
722 {
+
723  Json::Value jv;
+
724  jv[jss::Account] = to_string(deleter);
+
725  setTokens(jv);
+
726  jv[jss::TransactionType] = jss::AMMDelete;
+
727  if (fee_ != 0)
+
728  jv[jss::Fee] = std::to_string(fee_);
+
729  submit(jv, std::nullopt, ter);
+
730 }
+
731 
+
732 namespace amm {
733 Json::Value
-
734 pay(Account const& account, AccountID const& to, STAmount const& amount)
+
734 trust(AccountID const& account, STAmount const& amount, std::uint32_t flags)
735 {
-
736  Json::Value jv;
-
737  jv[jss::Account] = account.human();
-
738  jv[jss::Amount] = amount.getJson(JsonOptions::none);
-
739  jv[jss::Destination] = to_string(to);
-
740  jv[jss::TransactionType] = jss::Payment;
-
741  jv[jss::Flags] = tfUniversal;
-
742  return jv;
-
743 }
-
744 } // namespace amm
-
745 } // namespace jtx
-
746 } // namespace test
-
747 } // namespace ripple
+
736  if (isXRP(amount))
+
737  Throw<std::runtime_error>("trust() requires IOU");
+
738  Json::Value jv;
+
739  jv[jss::Account] = to_string(account);
+
740  jv[jss::LimitAmount] = amount.getJson(JsonOptions::none);
+
741  jv[jss::TransactionType] = jss::TrustSet;
+
742  jv[jss::Flags] = flags;
+
743  return jv;
+
744 }
+
745 Json::Value
+
746 pay(Account const& account, AccountID const& to, STAmount const& amount)
+
747 {
+
748  Json::Value jv;
+
749  jv[jss::Account] = account.human();
+
750  jv[jss::Amount] = amount.getJson(JsonOptions::none);
+
751  jv[jss::Destination] = to_string(to);
+
752  jv[jss::TransactionType] = jss::Payment;
+
753  jv[jss::Flags] = tfUniversal;
+
754  return jv;
+
755 }
+
756 } // namespace amm
+
757 } // namespace jtx
+
758 } // namespace test
+
759 } // namespace ripple
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1021
Number root2(Number f)
Definition: Number.cpp:689
const SF_UINT16 sfDiscountedFee
A currency issued by an account.
Definition: Issue.h:35
const SF_ISSUE sfAsset
-
void ammDelete(AccountID const &deleter, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:709
+
void ammDelete(AccountID const &deleter, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:721
const std::optional< msig > msig_
Definition: AMM.h:77
+
AccountID const & ammAccount() const
Definition: AMM.h:255
Issue const & issue() const
Definition: STAmount.h:347
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
Definition: AMMCore.cpp:56
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
-
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< std::pair< Issue, Issue >> tokens=std::nullopt) const
Send amm_info RPC command.
Definition: AMM.cpp:136
A balance matches.
Definition: balance.h:38
const SF_AMOUNT sfLPTokenBalance
STL class.
@@ -838,19 +850,19 @@
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:226
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:375
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:642
-
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:566
-
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:734
+
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:578
+
Json::Value pay(Account const &account, AccountID const &to, STAmount const &amount)
Definition: AMM.cpp:746
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:113
const beast::Journal journal
Definition: Env.h:145
-
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:371
+
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:383
-
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:587
+
void bid(std::optional< Account > const &account, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMin=std::nullopt, std::optional< std::variant< int, IOUAmount, STAmount >> const &bidMax=std::nullopt, std::vector< Account > const &authAccounts={}, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:599
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
Application & app()
Definition: Env.h:242
Convenience class to test AMM functionality.
Definition: AMM.h:62
std::string toStyledString() const
virtual TimeKeeper & timeKeeper()=0
-
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
Definition: AMM.cpp:302
+
bool expectAmmInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, Json::Value const &jv) const
Definition: AMM.cpp:314
const Account creatorAccount_
Definition: AMM.h:65
const SF_AMOUNT sfPrice
IOUAmount iou() const
Definition: STAmount.cpp:349
@@ -858,18 +870,19 @@
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
XRPAmount xrp() const
Definition: STAmount.cpp:334
const SF_UINT16 sfTradingFee
-
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Definition: AMM.cpp:193
+
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Definition: AMM.cpp:203
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:29
+
Json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< Issue > issue1=std::nullopt, std::optional< Issue > issue2=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt, bool ignoreParams=false) const
Send amm_info RPC command.
Definition: AMM.cpp:136
Json::Value getJson(JsonOptions) const override
Definition: STIssue.cpp:63
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
+
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledger_index=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt) const
Definition: AMM.cpp:300
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
const SF_ISSUE sfAsset2
void setJson(Json::Value &) const
Definition: STAmount.cpp:517
static IOUAmount initialTokens(STAmount const &asset1, STAmount const &asset2)
Definition: AMM.cpp:42
-
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition: AMM.cpp:224
+
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Definition: AMM.cpp:234
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
-
bool expectAmmRpcInfo(STAmount const &asset1, STAmount const &asset2, IOUAmount const &balance, std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledger_index=std::nullopt) const
Definition: AMM.cpp:290
IOUAmount lastPurchasePrice_
Definition: AMM.h:73
@ none
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
@@ -883,29 +896,29 @@
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
std::optional< IOUAmount > bidMax_
Definition: AMM.h:75
Definition: STAmount.h:45
-
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:722
+
Json::Value trust(AccountID const &account, STAmount const &amount, std::uint32_t flags=0)
Definition: AMM.cpp:734
AMM(Env &env, Account const &account, STAmount const &asset1, STAmount const &asset2, bool log=false, std::uint16_t tfee=0, std::uint32_t fee=0, std::optional< std::uint32_t > flags=std::nullopt, std::optional< jtx::seq > seq=std::nullopt, std::optional< jtx::msig > ms=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:49
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
constexpr std::uint32_t tfSingleAsset
Definition: TxFlags.h:170
Definition: STIssue.h:31
-
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:274
+
bool expectTradingFee(std::uint16_t fee) const
Definition: AMM.cpp:284
Set the fee on a JTx.
Definition: fee.h:35
T swap(T... args)
const STAmount asset1_
Definition: AMM.h:66
-
IOUAmount withdraw(std::optional< Account > const &account, std::optional< LPToken > const &tokens, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:481
+
IOUAmount withdraw(std::optional< Account > const &account, std::optional< LPToken > const &tokens, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:493
Set the sequence number on a JTx.
Definition: seq.h:33
-
bool ammExists() const
Definition: AMM.cpp:282
+
bool ammExists() const
Definition: AMM.cpp:292
Definition: STObject.h:52
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
const STAmount asset2_
Definition: AMM.h:67
-
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt)
Definition: AMM.cpp:331
+
void setTokens(Json::Value &jv, std::optional< std::pair< Issue, Issue >> const &assets=std::nullopt)
Definition: AMM.cpp:343
constexpr std::uint32_t tfLPToken
Definition: TxFlags.h:167
Match set account flags.
Definition: flags.h:111
const AccountID ammAccount_
Definition: AMM.h:80
constexpr std::uint32_t tfDepositSubTx
Definition: TxFlags.h:178
-
IOUAmount tokens() const
Definition: AMM.h:263
+
IOUAmount tokens() const
Definition: AMM.h:267
T cbegin(T... args)
STL namespace.
constexpr std::uint32_t tfTwoAsset
Definition: TxFlags.h:171
@@ -913,14 +926,14 @@
@ nullValue
'null' value
Definition: json_value.h:36
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:104
-
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition: AMM.cpp:237
+
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
Definition: AMM.cpp:247
bool doClose_
Definition: AMM.h:71
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
AccountID create(std::uint32_t tfee=0, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::seq > const &seq=std::nullopt, std::optional< ter > const &ter=std::nullopt)
Definition: AMM.cpp:104
Immutable cryptographic account descriptor.
Definition: Account.h:37
const SF_ACCOUNT sfAccount
-
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
Definition: AMM.cpp:655
+
void submit(Json::Value const &jv, std::optional< jtx::seq > const &seq, std::optional< ter > const &ter)
Definition: AMM.cpp:667
T cend(T... args)
Definition: AMM.h:37
const std::uint32_t fee_
Definition: AMM.h:79
@@ -935,10 +948,10 @@
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:700
std::optional< std::uint8_t > ammAuctionTimeSlot(std::uint64_t current, STObject const &auctionSlot)
Get time slot of the auction slot.
Definition: AMMCore.cpp:107
Represents a JSON value.
Definition: json_value.h:145
-
std::tuple< STAmount, STAmount, STAmount > balances(Issue const &issue1, Issue const &issue2, std::optional< AccountID > const &account=std::nullopt) const
Get AMM balances for the token pair.
Definition: AMM.cpp:168
+
std::tuple< STAmount, STAmount, STAmount > balances(Issue const &issue1, Issue const &issue2, std::optional< AccountID > const &account=std::nullopt) const
Get AMM balances for the token pair.
Definition: AMM.cpp:178
constexpr std::uint32_t tfLimitLPToken
Definition: TxFlags.h:173
-
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition: AMM.cpp:207
+
IOUAmount getLPTokensBalance(std::optional< AccountID > const &account=std::nullopt) const
Definition: AMM.cpp:217