@acurast/cli
Version:
A cli to interact with the Acurast Cloud.
142 lines • 8.05 kB
JavaScript
import { getFeeAnalysis, toCacu } from '@acurast/sdk/matcher';
import { pluralize } from '../util/pluralize.js';
import { red, green, yellow } from 'ansis';
import { acurastColor } from '../util.js';
import { consoleOutput } from './console-output.js';
import { getSymbolForNetwork } from '../config.js';
import { BigNumber } from 'bignumber.js';
export const printFeeCosts = (config, options) => {
const log = consoleOutput(options.output);
const toAcurastColor = (text) => {
if (options.output === 'json') {
return text;
}
return acurastColor(text);
};
if (options.output === 'text') {
log(yellow('Note: Live market pricing is unavailable. The estimates below use a legacy formula and may not reflect actual processor prices. Re-run with network access for accurate pricing.'));
log('');
}
const symbol = getSymbolForNetwork(config.network);
const feeAnalysis = getFeeAnalysis(config);
const numberOfExecutions = feeAnalysis.numberOfExecutions.toNumber();
const numberOfReplicas = feeAnalysis.numberOfReplicas.toNumber();
const totalRuns = feeAnalysis.totalRuns.toNumber();
const suggestedCostPerExecution = feeAnalysis.suggestedCostPerExecution;
const maxCostPerExecution = feeAnalysis.maxCostPerExecution;
const maxCostPerExecutionCACU = feeAnalysis.maxCostPerExecutionCACU;
const maxCostPerExecutionPerReplicaCACU = feeAnalysis.maxCostPerExecutionPerReplicaCACU;
const excessCostPerExecution = feeAnalysis.excessCostPerExecution;
const excessCostPerExecutionPercentage = feeAnalysis.excessCostPerExecutionPercentage;
const maxTotalCostCACU = feeAnalysis.maxTotalCostCACU;
const suggestedFeeString = `Suggested fee: ${toAcurastColor(toCacu(suggestedCostPerExecution).toFixed())} ${symbol} (${suggestedCostPerExecution.toFixed()}), your max fee: ${toAcurastColor(toCacu(maxCostPerExecution).toFixed())} ${symbol} (${maxCostPerExecution.toFixed()}), excess: ${toAcurastColor(toCacu(excessCostPerExecution).toFixed())} ${symbol} (${excessCostPerExecution.toFixed()})`;
if (excessCostPerExecution.lt(0)) {
log(`${red(`The "maxExecutionFee" you set in acurast.json is below the suggested fee. There is a chance that your deployment will not get matched!`)}\n${suggestedFeeString}`);
log('');
}
else if (excessCostPerExecutionPercentage.gt(0.1)) {
log(`${red(`The "maxExecutionFee" you set in acurast.json is ${excessCostPerExecutionPercentage.multipliedBy(100).toFixed(0)}% above the suggested fee. It is possible that you are overpaying for your deployment!`)}\n${suggestedFeeString}`);
log('');
}
log(`There will be ${toAcurastColor(numberOfExecutions.toString())} ${pluralize(numberOfExecutions, 'execution')} with ${toAcurastColor(numberOfReplicas.toString())} ${pluralize(numberOfReplicas, 'replica')}. (Total runs: ${toAcurastColor(totalRuns.toString())})`);
log('');
log(`The maximum cost per execution is ${toAcurastColor(maxCostPerExecutionCACU.toString())} ${symbol}, which means each replica will cost ${toAcurastColor(maxCostPerExecutionPerReplicaCACU.toString())} ${symbol}.`);
log('');
log(`The total cost will be ${toAcurastColor(maxTotalCostCACU.toString())} ${symbol}.`);
log('');
};
const ACURAST_DECIMALS = 12;
function satoshiToDisplay(satoshi) {
return new BigNumber(satoshi).shiftedBy(-ACURAST_DECIMALS).toFixed();
}
export const printMatcherPricingInfo = (advice, config, options) => {
const log = consoleOutput(options.output);
const symbol = getSymbolForNetwork(config.network);
if (options.output === 'json') {
log('', JSON.stringify({
type: 'pricing',
status: advice.status,
matchable: advice.matchedProcessors >= advice.requiredProcessors,
matched_processors: advice.matchedProcessors,
required_processors: advice.requiredProcessors,
current_price: advice.currentPrice.toFixed(),
suggested_price: advice.suggestedPrice?.toFixed() ?? null,
average_price: advice.averagePrice?.toFixed() ?? null,
distribution: advice.distribution,
}));
return;
}
const toColor = (text) => acurastColor(text);
log('Processor pricing (live market data):');
log('');
log(` Your max price: ${toColor(satoshiToDisplay(advice.currentPrice))} ${symbol} per execution`);
if (advice.averagePrice) {
log(` Market average: ${toColor(satoshiToDisplay(advice.averagePrice))} ${symbol} per execution`);
}
if (advice.suggestedPrice) {
log(` Suggested price: ${toColor(satoshiToDisplay(advice.suggestedPrice))} ${symbol} per execution`);
}
log(` Matched processors: ${toColor(String(advice.matchedProcessors))} of ${toColor(String(advice.requiredProcessors))} required`);
log('');
// Distribution bar chart
if (advice.distribution.length > 0) {
log(' Price distribution (per execution):');
const maxCount = Math.max(...advice.distribution.map((b) => b.count));
const barWidth = 20;
for (const bucket of advice.distribution) {
const min = satoshiToDisplay(bucket.range_min);
const max = satoshiToDisplay(bucket.range_max);
const filled = maxCount > 0 ? Math.round((bucket.count / maxCount) * barWidth) : 0;
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
const countStr = String(bucket.count).padStart(4);
const bucketMin = new BigNumber(bucket.range_min);
const bucketMax = new BigNumber(bucket.range_max);
let marker = '';
if (advice.currentPrice.gte(bucketMin) &&
advice.currentPrice.lt(bucketMax)) {
marker = ' \u25C4 your price';
}
else if (advice.suggestedPrice &&
advice.suggestedPrice.gte(bucketMin) &&
advice.suggestedPrice.lt(bucketMax)) {
marker = ' \u25C4 suggested';
}
log(` ${min.padStart(10)} - ${max.padEnd(10)} ${symbol}: ${bar} ${countStr} ${pluralize(bucket.count, 'processor')}${marker}`);
}
// If the user's price is above all buckets, note it
const lastBucket = advice.distribution[advice.distribution.length - 1];
if (lastBucket &&
advice.currentPrice.gte(new BigNumber(lastBucket.range_max))) {
log(` ${''.padStart(10)} ${'(your price is above all buckets)'.padEnd(10)}`);
}
log('');
}
// Status message
if (advice.status === 'insufficient') {
if (advice.matchedProcessors === 0) {
log(red('No processors are available at your current price.'));
}
else {
log(red(`Not enough processors at your current price (${advice.matchedProcessors} of ${advice.requiredProcessors} required).`));
}
if (advice.suggestedPrice) {
log(`Suggested price: ${toColor(satoshiToDisplay(advice.suggestedPrice))} ${symbol} (covers ${advice.requiredProcessors} ${pluralize(advice.requiredProcessors, 'processor')})`);
}
log('');
}
else if (advice.status === 'overpaying') {
const savings = advice.suggestedPrice
? advice.currentPrice.minus(advice.suggestedPrice)
: null;
log(yellow(`Your price is significantly above what is needed to match ${advice.requiredProcessors} ${pluralize(advice.requiredProcessors, 'processor')}.`));
if (savings) {
log(`You could save ${toColor(satoshiToDisplay(savings))} ${symbol} per execution by lowering to ${toColor(satoshiToDisplay(advice.suggestedPrice))} ${symbol}.`);
}
log('');
}
else {
log(green(`Your price matches ${advice.matchedProcessors} ${pluralize(advice.matchedProcessors, 'processor')} (${advice.requiredProcessors} required).`));
log('');
}
};
//# sourceMappingURL=printFeeCosts.js.map