137 auto const& params(context.
params);
140 if (!params.isMember(jss::oracles))
142 if (!params[jss::oracles].isArray() || params[jss::oracles].size() == 0 ||
143 params[jss::oracles].size() > maxOracles)
149 if (!params.isMember(jss::base_asset))
152 if (!params.isMember(jss::quote_asset))
159 auto const& jv = params[field];
161 return jv.isUInt() || (jv.isInt() && jv.asInt() >= 0) ||
167 auto getField = [¶ms, &validUInt](
173 if (!validUInt(params, field))
175 return params[field].
asUInt();
187 if (params[field].asString().empty())
190 return params[field];
198 auto const trim = getField(jss::trim);
212 auto const timeThreshold = getField(jss::time_threshold, 0);
219 auto const baseAsset = getCurrency(sfBaseAsset, jss::base_asset);
225 auto const quoteAsset = getCurrency(sfQuoteAsset, jss::quote_asset);
235 for (
auto const& oracle : params[jss::oracles])
237 if (!oracle.isMember(jss::oracle_document_id) ||
238 !oracle.isMember(jss::account))
243 auto const documentID = validUInt(oracle, jss::oracle_document_id)
247 parseBase58<AccountID>(oracle[jss::account].asString());
248 if (!account || account->
isZero() || !documentID)
259 auto const sle = ledger->read(
keylet::oracle(*account, *documentID));
267 return o.getFieldCurrency(sfBaseAsset).getText() ==
268 std::get<Json::Value>(baseAsset) &&
269 o.getFieldCurrency(sfQuoteAsset).getText() ==
270 std::get<Json::Value>(quoteAsset) &&
271 o.isFieldPresent(sfAssetPrice);
273 iter != series.end())
275 auto const price = iter->getFieldU64(sfAssetPrice);
276 auto const scale = iter->isFieldPresent(sfScale)
277 ? -
static_cast<int>(iter->getFieldU8(sfScale))
279 prices.insert(Prices::value_type(
281 STAmount{noIssue(), price, scale}));
296 auto const latestTime = prices.left.
begin()->first;
302 auto const oldestTime = prices.left.rbegin()->first;
303 auto const upperBound =
304 latestTime > threshold ? (latestTime - threshold) : oldestTime;
305 if (upperBound > oldestTime)
307 prices.left.upper_bound(upperBound), prices.left.end());
320 result[jss::time] = latestTime;
323 auto const [avg, sd, size] =
324 getStats(prices.right.begin(), prices.right.end());
325 result[jss::entire_set][jss::mean] = avg.getText();
326 result[jss::entire_set][jss::size] = size;
327 result[jss::entire_set][jss::standard_deviation] =
to_string(sd);
329 auto itAdvance = [&](
auto it,
int distance) {
334 auto const median = [&prices, &itAdvance, &size_ = size]() {
335 auto const middle = size_ / 2;
336 if ((size_ % 2) == 0)
339 auto it = itAdvance(prices.right.begin(), middle - 1);
340 auto const& a1 = it->first;
341 auto const& a2 = (++it)->first;
344 return itAdvance(prices.right.begin(), middle)->first;
346 result[jss::median] = median.getText();
350 auto const trimCount =
353 auto const [avg, sd, size] =
getStats(
354 itAdvance(prices.right.begin(), trimCount),
355 itAdvance(prices.right.end(), -trimCount));
356 result[jss::trimmed_set][jss::mean] = avg.getText();
357 result[jss::trimmed_set][jss::size] = size;
358 result[jss::trimmed_set][jss::standard_deviation] =
to_string(sd);
LedgerMaster & ledgerMaster