mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Bug fixes for incoming transactions (#7043)
* Fix styling of `.transaction-list` * Filter `incomingTxListSelector` by network as well * Start and stop block tracker polling in incoming tx controller * Add fetch with abort in bg for `IncomingTxController`
This commit is contained in:
parent
821529622e
commit
e47448362d
@ -2,7 +2,7 @@ const ObservableStore = require('obs-store')
|
|||||||
const log = require('loglevel')
|
const log = require('loglevel')
|
||||||
const BN = require('bn.js')
|
const BN = require('bn.js')
|
||||||
const createId = require('../lib/random-id')
|
const createId = require('../lib/random-id')
|
||||||
const { bnToHex } = require('../lib/util')
|
const { bnToHex, fetchWithTimeout } = require('../lib/util')
|
||||||
const {
|
const {
|
||||||
MAINNET_CODE,
|
MAINNET_CODE,
|
||||||
ROPSTEN_CODE,
|
ROPSTEN_CODE,
|
||||||
@ -14,11 +14,14 @@ const {
|
|||||||
MAINNET,
|
MAINNET,
|
||||||
} = require('./network/enums')
|
} = require('./network/enums')
|
||||||
const networkTypeToIdMap = {
|
const networkTypeToIdMap = {
|
||||||
[ROPSTEN]: ROPSTEN_CODE,
|
[ROPSTEN]: String(ROPSTEN_CODE),
|
||||||
[RINKEBY]: RINKEYBY_CODE,
|
[RINKEBY]: String(RINKEYBY_CODE),
|
||||||
[KOVAN]: KOVAN_CODE,
|
[KOVAN]: String(KOVAN_CODE),
|
||||||
[MAINNET]: MAINNET_CODE,
|
[MAINNET]: String(MAINNET_CODE),
|
||||||
}
|
}
|
||||||
|
const fetch = fetchWithTimeout({
|
||||||
|
timeout: 30000,
|
||||||
|
})
|
||||||
|
|
||||||
class IncomingTransactionsController {
|
class IncomingTransactionsController {
|
||||||
|
|
||||||
@ -33,6 +36,15 @@ class IncomingTransactionsController {
|
|||||||
this.preferencesController = preferencesController
|
this.preferencesController = preferencesController
|
||||||
this.getCurrentNetwork = () => networkController.getProviderConfig().type
|
this.getCurrentNetwork = () => networkController.getProviderConfig().type
|
||||||
|
|
||||||
|
this._onLatestBlock = async (newBlockNumberHex) => {
|
||||||
|
const selectedAddress = this.preferencesController.getSelectedAddress()
|
||||||
|
const newBlockNumberDec = parseInt(newBlockNumberHex, 16)
|
||||||
|
await this._update({
|
||||||
|
address: selectedAddress,
|
||||||
|
newBlockNumberDec,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const initState = Object.assign({
|
const initState = Object.assign({
|
||||||
incomingTransactions: {},
|
incomingTransactions: {},
|
||||||
incomingTxLastFetchedBlocksByNetwork: {
|
incomingTxLastFetchedBlocksByNetwork: {
|
||||||
@ -51,13 +63,6 @@ class IncomingTransactionsController {
|
|||||||
networkType: newType,
|
networkType: newType,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.blockTracker.on('latest', async (newBlockNumberHex) => {
|
|
||||||
const address = this.preferencesController.getSelectedAddress()
|
|
||||||
await this._update({
|
|
||||||
address,
|
|
||||||
newBlockNumberDec: parseInt(newBlockNumberHex, 16),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
this.preferencesController.store.subscribe(async ({ selectedAddress }) => {
|
this.preferencesController.store.subscribe(async ({ selectedAddress }) => {
|
||||||
await this._update({
|
await this._update({
|
||||||
address: selectedAddress,
|
address: selectedAddress,
|
||||||
@ -65,6 +70,15 @@ class IncomingTransactionsController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
|
this.blockTracker.removeListener('latest', this._onLatestBlock)
|
||||||
|
this.blockTracker.addListener('latest', this._onLatestBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
this.blockTracker.removeListener('latest', this._onLatestBlock)
|
||||||
|
}
|
||||||
|
|
||||||
async _update ({ address, newBlockNumberDec, networkType } = {}) {
|
async _update ({ address, newBlockNumberDec, networkType } = {}) {
|
||||||
try {
|
try {
|
||||||
const dataForUpdate = await this._getDataForUpdate({ address, newBlockNumberDec, networkType })
|
const dataForUpdate = await this._getDataForUpdate({ address, newBlockNumberDec, networkType })
|
||||||
|
@ -144,6 +144,29 @@ function removeListeners (listeners, emitter) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchWithTimeout ({ timeout = 120000 } = {}) {
|
||||||
|
return async function _fetch (url, opts) {
|
||||||
|
const abortController = new AbortController()
|
||||||
|
const abortSignal = abortController.signal
|
||||||
|
const f = fetch(url, {
|
||||||
|
...opts,
|
||||||
|
signal: abortSignal,
|
||||||
|
})
|
||||||
|
|
||||||
|
const timer = setTimeout(() => abortController.abort(), timeout)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await f
|
||||||
|
clearTimeout(timer)
|
||||||
|
return res
|
||||||
|
} catch (e) {
|
||||||
|
clearTimeout(timer)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
removeListeners,
|
removeListeners,
|
||||||
applyListeners,
|
applyListeners,
|
||||||
@ -154,4 +177,5 @@ module.exports = {
|
|||||||
hexToBn,
|
hexToBn,
|
||||||
bnToHex,
|
bnToHex,
|
||||||
BnMultiplyByFraction,
|
BnMultiplyByFraction,
|
||||||
|
fetchWithTimeout,
|
||||||
}
|
}
|
||||||
|
@ -156,8 +156,10 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
this.on('controllerConnectionChanged', (activeControllerConnections) => {
|
this.on('controllerConnectionChanged', (activeControllerConnections) => {
|
||||||
if (activeControllerConnections > 0) {
|
if (activeControllerConnections > 0) {
|
||||||
this.accountTracker.start()
|
this.accountTracker.start()
|
||||||
|
this.incomingTransactionsController.start()
|
||||||
} else {
|
} else {
|
||||||
this.accountTracker.stop()
|
this.accountTracker.stop()
|
||||||
|
this.incomingTransactionsController.stop()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,7 +49,8 @@ describe('IncomingTransactionsController', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MOCK_BLOCKTRACKER = {
|
const MOCK_BLOCKTRACKER = {
|
||||||
on: sinon.spy(),
|
addListener: sinon.spy(),
|
||||||
|
removeListener: sinon.spy(),
|
||||||
testProperty: 'fakeBlockTracker',
|
testProperty: 'fakeBlockTracker',
|
||||||
getCurrentBlock: () => '0xa',
|
getCurrentBlock: () => '0xa',
|
||||||
}
|
}
|
||||||
@ -95,17 +96,6 @@ describe('IncomingTransactionsController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
incomingTransactionsController._update.resetHistory()
|
incomingTransactionsController._update.resetHistory()
|
||||||
|
|
||||||
assert(incomingTransactionsController.blockTracker.on.calledOnce)
|
|
||||||
assert.equal(incomingTransactionsController.blockTracker.on.getCall(0).args[0], 'latest')
|
|
||||||
const blockTrackerListenerCallback = incomingTransactionsController.blockTracker.on.getCall(0).args[1]
|
|
||||||
assert.equal(incomingTransactionsController._update.callCount, 0)
|
|
||||||
blockTrackerListenerCallback('0xabc')
|
|
||||||
assert.equal(incomingTransactionsController._update.callCount, 1)
|
|
||||||
assert.deepEqual(incomingTransactionsController._update.getCall(0).args[0], {
|
|
||||||
address: '0x0101',
|
|
||||||
newBlockNumberDec: 2748,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should set the store to a provided initial state', () => {
|
it('should set the store to a provided initial state', () => {
|
||||||
@ -120,6 +110,31 @@ describe('IncomingTransactionsController', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#start', () => {
|
||||||
|
it('should set up a listener for the latest block', () => {
|
||||||
|
const incomingTransactionsController = new IncomingTransactionsController({
|
||||||
|
blockTracker: MOCK_BLOCKTRACKER,
|
||||||
|
networkController: MOCK_NETWORK_CONTROLLER,
|
||||||
|
preferencesController: MOCK_PREFERENCES_CONTROLLER,
|
||||||
|
initState: {},
|
||||||
|
})
|
||||||
|
sinon.spy(incomingTransactionsController, '_update')
|
||||||
|
|
||||||
|
incomingTransactionsController.start()
|
||||||
|
|
||||||
|
assert(incomingTransactionsController.blockTracker.addListener.calledOnce)
|
||||||
|
assert.equal(incomingTransactionsController.blockTracker.addListener.getCall(0).args[0], 'latest')
|
||||||
|
const blockTrackerListenerCallback = incomingTransactionsController.blockTracker.addListener.getCall(0).args[1]
|
||||||
|
assert.equal(incomingTransactionsController._update.callCount, 0)
|
||||||
|
blockTrackerListenerCallback('0xabc')
|
||||||
|
assert.equal(incomingTransactionsController._update.callCount, 1)
|
||||||
|
assert.deepEqual(incomingTransactionsController._update.getCall(0).args[0], {
|
||||||
|
address: '0x0101',
|
||||||
|
newBlockNumberDec: 2748,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('_getDataForUpdate', () => {
|
describe('_getDataForUpdate', () => {
|
||||||
it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async () => {
|
it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async () => {
|
||||||
const incomingTransactionsController = new IncomingTransactionsController({
|
const incomingTransactionsController = new IncomingTransactionsController({
|
||||||
|
@ -11,34 +11,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: $Grey-400;
|
||||||
border-bottom: 1px solid $Grey-100;
|
border-bottom: 1px solid $Grey-100;
|
||||||
|
padding: 8px 0 8px 20px;
|
||||||
|
|
||||||
&__tabs {
|
@media screen and (max-width: $break-small) {
|
||||||
display: flex;
|
padding: 8px 0 8px 16px;
|
||||||
}
|
|
||||||
|
|
||||||
&__tab,
|
|
||||||
&__tab--selected {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
color: $Grey-400;
|
|
||||||
padding: 8px 0 8px 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $break-small) {
|
|
||||||
padding: 8px 0 8px 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__tab--selected {
|
|
||||||
font-weight: bold;
|
|
||||||
color: $Blue-400;
|
|
||||||
cursor: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,12 @@ import txHelper from '../../lib/tx-helper'
|
|||||||
export const shapeShiftTxListSelector = state => state.metamask.shapeShiftTxList
|
export const shapeShiftTxListSelector = state => state.metamask.shapeShiftTxList
|
||||||
|
|
||||||
export const incomingTxListSelector = state => {
|
export const incomingTxListSelector = state => {
|
||||||
|
const network = state.metamask.network
|
||||||
const selectedAddress = state.metamask.selectedAddress
|
const selectedAddress = state.metamask.selectedAddress
|
||||||
return Object.values(state.metamask.incomingTransactions)
|
return Object.values(state.metamask.incomingTransactions)
|
||||||
.filter(({ txParams }) => txParams.to === selectedAddress)
|
.filter(({ metamaskNetworkId, txParams }) => (
|
||||||
|
txParams.to === selectedAddress && metamaskNetworkId === network
|
||||||
|
))
|
||||||
}
|
}
|
||||||
export const unapprovedMsgsSelector = state => state.metamask.unapprovedMsgs
|
export const unapprovedMsgsSelector = state => state.metamask.unapprovedMsgs
|
||||||
export const selectedAddressTxListSelector = state => state.metamask.selectedAddressTxList
|
export const selectedAddressTxListSelector = state => state.metamask.selectedAddressTxList
|
||||||
|
Loading…
x
Reference in New Issue
Block a user