130 auto const& params(context.
params);
133 if (!params.isMember(jss::oracles))
135 if (!params[jss::oracles].isArray() || params[jss::oracles].size() == 0 ||
136 params[jss::oracles].size() > maxOracles)
142 if (!params.isMember(jss::base_asset))
145 if (!params.isMember(jss::quote_asset))
151 auto const& jv = params[field];
153 return jv.isUInt() || (jv.isInt() && jv.asInt() >= 0) ||
159 auto getField = [¶ms, &validUInt](
164 if (!validUInt(params, field))
166 return params[field].
asUInt();
177 if (params[field].asString().empty())
180 return params[field];
188 auto const trim = getField(jss::trim);
201 auto const timeThreshold = getField(jss::time_threshold, 0);
208 auto const baseAsset = getCurrency(sfBaseAsset, jss::base_asset);
214 auto const quoteAsset = getCurrency(sfQuoteAsset, jss::quote_asset);
230 for (
auto const& oracle : params[jss::oracles])
232 if (!oracle.isMember(jss::oracle_document_id) || !oracle.isMember(jss::account))
237 auto const documentID = validUInt(oracle, jss::oracle_document_id)
240 auto const account = parseBase58<AccountID>(oracle[jss::account].asString());
241 if (!account || account->
isZero() || !documentID)
247 auto const sle = ledger->read(
keylet::oracle(*account, *documentID));
255 return o.getFieldCurrency(sfBaseAsset).getText() ==
256 std::get<Json::Value>(baseAsset) &&
257 o.getFieldCurrency(sfQuoteAsset).getText() ==
258 std::get<Json::Value>(quoteAsset) &&
259 o.isFieldPresent(sfAssetPrice);
261 iter != series.end())
263 auto const price = iter->getFieldU64(sfAssetPrice);
264 auto const scale = iter->isFieldPresent(sfScale)
265 ? -
static_cast<int>(iter->getFieldU8(sfScale))
284 auto const latestTime = prices.left.
begin()->first;
290 auto const oldestTime = prices.left.rbegin()->first;
291 auto const upperBound = latestTime > threshold ? (latestTime - threshold) : oldestTime;
292 if (upperBound > oldestTime)
293 prices.left.erase(prices.left.upper_bound(upperBound), prices.left.end());
306 result[jss::time] = latestTime;
309 auto const [avg, sd, size] =
getStats(prices.right.begin(), prices.right.end());
310 result[jss::entire_set][jss::mean] = avg.getText();
311 result[jss::entire_set][jss::size] = size;
312 result[jss::entire_set][jss::standard_deviation] =
to_string(sd);
314 auto itAdvance = [&](
auto it,
int distance) {
319 auto const median = [&prices, &itAdvance, &size_ = size]() {
320 auto const middle = size_ / 2;
321 if ((size_ % 2) == 0)
324 auto it = itAdvance(prices.right.begin(), middle - 1);
325 auto const& a1 = it->first;
326 auto const& a2 = (++it)->first;
329 return itAdvance(prices.right.begin(), middle)->first;
331 result[jss::median] = median.getText();
337 auto const [avg, sd, size] =
getStats(
338 itAdvance(prices.right.begin(), trimCount), itAdvance(prices.right.end(), -trimCount));
339 result[jss::trimmed_set][jss::mean] = avg.getText();
340 result[jss::trimmed_set][jss::size] = size;
341 result[jss::trimmed_set][jss::standard_deviation] =
to_string(sd);
LedgerMaster & ledgerMaster