mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix batch transaction UX (#7473)
* order transactions from oldest to newest in UI * update json-rpc-engine, eth-json-rpc-middleware * update e2e and integration tests
This commit is contained in:
parent
4f5f671cb1
commit
728026d1f7
@ -96,7 +96,7 @@
|
|||||||
"eth-json-rpc-errors": "^2.0.0",
|
"eth-json-rpc-errors": "^2.0.0",
|
||||||
"eth-json-rpc-filters": "^4.1.1",
|
"eth-json-rpc-filters": "^4.1.1",
|
||||||
"eth-json-rpc-infura": "^4.0.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-keyring-controller": "^5.3.0",
|
||||||
"eth-ledger-bridge-keyring": "^0.2.0",
|
"eth-ledger-bridge-keyring": "^0.2.0",
|
||||||
"eth-method-registry": "^1.2.0",
|
"eth-method-registry": "^1.2.0",
|
||||||
@ -122,7 +122,7 @@
|
|||||||
"gaba": "^1.9.0",
|
"gaba": "^1.9.0",
|
||||||
"human-standard-token-abi": "^2.0.0",
|
"human-standard-token-abi": "^2.0.0",
|
||||||
"jazzicon": "^1.2.0",
|
"jazzicon": "^1.2.0",
|
||||||
"json-rpc-engine": "^5.1.5",
|
"json-rpc-engine": "^5.1.6",
|
||||||
"json-rpc-middleware-stream": "^2.1.1",
|
"json-rpc-middleware-stream": "^2.1.1",
|
||||||
"jsonschema": "^1.2.4",
|
"jsonschema": "^1.2.4",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
|
@ -569,11 +569,11 @@ describe('MetaMask', function () {
|
|||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
|
|
||||||
let transactions = await findElements(driver, By.css('.transaction-list-item'))
|
let transactions = await findElements(driver, By.css('.transaction-list-item'))
|
||||||
await transactions[3].click()
|
await transactions[0].click()
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
try {
|
try {
|
||||||
transactions = await findElements(driver, By.css('.transaction-list-item'), 1000)
|
transactions = await findElements(driver, By.css('.transaction-list-item'), 1000)
|
||||||
await transactions[3].click()
|
await transactions[0].click()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
@ -647,7 +647,7 @@ describe('MetaMask', function () {
|
|||||||
|
|
||||||
navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
|
navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
|
||||||
navigationText = await navigationElement.getText()
|
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('confirms a transaction', async () => {
|
||||||
@ -854,9 +854,9 @@ describe('MetaMask', function () {
|
|||||||
it('renders the correct ETH balance', async () => {
|
it('renders the correct ETH balance', async () => {
|
||||||
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
|
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000)
|
await driver.wait(until.elementTextMatches(balance, /^90.*\s*ETH.*$/), 10000)
|
||||||
const tokenAmount = await balance.getText()
|
const tokenAmount = await balance.getText()
|
||||||
assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount))
|
assert.ok(/^90.*\s*ETH.*$/.test(tokenAmount))
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -36,8 +36,8 @@ async function runConfirmSigRequestsTest (assert) {
|
|||||||
|
|
||||||
const pendingRequestItem = $.find('.transaction-list-item .transaction-list-item__grid')
|
const pendingRequestItem = $.find('.transaction-list-item .transaction-list-item__grid')
|
||||||
|
|
||||||
if (pendingRequestItem[2]) {
|
if (pendingRequestItem[0]) {
|
||||||
pendingRequestItem[2].click()
|
pendingRequestItem[0].click()
|
||||||
}
|
}
|
||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
@ -45,11 +45,9 @@ async function runConfirmSigRequestsTest (assert) {
|
|||||||
let confirmSigHeadline = await queryAsync($, '.request-signature__headline')
|
let confirmSigHeadline = await queryAsync($, '.request-signature__headline')
|
||||||
assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested')
|
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')
|
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')
|
let confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large')
|
||||||
confirmSigSignButton[0].click()
|
confirmSigSignButton[0].click()
|
||||||
@ -66,9 +64,11 @@ async function runConfirmSigRequestsTest (assert) {
|
|||||||
confirmSigHeadline = await queryAsync($, '.request-signature__headline')
|
confirmSigHeadline = await queryAsync($, '.request-signature__headline')
|
||||||
assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested')
|
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')
|
confirmSigRowValue = await queryAsync($, '.request-signature__row-value')
|
||||||
assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!')
|
assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0')
|
||||||
assert.equal(confirmSigRowValue[1].textContent, '1337')
|
|
||||||
|
|
||||||
confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large')
|
confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large')
|
||||||
confirmSigSignButton[0].click()
|
confirmSigSignButton[0].click()
|
||||||
|
@ -26,7 +26,7 @@ const typeHash = {
|
|||||||
|
|
||||||
const Button = ({ type, submit, large, children, className, ...buttonProps }) => (
|
const Button = ({ type, submit, large, children, className, ...buttonProps }) => (
|
||||||
<button
|
<button
|
||||||
type={submit && 'submit'}
|
type={submit ? 'submit' : undefined}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
'button',
|
'button',
|
||||||
typeHash[type] || CLASSNAME_DEFAULT,
|
typeHash[type] || CLASSNAME_DEFAULT,
|
||||||
|
@ -551,7 +551,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
|
|
||||||
getNavigateTxData () {
|
getNavigateTxData () {
|
||||||
const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props
|
const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props
|
||||||
const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs).reverse()
|
const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs)
|
||||||
const currentPosition = enumUnapprovedTxs.indexOf(id ? id.toString() : '')
|
const currentPosition = enumUnapprovedTxs.indexOf(id ? id.toString() : '')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { compose } from 'recompose'
|
import { compose } from 'recompose'
|
||||||
import { withRouter } from 'react-router-dom'
|
import { withRouter } from 'react-router-dom'
|
||||||
import R from 'ramda'
|
|
||||||
import contractMap from 'eth-contract-metadata'
|
import contractMap from 'eth-contract-metadata'
|
||||||
import ConfirmTransactionBase from './confirm-transaction-base.component'
|
import ConfirmTransactionBase from './confirm-transaction-base.component'
|
||||||
import {
|
import {
|
||||||
@ -68,7 +67,9 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
nonce,
|
nonce,
|
||||||
} = confirmTransaction
|
} = confirmTransaction
|
||||||
const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory } = txData
|
const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory } = txData
|
||||||
const transaction = Object.values(unapprovedTxs).find(({ id }) => id === (transactionId || Number(paramsTransactionId))) || {}
|
const transaction = Object.values(unapprovedTxs).find(
|
||||||
|
({ id }) => id === (transactionId || Number(paramsTransactionId))
|
||||||
|
) || {}
|
||||||
const {
|
const {
|
||||||
from: fromAddress,
|
from: fromAddress,
|
||||||
to: txParamsToAddress,
|
to: txParamsToAddress,
|
||||||
@ -108,10 +109,9 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
txData.simulationFails = transaction.simulationFails
|
txData.simulationFails = transaction.simulationFails
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentNetworkUnapprovedTxs = R.filter(
|
const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs)
|
||||||
({ metamaskNetworkId }) => metamaskNetworkId === network,
|
.filter(key => unapprovedTxs[key].metamaskNetworkId === network)
|
||||||
unapprovedTxs,
|
.reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {})
|
||||||
)
|
|
||||||
const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length
|
const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length
|
||||||
|
|
||||||
const insufficientBalance = !isBalanceSufficient({
|
const insufficientBalance = !isBalanceSufficient({
|
||||||
|
@ -12,7 +12,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const unconfirmedTransactions = unconfirmedTransactionsListSelector(state)
|
const unconfirmedTransactions = unconfirmedTransactionsListSelector(state)
|
||||||
const totalUnconfirmed = unconfirmedTransactions.length
|
const totalUnconfirmed = unconfirmedTransactions.length
|
||||||
const transaction = totalUnconfirmed
|
const transaction = totalUnconfirmed
|
||||||
? unapprovedTxs[transactionId] || unconfirmedTransactions[totalUnconfirmed - 1]
|
? unapprovedTxs[transactionId] || unconfirmedTransactions[0]
|
||||||
: {}
|
: {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -33,7 +33,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const unconfirmedTransactions = unconfirmedTransactionsListSelector(state)
|
const unconfirmedTransactions = unconfirmedTransactionsListSelector(state)
|
||||||
const totalUnconfirmed = unconfirmedTransactions.length
|
const totalUnconfirmed = unconfirmedTransactions.length
|
||||||
const transaction = totalUnconfirmed
|
const transaction = totalUnconfirmed
|
||||||
? unapprovedTxs[id] || unconfirmedTransactions[totalUnconfirmed - 1]
|
? unapprovedTxs[id] || unconfirmedTransactions[0]
|
||||||
: {}
|
: {}
|
||||||
const { id: transactionId, transactionCategory } = transaction
|
const { id: transactionId, transactionCategory } = transaction
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
|||||||
const numberOfUnapprivedTx = unapprovedTxsAll.length
|
const numberOfUnapprivedTx = unapprovedTxsAll.length
|
||||||
if (numberOfUnapprivedTx > 0) {
|
if (numberOfUnapprivedTx > 0) {
|
||||||
store.dispatch(actions.showConfTxPage({
|
store.dispatch(actions.showConfTxPage({
|
||||||
id: unapprovedTxsAll[numberOfUnapprivedTx - 1].id,
|
id: unapprovedTxsAll[0].id,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
yarn.lock
30
yarn.lock
@ -10424,7 +10424,7 @@ eth-json-rpc-middleware@^1.5.0:
|
|||||||
promise-to-callback "^1.0.0"
|
promise-to-callback "^1.0.0"
|
||||||
tape "^4.6.3"
|
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"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.2.0.tgz#cfb77c5056cb8001548c6c7d54f4af5fce04d489"
|
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.2.0.tgz#cfb77c5056cb8001548c6c7d54f4af5fce04d489"
|
||||||
integrity sha512-90LljqRyJhkg7fOwKunh1lu1Mr5bspXMBDitaTGyGPPNiFTbMrhtfbf9fteYlXRFCbq+aIFWwl/X+P7nkrdkLg==
|
integrity sha512-90LljqRyJhkg7fOwKunh1lu1Mr5bspXMBDitaTGyGPPNiFTbMrhtfbf9fteYlXRFCbq+aIFWwl/X+P7nkrdkLg==
|
||||||
@ -10444,6 +10444,26 @@ eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-mid
|
|||||||
pify "^3.0.0"
|
pify "^3.0.0"
|
||||||
safe-event-emitter "^1.0.1"
|
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:
|
eth-keyring-controller@^5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.3.0.tgz#8d85a67b894360ab7d601222ca71df8ed5f456c6"
|
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.3.0.tgz#8d85a67b894360ab7d601222ca71df8ed5f456c6"
|
||||||
@ -16190,10 +16210,10 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0:
|
|||||||
promise-to-callback "^1.0.0"
|
promise-to-callback "^1.0.0"
|
||||||
safe-event-emitter "^1.0.1"
|
safe-event-emitter "^1.0.1"
|
||||||
|
|
||||||
json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5:
|
json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5, json-rpc-engine@^5.1.6:
|
||||||
version "5.1.5"
|
version "5.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.5.tgz#a5f9915356ea916d5305716354080723c63dede7"
|
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.6.tgz#3823c1e227657ac5f22a36351db5bb76fa70cf38"
|
||||||
integrity sha512-HTT9HixG4j8vHYrmJIckgbISW9Q8tCkySv7x7Q8zjMpcw10wSe/dZSQ0w08VkDm3y195K4074UlvD3hxaznvlw==
|
integrity sha512-9nDeIIu6o7cvzWRrHNuNi+TiGe+YWOp3ZQkHtpPnQzXuX8Y5ZU2Oot3FDI+DaQyXIqQ6SjtM6rixDOJTjjA8NA==
|
||||||
dependencies:
|
dependencies:
|
||||||
async "^2.0.1"
|
async "^2.0.1"
|
||||||
eth-json-rpc-errors "^2.0.0"
|
eth-json-rpc-errors "^2.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user