127 auto const& params(context.
params);
130 if (!params.isMember(jss::oracles))
132 if (!params[jss::oracles].isArray() || params[jss::oracles].size() == 0 || params[jss::oracles].size() > maxOracles)
138 if (!params.isMember(jss::base_asset))
141 if (!params.isMember(jss::quote_asset))
147 auto const& jv = params[field];
149 return jv.isUInt() || (jv.isInt() && jv.asInt() >= 0) ||
155 auto getField = [¶ms, &validUInt](
160 if (!validUInt(params, field))
162 return params[field].
asUInt();
173 if (params[field].asString().empty())
176 return params[field];
184 auto const trim = getField(jss::trim);
196 auto const timeThreshold = getField(jss::time_threshold, 0);
203 auto const baseAsset = getCurrency(sfBaseAsset, jss::base_asset);
209 auto const quoteAsset = getCurrency(sfQuoteAsset, jss::quote_asset);
219 for (
auto const& oracle : params[jss::oracles])
221 if (!oracle.isMember(jss::oracle_document_id) || !oracle.isMember(jss::account))
226 auto const documentID = validUInt(oracle, jss::oracle_document_id)
229 auto const account = parseBase58<AccountID>(oracle[jss::account].asString());
230 if (!account || account->isZero() || !documentID)
241 auto const sle = ledger->read(
keylet::oracle(*account, *documentID));
249 return o.getFieldCurrency(sfBaseAsset).getText() == std::get<Json::Value>(baseAsset) &&
250 o.getFieldCurrency(sfQuoteAsset).getText() == std::get<Json::Value>(quoteAsset) &&
251 o.isFieldPresent(sfAssetPrice);
253 iter != series.end())
255 auto const price = iter->getFieldU64(sfAssetPrice);
256 auto const scale = iter->isFieldPresent(sfScale) ? -
static_cast<int>(iter->getFieldU8(sfScale)) : 0;
258 Prices::value_type(node.
getFieldU32(sfLastUpdateTime),
STAmount{noIssue(), price, scale}));
273 auto const latestTime = prices.left.
begin()->first;
279 auto const oldestTime = prices.left.rbegin()->first;
280 auto const upperBound = latestTime > threshold ? (latestTime - threshold) : oldestTime;
281 if (upperBound > oldestTime)
282 prices.left.erase(prices.left.upper_bound(upperBound), prices.left.end());
295 result[jss::time] = latestTime;
298 auto const [avg, sd, size] =
getStats(prices.right.begin(), prices.right.end());
299 result[jss::entire_set][jss::mean] = avg.getText();
300 result[jss::entire_set][jss::size] = size;
301 result[jss::entire_set][jss::standard_deviation] =
to_string(sd);
303 auto itAdvance = [&](
auto it,
int distance) {
308 auto const median = [&prices, &itAdvance, &size_ = size]() {
309 auto const middle = size_ / 2;
310 if ((size_ % 2) == 0)
313 auto it = itAdvance(prices.right.begin(), middle - 1);
314 auto const& a1 = it->first;
315 auto const& a2 = (++it)->first;
318 return itAdvance(prices.right.begin(), middle)->first;
320 result[jss::median] = median.getText();
326 auto const [avg, sd, size] =
327 getStats(itAdvance(prices.right.begin(), trimCount), itAdvance(prices.right.end(), -trimCount));
328 result[jss::trimmed_set][jss::mean] = avg.getText();
329 result[jss::trimmed_set][jss::size] = size;
330 result[jss::trimmed_set][jss::standard_deviation] =
to_string(sd);
LedgerMaster & ledgerMaster