56 .fee =
static_cast<int>(env.
current()->fees().base.drops()),
63 env.
fund(env.
current()->fees().accountReserve(0), owner);
67 .fee =
static_cast<int>(env.
current()->fees().base.drops()),
74 env.
current()->fees().accountReserve(1) + env.
current()->fees().base * 2, owner);
76 env, {.owner = owner, .fee =
static_cast<int>(env.
current()->fees().base.drops())});
77 BEAST_EXPECT(
oracle.exists());
82 {
"XRP",
"EUR", 740, 1},
83 {
"XRP",
"GBP", 740, 1},
84 {
"XRP",
"CNY", 740, 1},
85 {
"XRP",
"CAD", 740, 1},
86 {
"XRP",
"AUD", 740, 1},
88 .fee =
static_cast<int>(env.
current()->fees().base.drops()),
94 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
96 Oracle oracle(env, {.owner = owner, .fee = baseFee},
false);
105 .series = {{
"XRP",
"USD", 740, 1}, {
"XRP",
"USD", 750, 1}},
112 .series = {{
"XRP",
"USD", 740, 1}, {
"XRP",
"EUR", std::nullopt, 1}},
119 .series = {{
"XRP",
"USD", 740, 1}, {
"XRP",
"USD", std::nullopt, 1}},
125 .series = {{
"XRP",
"EUR", 740, 1}, {
"XRP",
"EUR", std::nullopt, 1}},
133 {{
"XRP",
"US1", 740, 1},
134 {
"XRP",
"US2", 750, 1},
135 {
"XRP",
"US3", 740, 1},
136 {
"XRP",
"US4", 750, 1},
137 {
"XRP",
"US5", 740, 1},
138 {
"XRP",
"US6", 750, 1},
139 {
"XRP",
"US7", 740, 1},
140 {
"XRP",
"US8", 750, 1},
141 {
"XRP",
"US9", 740, 1},
142 {
"XRP",
"U10", 750, 1},
143 {
"XRP",
"U11", 740, 1}},
152 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
157 CreateArg{.owner = owner, .series = {{{
"XRP",
"USD", 740, 1}}}, .fee = baseFee});
162 {
"XRP",
"US1", 740, 1},
163 {
"XRP",
"US2", 750, 1},
164 {
"XRP",
"US3", 740, 1},
165 {
"XRP",
"US4", 750, 1},
166 {
"XRP",
"US5", 740, 1},
167 {
"XRP",
"US6", 750, 1},
168 {
"XRP",
"US7", 740, 1},
169 {
"XRP",
"US8", 750, 1},
170 {
"XRP",
"US9", 740, 1},
171 {
"XRP",
"U10", 750, 1},
179 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
181 Oracle oracle(env, {.owner = owner, .fee = baseFee},
false);
186 .assetClass = std::nullopt,
187 .provider =
"provider",
192 .assetClass =
"currency",
193 .provider = std::nullopt,
201 BEAST_EXPECT(
oracle.exists());
204 .series = {{
"XRP",
"USD", 740, 1}},
205 .provider =
"provider1",
210 .series = {{
"XRP",
"USD", 740, 1}},
211 .assetClass =
"currency1",
218 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
220 Oracle oracle(env, {.owner = owner, .fee = baseFee},
false);
245 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
250 BEAST_EXPECT(
oracle.exists());
254 .series = {{
"XRP",
"USD", 740, 1}},
263 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
264 auto closeTime = [&]() {
266 env.
current()->header().closeTime.time_since_epoch() - 10'000s)
271 BEAST_EXPECT(
oracle.exists());
276 .series = {{
"XRP",
"USD", 740, 1}},
277 .lastUpdateTime =
static_cast<std::uint32_t>(closeTime() - 301),
283 .series = {{
"XRP",
"USD", 740, 1}},
284 .lastUpdateTime =
static_cast<std::uint32_t>(closeTime() + 311),
287 oracle.set(
UpdateArg{.series = {{
"XRP",
"USD", 740, 1}}, .fee = baseFee});
288 BEAST_EXPECT(
oracle.expectLastUpdateTime(
293 .series = {{
"XRP",
"USD", 740, 1}},
300 .series = {{
"XRP",
"USD", 740, 1}},
301 .lastUpdateTime =
static_cast<int>(
kEpochOffset.count() - 1),
309 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
312 BEAST_EXPECT(
oracle.exists());
315 .series = {{
"XRP",
"EUR", std::nullopt, std::nullopt}},
321 .series = {{
"XRP",
"USD", std::nullopt, std::nullopt}},
329 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
334 .series = {{
"USD",
"USD", 740, 1}},
342 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
355 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
360 .series = {{
"XRP",
"EUR", std::nullopt, std::nullopt}, {
"XRP",
"EUR", 740, 1}},
366 .series = {{
"XRP",
"EUR", std::nullopt, std::nullopt}},
373 .series = {{
"XRP",
"EUR", std::nullopt, std::nullopt}},
384 env, {.owner = owner, .fee =
static_cast<int>(env.
current()->fees().base.drops())});
397 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
400 Oracle const oracle(env, {.owner = owner, .series = series, .fee = baseFee});
401 BEAST_EXPECT(
oracle.exists());
403 auto const entry =
oracle.ledgerEntry();
404 BEAST_EXPECT(entry[jss::node][jss::Owner] == owner.
human());
405 if (features[fixIncludeKeyletFields])
407 BEAST_EXPECT(entry[jss::node][jss::OracleDocumentID] ==
oracle.documentID());
411 BEAST_EXPECT(!entry[jss::node].isMember(jss::OracleDocumentID));
413 BEAST_EXPECT(
oracle.expectLastUpdateTime(946694810));
418 Env env(*
this, features);
419 test(env, {{
"XRP",
"USD", 740, 1}}, 1);
424 Env env(*
this, features);
427 {{
"XRP",
"USD", 740, 1},
428 {
"BTC",
"USD", 740, 1},
429 {
"ETH",
"USD", 740, 1},
430 {
"CAN",
"USD", 740, 1},
431 {
"YAN",
"USD", 740, 1},
432 {
"GBP",
"USD", 740, 1}},
438 Env env(*
this, features);
439 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
444 BEAST_EXPECT(
oracle.exists());
446 CreateArg{.owner = some, .series = {{
"912810RR9",
"USD", 740, 1}}, .fee = baseFee});
458 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
462 BEAST_EXPECT(
oracle.exists());
475 Account const invalid(
"invalid");
494 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
496 Oracle oracle(env, {.owner = owner, .series = series, .fee = baseFee});
498 BEAST_EXPECT(
oracle.exists());
499 oracle.remove({.fee = baseFee});
500 BEAST_EXPECT(!
oracle.exists());
507 test(env, {{
"XRP",
"USD", 740, 1}}, 1);
516 {
"XRP",
"USD", 740, 1},
517 {
"BTC",
"USD", 740, 1},
518 {
"ETH",
"USD", 740, 1},
519 {
"CAN",
"USD", 740, 1},
520 {
"YAN",
"USD", 740, 1},
521 {
"GBP",
"USD", 740, 1},
529 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
531 auto const alice =
Account(
"alice");
532 auto const acctDelFee{
drops(env.
current()->fees().increment)};
536 env, {.owner = owner, .series = {{
"XRP",
"USD", 740, 1}}, .fee = baseFee});
541 .series = {{
"XRP",
"EUR", 740, 1}},
544 BEAST_EXPECT(
oracle.exists());
545 BEAST_EXPECT(oracle1.exists());
546 auto const index = env.
closed()->seq();
547 auto const hash = env.
closed()->header().hash;
548 for (
int i = 0; i < 256; ++i)
552 BEAST_EXPECT(!
oracle.exists());
553 BEAST_EXPECT(!oracle1.exists());
556 auto verifyLedgerData = [&](
auto const& field,
auto const& value) {
558 jvParams[field] = value;
559 jvParams[jss::binary] =
false;
560 jvParams[jss::type] = jss::oracle;
562 BEAST_EXPECT(jrr[jss::result][jss::state].
size() == 2);
564 verifyLedgerData(jss::ledger_index, index);
578 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
582 BEAST_EXPECT(
oracle.exists());
585 oracle.set(
UpdateArg{.series = {{
"XRP",
"USD", 740, 2}}, .fee = baseFee});
586 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 740, 2}}));
593 oracle.set(
UpdateArg{.series = {{
"XRP",
"EUR", 700, 2}}, .fee = baseFee});
594 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 0, 0}, {
"XRP",
"EUR", 700, 2}}));
601 .series = {{
"XRP",
"USD", 741, 2}, {
"XRP",
"EUR", 710, 2}}, .fee = baseFee});
602 BEAST_EXPECT(oracle.expectPrice({{
"XRP",
"USD", 741, 2}, {
"XRP",
"EUR", 710, 2}}));
604 BEAST_EXPECT(
ownerCount(env, owner) == count);
611 {
"BTC",
"USD", 741, 2},
612 {
"ETH",
"EUR", 710, 2},
613 {
"YAN",
"EUR", 710, 2},
614 {
"CAN",
"EUR", 710, 2},
618 BEAST_EXPECT(
ownerCount(env, owner) == count);
622 UpdateArg{.series = {{
"BTC",
"USD", std::nullopt, std::nullopt}}, .fee = baseFee});
626 {{
"XRP",
"USD", 742, 2},
627 {
"XRP",
"EUR", 711, 2},
628 {
"ETH",
"EUR", std::nullopt, std::nullopt},
629 {
"YAN",
"EUR", std::nullopt, std::nullopt},
630 {
"CAN",
"EUR", std::nullopt, std::nullopt}},
632 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 742, 2}, {
"XRP",
"EUR", 711, 2}}));
641 auto const baseFee =
static_cast<int>(env.current()->fees().base.drops());
643 env.current()->fees().accountReserve(1) + env.current()->fees().base * 2, owner);
645 oracle.set(UpdateArg{.series = {{
"XRP",
"USD", 742, 2}}, .fee = baseFee});
648 for (
bool const withFixOrder : {
false,
true})
654 auto const baseFee =
static_cast<int>(env.current()->fees().base.drops());
656 auto test = [&](Env& env,
DataSeries const& series) {
657 env.fund(
XRP(1'000), owner);
658 Oracle oracle(env, {.owner = owner, .series = series, .fee = baseFee});
659 BEAST_EXPECT(
oracle.exists());
660 auto sle = env.le(keylet::oracle(owner,
oracle.documentID()));
661 BEAST_EXPECT(sle->getFieldArray(sfPriceDataSeries).size() == series.size());
663 auto const beforeQuoteAssetName1 = sle->getFieldArray(sfPriceDataSeries)[0]
664 .getFieldCurrency(sfQuoteAsset)
666 auto const beforeQuoteAssetName2 = sle->getFieldArray(sfPriceDataSeries)[1]
667 .getFieldCurrency(sfQuoteAsset)
670 oracle.set(UpdateArg{.series = series, .fee = baseFee});
671 sle = env.le(keylet::oracle(owner,
oracle.documentID()));
673 auto const afterQuoteAssetName1 = sle->getFieldArray(sfPriceDataSeries)[0]
674 .getFieldCurrency(sfQuoteAsset)
676 auto const afterQuoteAssetName2 = sle->getFieldArray(sfPriceDataSeries)[1]
677 .getFieldCurrency(sfQuoteAsset)
680 if (env.current()->rules().enabled(fixPriceOracleOrder))
682 BEAST_EXPECT(afterQuoteAssetName1 == beforeQuoteAssetName1);
683 BEAST_EXPECT(afterQuoteAssetName2 == beforeQuoteAssetName2);
687 BEAST_EXPECT(afterQuoteAssetName1 != beforeQuoteAssetName1);
688 BEAST_EXPECT(afterQuoteAssetName2 != beforeQuoteAssetName2);
691 test(env, {{
"XRP",
"USD", 742, 2}, {
"XRP",
"EUR", 711, 2}});
703 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
711 env.
fund(
XRP(10'000), alice, becky, zelda, ed, bob);
716 env(
fset(alice, asfDisableMaster),
Sig(alice));
719 env(
signers(alice, 2, {{becky, 1}, {bogie, 1}, {ed, 2}}),
Sig(alie));
731 BEAST_EXPECT(
oracle.exists());
736 .series = {{
"XRP",
"USD", 740, 1}},
742 .series = {{
"XRP",
"USD", 740, 1}},
748 .series = {{
"XRP",
"USD", 741, 1}}, .msig =
Msig(becky, bogie), .fee = baseFee});
749 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 741, 1}}));
753 env.require(
Owners(alice, 1));
755 env(
signers(alice, 2, {{zelda, 1}, {bob, 1}, {ed, 2}}), Sig(alie));
760 .series = {{
"XRP",
"USD", 740, 1}},
761 .msig = Msig(becky, bogie),
763 .err = Ter(tefBAD_SIGNATURE)});
767 .series = {{
"XRP",
"USD", 7412, 2}}, .msig = Msig(zelda, bob), .fee = baseFee});
768 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 7412, 2}}));
770 UpdateArg{.series = {{
"XRP",
"USD", 74245, 3}}, .msig = Msig(ed), .fee = baseFee});
771 BEAST_EXPECT(
oracle.expectPrice({{
"XRP",
"USD", 74245, 3}}));
774 oracle.remove({.msig = Msig(bob), .fee = baseFee, .err = Ter(tefBAD_QUORUM)});
775 oracle.remove({.msig = Msig(becky), .fee = baseFee, .err = Ter(tefBAD_SIGNATURE)});
776 oracle.remove({.msig = Msig(ed), .fee = baseFee});
777 BEAST_EXPECT(!
oracle.exists());