mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
LoginPerSite: Support multiple accounts without automatic switching (#8079)
* transaction editing: use txParams 'from' account * signature-request: use txParams 'from' account * signature-request-original: use txParams 'from' account * encryption/decryption: use txParams 'from' account * update tests * set 'send' state 'from' address in confirm containers
This commit is contained in:
parent
0775c61f09
commit
2df8b85c5f
@ -122,16 +122,16 @@ initialize().catch(log.error)
|
||||
* @property {string} network - A stringified number of the current network ID.
|
||||
* @property {Object} accounts - An object mapping lower-case hex addresses to objects with "balance" and "address" keys, both storing hex string values.
|
||||
* @property {hex} currentBlockGasLimit - The most recently seen block gas limit, in a lower case hex prefixed string.
|
||||
* @property {TransactionMeta[]} selectedAddressTxList - An array of transactions associated with the currently selected account.
|
||||
* @property {Object} unapprovedMsgs - An object of messages associated with the currently selected account, mapping a unique ID to the options.
|
||||
* @property {TransactionMeta[]} currentNetworkTxList - An array of transactions associated with the currently selected network.
|
||||
* @property {Object} unapprovedMsgs - An object of messages pending approval, mapping a unique ID to the options.
|
||||
* @property {number} unapprovedMsgCount - The number of messages in unapprovedMsgs.
|
||||
* @property {Object} unapprovedPersonalMsgs - An object of messages associated with the currently selected account, mapping a unique ID to the options.
|
||||
* @property {Object} unapprovedPersonalMsgs - An object of messages pending approval, mapping a unique ID to the options.
|
||||
* @property {number} unapprovedPersonalMsgCount - The number of messages in unapprovedPersonalMsgs.
|
||||
* @property {Object} EncryptionPublicKeyMsgs - An object of messages associated with the currently selected account, mapping a unique ID to the options.
|
||||
* @property {Object} unapprovedEncryptionPublicKeyMsgs - An object of messages pending approval, mapping a unique ID to the options.
|
||||
* @property {number} unapprovedEncryptionPublicKeyMsgCount - The number of messages in EncryptionPublicKeyMsgs.
|
||||
* @property {Object} unapprovedDecryptMsgs - An object of messages associated with the currently selected account, mapping a unique ID to the options.
|
||||
* @property {Object} unapprovedDecryptMsgs - An object of messages pending approval, mapping a unique ID to the options.
|
||||
* @property {number} unapprovedDecryptMsgCount - The number of messages in unapprovedDecryptMsgs.
|
||||
* @property {Object} unapprovedTypedMsgs - An object of messages associated with the currently selected account, mapping a unique ID to the options.
|
||||
* @property {Object} unapprovedTypedMsgs - An object of messages pending approval, mapping a unique ID to the options.
|
||||
* @property {number} unapprovedTypedMsgCount - The number of messages in unapprovedTypedMsgs.
|
||||
* @property {string[]} keyringTypes - An array of unique keyring identifying strings, representing available strategies for creating accounts.
|
||||
* @property {Keyring[]} keyrings - An array of keyring descriptions, summarizing the accounts that are available for use, and what keyrings they belong to.
|
||||
|
@ -119,7 +119,6 @@ class TransactionController extends EventEmitter {
|
||||
this._onBootCleanUp()
|
||||
this._updateMemstore()
|
||||
})
|
||||
this.preferencesStore.subscribe(() => this._updateMemstore())
|
||||
|
||||
// request state update to finalize initialization
|
||||
this._updatePendingTxsAfterFirstBlock()
|
||||
@ -748,11 +747,10 @@ class TransactionController extends EventEmitter {
|
||||
_updateMemstore () {
|
||||
this.pendingTxTracker.updatePendingTxs()
|
||||
const unapprovedTxs = this.txStateManager.getUnapprovedTxList()
|
||||
const selectedAddressTxList = this.txStateManager.getFilteredTxList({
|
||||
from: this.getSelectedAddress(),
|
||||
const currentNetworkTxList = this.txStateManager.getFilteredTxList({
|
||||
metamaskNetworkId: this.getNetwork(),
|
||||
})
|
||||
this.memStore.updateState({ unapprovedTxs, selectedAddressTxList })
|
||||
this.memStore.updateState({ unapprovedTxs, currentNetworkTxList })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
* @returns {number} The id of the newly created EncryptionPublicKey.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (address, _req) {
|
||||
addUnapprovedMessage (address, req) {
|
||||
log.debug(`EncryptionPublicKeyManager addUnapprovedMessage: address`)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
@ -117,8 +117,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
type: 'eth_getEncryptionPublicKey',
|
||||
}
|
||||
|
||||
if (_req) {
|
||||
msgData.origin = _req.origin
|
||||
if (req) {
|
||||
msgData.origin = req.origin
|
||||
}
|
||||
|
||||
this.addMsg(msgData)
|
||||
|
@ -62,7 +62,7 @@
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -92,7 +92,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [
|
||||
"currentNetworkTxList": [
|
||||
{
|
||||
"id": 3870222542191014,
|
||||
"time": 1487271497135,
|
||||
|
@ -61,7 +61,7 @@
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedTxs": {
|
||||
"4768706228115573": {
|
||||
"id": 4768706228115573,
|
||||
|
File diff suppressed because one or more lines are too long
@ -68,7 +68,7 @@
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"incomingTransactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -20,7 +20,7 @@
|
||||
"network": "3",
|
||||
"accounts": {},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"keyringTypes": [
|
||||
|
@ -169,7 +169,7 @@
|
||||
}
|
||||
},
|
||||
"currentBlockGasLimit": "0x731e25",
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -44,7 +44,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [
|
||||
"currentNetworkTxList": [
|
||||
{
|
||||
"id": 1188547363326880,
|
||||
"time": 1487662234127,
|
||||
|
@ -31,7 +31,7 @@
|
||||
}
|
||||
},
|
||||
"currentBlockGasLimit": "0x66df83",
|
||||
"selectedAddressTxList": [
|
||||
"currentNetworkTxList": [
|
||||
{
|
||||
"id": 3516145537630216,
|
||||
"time": 1512615655535,
|
||||
|
@ -43,7 +43,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {
|
||||
|
@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -64,7 +64,7 @@
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [{
|
||||
"currentNetworkTxList": [{
|
||||
"id": 4768706228115573,
|
||||
"time": 1487363153561,
|
||||
"status": "unapproved",
|
||||
|
@ -66,7 +66,7 @@
|
||||
"assetImages": {},
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -55,7 +55,7 @@
|
||||
}
|
||||
},
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -3,7 +3,9 @@
|
||||
"completedOnboarding": true,
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"featureFlags": {"betaUI": true},
|
||||
"featureFlags": {
|
||||
"betaUI": true
|
||||
},
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
@ -68,7 +70,7 @@
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"incomingTransactions": {},
|
||||
"selectedAddressTxList": [
|
||||
"currentNetworkTxList": [
|
||||
{
|
||||
"err": {
|
||||
"message": "Error: intrinsic gas too low",
|
||||
@ -226,7 +228,7 @@
|
||||
"time": 1522378334455,
|
||||
"txParams": {
|
||||
"chainId": "0x3",
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"gas": "0x0",
|
||||
"gasPrice": "0x77359400",
|
||||
"nonce": "0x3",
|
||||
@ -241,7 +243,7 @@
|
||||
"metamaskNetworkId": "1",
|
||||
"loadingDefaults": false,
|
||||
"txParams": {
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"to": "0xf45d68f31b3c9ac84ff0d07b86c59b753a60b1e3",
|
||||
"value": "0x0",
|
||||
"gas": "0x0",
|
||||
@ -506,7 +508,7 @@
|
||||
"txParams": {
|
||||
"chainId": "0x3",
|
||||
"data": "0xa9059cbb000000000000000000000000e7884118ee52ec3f4eef715cb022279d7d4181a9000000000000000000000000000000000000000000000000000000000000000b",
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"gas": "0xd3e1",
|
||||
"gasPrice": "0x5f5e100",
|
||||
"nonce": "0x6",
|
||||
@ -714,7 +716,7 @@
|
||||
"txParams": {
|
||||
"chainId": "0x3",
|
||||
"data": "0xa9059cbb000000000000000000000000e7884118ee52ec3f4eef715cb022279d7d4181a9000000000000000000000000000000000000000000000000000000000000000b",
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"gas": "0xd3e1",
|
||||
"gasPrice": "0x5f5e100",
|
||||
"nonce": "0x2",
|
||||
@ -729,7 +731,7 @@
|
||||
"metamaskNetworkId": "1",
|
||||
"loadingDefaults": false,
|
||||
"txParams": {
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"to": "0xf45d68f31b3c9ac84ff0d07b86c59b753a60b1e3",
|
||||
"value": "0x0",
|
||||
"gas": "0xcf08",
|
||||
@ -908,7 +910,7 @@
|
||||
"metamaskNetworkId": "1",
|
||||
"loadingDefaults": false,
|
||||
"txParams": {
|
||||
"from": "0x5b1cbd5636d484bf1cb6927a9425db9e7dc73ce4",
|
||||
"from": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"to": "0xf45d68f31b3c9ac84ff0d07b86c59b753a60b1e3",
|
||||
"value": "0x0",
|
||||
"gas": "0xcf08",
|
||||
|
@ -13,7 +13,7 @@
|
||||
},
|
||||
"currentBlockGasLimit": "",
|
||||
"unapprovedTxs": {},
|
||||
"selectedAddressTxList": [],
|
||||
"currentNetworkTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
|
@ -157,7 +157,7 @@
|
||||
"forceGasMin": null,
|
||||
"toNickname": ""
|
||||
},
|
||||
"selectedAddressTxList": [
|
||||
"currentNetworkTxList": [
|
||||
{
|
||||
"id": 3387511061307736,
|
||||
"time": 1528133130531,
|
||||
|
@ -56,9 +56,9 @@ describe('Transaction Controller', function () {
|
||||
it('should return a state object with the right keys and datat types', function () {
|
||||
const exposedState = txController.getState()
|
||||
assert('unapprovedTxs' in exposedState, 'state should have the key unapprovedTxs')
|
||||
assert('selectedAddressTxList' in exposedState, 'state should have the key selectedAddressTxList')
|
||||
assert('currentNetworkTxList' in exposedState, 'state should have the key currentNetworkTxList')
|
||||
assert(exposedState && typeof exposedState.unapprovedTxs === 'object', 'should be an object')
|
||||
assert(Array.isArray(exposedState.selectedAddressTxList), 'should be an array')
|
||||
assert(Array.isArray(exposedState.currentNetworkTxList), 'should be an array')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -274,7 +274,7 @@ describe('MetaMask Reducers', function () {
|
||||
|
||||
it('updates value of tx by id', function () {
|
||||
const oldState = {
|
||||
selectedAddressTxList: [
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
id: 1,
|
||||
txParams: 'foo',
|
||||
@ -288,7 +288,7 @@ describe('MetaMask Reducers', function () {
|
||||
value: 'bar',
|
||||
})
|
||||
|
||||
assert.equal(state.selectedAddressTxList[0].txParams, 'bar')
|
||||
assert.equal(state.currentNetworkTxList[0].txParams, 'bar')
|
||||
})
|
||||
|
||||
it('sets blockies', function () {
|
||||
|
@ -71,11 +71,11 @@ import { getMaxModeOn } from '../../../../pages/send/send-content/send-amount-ro
|
||||
import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils'
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { selectedAddressTxList } = state.metamask
|
||||
const { currentNetworkTxList } = state.metamask
|
||||
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
|
||||
const { txData = {} } = modalProps || {}
|
||||
const { transaction = {} } = ownProps
|
||||
const selectedTransaction = selectedAddressTxList.find(({ id }) => id === (transaction.id || txData.id))
|
||||
const selectedTransaction = currentNetworkTxList.find(({ id }) => id === (transaction.id || txData.id))
|
||||
|
||||
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
|
||||
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
|
||||
|
@ -85,7 +85,7 @@ describe('gas-modal-page-container container', function () {
|
||||
provider: {
|
||||
type: 'mainnet',
|
||||
},
|
||||
selectedAddressTxList: [{
|
||||
currentNetworkTxList: [{
|
||||
id: 34,
|
||||
txParams: {
|
||||
gas: '0x1600000',
|
||||
|
@ -10,8 +10,8 @@ import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util'
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { metamask } = state
|
||||
const { transactionId, originalGasPrice } = ownProps
|
||||
const { selectedAddressTxList } = metamask
|
||||
const transaction = selectedAddressTxList.find(({ id }) => id === transactionId)
|
||||
const { currentNetworkTxList } = metamask
|
||||
const transaction = currentNetworkTxList.find(({ id }) => id === transactionId)
|
||||
const transactionStatus = transaction ? transaction.status : ''
|
||||
|
||||
const defaultNewGasPrice = ethUtil.addHexPrefix(
|
||||
|
@ -19,19 +19,22 @@ export default class SignatureRequestOriginal extends Component {
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
balance: PropTypes.string,
|
||||
fromAccount: PropTypes.shape({
|
||||
address: PropTypes.string.isRequired,
|
||||
balance: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}).isRequired,
|
||||
cancel: PropTypes.func.isRequired,
|
||||
clearConfirmTransaction: PropTypes.func.isRequired,
|
||||
conversionRate: PropTypes.number,
|
||||
history: PropTypes.object.isRequired,
|
||||
requesterAddress: PropTypes.string,
|
||||
selectedAccount: PropTypes.string,
|
||||
sign: PropTypes.func.isRequired,
|
||||
txData: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
selectedAccount: this.props.selectedAccount,
|
||||
fromAccount: this.props.fromAccount,
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
@ -81,7 +84,7 @@ export default class SignatureRequestOriginal extends Component {
|
||||
}
|
||||
|
||||
renderAccount = () => {
|
||||
const { selectedAccount } = this.state
|
||||
const { fromAccount } = this.state
|
||||
|
||||
return (
|
||||
<div className="request-signature__account">
|
||||
@ -91,7 +94,7 @@ export default class SignatureRequestOriginal extends Component {
|
||||
|
||||
<div className="request-signature__account-item">
|
||||
<AccountListItem
|
||||
account={selectedAccount}
|
||||
account={fromAccount}
|
||||
displayBalance={false}
|
||||
/>
|
||||
</div>
|
||||
@ -100,7 +103,8 @@ export default class SignatureRequestOriginal extends Component {
|
||||
}
|
||||
|
||||
renderBalance = () => {
|
||||
const { balance, conversionRate } = this.props
|
||||
const { conversionRate } = this.props
|
||||
const { fromAccount: { balance } } = this.state
|
||||
|
||||
const balanceInEther = conversionUtil(balance, {
|
||||
fromNumericBase: 'hex',
|
||||
|
@ -2,30 +2,28 @@ import { connect } from 'react-redux'
|
||||
import { compose } from 'redux'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
|
||||
import * as actions from '../../../store/actions'
|
||||
import { goHome } from '../../../store/actions'
|
||||
import {
|
||||
getSelectedAccount,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getSelectedAddress,
|
||||
accountsWithSendEtherInfoSelector,
|
||||
conversionRateSelector,
|
||||
} from '../../../selectors/selectors.js'
|
||||
import { getAccountByAddress } from '../../../helpers/utils/util'
|
||||
import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'
|
||||
import SignatureRequestOriginal from './signature-request-original.component'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
balance: getSelectedAccount(state).balance,
|
||||
selectedAccount: getCurrentAccountWithSendEtherInfo(state),
|
||||
selectedAddress: getSelectedAddress(state),
|
||||
requester: null,
|
||||
requesterAddress: null,
|
||||
conversionRate: conversionRateSelector(state),
|
||||
// not passed to component
|
||||
allAccounts: accountsWithSendEtherInfoSelector(state),
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
goHome: () => dispatch(actions.goHome()),
|
||||
goHome: () => dispatch(goHome()),
|
||||
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
||||
}
|
||||
}
|
||||
@ -41,7 +39,12 @@ function mergeProps (stateProps, dispatchProps, ownProps) {
|
||||
txData,
|
||||
} = ownProps
|
||||
|
||||
const { type } = txData
|
||||
const { allAccounts } = stateProps
|
||||
delete stateProps.allAccounts
|
||||
|
||||
const { type, msgParams: { from } } = txData
|
||||
|
||||
const fromAccount = getAccountByAddress(allAccounts, from)
|
||||
|
||||
let cancel
|
||||
let sign
|
||||
@ -60,6 +63,7 @@ function mergeProps (stateProps, dispatchProps, ownProps) {
|
||||
...ownProps,
|
||||
...stateProps,
|
||||
...dispatchProps,
|
||||
fromAccount,
|
||||
txData,
|
||||
cancel,
|
||||
sign,
|
||||
|
@ -10,11 +10,11 @@ import Identicon from '../../ui/identicon'
|
||||
export default class SignatureRequest extends PureComponent {
|
||||
static propTypes = {
|
||||
txData: PropTypes.object.isRequired,
|
||||
selectedAccount: PropTypes.shape({
|
||||
address: PropTypes.string,
|
||||
fromAccount: PropTypes.shape({
|
||||
address: PropTypes.string.isRequired,
|
||||
balance: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}),
|
||||
}).isRequired,
|
||||
|
||||
clearConfirmTransaction: PropTypes.func.isRequired,
|
||||
cancel: PropTypes.func.isRequired,
|
||||
@ -50,29 +50,30 @@ export default class SignatureRequest extends PureComponent {
|
||||
|
||||
render () {
|
||||
const {
|
||||
selectedAccount,
|
||||
txData: { msgParams: { data, origin, from: senderWallet } },
|
||||
fromAccount,
|
||||
txData: { msgParams: { data, origin } },
|
||||
cancel,
|
||||
sign,
|
||||
} = this.props
|
||||
const { address: fromAddress } = fromAccount
|
||||
const { message, domain = {} } = JSON.parse(data)
|
||||
|
||||
return (
|
||||
<div className="signature-request page-container">
|
||||
<Header selectedAccount={selectedAccount} />
|
||||
<Header fromAccount={fromAccount} />
|
||||
<div className="signature-request-content">
|
||||
<div className="signature-request-content__title">{this.context.t('sigRequest')}</div>
|
||||
<div className="signature-request-content__identicon-container">
|
||||
<div className="signature-request-content__identicon-initial" >{ domain.name && domain.name[0] }</div>
|
||||
<div className="signature-request-content__identicon-border" />
|
||||
<Identicon
|
||||
address={senderWallet}
|
||||
address={fromAddress}
|
||||
diameter={70}
|
||||
/>
|
||||
</div>
|
||||
<div className="signature-request-content__info--bolded">{domain.name}</div>
|
||||
<div className="signature-request-content__info">{origin}</div>
|
||||
<div className="signature-request-content__info">{this.formatWallet(senderWallet)}</div>
|
||||
<div className="signature-request-content__info">{this.formatWallet(fromAddress)}</div>
|
||||
</div>
|
||||
<Message data={message} />
|
||||
<Footer cancelAction={cancel} signAction={sign} />
|
||||
|
@ -1,33 +1,26 @@
|
||||
import { connect } from 'react-redux'
|
||||
import SignatureRequest from './signature-request.component'
|
||||
import { goHome } from '../../../store/actions'
|
||||
import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'
|
||||
import {
|
||||
getSelectedAccount,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getSelectedAddress,
|
||||
accountsWithSendEtherInfoSelector,
|
||||
conversionRateSelector,
|
||||
} from '../../../selectors/selectors.js'
|
||||
import { getAccountByAddress } from '../../../helpers/utils/util'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
balance: getSelectedAccount(state).balance,
|
||||
selectedAccount: getCurrentAccountWithSendEtherInfo(state),
|
||||
selectedAddress: getSelectedAddress(state),
|
||||
accounts: accountsWithSendEtherInfoSelector(state),
|
||||
conversionRate: conversionRateSelector(state),
|
||||
// not forwarded to component
|
||||
allAccounts: accountsWithSendEtherInfoSelector(state),
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
goHome: () => dispatch(goHome()),
|
||||
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
||||
}
|
||||
}
|
||||
|
||||
function mergeProps (stateProps, dispatchProps, ownProps) {
|
||||
const { allAccounts } = stateProps
|
||||
const {
|
||||
signPersonalMessage,
|
||||
signTypedMessage,
|
||||
@ -38,7 +31,9 @@ function mergeProps (stateProps, dispatchProps, ownProps) {
|
||||
txData,
|
||||
} = ownProps
|
||||
|
||||
const { type } = txData
|
||||
const { type, msgParams: { from } } = txData
|
||||
|
||||
const fromAccount = getAccountByAddress(allAccounts, from)
|
||||
|
||||
let cancel
|
||||
let sign
|
||||
@ -55,9 +50,9 @@ function mergeProps (stateProps, dispatchProps, ownProps) {
|
||||
}
|
||||
|
||||
return {
|
||||
...stateProps,
|
||||
...dispatchProps,
|
||||
...ownProps,
|
||||
...dispatchProps,
|
||||
fromAccount,
|
||||
txData,
|
||||
cancel,
|
||||
sign,
|
||||
|
@ -6,6 +6,7 @@ import SignatureRequest from '../signature-request.component'
|
||||
|
||||
describe('Signature Request Component', function () {
|
||||
describe('render', function () {
|
||||
const fromAddress = '0x123456789abcdef'
|
||||
it('should render a div with one child', function () {
|
||||
const wrapper = shallow((
|
||||
<SignatureRequest
|
||||
@ -15,9 +16,10 @@ describe('Signature Request Component', function () {
|
||||
txData={{
|
||||
msgParams: {
|
||||
data: '{"message": {"from": {"name": "hello"}}}',
|
||||
from: '0x123456789abcdef',
|
||||
from: fromAddress,
|
||||
},
|
||||
}}
|
||||
fromAccount={{ address: fromAddress }}
|
||||
/>
|
||||
))
|
||||
|
||||
|
@ -19,7 +19,9 @@ describe('Signature Request', function () {
|
||||
const store = configureMockStore()(mockStore)
|
||||
|
||||
const props = {
|
||||
selectedAccount: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
||||
fromAccount: {
|
||||
address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
||||
},
|
||||
history: {
|
||||
push: sinon.spy(),
|
||||
},
|
||||
|
@ -118,6 +118,7 @@ export default function reduceMetamask (state = {}, action) {
|
||||
}
|
||||
newSend.tokenBalance = null
|
||||
newSend.balance = '0'
|
||||
newSend.from = unapprovedTx.from || ''
|
||||
}
|
||||
|
||||
newState.send = newSend
|
||||
@ -279,8 +280,8 @@ export default function reduceMetamask (state = {}, action) {
|
||||
|
||||
case actions.UPDATE_TRANSACTION_PARAMS:
|
||||
const { id: txId, value } = action
|
||||
let { selectedAddressTxList } = metamaskState
|
||||
selectedAddressTxList = selectedAddressTxList.map((tx) => {
|
||||
let { currentNetworkTxList } = metamaskState
|
||||
currentNetworkTxList = currentNetworkTxList.map((tx) => {
|
||||
if (tx.id === txId) {
|
||||
const newTx = Object.assign({}, tx)
|
||||
newTx.txParams = value
|
||||
@ -291,7 +292,7 @@ export default function reduceMetamask (state = {}, action) {
|
||||
|
||||
return {
|
||||
...metamaskState,
|
||||
selectedAddressTxList,
|
||||
currentNetworkTxList,
|
||||
}
|
||||
|
||||
case actions.SET_PARTICIPATE_IN_METAMETRICS:
|
||||
|
@ -287,3 +287,11 @@ export function getOriginFromUrl (url) {
|
||||
const origin = url.hostname
|
||||
return origin
|
||||
}
|
||||
|
||||
export function getTxById (transactions = [], targetId) {
|
||||
return transactions.find(({ id }) => String(id) === targetId)
|
||||
}
|
||||
|
||||
export function getAccountByAddress (accounts = [], targetAddress) {
|
||||
return accounts.find(({ address }) => address === targetAddress)
|
||||
}
|
||||
|
@ -23,14 +23,23 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const { id: paramsTransactionId } = params
|
||||
const {
|
||||
confirmTransaction,
|
||||
metamask: { currentCurrency, conversionRate, selectedAddressTxList, domainMetadata = {}, selectedAddress },
|
||||
metamask: {
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
currentNetworkTxList,
|
||||
domainMetadata = {},
|
||||
selectedAddress,
|
||||
},
|
||||
} = state
|
||||
|
||||
const {
|
||||
txData: { id: transactionId, txParams: { to: tokenAddress, data } = {} } = {},
|
||||
} = confirmTransaction
|
||||
|
||||
const transaction = selectedAddressTxList.find(({ id }) => id === (Number(paramsTransactionId) || transactionId)) || {}
|
||||
const transaction = (
|
||||
currentNetworkTxList.find(({ id }) => id === (Number(paramsTransactionId) ||
|
||||
transactionId)) || {}
|
||||
)
|
||||
|
||||
const {
|
||||
ethTransactionTotal,
|
||||
|
@ -1,15 +1,16 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Tooltip from '../../components/ui/tooltip-v2'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import AccountListItem from '../send/account-list-item/account-list-item.component'
|
||||
import Button from '../../components/ui/button'
|
||||
import Identicon from '../../components/ui/identicon'
|
||||
import Tooltip from '../../components/ui/tooltip-v2'
|
||||
|
||||
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
||||
import Identicon from '../../components/ui/identicon'
|
||||
import AccountListItem from '../send/account-list-item/account-list-item.component'
|
||||
import { conversionUtil } from '../../helpers/utils/conversion-util'
|
||||
import Button from '../../components/ui/button'
|
||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
|
||||
|
||||
export default class ConfirmDecryptMessage extends Component {
|
||||
@ -19,7 +20,11 @@ export default class ConfirmDecryptMessage extends Component {
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
balance: PropTypes.string,
|
||||
fromAccount: PropTypes.shape({
|
||||
address: PropTypes.string.isRequired,
|
||||
balance: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}).isRequired,
|
||||
clearConfirmTransaction: PropTypes.func.isRequired,
|
||||
cancelDecryptMessage: PropTypes.func.isRequired,
|
||||
decryptMessage: PropTypes.func.isRequired,
|
||||
@ -27,15 +32,14 @@ export default class ConfirmDecryptMessage extends Component {
|
||||
conversionRate: PropTypes.number,
|
||||
history: PropTypes.object.isRequired,
|
||||
requesterAddress: PropTypes.string,
|
||||
selectedAccount: PropTypes.object,
|
||||
txData: PropTypes.object,
|
||||
domainMetadata: PropTypes.object,
|
||||
}
|
||||
|
||||
state = {
|
||||
selectedAccount: this.props.selectedAccount,
|
||||
hasCopied: false,
|
||||
fromAccount: this.props.fromAccount,
|
||||
copyToClipboardPressed: false,
|
||||
hasCopied: false,
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
@ -98,7 +102,7 @@ export default class ConfirmDecryptMessage extends Component {
|
||||
}
|
||||
|
||||
renderAccount = () => {
|
||||
const { selectedAccount } = this.state
|
||||
const { fromAccount } = this.state
|
||||
|
||||
return (
|
||||
<div className="request-decrypt-message__account">
|
||||
@ -108,7 +112,7 @@ export default class ConfirmDecryptMessage extends Component {
|
||||
|
||||
<div className="request-decrypt-message__account-item">
|
||||
<AccountListItem
|
||||
account={selectedAccount}
|
||||
account={fromAccount}
|
||||
displayBalance={false}
|
||||
/>
|
||||
</div>
|
||||
@ -117,7 +121,8 @@ export default class ConfirmDecryptMessage extends Component {
|
||||
}
|
||||
|
||||
renderBalance = () => {
|
||||
const { balance, conversionRate } = this.props
|
||||
const { conversionRate } = this.props
|
||||
const { fromAccount: { balance } } = this.state
|
||||
|
||||
const balanceInEther = conversionUtil(balance, {
|
||||
fromNumericBase: 'hex',
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { connect } from 'react-redux'
|
||||
import { compose } from 'redux'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
import { goHome, decryptMsg, cancelDecryptMsg, decryptMsgInline } from '../../store/actions'
|
||||
|
||||
import {
|
||||
getSelectedAccount,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getSelectedAddress,
|
||||
goHome,
|
||||
decryptMsg,
|
||||
cancelDecryptMsg,
|
||||
decryptMsgInline,
|
||||
} from '../../store/actions'
|
||||
import {
|
||||
getTargetAccountWithSendEtherInfo,
|
||||
conversionRateSelector,
|
||||
} from '../../selectors/selectors.js'
|
||||
} from '../../selectors/selectors'
|
||||
import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'
|
||||
import ConfirmDecryptMessage from './confirm-decrypt-message.component'
|
||||
|
||||
@ -21,12 +24,14 @@ function mapStateToProps (state) {
|
||||
txData = {},
|
||||
} = confirmTransaction
|
||||
|
||||
const { msgParams: { from } } = txData
|
||||
|
||||
const fromAccount = getTargetAccountWithSendEtherInfo(state, from)
|
||||
|
||||
return {
|
||||
txData: txData,
|
||||
domainMetadata: domainMetadata,
|
||||
balance: getSelectedAccount(state).balance,
|
||||
selectedAccount: getCurrentAccountWithSendEtherInfo(state),
|
||||
selectedAddress: getSelectedAddress(state),
|
||||
domainMetadata,
|
||||
fromAccount,
|
||||
requester: null,
|
||||
requesterAddress: null,
|
||||
conversionRate: conversionRateSelector(state),
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import AccountListItem from '../send/account-list-item/account-list-item.component'
|
||||
import Button from '../../components/ui/button'
|
||||
import Identicon from '../../components/ui/identicon'
|
||||
|
||||
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
||||
import Identicon from '../../components/ui/identicon'
|
||||
import AccountListItem from '../send/account-list-item/account-list-item.component'
|
||||
import { conversionUtil } from '../../helpers/utils/conversion-util'
|
||||
import Button from '../../components/ui/button'
|
||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
|
||||
|
||||
export default class ConfirmEncryptionPublicKey extends Component {
|
||||
@ -16,20 +17,23 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
balance: PropTypes.string,
|
||||
fromAccount: PropTypes.shape({
|
||||
address: PropTypes.string.isRequired,
|
||||
balance: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}).isRequired,
|
||||
clearConfirmTransaction: PropTypes.func.isRequired,
|
||||
cancelEncryptionPublicKey: PropTypes.func.isRequired,
|
||||
encryptionPublicKey: PropTypes.func.isRequired,
|
||||
conversionRate: PropTypes.number,
|
||||
history: PropTypes.object.isRequired,
|
||||
requesterAddress: PropTypes.string,
|
||||
selectedAccount: PropTypes.object,
|
||||
txData: PropTypes.object,
|
||||
domainMetadata: PropTypes.object,
|
||||
}
|
||||
|
||||
state = {
|
||||
selectedAccount: this.props.selectedAccount,
|
||||
fromAccount: this.props.fromAccount,
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
@ -79,7 +83,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
||||
}
|
||||
|
||||
renderAccount = () => {
|
||||
const { selectedAccount } = this.state
|
||||
const { fromAccount } = this.state
|
||||
|
||||
return (
|
||||
<div className="request-encryption-public-key__account">
|
||||
@ -89,7 +93,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
||||
|
||||
<div className="request-encryption-public-key__account-item">
|
||||
<AccountListItem
|
||||
account={selectedAccount}
|
||||
account={fromAccount}
|
||||
displayBalance={false}
|
||||
/>
|
||||
</div>
|
||||
@ -98,7 +102,8 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
||||
}
|
||||
|
||||
renderBalance = () => {
|
||||
const { balance, conversionRate } = this.props
|
||||
const { conversionRate } = this.props
|
||||
const { fromAccount: { balance } } = this.state
|
||||
|
||||
const balanceInEther = conversionUtil(balance, {
|
||||
fromNumericBase: 'hex',
|
||||
|
@ -1,14 +1,18 @@
|
||||
import { connect } from 'react-redux'
|
||||
import { compose } from 'redux'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
import { goHome, encryptionPublicKeyMsg, cancelEncryptionPublicKeyMsg } from '../../store/actions'
|
||||
|
||||
import {
|
||||
getSelectedAccount,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getSelectedAddress,
|
||||
goHome,
|
||||
encryptionPublicKeyMsg,
|
||||
cancelEncryptionPublicKeyMsg,
|
||||
} from '../../store/actions'
|
||||
|
||||
import {
|
||||
conversionRateSelector,
|
||||
} from '../../selectors/selectors.js'
|
||||
getTargetAccountWithSendEtherInfo,
|
||||
} from '../../selectors/selectors'
|
||||
|
||||
import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'
|
||||
import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component'
|
||||
|
||||
@ -21,12 +25,14 @@ function mapStateToProps (state) {
|
||||
txData = {},
|
||||
} = confirmTransaction
|
||||
|
||||
const { msgParams: from } = txData
|
||||
|
||||
const fromAccount = getTargetAccountWithSendEtherInfo(state, from)
|
||||
|
||||
return {
|
||||
txData: txData,
|
||||
domainMetadata: domainMetadata,
|
||||
balance: getSelectedAccount(state).balance,
|
||||
selectedAccount: getCurrentAccountWithSendEtherInfo(state),
|
||||
selectedAddress: getSelectedAddress(state),
|
||||
fromAccount,
|
||||
requester: null,
|
||||
requesterAddress: null,
|
||||
conversionRate: conversionRateSelector(state),
|
||||
|
@ -18,6 +18,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
editTransaction: (txData) => {
|
||||
const { id, txParams } = txData
|
||||
const {
|
||||
from,
|
||||
gas: gasLimit,
|
||||
gasPrice,
|
||||
to,
|
||||
@ -25,6 +26,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
} = txParams
|
||||
|
||||
dispatch(updateSend({
|
||||
from,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
gasTotal: null,
|
||||
|
@ -18,16 +18,29 @@ const mapStateToProps = (state) => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
editTransaction: ({ txData, tokenData, tokenProps }) => {
|
||||
const { txParams: { to: tokenAddress, gas: gasLimit, gasPrice } = {}, id } = txData
|
||||
|
||||
const {
|
||||
id,
|
||||
txParams: {
|
||||
from,
|
||||
to: tokenAddress,
|
||||
gas: gasLimit,
|
||||
gasPrice,
|
||||
} = {},
|
||||
} = txData
|
||||
|
||||
const { params = [] } = tokenData
|
||||
const { value: to } = params[0] || {}
|
||||
const { value: tokenAmountInDec } = params[1] || {}
|
||||
|
||||
const tokenAmountInHex = conversionUtil(tokenAmountInDec, {
|
||||
fromNumericBase: 'dec',
|
||||
toNumericBase: 'hex',
|
||||
})
|
||||
|
||||
dispatch(setSelectedToken(tokenAddress))
|
||||
dispatch(updateSend({
|
||||
from,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
gasTotal: null,
|
||||
|
@ -20,13 +20,19 @@ import {
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { match: { params = {} } } = ownProps
|
||||
const { id: paramsTransactionId } = params
|
||||
const { confirmTransaction, metamask: { currentCurrency, conversionRate, selectedAddressTxList } } = state
|
||||
const {
|
||||
confirmTransaction,
|
||||
metamask: { currentCurrency, conversionRate, currentNetworkTxList },
|
||||
} = state
|
||||
|
||||
const {
|
||||
txData: { id: transactionId, txParams: { to: tokenAddress, data } = {} } = {},
|
||||
} = confirmTransaction
|
||||
|
||||
const transaction = selectedAddressTxList.find(({ id }) => id === (Number(paramsTransactionId) || transactionId)) || {}
|
||||
const transaction = (
|
||||
currentNetworkTxList.find(({ id }) => id === (Number(paramsTransactionId) ||
|
||||
transactionId)) || {}
|
||||
)
|
||||
|
||||
const {
|
||||
ethTransactionTotal,
|
||||
|
@ -39,7 +39,7 @@ function mapStateToProps (state) {
|
||||
unapprovedPersonalMsgCount,
|
||||
unapprovedTypedMessagesCount,
|
||||
send: state.metamask.send,
|
||||
selectedAddressTxList: state.metamask.selectedAddressTxList,
|
||||
currentNetworkTxList: state.metamask.currentNetworkTxList,
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ class ConfirmTxScreen extends Component {
|
||||
unapprovedTypedMessages: PropTypes.object,
|
||||
match: PropTypes.shape({
|
||||
params: PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
id: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
|
||||
selectedAddressTxList: PropTypes.array,
|
||||
currentNetworkTxList: PropTypes.array,
|
||||
currentCurrency: PropTypes.string,
|
||||
blockGasLimit: PropTypes.string,
|
||||
history: PropTypes.object,
|
||||
@ -181,7 +181,7 @@ class ConfirmTxScreen extends Component {
|
||||
const {
|
||||
unapprovedTxs = {},
|
||||
network,
|
||||
selectedAddressTxList,
|
||||
currentNetworkTxList,
|
||||
send,
|
||||
history,
|
||||
match: { params: { id: transactionId } = {} },
|
||||
@ -190,12 +190,12 @@ class ConfirmTxScreen extends Component {
|
||||
let prevTx
|
||||
|
||||
if (transactionId) {
|
||||
prevTx = R.find(({ id }) => id + '' === transactionId)(selectedAddressTxList)
|
||||
prevTx = R.find(({ id }) => id + '' === transactionId)(currentNetworkTxList)
|
||||
} else {
|
||||
const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps
|
||||
const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network)
|
||||
const prevTxData = prevUnconfTxList[prevIndex] || {}
|
||||
prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {}
|
||||
prevTx = currentNetworkTxList.find(({ id }) => id === prevTxData.id) || {}
|
||||
}
|
||||
|
||||
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network)
|
||||
|
@ -389,7 +389,6 @@ function mapStateToProps (state) {
|
||||
submittedPendingTransactions: submittedPendingTransactionsSelector(state),
|
||||
network: state.metamask.network,
|
||||
provider: state.metamask.provider,
|
||||
selectedAddress: state.metamask.selectedAddress,
|
||||
frequentRpcListDetail: state.metamask.frequentRpcListDetail || [],
|
||||
currentCurrency: state.metamask.currentCurrency,
|
||||
isMouseUser: state.appState.isMouseUser,
|
||||
@ -406,7 +405,6 @@ function mapDispatchToProps (dispatch) {
|
||||
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
|
||||
setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)),
|
||||
setLastActiveTime: () => dispatch(actions.setLastActiveTime()),
|
||||
showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { connect } from 'react-redux'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getSendEnsResolution,
|
||||
getSendEnsResolutionError,
|
||||
} from '../../send.selectors.js'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getAddressBook,
|
||||
getAddressBookEntry,
|
||||
} from '../../../../selectors/selectors'
|
||||
|
@ -20,11 +20,11 @@ proxyquire('../add-recipient.container.js', {
|
||||
'../../send.selectors.js': {
|
||||
getSendEnsResolution: (s) => `mockSendEnsResolution:${s}`,
|
||||
getSendEnsResolutionError: (s) => `mockSendEnsResolutionError:${s}`,
|
||||
accountsWithSendEtherInfoSelector: (s) => `mockAccountsWithSendEtherInfoSelector:${s}`,
|
||||
},
|
||||
'../../../../selectors/selectors': {
|
||||
getAddressBook: (s) => [{ name: `mockAddressBook:${s}` }],
|
||||
getAddressBookEntry: (s) => `mockAddressBookEntry:${s}`,
|
||||
accountsWithSendEtherInfoSelector: (s) => `mockAccountsWithSendEtherInfoSelector:${s}`,
|
||||
},
|
||||
'../../../../store/actions': actionSpies,
|
||||
})
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { connect } from 'react-redux'
|
||||
import SendContent from './send-content.component'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getSendTo,
|
||||
} from '../send.selectors'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getAddressBookEntry,
|
||||
} from '../../../selectors/selectors'
|
||||
import * as actions from '../../../store/actions'
|
||||
|
@ -24,6 +24,10 @@ import {
|
||||
getSendErrors,
|
||||
} from '../send.selectors'
|
||||
import { getGasIsLoading } from '../../../selectors/selectors'
|
||||
import { networkTransactionsSelector } from '../../../selectors/transactions'
|
||||
import {
|
||||
getTxById,
|
||||
} from '../../../helpers/utils/util'
|
||||
import {
|
||||
isSendFormInError,
|
||||
} from './send-footer.selectors'
|
||||
@ -40,6 +44,7 @@ import {
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendFooter)
|
||||
|
||||
function mapStateToProps (state) {
|
||||
|
||||
const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state)
|
||||
const gasPrice = getGasPrice(state)
|
||||
const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, gasPrice)
|
||||
@ -47,11 +52,19 @@ function mapStateToProps (state) {
|
||||
? gasButtonInfo[activeButtonIndex].gasEstimateType
|
||||
: 'custom'
|
||||
|
||||
let fromAddress
|
||||
const editingTransactionId = getSendEditingTransactionId(state)
|
||||
if (editingTransactionId) {
|
||||
const transactions = networkTransactionsSelector(state)
|
||||
const tx = getTxById(transactions, editingTransactionId)
|
||||
fromAddress = tx && tx.txParams && tx.txParams.from
|
||||
}
|
||||
|
||||
return {
|
||||
amount: getSendAmount(state),
|
||||
data: getSendHexData(state),
|
||||
editingTransactionId: getSendEditingTransactionId(state),
|
||||
from: getSendFromObject(state),
|
||||
editingTransactionId,
|
||||
from: getSendFromObject(state, fromAddress),
|
||||
gasLimit: getGasLimit(state),
|
||||
gasPrice: getGasPrice(state),
|
||||
gasTotal: getGasTotal(state),
|
||||
|
@ -28,6 +28,9 @@ import {
|
||||
getSelectedAddress,
|
||||
getAddressBook,
|
||||
} from '../../selectors/selectors'
|
||||
import {
|
||||
networkTransactionsSelector,
|
||||
} from '../../selectors/transactions'
|
||||
import { getTokens } from './send-content/add-recipient/add-recipient.selectors'
|
||||
import {
|
||||
updateSendTo,
|
||||
@ -51,17 +54,27 @@ import {
|
||||
} from './send.utils.js'
|
||||
import {
|
||||
isValidDomainName,
|
||||
getTxById,
|
||||
} from '../../helpers/utils/util'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
|
||||
let fromAddress
|
||||
const editingTransactionId = getSendEditingTransactionId(state)
|
||||
if (editingTransactionId) {
|
||||
const transactions = networkTransactionsSelector(state)
|
||||
const tx = getTxById(transactions, editingTransactionId)
|
||||
fromAddress = tx && tx.txParams && tx.txParams.from
|
||||
}
|
||||
|
||||
return {
|
||||
addressBook: getAddressBook(state),
|
||||
amount: getSendAmount(state),
|
||||
amountConversionRate: getAmountConversionRate(state),
|
||||
blockGasLimit: getBlockGasLimit(state),
|
||||
conversionRate: getConversionRate(state),
|
||||
editingTransactionId: getSendEditingTransactionId(state),
|
||||
from: getSendFromObject(state),
|
||||
editingTransactionId,
|
||||
from: getSendFromObject(state, fromAddress),
|
||||
gasLimit: getGasLimit(state),
|
||||
gasPrice: getGasPrice(state),
|
||||
gasTotal: getGasTotal(state),
|
||||
|
@ -1,22 +1,18 @@
|
||||
import { valuesFor } from '../../helpers/utils/util'
|
||||
import abi from 'human-standard-token-abi'
|
||||
import { multiplyCurrencies } from '../../helpers/utils/conversion-util'
|
||||
import { getMetaMaskAccounts, getSelectedAddress, getAddressBook } from '../../selectors/selectors'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getAddressBook,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getTargetAccountWithSendEtherInfo,
|
||||
getMetaMaskAccounts,
|
||||
getSelectedAddress,
|
||||
} from '../../selectors/selectors'
|
||||
import { estimateGasPriceFromRecentBlocks, calcGasTotal } from './send.utils'
|
||||
import {
|
||||
getAveragePriceEstimateInHexWEI,
|
||||
} from '../../selectors/custom-gas'
|
||||
|
||||
export function accountsWithSendEtherInfoSelector (state) {
|
||||
const accounts = getMetaMaskAccounts(state)
|
||||
const { identities } = state.metamask
|
||||
const accountsWithSendEtherInfo = Object.entries(accounts).map(([key, account]) => {
|
||||
return Object.assign({}, account, identities[key])
|
||||
})
|
||||
|
||||
return accountsWithSendEtherInfo
|
||||
}
|
||||
|
||||
export function getAmountConversionRate (state) {
|
||||
return getSelectedToken(state)
|
||||
? getSelectedTokenToFiatRate(state)
|
||||
@ -31,13 +27,6 @@ export function getConversionRate (state) {
|
||||
return state.metamask.conversionRate
|
||||
}
|
||||
|
||||
export function getCurrentAccountWithSendEtherInfo (state) {
|
||||
const currentAddress = getSelectedAddress(state)
|
||||
const accounts = accountsWithSendEtherInfoSelector(state)
|
||||
|
||||
return accounts.find(({ address }) => address === currentAddress)
|
||||
}
|
||||
|
||||
export function getCurrentCurrency (state) {
|
||||
return state.metamask.currentCurrency
|
||||
}
|
||||
@ -162,7 +151,10 @@ export function getSendFromBalance (state) {
|
||||
return from.balance
|
||||
}
|
||||
|
||||
export function getSendFromObject (state) {
|
||||
export function getSendFromObject (state, address) {
|
||||
if (address) {
|
||||
return getTargetAccountWithSendEtherInfo(state, address)
|
||||
}
|
||||
return getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state)
|
||||
}
|
||||
|
||||
@ -207,21 +199,6 @@ export function getUnapprovedTxs (state) {
|
||||
return state.metamask.unapprovedTxs
|
||||
}
|
||||
|
||||
export function transactionsSelector (state) {
|
||||
const { network, selectedTokenAddress } = state.metamask
|
||||
const unapprovedMsgs = valuesFor(state.metamask.unapprovedMsgs)
|
||||
const shapeShiftTxList = (network === '1') ? state.metamask.shapeShiftTxList : undefined
|
||||
const transactions = state.metamask.selectedAddressTxList || []
|
||||
const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList)
|
||||
|
||||
return selectedTokenAddress
|
||||
? txsToRender
|
||||
.filter(({ txParams }) => txParams && txParams.to === selectedTokenAddress)
|
||||
.sort((a, b) => b.time - a.time)
|
||||
: txsToRender
|
||||
.sort((a, b) => b.time - a.time)
|
||||
}
|
||||
|
||||
export function getQrCodeData (state) {
|
||||
return state.appState.qrCodeData
|
||||
}
|
||||
|
@ -91,11 +91,12 @@ export default {
|
||||
},
|
||||
},
|
||||
'transactions': {},
|
||||
'selectedAddressTxList': [
|
||||
'currentNetworkTxList': [
|
||||
{
|
||||
'id': 'mockTokenTx1',
|
||||
'txParams': {
|
||||
'to': '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
'from': '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
'time': 1700000000000,
|
||||
},
|
||||
@ -103,6 +104,7 @@ export default {
|
||||
'id': 'mockTokenTx2',
|
||||
'txParams': {
|
||||
'to': '0xafaketokenaddress',
|
||||
'from': '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
'time': 1600000000000,
|
||||
},
|
||||
@ -110,6 +112,7 @@ export default {
|
||||
'id': 'mockTokenTx3',
|
||||
'txParams': {
|
||||
'to': '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
'from': '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
'time': 1500000000000,
|
||||
},
|
||||
@ -117,6 +120,7 @@ export default {
|
||||
'id': 'mockEthTx1',
|
||||
'txParams': {
|
||||
'to': '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
'from': '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
'time': 1400000000000,
|
||||
},
|
||||
|
@ -2,11 +2,12 @@ import assert from 'assert'
|
||||
import sinon from 'sinon'
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
// autoAddToBetaUI,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
} from '../../../selectors/selectors'
|
||||
import {
|
||||
getBlockGasLimit,
|
||||
getAmountConversionRate,
|
||||
getConversionRate,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getCurrentCurrency,
|
||||
getCurrentNetwork,
|
||||
getNativeCurrency,
|
||||
@ -35,7 +36,6 @@ import {
|
||||
getTokenBalance,
|
||||
getTokenExchangeRate,
|
||||
getUnapprovedTxs,
|
||||
transactionsSelector,
|
||||
} from '../send.selectors.js'
|
||||
import mockState from './send-selectors-test-data'
|
||||
|
||||
@ -540,132 +540,4 @@ describe('send selectors', function () {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('transactionsSelector()', function () {
|
||||
it('should return the selected addresses selected token transactions', function () {
|
||||
assert.deepEqual(
|
||||
transactionsSelector(mockState),
|
||||
[
|
||||
{
|
||||
id: 'mockTokenTx1',
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
time: 1700000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockTokenTx3',
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
time: 1500000000000,
|
||||
},
|
||||
]
|
||||
)
|
||||
})
|
||||
|
||||
it('should return all transactions if no token is selected', function () {
|
||||
const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false })
|
||||
const modifiedState = Object.assign({}, mockState, { metamask: modifiedMetamaskState })
|
||||
assert.deepEqual(
|
||||
transactionsSelector(modifiedState),
|
||||
[
|
||||
{
|
||||
id: 'mockTokenTx1',
|
||||
time: 1700000000000,
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'unapprovedMessage1',
|
||||
time: 1650000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockTokenTx2',
|
||||
time: 1600000000000,
|
||||
txParams: {
|
||||
to: '0xafaketokenaddress',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'unapprovedMessage2',
|
||||
time: 1550000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockTokenTx3',
|
||||
time: 1500000000000,
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'unapprovedMessage3',
|
||||
time: 1450000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockEthTx1',
|
||||
time: 1400000000000,
|
||||
txParams: {
|
||||
to: '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
})
|
||||
|
||||
it('should return shapeshift transactions if current network is 1', function () {
|
||||
const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false, network: '1' })
|
||||
const modifiedState = Object.assign({}, mockState, { metamask: modifiedMetamaskState })
|
||||
assert.deepEqual(
|
||||
transactionsSelector(modifiedState),
|
||||
[
|
||||
{
|
||||
id: 'mockTokenTx1',
|
||||
time: 1700000000000,
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
},
|
||||
{ id: 'shapeShiftTx1', 'time': 1675000000000 },
|
||||
{
|
||||
id: 'unapprovedMessage1',
|
||||
time: 1650000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockTokenTx2',
|
||||
time: 1600000000000,
|
||||
txParams: {
|
||||
to: '0xafaketokenaddress',
|
||||
},
|
||||
},
|
||||
{ id: 'shapeShiftTx2', 'time': 1575000000000 },
|
||||
{
|
||||
id: 'unapprovedMessage2',
|
||||
time: 1550000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockTokenTx3',
|
||||
time: 1500000000000,
|
||||
txParams: {
|
||||
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
|
||||
},
|
||||
},
|
||||
{ id: 'shapeShiftTx3', 'time': 1475000000000 },
|
||||
{
|
||||
id: 'unapprovedMessage3',
|
||||
time: 1450000000000,
|
||||
},
|
||||
{
|
||||
id: 'mockEthTx1',
|
||||
time: 1400000000000,
|
||||
txParams: {
|
||||
to: '0xd85a4b6a394794842887b8284293d69163007bbb',
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
checksumAddress,
|
||||
formatDate,
|
||||
getOriginFromUrl,
|
||||
getAccountByAddress,
|
||||
} from '../helpers/utils/util'
|
||||
|
||||
import { getPermittedAccountsMap } from './permissions'
|
||||
@ -250,7 +251,12 @@ export function getCurrentAccountWithSendEtherInfo (state) {
|
||||
const currentAddress = getSelectedAddress(state)
|
||||
const accounts = accountsWithSendEtherInfoSelector(state)
|
||||
|
||||
return accounts.find(({ address }) => address === currentAddress)
|
||||
return getAccountByAddress(accounts, currentAddress)
|
||||
}
|
||||
|
||||
export function getTargetAccountWithSendEtherInfo (state, targetAddress) {
|
||||
const accounts = accountsWithSendEtherInfoSelector(state)
|
||||
return getAccountByAddress(accounts, targetAddress)
|
||||
}
|
||||
|
||||
export function getCurrentEthBalance (state) {
|
||||
|
@ -93,7 +93,7 @@ export default {
|
||||
},
|
||||
},
|
||||
'transactions': {},
|
||||
'selectedAddressTxList': [
|
||||
'currentNetworkTxList': [
|
||||
{
|
||||
'id': 'mockTokenTx1',
|
||||
'txParams': {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import assert from 'assert'
|
||||
import { strict as assert } from 'assert'
|
||||
import {
|
||||
unapprovedMessagesSelector,
|
||||
transactionsSelector,
|
||||
@ -11,6 +11,7 @@ import {
|
||||
describe('Transaction Selectors', function () {
|
||||
|
||||
describe('unapprovedMessagesSelector', function () {
|
||||
|
||||
it('returns eth sign msg from unapprovedMsgs', function () {
|
||||
|
||||
const msg = {
|
||||
@ -94,13 +95,12 @@ describe('Transaction Selectors', function () {
|
||||
|
||||
assert(Array.isArray(msgSelector))
|
||||
assert.deepEqual(msgSelector, [msg])
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('transactionsSelector', function () {
|
||||
|
||||
it('selectedAddressTxList', function () {
|
||||
it('selects the currentNetworkTxList', function () {
|
||||
|
||||
const state = {
|
||||
metamask: {
|
||||
@ -110,7 +110,8 @@ describe('Transaction Selectors', function () {
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddressTxList: [
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
id: 0,
|
||||
time: 0,
|
||||
@ -131,15 +132,15 @@ describe('Transaction Selectors', function () {
|
||||
},
|
||||
}
|
||||
|
||||
const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time)
|
||||
const orderedTxList = state.metamask.currentNetworkTxList.sort((a, b) => b.time - a.time)
|
||||
|
||||
const txSelector = transactionsSelector(state)
|
||||
const selectedTx = transactionsSelector(state)
|
||||
|
||||
assert(Array.isArray(txSelector))
|
||||
assert.deepEqual(txSelector, orderedTxlist)
|
||||
assert(Array.isArray(selectedTx))
|
||||
assert.deepEqual(selectedTx, orderedTxList)
|
||||
})
|
||||
|
||||
it('returns token tx from selectedAddressTxList when selectedTokenAddress is valid', function () {
|
||||
it('returns token transactions from currentNetworkTxList when selectedTokenAddress is valid', function () {
|
||||
|
||||
const state = {
|
||||
metamask: {
|
||||
@ -149,8 +150,9 @@ describe('Transaction Selectors', function () {
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
selectedTokenAddress: '0xToken',
|
||||
selectedAddressTxList: [
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
id: 0,
|
||||
time: 0,
|
||||
@ -162,6 +164,14 @@ describe('Transaction Selectors', function () {
|
||||
{
|
||||
id: 1,
|
||||
time: 1,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xRecipient',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
time: 2,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xToken',
|
||||
@ -169,18 +179,110 @@ describe('Transaction Selectors', function () {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time)
|
||||
const orderedTxList = state.metamask.currentNetworkTxList
|
||||
.filter((tx) => tx.txParams.to === '0xToken')
|
||||
.sort((a, b) => b.time - a.time)
|
||||
|
||||
const txSelector = transactionsSelector(state)
|
||||
|
||||
assert(Array.isArray(txSelector))
|
||||
assert.deepEqual(txSelector, orderedTxlist)
|
||||
const selectedTx = transactionsSelector(state)
|
||||
|
||||
assert(Array.isArray(selectedTx))
|
||||
assert.deepEqual(selectedTx, orderedTxList)
|
||||
})
|
||||
|
||||
it('should return shapeshift transactions if current network is mainnet', function () {
|
||||
|
||||
const state = {
|
||||
metamask: {
|
||||
provider: {
|
||||
nickname: 'mainnet',
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
id: 0,
|
||||
time: 0,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xRecipient',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
time: 2,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xRecipient',
|
||||
},
|
||||
},
|
||||
],
|
||||
shapeShiftTxList: [
|
||||
{ id: 'shapeShiftTx1', 'time': 1 },
|
||||
{ id: 'shapeShiftTx2', 'time': 3 },
|
||||
{ id: 'shapeShiftTx3', 'time': 4 },
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const orderedTxList = state.metamask.currentNetworkTxList
|
||||
.concat(state.metamask.shapeShiftTxList)
|
||||
.sort((a, b) => b.time - a.time)
|
||||
|
||||
const selectedTx = transactionsSelector(state)
|
||||
|
||||
assert(Array.isArray(selectedTx))
|
||||
assert.deepEqual(selectedTx, orderedTxList)
|
||||
})
|
||||
|
||||
it('should not return shapeshift transactions if current network is not mainnet', function () {
|
||||
|
||||
const state = {
|
||||
metamask: {
|
||||
provider: {
|
||||
nickname: 'rinkeby',
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
id: 0,
|
||||
time: 0,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xRecipient',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
time: 2,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xRecipient',
|
||||
},
|
||||
},
|
||||
],
|
||||
shapeShiftTxList: [
|
||||
{ id: 'shapeShiftTx1', 'time': 1 },
|
||||
{ id: 'shapeShiftTx2', 'time': 3 },
|
||||
{ id: 'shapeShiftTx3', 'time': 4 },
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const orderedTxList = state.metamask.currentNetworkTxList
|
||||
.sort((a, b) => b.time - a.time)
|
||||
|
||||
const selectedTx = transactionsSelector(state)
|
||||
|
||||
assert(Array.isArray(selectedTx))
|
||||
assert.deepEqual(selectedTx, orderedTxList)
|
||||
})
|
||||
})
|
||||
|
||||
describe('nonceSortedTransactionsSelector', function () {
|
||||
@ -212,10 +314,11 @@ describe('Transaction Selectors', function () {
|
||||
provider: {
|
||||
nickname: 'mainnet',
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddressTxList: [
|
||||
currentNetworkTxList: [
|
||||
tx1,
|
||||
tx2,
|
||||
],
|
||||
@ -296,10 +399,11 @@ describe('Transaction Selectors', function () {
|
||||
provider: {
|
||||
nickname: 'mainnet',
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
selectedAddressTxList: [
|
||||
currentNetworkTxList: [
|
||||
submittedTx,
|
||||
unapprovedTx,
|
||||
approvedTx,
|
||||
@ -360,9 +464,6 @@ describe('Transaction Selectors', function () {
|
||||
|
||||
const expectedResult = [ submittedTx ]
|
||||
assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult)
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -12,7 +12,11 @@ import {
|
||||
import { hexToDecimal } from '../helpers/utils/conversions.util'
|
||||
import { selectedTokenAddressSelector } from './tokens'
|
||||
import { getFastPriceEstimateInHexWEI } from './custom-gas'
|
||||
import { getSelectedToken, getIsMainnet } from './selectors'
|
||||
import {
|
||||
getIsMainnet,
|
||||
getSelectedToken,
|
||||
getSelectedAddress,
|
||||
} from './selectors'
|
||||
import txHelper from '../../lib/tx-helper'
|
||||
|
||||
export const shapeShiftTxListSelector = (state) => {
|
||||
@ -29,20 +33,28 @@ export const incomingTxListSelector = (state) => {
|
||||
}
|
||||
|
||||
const network = state.metamask.network
|
||||
const selectedAddress = state.metamask.selectedAddress
|
||||
const selectedAddress = getSelectedAddress(state)
|
||||
return Object.values(state.metamask.incomingTransactions)
|
||||
.filter(({ metamaskNetworkId, txParams }) => (
|
||||
txParams.to === selectedAddress && metamaskNetworkId === network
|
||||
))
|
||||
}
|
||||
export const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs
|
||||
export const selectedAddressTxListSelector = (state) => state.metamask.selectedAddressTxList
|
||||
export const currentNetworkTxListSelector = (state) => state.metamask.currentNetworkTxList
|
||||
export const unapprovedPersonalMsgsSelector = (state) => state.metamask.unapprovedPersonalMsgs
|
||||
export const unapprovedDecryptMsgsSelector = (state) => state.metamask.unapprovedDecryptMsgs
|
||||
export const unapprovedEncryptionPublicKeyMsgsSelector = (state) => state.metamask.unapprovedEncryptionPublicKeyMsgs
|
||||
export const unapprovedTypedMessagesSelector = (state) => state.metamask.unapprovedTypedMessages
|
||||
export const networkSelector = (state) => state.metamask.network
|
||||
|
||||
export const selectedAddressTxListSelector = createSelector(
|
||||
getSelectedAddress,
|
||||
currentNetworkTxListSelector,
|
||||
(selectedAddress, transactions = []) => {
|
||||
return transactions.filter(({ txParams }) => txParams.from === selectedAddress)
|
||||
}
|
||||
)
|
||||
|
||||
export const unapprovedMessagesSelector = createSelector(
|
||||
unapprovedMsgsSelector,
|
||||
unapprovedPersonalMsgsSelector,
|
||||
@ -79,21 +91,43 @@ const priorityStatusHash = {
|
||||
[CONFIRMED_STATUS]: true,
|
||||
}
|
||||
|
||||
export const transactionsSelector = createSelector(
|
||||
selectedTokenAddressSelector,
|
||||
export const transactionSubSelector = createSelector(
|
||||
unapprovedMessagesSelector,
|
||||
shapeShiftTxListSelector,
|
||||
incomingTxListSelector,
|
||||
selectedAddressTxListSelector,
|
||||
(selectedTokenAddress, unapprovedMessages = [], shapeShiftTxList = [], incomingTxList = [], transactions = []) => {
|
||||
const txsToRender = transactions.concat(unapprovedMessages, shapeShiftTxList, incomingTxList)
|
||||
(unapprovedMessages = [], shapeShiftTxList = [], incomingTxList = []) => {
|
||||
return unapprovedMessages.concat(shapeShiftTxList, incomingTxList)
|
||||
}
|
||||
)
|
||||
|
||||
return selectedTokenAddress
|
||||
? txsToRender
|
||||
.filter(({ txParams }) => txParams && txParams.to === selectedTokenAddress)
|
||||
.sort((a, b) => b.time - a.time)
|
||||
: txsToRender
|
||||
.sort((a, b) => b.time - a.time)
|
||||
const transactionSelectorReturnHelper = (selectedTokenAddress, transactions) => {
|
||||
return selectedTokenAddress
|
||||
? transactions
|
||||
.filter(({ txParams }) => txParams && txParams.to === selectedTokenAddress)
|
||||
.sort((a, b) => b.time - a.time)
|
||||
: transactions
|
||||
.sort((a, b) => b.time - a.time)
|
||||
}
|
||||
|
||||
export const networkTransactionsSelector = createSelector(
|
||||
selectedTokenAddressSelector,
|
||||
transactionSubSelector,
|
||||
currentNetworkTxListSelector,
|
||||
(selectedTokenAddress, subSelectorTxList = [], networkTxList = []) => {
|
||||
const txsToRender = networkTxList.concat(subSelectorTxList)
|
||||
|
||||
return transactionSelectorReturnHelper(selectedTokenAddress, txsToRender)
|
||||
}
|
||||
)
|
||||
|
||||
export const transactionsSelector = createSelector(
|
||||
selectedTokenAddressSelector,
|
||||
transactionSubSelector,
|
||||
selectedAddressTxListSelector,
|
||||
(selectedTokenAddress, subSelectorTxList = [], selectedAddressTxList = []) => {
|
||||
const txsToRender = selectedAddressTxList.concat(subSelectorTxList)
|
||||
|
||||
return transactionSelectorReturnHelper(selectedTokenAddress, txsToRender)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1473,8 +1473,8 @@ export function retryTransaction (txId, gasPrice) {
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
const { selectedAddressTxList } = newState
|
||||
const { id } = selectedAddressTxList[selectedAddressTxList.length - 1]
|
||||
const { currentNetworkTxList } = newState
|
||||
const { id } = currentNetworkTxList[currentNetworkTxList.length - 1]
|
||||
newTxId = id
|
||||
resolve(newState)
|
||||
})
|
||||
@ -1496,8 +1496,8 @@ export function createCancelTransaction (txId, customGasPrice) {
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
const { selectedAddressTxList } = newState
|
||||
const { id } = selectedAddressTxList[selectedAddressTxList.length - 1]
|
||||
const { currentNetworkTxList } = newState
|
||||
const { id } = currentNetworkTxList[currentNetworkTxList.length - 1]
|
||||
newTxId = id
|
||||
resolve(newState)
|
||||
})
|
||||
@ -1519,8 +1519,8 @@ export function createSpeedUpTransaction (txId, customGasPrice) {
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
const { selectedAddressTxList } = newState
|
||||
newTx = selectedAddressTxList[selectedAddressTxList.length - 1]
|
||||
const { currentNetworkTxList } = newState
|
||||
newTx = currentNetworkTxList[currentNetworkTxList.length - 1]
|
||||
resolve(newState)
|
||||
})
|
||||
})
|
||||
@ -1541,8 +1541,8 @@ export function createRetryTransaction (txId, customGasPrice) {
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
const { selectedAddressTxList } = newState
|
||||
newTx = selectedAddressTxList[selectedAddressTxList.length - 1]
|
||||
const { currentNetworkTxList } = newState
|
||||
newTx = currentNetworkTxList[currentNetworkTxList.length - 1]
|
||||
resolve(newState)
|
||||
})
|
||||
})
|
||||
|
10
ui/index.js
10
ui/index.js
@ -59,7 +59,15 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
||||
})
|
||||
|
||||
// if unconfirmed txs, start on txConf page
|
||||
const unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.unapprovedDecryptMsgs, metamaskState.unapprovedEncryptionPublicKeyMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network)
|
||||
const unapprovedTxsAll = txHelper(
|
||||
metamaskState.unapprovedTxs,
|
||||
metamaskState.unapprovedMsgs,
|
||||
metamaskState.unapprovedPersonalMsgs,
|
||||
metamaskState.unapprovedDecryptMsgs,
|
||||
metamaskState.unapprovedEncryptionPublicKeyMsgs,
|
||||
metamaskState.unapprovedTypedMessages,
|
||||
metamaskState.network
|
||||
)
|
||||
const numberOfUnapprivedTx = unapprovedTxsAll.length
|
||||
if (numberOfUnapprivedTx > 0) {
|
||||
store.dispatch(actions.showConfTxPage({
|
||||
|
Loading…
Reference in New Issue
Block a user