Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 5x 5x 5x 5x 46x 46x 46x 115x 5x 115x 115x 157x 115x 46x 115x 122x 5x 46x 46x 115x 157x 157x 46x | import {
SignedDataPackage,
SignedDataPackagePlainObj,
} from "@redstone-finance/protocol";
import { MathUtils, SafeNumber } from "@redstone-finance/utils";
import _ from "lodash";
export const pickDataFeedPackagesClosestToMedian = (
dataFeedPackages: SignedDataPackagePlainObj[],
count: number
): SignedDataPackage[] => {
const allValues = getAllValues(dataFeedPackages) as Record<string, number[]>;
const allMedians = _.mapValues(allValues, MathUtils.getMedian);
return sortByDistanceFromMedian(dataFeedPackages, allMedians)
.map((diff) => SignedDataPackage.fromObj(diff.dp))
.slice(0, count);
};
const getMaxDistanceFromMedian = (
dataPackage: SignedDataPackagePlainObj,
medians: Record<string, number>
) => {
let maxDistanceFromMedian = 0;
for (const dataPoint of dataPackage.dataPoints) {
maxDistanceFromMedian = Math.max(
maxDistanceFromMedian,
SafeNumber.createSafeNumber(dataPoint.value)
.sub(medians[dataPoint.dataFeedId])
.abs()
.div(medians[dataPoint.dataFeedId])
.unsafeToNumber()
);
}
return maxDistanceFromMedian;
};
function sortByDistanceFromMedian(
dataFeedPackages: SignedDataPackagePlainObj[],
medians: Record<string, number>
) {
return dataFeedPackages
.map((dp) => ({
dp,
diff: getMaxDistanceFromMedian(dp, medians),
}))
.sort((first, second) => first.diff - second.diff);
}
const getAllValues = (dataPackages: SignedDataPackagePlainObj[]) => {
const allValues: Partial<Record<string, number[]>> = {};
for (const dataPackage of dataPackages) {
for (const dataPoint of dataPackage.dataPoints) {
allValues[dataPoint.dataFeedId] ??= [];
allValues[dataPoint.dataFeedId]!.push(Number(dataPoint.value));
}
}
return allValues;
};
|