diff --git a/CHANGELOG.md b/CHANGELOG.md index 30554afd9..a21afef24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Current Develop Branch +## 7.7.2 Fri Jan 10 2020 +- [#7753](https://github.com/MetaMask/metamask-extension/pull/7753): Fix gas estimate for tokens +- [#7473](https://github.com/MetaMask/metamask-extension/pull/7473): Fix transaction order on transaction confirmation screen + ## 7.7.1 Wed Dec 04 2019 - [#7488](https://github.com/MetaMask/metamask-extension/pull/7488): Fix text overlap when expanding transaction - [#7491](https://github.com/MetaMask/metamask-extension/pull/7491): Update gas when asset is changed on send screen diff --git a/app/manifest.json b/app/manifest.json index 299158d7f..7818b046b 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "7.7.1", + "version": "7.7.2", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", diff --git a/package.json b/package.json index 047911146..924f1a918 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "eth-json-rpc-errors": "^1.1.0", "eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-infura": "^4.0.1", - "eth-json-rpc-middleware": "^4.2.0", + "eth-json-rpc-middleware": "^4.4.0", "eth-keyring-controller": "^5.3.0", "eth-ledger-bridge-keyring": "^0.2.0", "eth-method-registry": "^1.2.0", @@ -117,7 +117,7 @@ "gaba": "^1.9.0", "human-standard-token-abi": "^2.0.0", "jazzicon": "^1.2.0", - "json-rpc-engine": "^5.1.5", + "json-rpc-engine": "^5.1.6", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", "lodash.debounce": "^4.0.8", diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index a0efe56f9..1ee01595b 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -553,11 +553,11 @@ describe('MetaMask', function () { await delay(regularDelayMs) let transactions = await findElements(driver, By.css('.transaction-list-item')) - await transactions[3].click() + await transactions[0].click() await delay(regularDelayMs) try { transactions = await findElements(driver, By.css('.transaction-list-item'), 1000) - await transactions[3].click() + await transactions[0].click() } catch (e) { console.log(e) } @@ -631,24 +631,24 @@ describe('MetaMask', function () { navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() - assert.equal(navigationText.includes('3'), true, 'correct transaction in focus') + assert.equal(navigationText.includes('2'), true, 'correct (same) transaction in focus') }) - it('confirms a transaction', async () => { + it('rejects a transaction', async () => { await delay(tinyDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000) await confirmButton.click() await delay(largeDelayMs * 2) const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) await delay(tinyDelayMs) const navigationText = await navigationElement.getText() - assert.equal(navigationText.includes('4'), true, 'transaction confirmed') + assert.equal(navigationText.includes('4'), true, 'transaction rejected') }) - it('rejects a transaction', async () => { + it('confirms a transaction', async () => { await delay(tinyDelayMs / 2) - const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000) + const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) await delay(tinyDelayMs / 2) await rejectButton.click() await delay(regularDelayMs) @@ -657,7 +657,7 @@ describe('MetaMask', function () { await delay(tinyDelayMs / 2) const navigationText = await navigationElement.getText() await delay(tinyDelayMs / 2) - assert.equal(navigationText.includes('3'), true, 'transaction rejected') + assert.equal(navigationText.includes('3'), true, 'transaction confirmed') }) it('rejects the rest of the transactions', async () => { @@ -965,6 +965,7 @@ describe('MetaMask', function () { // Continue to next screen const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + await driver.wait(until.elementIsEnabled(nextScreen)) await nextScreen.click() await delay(regularDelayMs) }) diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index 65cec89e7..cc32872f4 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -38,8 +38,8 @@ async function runConfirmSigRequestsTest (assert) { const pendingRequestItem = $.find('.transaction-list-item .transaction-list-item__grid') - if (pendingRequestItem[2]) { - pendingRequestItem[2].click() + if (pendingRequestItem[0]) { + pendingRequestItem[0].click() } await timeout(1000) @@ -47,11 +47,9 @@ async function runConfirmSigRequestsTest (assert) { let confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') - const confirmSigMessage = await queryAsync($, '.request-signature__notice') - assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) - let confirmSigRowValue = await queryAsync($, '.request-signature__row-value') - assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') + assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') + assert.equal(confirmSigRowValue[1].textContent, '1337') let confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large') confirmSigSignButton[0].click() @@ -68,9 +66,11 @@ async function runConfirmSigRequestsTest (assert) { confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') + const confirmSigMessage = await queryAsync($, '.request-signature__notice') + assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) + confirmSigRowValue = await queryAsync($, '.request-signature__row-value') - assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') - assert.equal(confirmSigRowValue[1].textContent, '1337') + assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large') confirmSigSignButton[0].click() diff --git a/ui/app/components/ui/token-input/token-input.component.js b/ui/app/components/ui/token-input/token-input.component.js index c28af5fde..316463f5b 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/app/components/ui/token-input/token-input.component.js @@ -78,7 +78,7 @@ export default class TokenInput extends PureComponent { } handleBlur = () => { - this.props.onBlur(this.state.hexValue) + this.props.onBlur && this.props.onBlur(this.state.hexValue) } renderConversionComponent () { diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 44b49d697..f67daca62 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -557,7 +557,7 @@ export default class ConfirmTransactionBase extends Component { getNavigateTxData () { const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props - const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs).reverse() + const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs) const currentPosition = enumUnapprovedTxs.indexOf(id ? id.toString() : '') return { diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 9a238e780..139edbc02 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux' import { compose } from 'recompose' import { withRouter } from 'react-router-dom' -import R from 'ramda' import contractMap from 'eth-contract-metadata' import ConfirmTransactionBase from './confirm-transaction-base.component' import { @@ -72,7 +71,9 @@ const mapStateToProps = (state, ownProps) => { nonce, } = confirmTransaction const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory } = txData - const transaction = R.find(({ id }) => id === (transactionId || Number(paramsTransactionId)))(selectedAddressTxList) || {} + const transaction = Object.values(selectedAddressTxList).find( + ({ id }) => id === (transactionId || Number(paramsTransactionId)) + ) || {} const { from: fromAddress, to: txParamsToAddress, @@ -118,10 +119,9 @@ const mapStateToProps = (state, ownProps) => { txData.simulationFails = transaction.simulationFails } - const currentNetworkUnapprovedTxs = R.filter( - ({ metamaskNetworkId }) => metamaskNetworkId === network, - unapprovedTxs, - ) + const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs) + .filter(key => unapprovedTxs[key].metamaskNetworkId === network) + .reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {}) const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length const insufficientBalance = !isBalanceSufficient({ diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js index 230a931ad..613507e63 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js @@ -18,7 +18,7 @@ const mapStateToProps = (state, ownProps) => { const unconfirmedTransactions = unconfirmedTransactionsListSelector(state) const totalUnconfirmed = unconfirmedTransactions.length const transaction = totalUnconfirmed - ? unapprovedTxs[transactionId] || unconfirmedTransactions[totalUnconfirmed - 1] + ? unapprovedTxs[transactionId] || unconfirmedTransactions[0] : {} return { diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index 7c3986441..9a45c6405 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -35,7 +35,7 @@ const mapStateToProps = (state, ownProps) => { const unconfirmedTransactions = unconfirmedTransactionsListSelector(state) const totalUnconfirmed = unconfirmedTransactions.length const transaction = totalUnconfirmed - ? unapprovedTxs[id] || unconfirmedTransactions[totalUnconfirmed - 1] + ? unapprovedTxs[id] || unconfirmedTransactions[0] : {} const { id: transactionId, transactionCategory } = transaction diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js index 495de58b5..0b46d48c5 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js @@ -1,5 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import debounce from 'lodash.debounce' import SendRowWrapper from '../send-row-wrapper' import AmountMaxButton from './amount-max-button' import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input' @@ -32,6 +33,8 @@ export default class SendAmountRow extends Component { t: PropTypes.func, } + updateGas = debounce(this.updateGas.bind(this), 500) + validateAmount (amount) { const { amountConversionRate, @@ -90,8 +93,8 @@ export default class SendAmountRow extends Component { return ( this.validateAmount(newAmount)} - onBlur={newAmount => { + onChange={newAmount => { + this.validateAmount(newAmount) this.updateGas(newAmount) this.updateAmount(newAmount) }} diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index bfc0f7e64..41a36e992 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -8,6 +8,8 @@ import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' import AmountMaxButton from '../amount-max-button/amount-max-button.container' import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input' +import timeout from '../../../../../../lib/test-timeout' + const propsMethodSpies = { setMaxModeTo: sinon.spy(), updateSendAmount: sinon.spy(), @@ -153,9 +155,8 @@ describe('SendAmountRow Component', function () { assert(wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput)) }) - it('should render the UserPreferencedTokenInput with the correct props', () => { + it('should render the UserPreferencedTokenInput with the correct props', async () => { const { - onBlur, onChange, error, value, @@ -164,8 +165,9 @@ describe('SendAmountRow Component', function () { assert.equal(value, 'mockAmount') assert.equal(SendAmountRow.prototype.updateGas.callCount, 0) assert.equal(SendAmountRow.prototype.updateAmount.callCount, 0) - onBlur('mockNewAmount') - assert.equal(SendAmountRow.prototype.updateGas.callCount, 1) + assert.equal(SendAmountRow.prototype.validateAmount.callCount, 0) + onChange('mockNewAmount') + await timeout(501) assert.deepEqual( SendAmountRow.prototype.updateGas.getCall(0).args, ['mockNewAmount'] @@ -175,8 +177,6 @@ describe('SendAmountRow Component', function () { SendAmountRow.prototype.updateAmount.getCall(0).args, ['mockNewAmount'] ) - assert.equal(SendAmountRow.prototype.validateAmount.callCount, 0) - onChange('mockNewAmount') assert.equal(SendAmountRow.prototype.validateAmount.callCount, 1) assert.deepEqual( SendAmountRow.prototype.validateAmount.getCall(0).args, diff --git a/ui/app/pages/send/send-footer/send-footer.component.js b/ui/app/pages/send/send-footer/send-footer.component.js index f637fb8c7..20ab50c3c 100644 --- a/ui/app/pages/send/send-footer/send-footer.component.js +++ b/ui/app/pages/send/send-footer/send-footer.component.js @@ -28,6 +28,7 @@ export default class SendFooter extends Component { update: PropTypes.func, sendErrors: PropTypes.object, gasEstimateType: PropTypes.string, + gasIsLoading: PropTypes.bool, } static contextTypes = { @@ -102,10 +103,10 @@ export default class SendFooter extends Component { } formShouldBeDisabled () { - const { data, inError, selectedToken, tokenBalance, gasTotal, to, gasLimit } = this.props + const { data, inError, selectedToken, tokenBalance, gasTotal, to, gasLimit, gasIsLoading } = this.props const missingTokenBalance = selectedToken && !tokenBalance const gasLimitTooLow = gasLimit < 5208 // 5208 is hex value of 21000, minimum gas limit - const shouldBeDisabled = inError || !gasTotal || missingTokenBalance || !(data || to) || gasLimitTooLow + const shouldBeDisabled = inError || !gasTotal || missingTokenBalance || !(data || to) || gasLimitTooLow || gasIsLoading return shouldBeDisabled } diff --git a/ui/app/pages/send/send-footer/send-footer.container.js b/ui/app/pages/send/send-footer/send-footer.container.js index 42c12f2d5..52348ca89 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.js +++ b/ui/app/pages/send/send-footer/send-footer.container.js @@ -23,6 +23,7 @@ import { getUnapprovedTxs, getSendErrors, } from '../send.selectors' +import { getGasIsLoading } from '../../../selectors/selectors' import { isSendFormInError, } from './send-footer.selectors' @@ -62,6 +63,7 @@ function mapStateToProps (state) { unapprovedTxs: getUnapprovedTxs(state), sendErrors: getSendErrors(state), gasEstimateType, + gasIsLoading: getGasIsLoading(state), } } diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index e1dd0d631..4f35e1b25 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -81,22 +81,34 @@ describe('SendFooter Component', function () { 'should return true if inError is truthy': { inError: true, expectedResult: true, + gasIsLoading: false, }, 'should return true if gasTotal is falsy': { inError: false, gasTotal: false, expectedResult: true, + gasIsLoading: false, }, 'should return true if to is truthy': { to: '0xsomevalidAddress', inError: false, gasTotal: false, expectedResult: true, + gasIsLoading: false, }, 'should return true if selectedToken is truthy and tokenBalance is falsy': { selectedToken: true, tokenBalance: null, expectedResult: true, + gasIsLoading: false, + }, + 'should return true if gasIsLoading is truthy but all other params are falsy': { + inError: false, + gasTotal: null, + selectedToken: null, + tokenBalance: 0, + expectedResult: true, + gasIsLoading: true, }, 'should return false if inError is false and all other params are truthy': { inError: false, @@ -104,7 +116,9 @@ describe('SendFooter Component', function () { selectedToken: true, tokenBalance: 123, expectedResult: false, + gasIsLoading: false, }, + } Object.entries(config).map(([description, obj]) => { it(description, () => { diff --git a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js index b8af19017..70bc078c8 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js @@ -2,7 +2,6 @@ import assert from 'assert' import proxyquire from 'proxyquire' import sinon from 'sinon' -let mapStateToProps let mapDispatchToProps const actionSpies = { @@ -22,8 +21,7 @@ const utilsStubs = { proxyquire('../send-footer.container.js', { 'react-redux': { - connect: (ms, md) => { - mapStateToProps = ms + connect: (_, md) => { mapDispatchToProps = md return () => ({}) }, @@ -55,30 +53,6 @@ proxyquire('../send-footer.container.js', { describe('send-footer container', () => { - describe('mapStateToProps()', () => { - - it('should map the correct properties to props', () => { - assert.deepEqual(mapStateToProps('mockState'), { - amount: 'mockAmount:mockState', - data: 'mockHexData:mockState', - selectedToken: 'mockSelectedToken:mockState', - editingTransactionId: 'mockEditingTransactionId:mockState', - from: 'mockFromObject:mockState', - gasLimit: 'mockGasLimit:mockState', - gasPrice: 'mockGasPrice:mockState', - gasTotal: 'mockGasTotal:mockState', - inError: 'mockInError:mockState', - to: 'mockTo:mockState', - toAccounts: 'mockToAccounts:mockState', - tokenBalance: 'mockTokenBalance:mockState', - unapprovedTxs: 'mockUnapprovedTxs:mockState', - sendErrors: 'mockSendErrors:mockState', - gasEstimateType: 'mockGasEstimateType:mockState', - }) - }) - - }) - describe('mapDispatchToProps()', () => { let dispatchSpy let mapDispatchToPropsObject diff --git a/ui/index.js b/ui/index.js index 058c09be0..f06b31f6c 100644 --- a/ui/index.js +++ b/ui/index.js @@ -61,7 +61,7 @@ async function startApp (metamaskState, backgroundConnection, opts) { const numberOfUnapprivedTx = unapprovedTxsAll.length if (numberOfUnapprivedTx > 0) { store.dispatch(actions.showConfTxPage({ - id: unapprovedTxsAll[numberOfUnapprivedTx - 1].id, + id: unapprovedTxsAll[0].id, })) } diff --git a/yarn.lock b/yarn.lock index 5e9578a16..c86122dd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10140,7 +10140,7 @@ eth-json-rpc-middleware@^1.5.0: promise-to-callback "^1.0.0" tape "^4.6.3" -eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-middleware@^4.2.0: +eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: version "4.2.0" resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.2.0.tgz#cfb77c5056cb8001548c6c7d54f4af5fce04d489" integrity sha512-90LljqRyJhkg7fOwKunh1lu1Mr5bspXMBDitaTGyGPPNiFTbMrhtfbf9fteYlXRFCbq+aIFWwl/X+P7nkrdkLg== @@ -10160,6 +10160,26 @@ eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-mid pify "^3.0.0" safe-event-emitter "^1.0.1" +eth-json-rpc-middleware@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.0.tgz#ef63b783b48dcbea9c1fe25c79e6ea01510e5877" + integrity sha512-IeOsil/XiHsybJO9nFf86+1+YIqGQWPPfiTEp3WLkpLZhJm97kw6tFM7GttIZXIcwtaO3zEXgY6PWAH1jkB3ag== + dependencies: + btoa "^1.2.1" + clone "^2.1.1" + eth-json-rpc-errors "^1.0.1" + eth-query "^2.1.2" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.7" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.6.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^5.1.3" + json-stable-stringify "^1.0.1" + pify "^3.0.0" + safe-event-emitter "^1.0.1" + eth-keyring-controller@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.3.0.tgz#8d85a67b894360ab7d601222ca71df8ed5f456c6" @@ -15861,10 +15881,10 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" -json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.5.tgz#a5f9915356ea916d5305716354080723c63dede7" - integrity sha512-HTT9HixG4j8vHYrmJIckgbISW9Q8tCkySv7x7Q8zjMpcw10wSe/dZSQ0w08VkDm3y195K4074UlvD3hxaznvlw== +json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.6.tgz#3823c1e227657ac5f22a36351db5bb76fa70cf38" + integrity sha512-9nDeIIu6o7cvzWRrHNuNi+TiGe+YWOp3ZQkHtpPnQzXuX8Y5ZU2Oot3FDI+DaQyXIqQ6SjtM6rixDOJTjjA8NA== dependencies: async "^2.0.1" eth-json-rpc-errors "^2.0.0"