mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-24 02:58:09 +01:00
86b165ea83
Maker has upgraded its Dai token to "Multi-Collateral Dai" (MCD) and requires all users interacting with Dai migrate their tokens to the new version. Dai now exclusively refers to Multi-Collateral Dai and what was previouly called Dai is now Sai (Single Collateral Dai). In this description, Sai refers to what was (prior to the 2019-11-18) known as Dai. Dai is the _new_ token. This changeset: 1. Only affects users who had non-zero Sai at the old contract address 2. Displays a persistent notification for users with Sai 3. Updates the token symbol for users already tracking the Sai token 4. Bumps our direct and indirect eth-contract-metadata dependencies The notification copy: > A message from Maker: The new Multi-Collateral Dai token has been released. Your old tokens are now called Sai. Please upgrade your Sai tokens to the new Dai. The copy is from the Maker team.
389 lines
10 KiB
JavaScript
389 lines
10 KiB
JavaScript
import { NETWORK_TYPES } from '../helpers/constants/common'
|
|
import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util'
|
|
|
|
const abi = require('human-standard-token-abi')
|
|
const {
|
|
multiplyCurrencies,
|
|
} = require('../helpers/utils/conversion-util')
|
|
import {
|
|
addressSlicer,
|
|
checksumAddress,
|
|
} from '../helpers/utils/util'
|
|
|
|
const selectors = {
|
|
getSelectedAddress,
|
|
getSelectedIdentity,
|
|
getSelectedAccount,
|
|
getSelectedToken,
|
|
getSelectedTokenExchangeRate,
|
|
getSelectedTokenAssetImage,
|
|
getAssetImages,
|
|
getTokenExchangeRate,
|
|
conversionRateSelector,
|
|
accountsWithSendEtherInfoSelector,
|
|
getCurrentAccountWithSendEtherInfo,
|
|
getGasIsLoading,
|
|
getForceGasMin,
|
|
getAddressBook,
|
|
getSendFrom,
|
|
getCurrentCurrency,
|
|
getNativeCurrency,
|
|
getSendAmount,
|
|
getSelectedTokenToFiatRate,
|
|
getSelectedTokenContract,
|
|
getSendMaxModeState,
|
|
getCurrentViewContext,
|
|
getTotalUnapprovedCount,
|
|
preferencesSelector,
|
|
getMetaMaskAccounts,
|
|
getCurrentEthBalance,
|
|
getNetworkIdentifier,
|
|
isBalanceCached,
|
|
getAdvancedInlineGasShown,
|
|
getUseNonceField,
|
|
getCustomNonceValue,
|
|
getIsMainnet,
|
|
getCurrentNetworkId,
|
|
getSelectedAsset,
|
|
getCurrentKeyring,
|
|
getAccountType,
|
|
getNumberOfAccounts,
|
|
getNumberOfTokens,
|
|
getDaiV1Token,
|
|
isEthereumNetwork,
|
|
getMetaMetricState,
|
|
getRpcPrefsForCurrentProvider,
|
|
getKnownMethodData,
|
|
getAddressBookEntry,
|
|
getAddressBookEntryName,
|
|
getFeatureFlags,
|
|
}
|
|
|
|
module.exports = selectors
|
|
|
|
function getNetworkIdentifier (state) {
|
|
const { metamask: { provider: { type, nickname, rpcTarget } } } = state
|
|
|
|
return nickname || rpcTarget || type
|
|
}
|
|
|
|
function getCurrentKeyring (state) {
|
|
const identity = getSelectedIdentity(state)
|
|
|
|
if (!identity) {
|
|
return null
|
|
}
|
|
|
|
const simpleAddress = stripHexPrefix(identity.address).toLowerCase()
|
|
|
|
const keyring = state.metamask.keyrings.find((kr) => {
|
|
return kr.accounts.includes(simpleAddress) ||
|
|
kr.accounts.includes(identity.address)
|
|
})
|
|
|
|
return keyring
|
|
}
|
|
|
|
function getAccountType (state) {
|
|
const currentKeyring = getCurrentKeyring(state)
|
|
const type = currentKeyring && currentKeyring.type
|
|
|
|
switch (type) {
|
|
case 'Trezor Hardware':
|
|
case 'Ledger Hardware':
|
|
return 'hardware'
|
|
case 'Simple Key Pair':
|
|
return 'imported'
|
|
default:
|
|
return 'default'
|
|
}
|
|
}
|
|
|
|
function getSelectedAsset (state) {
|
|
const selectedToken = getSelectedToken(state)
|
|
return selectedToken && selectedToken.symbol || 'ETH'
|
|
}
|
|
|
|
function getCurrentNetworkId (state) {
|
|
return state.metamask.network
|
|
}
|
|
|
|
function getSelectedAddress (state) {
|
|
const selectedAddress = state.metamask.selectedAddress || Object.keys(getMetaMaskAccounts(state))[0]
|
|
|
|
return selectedAddress
|
|
}
|
|
|
|
function getSelectedIdentity (state) {
|
|
const selectedAddress = getSelectedAddress(state)
|
|
const identities = state.metamask.identities
|
|
|
|
return identities[selectedAddress]
|
|
}
|
|
|
|
function getNumberOfAccounts (state) {
|
|
return Object.keys(state.metamask.accounts).length
|
|
}
|
|
|
|
function getNumberOfTokens (state) {
|
|
const tokens = state.metamask.tokens
|
|
return tokens ? tokens.length : 0
|
|
}
|
|
|
|
function getMetaMaskAccounts (state) {
|
|
const currentAccounts = state.metamask.accounts
|
|
const cachedBalances = state.metamask.cachedBalances[state.metamask.network]
|
|
const selectedAccounts = {}
|
|
|
|
Object.keys(currentAccounts).forEach(accountID => {
|
|
const account = currentAccounts[accountID]
|
|
if (account && account.balance === null || account.balance === undefined) {
|
|
selectedAccounts[accountID] = {
|
|
...account,
|
|
balance: cachedBalances && cachedBalances[accountID],
|
|
}
|
|
} else {
|
|
selectedAccounts[accountID] = account
|
|
}
|
|
})
|
|
return selectedAccounts
|
|
}
|
|
|
|
function isBalanceCached (state) {
|
|
const selectedAccountBalance = state.metamask.accounts[getSelectedAddress(state)].balance
|
|
const cachedBalance = getSelectedAccountCachedBalance(state)
|
|
|
|
return Boolean(!selectedAccountBalance && cachedBalance)
|
|
}
|
|
|
|
function getSelectedAccountCachedBalance (state) {
|
|
const cachedBalances = state.metamask.cachedBalances[state.metamask.network]
|
|
const selectedAddress = getSelectedAddress(state)
|
|
|
|
return cachedBalances && cachedBalances[selectedAddress]
|
|
}
|
|
|
|
function getSelectedAccount (state) {
|
|
const accounts = getMetaMaskAccounts(state)
|
|
const selectedAddress = getSelectedAddress(state)
|
|
|
|
return accounts[selectedAddress]
|
|
}
|
|
|
|
function getSelectedToken (state) {
|
|
const tokens = state.metamask.tokens || []
|
|
const selectedTokenAddress = state.metamask.selectedTokenAddress
|
|
const selectedToken = tokens.filter(({ address }) => address === selectedTokenAddress)[0]
|
|
const sendToken = state.metamask.send && state.metamask.send.token
|
|
|
|
return selectedToken || sendToken || null
|
|
}
|
|
|
|
function getSelectedTokenExchangeRate (state) {
|
|
const contractExchangeRates = state.metamask.contractExchangeRates
|
|
const selectedToken = getSelectedToken(state) || {}
|
|
const { address } = selectedToken
|
|
return contractExchangeRates[address] || 0
|
|
}
|
|
|
|
function getSelectedTokenAssetImage (state) {
|
|
const assetImages = state.metamask.assetImages || {}
|
|
const selectedToken = getSelectedToken(state) || {}
|
|
const { address } = selectedToken
|
|
return assetImages[address]
|
|
}
|
|
|
|
function getAssetImages (state) {
|
|
const assetImages = state.metamask.assetImages || {}
|
|
return assetImages
|
|
}
|
|
|
|
function getTokenExchangeRate (state, address) {
|
|
const contractExchangeRates = state.metamask.contractExchangeRates
|
|
return contractExchangeRates[address] || 0
|
|
}
|
|
|
|
function conversionRateSelector (state) {
|
|
return state.metamask.conversionRate
|
|
}
|
|
|
|
function getAddressBook (state) {
|
|
const network = state.metamask.network
|
|
if (!state.metamask.addressBook[network]) {
|
|
return []
|
|
}
|
|
return Object.values(state.metamask.addressBook[network])
|
|
}
|
|
|
|
function getAddressBookEntry (state, address) {
|
|
const addressBook = getAddressBook(state)
|
|
const entry = addressBook.find(contact => contact.address === checksumAddress(address))
|
|
return entry
|
|
}
|
|
|
|
function getAddressBookEntryName (state, address) {
|
|
const entry = getAddressBookEntry(state, address) || state.metamask.identities[address]
|
|
return entry && entry.name !== '' ? entry.name : addressSlicer(address)
|
|
}
|
|
|
|
function getDaiV1Token (state) {
|
|
const OLD_DAI_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'
|
|
const tokens = state.metamask.tokens || []
|
|
return tokens.find(({address}) => checksumAddress(address) === OLD_DAI_CONTRACT_ADDRESS)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
function getCurrentAccountWithSendEtherInfo (state) {
|
|
const currentAddress = getSelectedAddress(state)
|
|
const accounts = accountsWithSendEtherInfoSelector(state)
|
|
|
|
return accounts.find(({ address }) => address === currentAddress)
|
|
}
|
|
|
|
function getCurrentEthBalance (state) {
|
|
return getCurrentAccountWithSendEtherInfo(state).balance
|
|
}
|
|
|
|
function getGasIsLoading (state) {
|
|
return state.appState.gasIsLoading
|
|
}
|
|
|
|
function getForceGasMin (state) {
|
|
return state.metamask.send.forceGasMin
|
|
}
|
|
|
|
function getSendFrom (state) {
|
|
return state.metamask.send.from
|
|
}
|
|
|
|
function getSendAmount (state) {
|
|
return state.metamask.send.amount
|
|
}
|
|
|
|
function getSendMaxModeState (state) {
|
|
return state.metamask.send.maxModeOn
|
|
}
|
|
|
|
function getCurrentCurrency (state) {
|
|
return state.metamask.currentCurrency
|
|
}
|
|
|
|
function getNativeCurrency (state) {
|
|
return state.metamask.nativeCurrency
|
|
}
|
|
|
|
function getSelectedTokenToFiatRate (state) {
|
|
const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
|
|
const conversionRate = conversionRateSelector(state)
|
|
|
|
const tokenToFiatRate = multiplyCurrencies(
|
|
conversionRate,
|
|
selectedTokenExchangeRate,
|
|
{ toNumericBase: 'dec' }
|
|
)
|
|
|
|
return tokenToFiatRate
|
|
}
|
|
|
|
function getSelectedTokenContract (state) {
|
|
const selectedToken = getSelectedToken(state)
|
|
return selectedToken
|
|
? global.eth.contract(abi).at(selectedToken.address)
|
|
: null
|
|
}
|
|
|
|
function getCurrentViewContext (state) {
|
|
const { currentView = {} } = state.appState
|
|
return currentView.context
|
|
}
|
|
|
|
function getTotalUnapprovedCount ({ metamask }) {
|
|
const {
|
|
unapprovedTxs = {},
|
|
unapprovedMsgCount,
|
|
unapprovedPersonalMsgCount,
|
|
unapprovedTypedMessagesCount,
|
|
} = metamask
|
|
|
|
return Object.keys(unapprovedTxs).length + unapprovedMsgCount + unapprovedPersonalMsgCount +
|
|
unapprovedTypedMessagesCount
|
|
}
|
|
|
|
function getIsMainnet (state) {
|
|
const networkType = getNetworkIdentifier(state)
|
|
return networkType === NETWORK_TYPES.MAINNET
|
|
}
|
|
|
|
function isEthereumNetwork (state) {
|
|
const networkType = getNetworkIdentifier(state)
|
|
const {
|
|
KOVAN,
|
|
MAINNET,
|
|
RINKEBY,
|
|
ROPSTEN,
|
|
GOERLI,
|
|
} = NETWORK_TYPES
|
|
|
|
return [ KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType)
|
|
}
|
|
|
|
function preferencesSelector ({ metamask }) {
|
|
return metamask.preferences
|
|
}
|
|
|
|
function getAdvancedInlineGasShown (state) {
|
|
return Boolean(state.metamask.featureFlags.advancedInlineGas)
|
|
}
|
|
|
|
function getUseNonceField (state) {
|
|
return Boolean(state.metamask.useNonceField)
|
|
}
|
|
|
|
function getCustomNonceValue (state) {
|
|
return String(state.metamask.customNonceValue)
|
|
}
|
|
|
|
function getMetaMetricState (state) {
|
|
return {
|
|
network: getCurrentNetworkId(state),
|
|
activeCurrency: getSelectedAsset(state),
|
|
accountType: getAccountType(state),
|
|
metaMetricsId: state.metamask.metaMetricsId,
|
|
numberOfTokens: getNumberOfTokens(state),
|
|
numberOfAccounts: getNumberOfAccounts(state),
|
|
participateInMetaMetrics: state.metamask.participateInMetaMetrics,
|
|
}
|
|
}
|
|
|
|
function getRpcPrefsForCurrentProvider (state) {
|
|
const { frequentRpcListDetail, provider } = state.metamask
|
|
const selectRpcInfo = frequentRpcListDetail.find(rpcInfo => rpcInfo.rpcUrl === provider.rpcTarget)
|
|
const { rpcPrefs = {} } = selectRpcInfo || {}
|
|
return rpcPrefs
|
|
}
|
|
|
|
function getKnownMethodData (state, data) {
|
|
if (!data) {
|
|
return null
|
|
}
|
|
const prefixedData = addHexPrefix(data)
|
|
const fourBytePrefix = prefixedData.slice(0, 10)
|
|
const { knownMethodData } = state.metamask
|
|
|
|
return knownMethodData && knownMethodData[fourBytePrefix]
|
|
}
|
|
|
|
function getFeatureFlags (state) {
|
|
return state.metamask.featureFlags
|
|
}
|