Skip to content

Commit

Permalink
Add outputJSON option & Rename ethPrice to tokenPrice (#178)
Browse files Browse the repository at this point in the history
  • Loading branch information
cgewecke authored Feb 20, 2024
1 parent 354a3f4 commit 31c48ae
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ typings/
test/projects/options/artifacts
test/projects/options/cache
test/projects/options/gasReporterOutput.json
test/projects/options/gas.json
test/projects/options/testGasReport.txt

test/projects/waffle/artifacts
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const TASK_GAS_REPORTER_START = "gas-reporter:start";
export const TASK_GAS_REPORTER_STOP = "gas-reporter:stop";

export const DEFAULT_CURRENCY = "USD";
export const DEFAULT_JSON_OUTPUT_FILE = "./gasReporterOutput.json";
export const DEFAULT_GAS_PRICE_API_URL = "https://api.etherscan.io/api?module=proxy&action=eth_gasPrice"
export const DEFAULT_COINMARKET_BASE_URL = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/"
16 changes: 8 additions & 8 deletions src/lib/gasData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ export class GasData {
const total = method.gasData.reduce((acc: number, datum: number) => acc + datum, 0);
method.average = Math.round(total / method.gasData.length);
method.cost =
options.ethPrice && options.gasPrice
options.tokenPrice && options.gasPrice
? gasToCost(
method.average,
options.ethPrice,
options.tokenPrice,
options.gasPrice
)
: undefined;
Expand All @@ -146,10 +146,10 @@ export class GasData {
deployment.percent = gasToPercentOfLimit(deployment.average, blockGasLimit);

deployment.cost =
options.ethPrice && options.gasPrice
options.tokenPrice && options.gasPrice
? gasToCost(
deployment.average,
options.ethPrice,
options.tokenPrice,
options.gasPrice
)
: undefined;
Expand All @@ -165,20 +165,20 @@ export class GasData {

hre.__hhgrec.methodsTotalGas = methodsTotal;
hre.__hhgrec.methodsTotalCost =
options.ethPrice && options.gasPrice
options.tokenPrice && options.gasPrice
? gasToCost(
methodsTotal,
options.ethPrice,
options.tokenPrice,
options.gasPrice
)
: undefined;

hre.__hhgrec.deploymentsTotalGas = deploymentsTotal;
hre.__hhgrec.deploymentsTotalCost =
options.ethPrice && options.gasPrice
options.tokenPrice && options.gasPrice
? gasToCost(
deploymentsTotal,
options.ethPrice,
options.tokenPrice,
options.gasPrice
)
: undefined;
Expand Down
4 changes: 3 additions & 1 deletion src/lib/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DEFAULT_CURRENCY, DEFAULT_GAS_PRICE_API_URL } from "../constants";
import { DEFAULT_CURRENCY, DEFAULT_GAS_PRICE_API_URL, DEFAULT_JSON_OUTPUT_FILE } from "../constants";

import { GasReporterOptions } from "../types";

Expand All @@ -13,6 +13,8 @@ export function getDefaultOptions(): GasReporterOptions {
gasPriceApi: DEFAULT_GAS_PRICE_API_URL,
noColors: false,
showUncalledMethods: false,
outputJSON: false,
outputJSONFile: DEFAULT_JSON_OUTPUT_FILE,
proxyResolver: null,
rst: false,
rstTitle: "",
Expand Down
12 changes: 6 additions & 6 deletions src/lib/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ export class GasDetailsTextTable {
];

let methodSubtitle;
if (options.ethPrice && options.gasPrice) {
if (options.tokenPrice && options.gasPrice) {
const gwei = options.gasPrice;
const rate = parseFloat(options.ethPrice.toString()).toFixed(2);
const rate = parseFloat(options.tokenPrice.toString()).toFixed(2);
const currency = `${options.currency!.toLowerCase()}`;
const token = `${options.token!.toLowerCase()}`;

Expand Down Expand Up @@ -244,7 +244,9 @@ export class GasDetailsTextTable {
console.log(tableOutput);
}

this.writeJSON(data, options);
if (options.outputJSON || process.env.CI) {
this.writeJSON(data, options);
}
}

/**
Expand All @@ -261,8 +263,6 @@ export class GasDetailsTextTable {
data
};

if (process.env.CI) {
fs.writeFileSync("./gasReporterOutput.json", JSON.stringify(output));
}
fs.writeFileSync(options.outputJSONFile!, JSON.stringify(output));
}
}
60 changes: 47 additions & 13 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,61 @@ declare module "hardhat/types/config" {
}

export interface GasReporterOptions {
/**@property API key to access token/currency market price data with */
coinmarketcap?: string;

/**@property Coinmarketcap currency code to denominate network token costs in (eg: "USD") */
currency?: string;
token?: string;
ethPrice?: string;

/**@property Enable plugin */
enabled?: boolean;

/**@property List of contract names to exclude from report (e.g "Ownable") */
excludeContracts?: string[];

/**@property Gwei price per gas unit (eg: 20) */
gasPrice?: number;

/**@property Etherscan-like url to fetch live network gas price from */
gasPriceApi?: string;
coinmarketcap?: string;
outputFile?: string;

/**@property Omit terminal color in output */
noColors?: boolean;
showUncalledMethods?: boolean;

/**@property Relative path to a file to output terminal table to (instead of stdout) */
outputFile?: string;

/**@property Write JSON object with all options, methods, deployment data to file */
outputJSON?: boolean

/**@property: Relative path to a file to output JSON data to */
outputJSONFile?: string,

/**@property User-defined async function to help reporter identify targets of proxied calls */
proxyResolver?: any;

/**@property List of forked-network deployed contracts to track execution costs for */
remoteContracts?: RemoteContract[];

/**@property Format table output for `rst` documentation (eg sphinx, ReadTheDocs) */
rst?: boolean;

/**@property Optional title for `rst` documentation */
rstTitle?: string;
showTimeSpent?: boolean;
excludeContracts?: string[];
proxyResolver?: any;

/**@property Display the complete function signature of methods */
showMethodSig?: boolean;
maxMethodDiff?: number;
maxDeploymentDiff?: number;
enabled?: boolean;
remoteContracts?: RemoteContract[];

// Hardhat internals
/**@property Lists all methods and deployments, even if no transactions were recorded for them */
showUncalledMethods?: boolean;

/**@property Network token gas fees are paid in (eg:"ETH") */
token?: string;

/**@property Network token price per currency unit, to two decimal places (eg: "2145.00") */
tokenPrice?: string;

// INTERNAL: AUTOSET BY PLUGIN (ignore)
solcInfo?: any;
blockLimit?: number;
}
Expand Down
14 changes: 7 additions & 7 deletions src/utils/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { GasReporterOptions } from "../types";
/**
* Expresses gas usage as a nation-state currency price
* @param {Number} gas gas used
* @param {Number} ethPrice e.g chf/eth
* @param {Number} tokenPrice e.g chf/eth
* @param {Number} gasPrice in wei e.g 5000000000 (5 gwei)
* @return {Number} cost of gas used (0.00)
*/
export function gasToCost(gas: number, ethPrice: string, gasPrice: number): string {
return ((gasPrice / 1e9) * gas * parseFloat(ethPrice)).toFixed(2);
export function gasToCost(gas: number, tokenPrice: string, gasPrice: number): string {
return ((gasPrice / 1e9) * gas * parseFloat(tokenPrice)).toFixed(2);
}

/**
Expand All @@ -34,12 +34,12 @@ export function hexGasToDecimal(val: string): number {

/**
* Fetches gasPrices from etherscan and current market value of eth in currency specified by
* the options from coinmarketcap (defaults to usd). Sets options.ethPrice, options.gasPrice
* the options from coinmarketcap (defaults to usd). Sets options.tokenPrice, options.gasPrice
* unless these are already set as constants in the reporter options
* @param {GasReporterOptions} options
*/
export async function setGasAndPriceRates(options: GasReporterOptions): Promise<void> {
if ((options.ethPrice && options.gasPrice) || !options.coinmarketcap) return;
if ((options.tokenPrice && options.gasPrice) || !options.coinmarketcap) return;

const token = options.token!.toUpperCase();
const gasPriceApi = options.gasPriceApi;
Expand All @@ -56,10 +56,10 @@ export async function setGasAndPriceRates(options: GasReporterOptions): Promise<
const currencyPath = `${requestArgs}${currencyKey}`;

// Currency market data: coinmarketcap
if (!options.ethPrice) {
if (!options.tokenPrice) {
try {
const response = await axiosInstance.get(currencyPath);
options.ethPrice = response.data.data[token].quote[
options.tokenPrice = response.data.data[token].quote[
currencyKey
].price.toFixed(2);
} catch (error) {
Expand Down
4 changes: 3 additions & 1 deletion test/integration/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { assert } from "chai";
import { TASK_TEST } from "hardhat/builtin-tasks/task-names";
import path from "path";

import { DEFAULT_GAS_PRICE_API_URL } from "../../src/constants";
import { DEFAULT_GAS_PRICE_API_URL, DEFAULT_JSON_OUTPUT_FILE } from "../../src/constants";
import { Deployment, GasReporterOptions, GasReporterOutput, MethodData } from "../types";

import { useEnvironment, findMethod, findDeployment } from "../helpers";
Expand Down Expand Up @@ -48,6 +48,8 @@ describe("Default Options", function () {
assert.equal(options.rstTitle, "");
assert.equal(options.showMethodSig, false);
assert.equal(options.token, "ETH");
assert.equal(options.outputJSON, false);
assert.equal(options.outputJSONFile, DEFAULT_JSON_OUTPUT_FILE);

// Make sure we didn't hit endpoint
assert.equal(options.gasPrice, undefined);
Expand Down
2 changes: 1 addition & 1 deletion test/integration/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe("Independent Node: Hardhat", function () {
);
const outputPath = path.resolve(
__dirname,
"../projects/options/gasReporterOutput.json"
"../projects/options/gas.json"
);

const network = undefined;
Expand Down
4 changes: 2 additions & 2 deletions test/integration/options.a.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ describe("Options A", function () {
})

it("fetched a currency price", function () {
assert.exists(options.ethPrice);
assert.isNumber(parseFloat(options.ethPrice!));
assert.exists(options.tokenPrice);
assert.isNumber(parseFloat(options.tokenPrice!));
});

it("fetched a gas price", function() {
Expand Down
13 changes: 11 additions & 2 deletions test/integration/options.b.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { TASK_TEST } from "hardhat/builtin-tasks/task-names";
// eslint-disable-next-line import/no-extraneous-dependencies
import { assert } from "chai";
import path from "path";
import fs from "fs";
import { GasReporterOptions, GasReporterOutput } from "../types";
Expand All @@ -14,9 +16,10 @@ describe("Options B", function () {
"../projects/options"
);

// NB: test sets the outputJSONFile option
const outputPath = path.resolve(
__dirname,
"../projects/options/gasReporterOutput.json"
"../projects/options/gas.json"
);

const network = undefined;
Expand All @@ -30,7 +33,13 @@ describe("Options B", function () {
options = output.options;
})

it("wrote to file", function () {
it("set the options correctly", function(){
assert.equal(options.token, "ETC");
assert.equal(options.tokenPrice, "200.00");
assert.equal(options.gasPrice, 40);
});

it("wrote table to file", function () {
const outputFileOption = options.outputFile;
const outputFilePath = path.resolve(
__dirname,
Expand Down
4 changes: 4 additions & 0 deletions test/projects/options/hardhat.options.b.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ const config: HardhatUserConfig = {
},
gasReporter: {
enabled: true,
token: "ETC",
tokenPrice: "200.00",
gasPrice: 40,
showUncalledMethods: true,
outputFile: "./testGasReport.txt",
outputJSONFile: "./gas.json",
}
};

Expand Down

0 comments on commit 31c48ae

Please sign in to comment.