diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 62da6a56f3f7..1d58e3768520 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -207,7 +207,7 @@ class TransactionController extends EventEmitter { txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) let gasPrice = txParams.gasPrice if (!gasPrice) { - gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice() + gasPrice = this.getGasPrice ? await this.getGasPrice() : await this.query.gasPrice() } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) // set gasLimit diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index be09bb411c99..d4de5c8b869f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -58,7 +58,9 @@ const { LEDGER, TREZOR } = require('../../old-ui/app/components/connect-hardware const { POA_CODE, DAI_CODE, - POA_SOKOL_CODE } = require('./controllers/network/enums') + POA_SOKOL_CODE, + CLASSIC_CODE, + MAINNET_CODE } = require('./controllers/network/enums') const accountsPerPage = 5 module.exports = class MetamaskController extends EventEmitter { @@ -1503,6 +1505,43 @@ module.exports = class MetamaskController extends EventEmitter { this.emit('update', this.getState()) } + /** + * A method for estimating a good gas price + * For ETH, ETC: from gas price oracles + * For other networks: from recent blocks + * + * @returns {string} A hex representation of the suggested wei gas price. + */ + async getGasPrice () { + return new Promise(async (resolve, reject) => { + const { networkController } = this + + + const networkIdStr = networkController.store.getState().network + const networkId = parseInt(networkIdStr) + const isETHC = networkId === CLASSIC_CODE || networkId === MAINNET_CODE + let gasPrice + + if (isETHC) { + try { + gasPrice = await this.getGasPriceFromOracles(networkId) + if (gasPrice) { + const gasPriceBN = new BN(gasPrice) + gasPrice = gasPriceBN.mul(GWEI_BN) + resolve('0x' + gasPrice.toString(16)) + } + } catch (error) { + log.error(error) + gasPrice = this.getGasPriceFromBlocks(networkId) + resolve(gasPrice) + } + } else { + gasPrice = this.getGasPriceFromBlocks(networkId) + resolve(gasPrice) + } + }) + } + /** * A method for estimating a good gas price at recent prices. * Returns the lowest price that would have been included in @@ -1510,12 +1549,9 @@ module.exports = class MetamaskController extends EventEmitter { * * @returns {string} A hex representation of the suggested wei gas price. */ - getGasPrice () { - const { networkController, recentBlocksController } = this + getGasPriceFromBlocks (networkId) { + const { recentBlocksController } = this const { recentBlocks } = recentBlocksController.store.getState() - - const networkIdStr = networkController.store.getState().network - const networkId = parseInt(networkIdStr) const isPOA = networkId === POA_SOKOL_CODE || networkId === POA_CODE || networkId === DAI_CODE // Return 1 gwei if using a POA network or if there are no blocks have been observed: @@ -1541,6 +1577,34 @@ module.exports = class MetamaskController extends EventEmitter { return '0x' + percentileNumBn.mul(GWEI_BN).toString(16) } + /** + * A method for retrieving of gas price from POA gas price oracles + * + * @returns {string} A hex representation of the suggested wei gas price. + */ + getGasPriceFromOracles (networkId) { + return new Promise(async (resolve, reject) => { + const gasPriceOracleETC = 'https://gasprice-etc.poa.network' + const gasPriceOracleETH = 'https://gasprice.poa.network' + const gasPriceOracle = networkId === CLASSIC_CODE ? + gasPriceOracleETC : networkId === MAINNET_CODE ? gasPriceOracleETH : null + + try { + if (gasPriceOracle) { + const response = await fetch(gasPriceOracle) + const parsedResponse = await response.json() + if (parsedResponse && (parsedResponse.standard || parsedResponse.fast)) { + resolve(parsedResponse.standard || parsedResponse.fast) + } else { + reject() + } + } + } catch (error) { + reject(error) + } + }) + } + /** * Returns the nonce that will be associated with a transaction once approved * @param address {string} - The hex string address for the transaction diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index a81e69a8d502..e32e17b942fc 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -115,7 +115,7 @@ describe('MetaMaskController', function () { }, } - const gasPrice = metamaskController.getGasPrice() + const gasPrice = await metamaskController.getGasPrice() assert.equal(gasPrice, '0x174876e800', 'accurately estimates 65th percentile accepted gas price') metamaskController.recentBlocksController = realRecentBlocksController