import { EthGasReporterOutput } from './types';
/**
* Try to merge several gas reporter output objects into one. It will also
* validate that the config are the same to make sure that the reports were
* generated by the same source.
*/
export function mergeReports(reports: EthGasReporterOutput[]): EthGasReporterOutput {
const result: EthGasReporterOutput = {
namespace: null,
config: null,
info: {
methods: {},
deployments: [],
blockLimit: null,
},
};
for (const report of reports) {
if (!result.config) result.config = report.config;
if (!result.namespace) {
result.namespace = report.namespace;
}
if (result.namespace !== report.namespace) {
throw new Error('Cannot merge reports with different namespaces');
}
// Update config.gasPrice only if the newer one has a bigger number
if (typeof report.config.gasPrice === 'number') {
if (
typeof result.config.gasPrice !== 'number' ||
result.config.gasPrice < report.config.gasPrice
) {
result.config.gasPrice = report.config.gasPrice;
}
} else {
result.config.gasPrice = report.config.gasPrice;
}
if (!report.info || typeof report.info.blockLimit !== 'number') {
throw new Error(`Invalid "info" property for given report`);
}
if (!result.info.blockLimit) {
result.info.blockLimit = report.info.blockLimit;
} else if (result.info.blockLimit !== report.info.blockLimit) {
throw new Error('"info.blockLimit" should be the same on all reports');
}
if (!report.info.methods) {
throw new Error(`Missing "info.methods" property on given report`);
}
// Merge info.methods objects
Object.entries(report.info.methods).forEach(([key, value]) => {
if (!result.info.methods[key]) {
result.info.methods[key] = value;
return;
}
result.info.methods[key].gasData = [
...result.info.methods[key].gasData,
...report.info.methods[key].gasData,
].sort((a, b) => a - b);
result.info.methods[key].numberOfCalls += report.info.methods[key].numberOfCalls;
});
if (!Array.isArray(report.info.deployments)) {
throw new Error(`Invalid "info.deployments" property on given report`);
}
// Merge info.deployments objects
report.info.deployments.forEach(deployment => {
const current = result.info.deployments.find(d => d.name === deployment.name);
if (current) {
current.gasData = [...current.gasData, ...deployment.gasData].sort((a, b) => a - b);
} else {
result.info.deployments.push(deployment);
}
});
}
return result
}