1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import TransactionListItem from '../transaction-list-item'
import ShapeShiftTransactionListItem from '../shift-list-item'
import { TRANSACTION_TYPE_SHAPESHIFT } from '../../constants/transactions'
export default class TransactionList extends PureComponent {
static contextTypes = {
t: PropTypes.func,
}
static defaultProps = {
pendingTransactions: [],
completedTransactions: [],
}
static propTypes = {
pendingTransactions: PropTypes.array,
completedTransactions: PropTypes.array,
selectedToken: PropTypes.object,
updateNetworkNonce: PropTypes.func,
assetImages: PropTypes.object,
}
componentDidMount () {
this.props.updateNetworkNonce()
}
componentDidUpdate (prevProps) {
const { pendingTransactions: prevPendingTransactions = [] } = prevProps
const { pendingTransactions = [], updateNetworkNonce } = this.props
if (pendingTransactions.length > prevPendingTransactions.length) {
updateNetworkNonce()
}
}
shouldShowRetry = (transactionGroup, isEarliestNonce) => {
const { transactions = [], hasRetried } = transactionGroup
const [earliestTransaction = {}] = transactions
const { submittedTime } = earliestTransaction
return Date.now() - submittedTime > 30000 && isEarliestNonce && !hasRetried
}
shouldShowCancel (transactionGroup) {
const { hasCancelled } = transactionGroup
return !hasCancelled
}
renderTransactions () {
const { t } = this.context
const { pendingTransactions = [], completedTransactions = [] } = this.props
const pendingLength = pendingTransactions.length
return (
<div className="transaction-list__transactions">
{
pendingLength > 0 && (
<div className="transaction-list__pending-transactions">
<div className="transaction-list__header">
{ `${t('queue')} (${pendingTransactions.length})` }
</div>
{
pendingTransactions.map((transactionGroup, index) => (
this.renderTransaction(transactionGroup, index, true)
))
}
</div>
)
}
<div className="transaction-list__completed-transactions">
<div className="transaction-list__header">
{ t('history') }
</div>
{
completedTransactions.length > 0
? completedTransactions.map((transactionGroup, index) => (
this.renderTransaction(transactionGroup, index)
))
: this.renderEmpty()
}
</div>
</div>
)
}
renderTransaction (transactionGroup, index, isPendingTx = false) {
const { selectedToken, assetImages } = this.props
const { transactions = [] } = transactionGroup
return transactions[0].key === TRANSACTION_TYPE_SHAPESHIFT
? (
<ShapeShiftTransactionListItem
{ ...transactions[0] }
key={`shapeshift${index}`}
/>
) : (
<TransactionListItem
transactionGroup={transactionGroup}
key={`${transactionGroup.nonce}:${index}`}
showRetry={isPendingTx && this.shouldShowRetry(transactionGroup, index === 0)}
showCancel={isPendingTx && this.shouldShowCancel(transactionGroup)}
token={selectedToken}
assetImages={assetImages}
/>
)
}
renderEmpty () {
return (
<div className="transaction-list__empty">
<div className="transaction-list__empty-text">
{ this.context.t('noTransactions') }
</div>
</div>
)
}
render () {
return (
<div className="transaction-list">
{ this.renderTransactions() }
</div>
)
}
}
|