eth-gas-reporter
Advanced tools
Comparing version 0.0.10 to 0.0.11
## Changelog: eth-gas-reporter | ||
0.0.10 / 2017-10-22 | ||
================== | ||
* Add examples | ||
0.0.10 / 2017-10-22 | ||
================== | ||
* Filter deployment calls that throw from the stats | ||
0.0.8 / 2017-10-22 | ||
================= | ||
* Filter method calls that throw from the stats | ||
@@ -6,0 +17,0 @@ * Add deployment stats |
135
gasStats.js
@@ -14,3 +14,3 @@ /** | ||
const blockLimit = 6718946; | ||
const blockLimit = 6718946 | ||
/** | ||
@@ -24,4 +24,4 @@ * Expresses gas usage as a nation-state currency price | ||
function gasToCost (gas, ethPrice, gasPrice) { | ||
ethPrice = parseFloat(ethPrice); | ||
gasPrice = parseInt(gasPrice); | ||
ethPrice = parseFloat(ethPrice) | ||
gasPrice = parseInt(gasPrice) | ||
return ((gasPrice / 1e18) * gas * ethPrice).toFixed(2) | ||
@@ -36,4 +36,4 @@ } | ||
*/ | ||
function gasToPercentOfLimit(gasUsed){ | ||
return Math.round(1000 * gasUsed / blockLimit) / 10; | ||
function gasToPercentOfLimit (gasUsed) { | ||
return Math.round(1000 * gasUsed / blockLimit) / 10 | ||
} | ||
@@ -62,3 +62,3 @@ | ||
// Compose rows | ||
const methodRows = []; | ||
const methodRows = [] | ||
@@ -68,25 +68,25 @@ _.forEach(methodMap, (data, methodId) => { | ||
let stats = {}; | ||
let stats = {} | ||
if (data.gasData.length){ | ||
if (data.gasData.length) { | ||
const total = data.gasData.reduce((acc, datum) => acc + datum, 0) | ||
stats.average = Math.round(total / data.gasData.length) | ||
stats.average = Math.round(total / data.gasData.length) | ||
stats.cost = (ethPrice && gasPrice) ? gasToCost(stats.average, ethPrice, gasPrice) : '-'.grey | ||
} else { | ||
stats.average = '-'.grey; | ||
stats.cost = '-'.grey; | ||
stats.average = '-'.grey | ||
stats.cost = '-'.grey | ||
} | ||
const sortedData = data.gasData.sort((a,b) => a - b); | ||
const sortedData = data.gasData.sort((a, b) => a - b) | ||
stats.min = sortedData[0] | ||
stats.max = sortedData[sortedData.length - 1] | ||
const uniform = (stats.min === stats.max); | ||
stats.min = (uniform) ? '-' : stats.min.toString().yellow; | ||
stats.max = (uniform) ? '-' : stats.max.toString().red; | ||
const uniform = (stats.min === stats.max) | ||
stats.min = (uniform) ? '-' : stats.min.toString().yellow | ||
stats.max = (uniform) ? '-' : stats.max.toString().red | ||
stats.numberOfCalls = data.numberOfCalls.toString().grey; | ||
stats.numberOfCalls = data.numberOfCalls.toString().grey | ||
const section = []; | ||
section.push(data.contract.grey); | ||
const section = [] | ||
section.push(data.contract.grey) | ||
section.push(data.method) | ||
@@ -99,29 +99,28 @@ section.push({hAlign: 'right', content: stats.min}) | ||
methodRows.push(section); | ||
methodRows.push(section) | ||
}) | ||
const deployRows = []; | ||
const deployRows = [] | ||
deployMap.sort((a,b) => a.name.localeCompare(b.name)); | ||
deployMap.sort((a, b) => a.name.localeCompare(b.name)) | ||
deployMap.forEach(contract => { | ||
let stats = {}; | ||
if (!contract.gasData.length) return; | ||
let stats = {} | ||
if (!contract.gasData.length) return | ||
const total = contract.gasData.reduce((acc, datum) => acc + datum, 0) | ||
stats.average = Math.round(total / contract.gasData.length) | ||
stats.percent = gasToPercentOfLimit(stats.average); | ||
stats.cost = (ethPrice && gasPrice) ? gasToCost(stats.average, ethPrice, gasPrice) : '-'.grey; | ||
stats.average = Math.round(total / contract.gasData.length) | ||
stats.percent = gasToPercentOfLimit(stats.average) | ||
stats.cost = (ethPrice && gasPrice) ? gasToCost(stats.average, ethPrice, gasPrice) : '-'.grey | ||
const sortedData = contract.gasData.sort((a,b) => a - b); | ||
const sortedData = contract.gasData.sort((a, b) => a - b) | ||
stats.min = sortedData[0] | ||
stats.max = sortedData[sortedData.length - 1] | ||
const uniform = (stats.min === stats.max); | ||
stats.min = (uniform) ? '-' : stats.min.toString().yellow; | ||
stats.max = (uniform) ? '-' : stats.max.toString().red; | ||
const uniform = (stats.min === stats.max) | ||
stats.min = (uniform) ? '-' : stats.min.toString().yellow | ||
stats.max = (uniform) ? '-' : stats.max.toString().red | ||
section = []; | ||
section.push({hAlign: 'left', colSpan: 2, content: contract.name}); | ||
const section = [] | ||
section.push({hAlign: 'left', colSpan: 2, content: contract.name}) | ||
section.push({hAlign: 'right', content: stats.min}) | ||
@@ -133,12 +132,14 @@ section.push({hAlign: 'right', content: stats.max}) | ||
deployRows.push(section); | ||
}); | ||
deployRows.push(section) | ||
}) | ||
// Format table | ||
const table = new Table({ | ||
style:{head:[], border:[], 'padding-left': 2, 'padding-right': 2}, | ||
chars: {'mid': '·', 'top-mid': '·', 'left-mid': '·', 'mid-mid': '·', 'right-mid': '·', | ||
'top-left': '·', 'top-right': '·', 'bottom-left': '·', 'bottom-right': '·', | ||
'middle': '·', 'top': '-', 'bottom': '-', 'bottom-mid': '-'} | ||
}); | ||
style: {head: [], border: [], 'padding-left': 2, 'padding-right': 2}, | ||
chars: { | ||
'mid': '·', 'top-mid': '·', 'left-mid': '·', 'mid-mid': '·', 'right-mid': '·', | ||
'top-left': '·', 'top-right': '·', 'bottom-left': '·', 'bottom-right': '·', | ||
'middle': '·', 'top': '-', 'bottom': '-', 'bottom-mid': '-' | ||
} | ||
}) | ||
@@ -149,8 +150,8 @@ // Format and load methods metrics | ||
{hAlign: 'center', colSpan: 2, content: `Block limit: ${blockLimit} gas`.grey } | ||
]; | ||
] | ||
let methodSubtitle; | ||
if (ethPrice && gasPrice){ | ||
const gwei = parseInt(gasPrice) * 1e-9; | ||
const rate = parseFloat(ethPrice).toFixed(2); | ||
let methodSubtitle | ||
if (ethPrice && gasPrice) { | ||
const gwei = parseInt(gasPrice) * 1e-9 | ||
const rate = parseFloat(ethPrice).toFixed(2) | ||
@@ -160,6 +161,6 @@ methodSubtitle = [ | ||
{hAlign: 'center', colSpan: 3, content: `${gwei} gwei/gas`.grey}, | ||
{hAlign: 'center', colSpan: 2, content: `${rate} ${currency.toLowerCase()}/eth`.red}, | ||
]; | ||
{hAlign: 'center', colSpan: 2, content: `${rate} ${currency.toLowerCase()}/eth`.red} | ||
] | ||
} else { | ||
methodSubtitle = [{hAlign: 'left', colSpan: 7, content: 'Methods'.green.bold}]; | ||
methodSubtitle = [{hAlign: 'left', colSpan: 7, content: 'Methods'.green.bold}] | ||
} | ||
@@ -177,16 +178,16 @@ | ||
table.push(title); | ||
table.push(methodSubtitle); | ||
table.push(header); | ||
table.push(title) | ||
table.push(methodSubtitle) | ||
table.push(header) | ||
// Sort rows by contract, then method and push | ||
methodRows.sort((a,b) => { | ||
const contractName = a[0].localeCompare(b[0]); | ||
const methodName = a[1].localeCompare(b[1]); | ||
return contractName || methodName; | ||
}); | ||
methodRows.sort((a, b) => { | ||
const contractName = a[0].localeCompare(b[0]) | ||
const methodName = a[1].localeCompare(b[1]) | ||
return contractName || methodName | ||
}) | ||
methodRows.forEach(row => table.push(row)); | ||
methodRows.forEach(row => table.push(row)) | ||
if (deployRows.length){ | ||
if (deployRows.length) { | ||
const deploymentsSubtitle = [ | ||
@@ -196,5 +197,5 @@ {hAlign: 'left', colSpan: 2, content: 'Deployments'.green.bold}, | ||
{hAlign: 'left', colSpan: 1, content: `% of limit`.bold} | ||
]; | ||
table.push(deploymentsSubtitle); | ||
deployRows.forEach(row => table.push(row)); | ||
] | ||
table.push(deploymentsSubtitle) | ||
deployRows.forEach(row => table.push(row)) | ||
} | ||
@@ -285,6 +286,6 @@ | ||
const names = shell.ls('./contracts/**/*.sol') | ||
names.sort(); | ||
names.sort() | ||
names.forEach(name => { | ||
name = path.basename(name); | ||
name = path.basename(name) | ||
@@ -294,3 +295,5 @@ if (name === 'Migrations.sol') return | ||
// Create Deploy Map: | ||
const contract = truffleArtifacts.require(name) | ||
let contract | ||
try { contract = truffleArtifacts.require(name) } catch (error) { return } | ||
const contractInfo = { | ||
@@ -301,3 +304,2 @@ name: name.split('.sol')[0], | ||
} | ||
deployMap.push(contractInfo) | ||
@@ -316,3 +318,3 @@ abis.push(contract._json.abi) | ||
if (hasName && !isConstant && !isEvent){ | ||
if (hasName && !isConstant && !isEvent) { | ||
methodMap[key] = { | ||
@@ -352,2 +354,1 @@ contract: name.split('.sol')[0], | ||
41
index.js
@@ -35,11 +35,11 @@ const mocha = require('mocha') | ||
methodMap && block.transactions.forEach(tx => { | ||
const transaction = web3.eth.getTransaction(tx); | ||
const receipt = web3.eth.getTransactionReceipt(tx); | ||
const transaction = web3.eth.getTransaction(tx) | ||
const receipt = web3.eth.getTransactionReceipt(tx) | ||
const id = stats.getMethodID( transaction.input ); | ||
const threw = receipt.gasUsed === transaction.gas; // Change this @ Byzantium | ||
const id = stats.getMethodID(transaction.input) | ||
const threw = receipt.gasUsed === transaction.gas // Change this @ Byzantium | ||
if (methodMap[id] && !threw){ | ||
methodMap[id].gasData.push(receipt.gasUsed); | ||
methodMap[id].numberOfCalls++; | ||
if (methodMap[id] && !threw) { | ||
methodMap[id].gasData.push(receipt.gasUsed) | ||
methodMap[id].numberOfCalls++ | ||
} | ||
@@ -56,3 +56,3 @@ }) | ||
while(deployStartBlock <= endBlock){ | ||
while (deployStartBlock <= endBlock) { | ||
const block = web3.eth.getBlock(deployStartBlock) | ||
@@ -62,13 +62,13 @@ | ||
const transaction = web3.eth.getTransaction(tx) | ||
const receipt = web3.eth.getTransactionReceipt(tx); | ||
const threw = receipt.gasUsed === transaction.gas; // Change this @ Byzantium | ||
const receipt = web3.eth.getTransactionReceipt(tx) | ||
const threw = receipt.gasUsed === transaction.gas // Change this @ Byzantium | ||
if (receipt.contractAddress && !threw){ | ||
if (receipt.contractAddress && !threw) { | ||
const match = deployMap.filter(contract => { | ||
return (transaction.input.indexOf(contract.binary) === 0) | ||
})[0]; | ||
})[0] | ||
match && match.gasData.push(receipt.gasUsed); | ||
match && match.gasData.push(receipt.gasUsed) | ||
} | ||
}); | ||
}) | ||
deployStartBlock++ | ||
@@ -80,3 +80,3 @@ } | ||
runner.on('start', () => { | ||
({ methodMap, deployMap } = stats.mapMethodsToContracts(artifacts)); | ||
({ methodMap, deployMap } = stats.mapMethodsToContracts(artifacts)) | ||
log() | ||
@@ -107,10 +107,9 @@ }) | ||
let fmt | ||
let limitString | ||
let gasUsedString | ||
deployAnalytics(deployMap); | ||
deployAnalytics(deployMap) | ||
let gasUsed = methodAnalytics(methodMap) | ||
if (gasUsed){ | ||
gasUsedString = color('checkmark', ' (%d gas)'); | ||
if (gasUsed) { | ||
gasUsedString = color('checkmark', ' (%d gas)') | ||
@@ -120,3 +119,3 @@ fmt = indent() + | ||
color('pass', ' %s') + | ||
gasUsedString; | ||
gasUsedString | ||
@@ -140,3 +139,3 @@ log(fmt, test.title, gasUsed) | ||
runner.on('end', () => { | ||
stats.generateGasStatsReport (methodMap, deployMap) | ||
stats.generateGasStatsReport(methodMap, deployMap) | ||
self.epilogue() | ||
@@ -143,0 +142,0 @@ }) |
@@ -5,11 +5,11 @@ var ConvertLib = artifacts.require('./ConvertLib.sol') | ||
var VariableCosts = artifacts.require('./VariableCosts.sol') | ||
var VariableConstructor = artifacts.require('./VariableConstructor'); | ||
var VariableConstructor = artifacts.require('./VariableConstructor') | ||
module.exports = function (deployer) { | ||
deployer.deploy(ConvertLib); | ||
deployer.link(ConvertLib, MetaCoin); | ||
deployer.deploy(MetaCoin); | ||
deployer.deploy(Wallet); | ||
deployer.deploy(VariableCosts); | ||
deployer.deploy(ConvertLib) | ||
deployer.link(ConvertLib, MetaCoin) | ||
deployer.deploy(MetaCoin) | ||
deployer.deploy(Wallet) | ||
deployer.deploy(VariableCosts) | ||
deployer.deploy(VariableConstructor) | ||
} |
{ | ||
"name": "eth-gas-reporter", | ||
"version": "0.0.8", | ||
"version": "0.0.10", | ||
"description": "Mocha reporter which shows gas used per unit test.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,18 +0,17 @@ | ||
const VariableConstructor = artifacts.require('./VariableConstructor.sol'); | ||
const VariableConstructor = artifacts.require('./VariableConstructor.sol') | ||
contract('VariableConstructor', accounts => { | ||
it('should should initialize with a short string', async () => { | ||
await VariableConstructor.new('Exit Visa'); | ||
}); | ||
await VariableConstructor.new('Exit Visa') | ||
}) | ||
it('should should initialize with a medium length string', async () => { | ||
await VariableConstructor.new('Enclosed is my application for residency'); | ||
}); | ||
await VariableConstructor.new('Enclosed is my application for residency') | ||
}) | ||
it('should should initialize with a long string', async () => { | ||
let msg = 'Enclosed is my application for permanent residency in NewZealand.'; | ||
msg += 'I am a computer programmer.'; | ||
await VariableConstructor.new(msg); | ||
}); | ||
}); | ||
let msg = 'Enclosed is my application for permanent residency in NewZealand.' | ||
msg += 'I am a computer programmer.' | ||
await VariableConstructor.new(msg) | ||
}) | ||
}) |
@@ -1,49 +0,47 @@ | ||
const VariableCosts = artifacts.require('./VariableCosts.sol'); | ||
const VariableCosts = artifacts.require('./VariableCosts.sol') | ||
contract('VariableCosts', accounts => { | ||
const one = [1] | ||
const three = [2, 3, 4] | ||
const five = [5, 6, 7, 8, 9] | ||
let instance | ||
const one = [1]; | ||
const three = [2,3,4]; | ||
const five = [5,6,7,8,9]; | ||
let instance; | ||
beforeEach(async () => instance = await VariableCosts.new()) | ||
it('should add one', async () => { | ||
await instance.addToMap(one); | ||
}); | ||
await instance.addToMap(one) | ||
}) | ||
it('should add three', async () => { | ||
await instance.addToMap(three); | ||
}); | ||
await instance.addToMap(three) | ||
}) | ||
it('should add even 5!', async () => { | ||
await instance.addToMap(five); | ||
}); | ||
await instance.addToMap(five) | ||
}) | ||
it('should delete one', async() => { | ||
await instance.removeFromMap(one); | ||
}); | ||
await instance.removeFromMap(one) | ||
}) | ||
it('should delete three', async() => { | ||
await instance.removeFromMap(three); | ||
}); | ||
await instance.removeFromMap(three) | ||
}) | ||
it('should delete five', async() => { | ||
await instance.removeFromMap(five); | ||
}); | ||
await instance.removeFromMap(five) | ||
}) | ||
it('should add five and delete one', async() => { | ||
await instance.addToMap(five); | ||
await instance.removeFromMap(one); | ||
await instance.addToMap(five) | ||
await instance.removeFromMap(one) | ||
}) | ||
it('methods that do not throw', async() => { | ||
await instance.methodThatThrows(false); | ||
}); | ||
await instance.methodThatThrows(false) | ||
}) | ||
it('methods that throw', async() => { | ||
try {await instance.methodThatThrows(true)} | ||
catch(e){} | ||
}); | ||
try { await instance.methodThatThrows(true) } catch (e) {} | ||
}) | ||
}) |
@@ -13,4 +13,4 @@ const Wallet = artifacts.require('./Wallet.sol') | ||
it('should be very expensive to deploy', async() => { | ||
await Wallet.new(); | ||
}); | ||
await Wallet.new() | ||
}) | ||
@@ -17,0 +17,0 @@ it('should should allow transfers and sends', async () => { |
{ | ||
"name": "eth-gas-reporter", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"description": "Mocha reporter which shows gas used per unit test.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# eth-gas-reporter | ||
[![Build Status](https://travis-ci.org/cgewecke/eth-gas-reporter.svg?branch=add-travis)](https://travis-ci.org/cgewecke/eth-gas-reporter) | ||
A mocha reporter for Truffle. | ||
@@ -13,3 +15,3 @@ + Gas usage per unit test. | ||
### Install | ||
``` | ||
```javascript | ||
// Truffle installed globally | ||
@@ -16,0 +18,0 @@ npm install -g eth-gas-reporter |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
31998
26
568
57