mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
fix merge conflicts
This commit is contained in:
parent
0ebdd73e02
commit
286bde606f
@ -2,6 +2,10 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
- [#4884](https://github.com/MetaMask/metamask-extension/pull/4884): Allow to have tokens per account and network.
|
||||
|
||||
## 4.9.0 Tue Aug 07 2018
|
||||
|
||||
- Add new tokens auto detection
|
||||
- Remove rejected transactions from transaction history
|
||||
- Add Trezor Support
|
||||
|
@ -510,6 +510,9 @@
|
||||
"invalidRPC": {
|
||||
"message": "Invalid RPC URI"
|
||||
},
|
||||
"invalidSeedPhrase": {
|
||||
"message": "Invalid seed phrase"
|
||||
},
|
||||
"jsonFail": {
|
||||
"message": "Something went wrong. Please make sure your JSON file is properly formatted."
|
||||
},
|
||||
|
@ -85,7 +85,7 @@ class DetectTokensController {
|
||||
set preferences (preferences) {
|
||||
if (!preferences) { return }
|
||||
this._preferences = preferences
|
||||
preferences.store.subscribe(({ tokens }) => { this.tokenAddresses = tokens.map((obj) => { return obj.address }) })
|
||||
preferences.store.subscribe(({ tokens = [] }) => { this.tokenAddresses = tokens.map((obj) => { return obj.address }) })
|
||||
preferences.store.subscribe(({ selectedAddress }) => {
|
||||
if (this.selectedAddress !== selectedAddress) {
|
||||
this.selectedAddress = selectedAddress
|
||||
|
@ -13,6 +13,7 @@ class PreferencesController {
|
||||
* @property {array} store.frequentRpcList A list of custom rpcs to provide the user
|
||||
* @property {string} store.currentAccountTab Indicates the selected tab in the ui
|
||||
* @property {array} store.tokens The tokens the user wants display in their token lists
|
||||
* @property {object} store.accountTokens The tokens stored per account and then per network type
|
||||
* @property {boolean} store.useBlockie The users preference for blockie identicons within the UI
|
||||
* @property {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the
|
||||
* user wishes to see that feature
|
||||
@ -24,6 +25,7 @@ class PreferencesController {
|
||||
const initState = extend({
|
||||
frequentRpcList: [],
|
||||
currentAccountTab: 'history',
|
||||
accountTokens: {},
|
||||
tokens: [],
|
||||
useBlockie: false,
|
||||
featureFlags: {},
|
||||
@ -33,8 +35,9 @@ class PreferencesController {
|
||||
}, opts.initState)
|
||||
|
||||
this.diagnostics = opts.diagnostics
|
||||
|
||||
this.network = opts.network
|
||||
this.store = new ObservableStore(initState)
|
||||
this._subscribeProviderType()
|
||||
}
|
||||
// PUBLIC METHODS
|
||||
|
||||
@ -77,12 +80,19 @@ class PreferencesController {
|
||||
*/
|
||||
setAddresses (addresses) {
|
||||
const oldIdentities = this.store.getState().identities
|
||||
const oldAccountTokens = this.store.getState().accountTokens
|
||||
|
||||
const identities = addresses.reduce((ids, address, index) => {
|
||||
const oldId = oldIdentities[address] || {}
|
||||
ids[address] = {name: `Account ${index + 1}`, address, ...oldId}
|
||||
return ids
|
||||
}, {})
|
||||
this.store.updateState({ identities })
|
||||
const accountTokens = addresses.reduce((tokens, address) => {
|
||||
const oldTokens = oldAccountTokens[address] || {}
|
||||
tokens[address] = oldTokens
|
||||
return tokens
|
||||
}, {})
|
||||
this.store.updateState({ identities, accountTokens })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,11 +103,13 @@ class PreferencesController {
|
||||
*/
|
||||
removeAddress (address) {
|
||||
const identities = this.store.getState().identities
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
if (!identities[address]) {
|
||||
throw new Error(`${address} can't be deleted cause it was not found`)
|
||||
}
|
||||
delete identities[address]
|
||||
this.store.updateState({ identities })
|
||||
delete accountTokens[address]
|
||||
this.store.updateState({ identities, accountTokens })
|
||||
|
||||
// If the selected account is no longer valid,
|
||||
// select an arbitrary other account:
|
||||
@ -117,14 +129,17 @@ class PreferencesController {
|
||||
*/
|
||||
addAddresses (addresses) {
|
||||
const identities = this.store.getState().identities
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
addresses.forEach((address) => {
|
||||
// skip if already exists
|
||||
if (identities[address]) return
|
||||
// add missing identity
|
||||
const identityCount = Object.keys(identities).length
|
||||
|
||||
accountTokens[address] = {}
|
||||
identities[address] = { name: `Account ${identityCount + 1}`, address }
|
||||
})
|
||||
this.store.updateState({ identities })
|
||||
this.store.updateState({ identities, accountTokens })
|
||||
}
|
||||
|
||||
/*
|
||||
@ -175,15 +190,15 @@ class PreferencesController {
|
||||
* Setter for the `selectedAddress` property
|
||||
*
|
||||
* @param {string} _address A new hex address for an account
|
||||
* @returns {Promise<void>} Promise resolves with undefined
|
||||
* @returns {Promise<void>} Promise resolves with tokens
|
||||
*
|
||||
*/
|
||||
setSelectedAddress (_address) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const address = normalizeAddress(_address)
|
||||
this.store.updateState({ selectedAddress: address })
|
||||
resolve()
|
||||
})
|
||||
const address = normalizeAddress(_address)
|
||||
this._updateTokens(address)
|
||||
this.store.updateState({ selectedAddress: address })
|
||||
const tokens = this.store.getState().tokens
|
||||
return Promise.resolve(tokens)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,9 +247,7 @@ class PreferencesController {
|
||||
} else {
|
||||
tokens.push(newEntry)
|
||||
}
|
||||
|
||||
this.store.updateState({ tokens })
|
||||
|
||||
this._updateAccountTokens(tokens)
|
||||
return Promise.resolve(tokens)
|
||||
}
|
||||
|
||||
@ -247,10 +260,8 @@ class PreferencesController {
|
||||
*/
|
||||
removeToken (rawAddress) {
|
||||
const tokens = this.store.getState().tokens
|
||||
|
||||
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
|
||||
|
||||
this.store.updateState({ tokens: updatedTokens })
|
||||
this._updateAccountTokens(updatedTokens)
|
||||
return Promise.resolve(updatedTokens)
|
||||
}
|
||||
|
||||
@ -376,6 +387,57 @@ class PreferencesController {
|
||||
//
|
||||
// PRIVATE METHODS
|
||||
//
|
||||
/**
|
||||
* Subscription to network provider type.
|
||||
*
|
||||
*
|
||||
*/
|
||||
_subscribeProviderType () {
|
||||
this.network.providerStore.subscribe(() => {
|
||||
const { tokens } = this._getTokenRelatedStates()
|
||||
this.store.updateState({ tokens })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates `accountTokens` and `tokens` of current account and network according to it.
|
||||
*
|
||||
* @param {array} tokens Array of tokens to be updated.
|
||||
*
|
||||
*/
|
||||
_updateAccountTokens (tokens) {
|
||||
const { accountTokens, providerType, selectedAddress } = this._getTokenRelatedStates()
|
||||
accountTokens[selectedAddress][providerType] = tokens
|
||||
this.store.updateState({ accountTokens, tokens })
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates `tokens` of current account and network.
|
||||
*
|
||||
* @param {string} selectedAddress Account address to be updated with.
|
||||
*
|
||||
*/
|
||||
_updateTokens (selectedAddress) {
|
||||
const { tokens } = this._getTokenRelatedStates(selectedAddress)
|
||||
this.store.updateState({ tokens })
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for `tokens` and `accountTokens` related states.
|
||||
*
|
||||
* @param {string} selectedAddress A new hex address for an account
|
||||
* @returns {Object.<array, object, string, string>} States to interact with tokens in `accountTokens`
|
||||
*
|
||||
*/
|
||||
_getTokenRelatedStates (selectedAddress) {
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
if (!selectedAddress) selectedAddress = this.store.getState().selectedAddress
|
||||
const providerType = this.network.providerStore.getState().type
|
||||
if (!(selectedAddress in accountTokens)) accountTokens[selectedAddress] = {}
|
||||
if (!(providerType in accountTokens[selectedAddress])) accountTokens[selectedAddress][providerType] = []
|
||||
const tokens = accountTokens[selectedAddress][providerType]
|
||||
return { tokens, accountTokens, providerType, selectedAddress }
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PreferencesController
|
||||
|
@ -87,6 +87,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
this.preferencesController = new PreferencesController({
|
||||
initState: initState.PreferencesController,
|
||||
initLangCode: opts.initLangCode,
|
||||
network: this.networkController,
|
||||
})
|
||||
|
||||
// currency controller
|
||||
@ -1436,7 +1437,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* A method for activating the retrieval of price data and auto detect tokens,
|
||||
* A method for activating the retrieval of price data,
|
||||
* which should only be fetched when the UI is visible.
|
||||
* @private
|
||||
* @param {boolean} active - True if price data should be getting fetched.
|
||||
|
40
app/scripts/migrations/028.js
Normal file
40
app/scripts/migrations/028.js
Normal file
@ -0,0 +1,40 @@
|
||||
// next version number
|
||||
const version = 28
|
||||
|
||||
/*
|
||||
|
||||
normalizes txParams on unconfirmed txs
|
||||
|
||||
*/
|
||||
const clone = require('clone')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
const versionedData = clone(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
return versionedData
|
||||
},
|
||||
}
|
||||
|
||||
function transformState (state) {
|
||||
const newState = state
|
||||
|
||||
if (newState.PreferencesController) {
|
||||
if (newState.PreferencesController.tokens) {
|
||||
const identities = newState.TransactionController.identities
|
||||
const tokens = newState.PreferencesController.tokens
|
||||
newState.PreferencesController.accountTokens = {}
|
||||
for (const identity in identities) {
|
||||
newState.PreferencesController.accountTokens[identity] = {'mainnet': tokens}
|
||||
}
|
||||
newState.PreferencesController.tokens = []
|
||||
}
|
||||
}
|
||||
|
||||
return newState
|
||||
}
|
@ -38,4 +38,5 @@ module.exports = [
|
||||
require('./025'),
|
||||
require('./026'),
|
||||
require('./027'),
|
||||
require('./028'),
|
||||
]
|
||||
|
@ -106,6 +106,7 @@ class ConfirmSeedScreen extends Component {
|
||||
key={i}
|
||||
className={classnames('backup-phrase__confirm-seed-option', {
|
||||
'backup-phrase__confirm-seed-option--selected': isSelected,
|
||||
'backup-phrase__confirm-seed-option--unselected': !isSelected,
|
||||
})}
|
||||
onClick={() => {
|
||||
if (!isSelected) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import {validateMnemonic} from 'bip39'
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
@ -39,8 +40,12 @@ class ImportSeedPhraseScreen extends Component {
|
||||
handleSeedPhraseChange (seedPhrase) {
|
||||
let seedPhraseError = null
|
||||
|
||||
if (seedPhrase && this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) {
|
||||
seedPhraseError = this.context.t('seedPhraseReq')
|
||||
if (seedPhrase) {
|
||||
if (this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) {
|
||||
seedPhraseError = this.context.t('seedPhraseReq')
|
||||
} else if (!validateMnemonic(seedPhrase)) {
|
||||
seedPhraseError = this.context.t('invalidSeedPhrase')
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ seedPhrase, seedPhraseError })
|
||||
|
66777
package-lock.json
generated
66777
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -74,7 +74,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^1.0.0",
|
||||
"@material-ui/core": "1.0.0",
|
||||
"abi-decoder": "^1.0.9",
|
||||
"asmcrypto.js": "0.22.0",
|
||||
"async": "^2.5.0",
|
||||
@ -105,7 +105,7 @@
|
||||
"eth-bin-to-ops": "^1.0.1",
|
||||
"eth-contract-metadata": "github:MetaMask/eth-contract-metadata#master",
|
||||
"eth-ens-namehash": "^2.0.8",
|
||||
"eth-hd-keyring": "^2.0.0",
|
||||
"eth-hd-keyring": "^1.2.2",
|
||||
"eth-json-rpc-filters": "^1.2.6",
|
||||
"eth-json-rpc-infura": "^3.0.0",
|
||||
"eth-method-registry": "^1.0.0",
|
||||
@ -113,7 +113,7 @@
|
||||
"eth-query": "^2.1.2",
|
||||
"eth-sig-util": "^1.4.2",
|
||||
"eth-token-tracker": "^1.1.4",
|
||||
"eth-trezor-keyring": "^0.1.0",
|
||||
"eth-trezor-keyring": "github:MetaMask/eth-trezor-keyring#trezor-v5",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-tx": "^1.3.0",
|
||||
"ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
||||
@ -198,7 +198,6 @@
|
||||
"semaphore": "^1.0.5",
|
||||
"semver": "^5.4.1",
|
||||
"shallow-copy": "0.0.1",
|
||||
"superstatic": "^5.0.2",
|
||||
"sw-controller": "^1.0.3",
|
||||
"sw-stream": "^2.0.2",
|
||||
"textarea-caret": "^3.0.1",
|
||||
@ -228,7 +227,7 @@
|
||||
"brfs": "^1.6.1",
|
||||
"browserify": "^16.1.1",
|
||||
"chai": "^4.1.0",
|
||||
"chromedriver": "2.36.0",
|
||||
"chromedriver": "^2.41.0",
|
||||
"clipboardy": "^1.2.3",
|
||||
"compression": "^1.7.1",
|
||||
"coveralls": "^3.0.0",
|
||||
@ -245,7 +244,7 @@
|
||||
"eslint-plugin-mocha": "^5.0.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eth-json-rpc-middleware": "^1.6.0",
|
||||
"eth-keyring-controller": "^4.0.0",
|
||||
"eth-keyring-controller": "^3.3.1",
|
||||
"file-loader": "^1.1.11",
|
||||
"fs-promise": "^2.0.3",
|
||||
"ganache-cli": "^6.1.0",
|
||||
@ -308,6 +307,7 @@
|
||||
"shell-parallel": "^1.0.3",
|
||||
"sinon": "^5.0.0",
|
||||
"source-map": "^0.7.2",
|
||||
"static-server": "^2.2.1",
|
||||
"style-loader": "^0.21.0",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"tape": "^4.5.1",
|
||||
|
@ -50,15 +50,20 @@ deployButton.addEventListener('click', async function (event) {
|
||||
|
||||
console.log(`contract`, contract)
|
||||
|
||||
document.getElementById('contractStatus').innerHTML = 'Deployed'
|
||||
|
||||
depositButton.addEventListener('click', function (event) {
|
||||
document.getElementById('contractStatus').innerHTML = 'Deposit initiated'
|
||||
contract.deposit({ from: web3.eth.accounts[0], value: '0x3782dace9d900000' }, function (result) {
|
||||
console.log(result)
|
||||
document.getElementById('contractStatus').innerHTML = 'Deposit completed'
|
||||
})
|
||||
})
|
||||
|
||||
withdrawButton.addEventListener('click', function (event) {
|
||||
contract.withdraw('0xde0b6b3a7640000', { from: web3.eth.accounts[0] }, function (result) {
|
||||
console.log(result)
|
||||
document.getElementById('contractStatus').innerHTML = 'Withdrawn'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
<button id="depositButton">Deposit</button>
|
||||
<button id="withdrawButton">Withdraw</button>
|
||||
</div>
|
||||
<div id="contractStatus" style="display: flex; font-size: 1rem;">
|
||||
Not yet deployed
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-flow: column;">
|
||||
<div style="display: flex; font-size: 1.25rem;">Send eth</div>
|
||||
|
@ -232,7 +232,7 @@ describe('Using MetaMask with an existing account', function () {
|
||||
|
||||
const [localhost] = await findElements(driver, By.xpath(`//span[contains(text(), 'Localhost')]`))
|
||||
await localhost.click()
|
||||
await delay(largeDelayMs * 2)
|
||||
await delay(largeDelayMs)
|
||||
})
|
||||
|
||||
it('choose Create Account from the account menu', async () => {
|
||||
|
@ -195,7 +195,16 @@ describe('MetaMask', function () {
|
||||
await delay(regularDelayMs)
|
||||
})
|
||||
|
||||
async function retypeSeedPhrase (words, wasReloaded) {
|
||||
async function clickWordAndWait (word) {
|
||||
const xpathClass = 'backup-phrase__confirm-seed-option backup-phrase__confirm-seed-option--unselected'
|
||||
const xpath = `//button[@class='${xpathClass}' and contains(text(), '${word}')]`
|
||||
const word0 = await findElement(driver, By.xpath(xpath), 10000)
|
||||
|
||||
await word0.click()
|
||||
await delay(tinyDelayMs)
|
||||
}
|
||||
|
||||
async function retypeSeedPhrase (words, wasReloaded, count = 0) {
|
||||
try {
|
||||
if (wasReloaded) {
|
||||
const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
|
||||
@ -209,67 +218,26 @@ describe('MetaMask', function () {
|
||||
await delay(regularDelayMs)
|
||||
}
|
||||
|
||||
const word0 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[0]}')]`), 10000)
|
||||
await clickWordAndWait(words[0])
|
||||
await clickWordAndWait(words[1])
|
||||
await clickWordAndWait(words[2])
|
||||
await clickWordAndWait(words[3])
|
||||
await clickWordAndWait(words[4])
|
||||
await clickWordAndWait(words[5])
|
||||
await clickWordAndWait(words[6])
|
||||
await clickWordAndWait(words[7])
|
||||
await clickWordAndWait(words[8])
|
||||
await clickWordAndWait(words[9])
|
||||
await clickWordAndWait(words[10])
|
||||
await clickWordAndWait(words[11])
|
||||
|
||||
await word0.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word1 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[1]}')]`), 10000)
|
||||
|
||||
await word1.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word2 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[2]}')]`), 10000)
|
||||
|
||||
await word2.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word3 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[3]}')]`), 10000)
|
||||
|
||||
await word3.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word4 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[4]}')]`), 10000)
|
||||
|
||||
await word4.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word5 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[5]}')]`), 10000)
|
||||
|
||||
await word5.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word6 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[6]}')]`), 10000)
|
||||
|
||||
await word6.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word7 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[7]}')]`), 10000)
|
||||
|
||||
await word7.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word8 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[8]}')]`), 10000)
|
||||
|
||||
await word8.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word9 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[9]}')]`), 10000)
|
||||
|
||||
await word9.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word10 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[10]}')]`), 10000)
|
||||
|
||||
await word10.click()
|
||||
await delay(tinyDelayMs)
|
||||
|
||||
const word11 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[11]}')]`), 10000)
|
||||
await word11.click()
|
||||
await delay(tinyDelayMs)
|
||||
} catch (e) {
|
||||
await loadExtension(driver, extensionId)
|
||||
await retypeSeedPhrase(words, true)
|
||||
if (count > 2) {
|
||||
throw e
|
||||
} else {
|
||||
await loadExtension(driver, extensionId)
|
||||
await retypeSeedPhrase(words, true, count + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +484,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('displays the contract creation data', async () => {
|
||||
const dataTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Data')]`))
|
||||
dataTab.click()
|
||||
await dataTab.click()
|
||||
await delay(regularDelayMs)
|
||||
|
||||
await findElement(driver, By.xpath(`//div[contains(text(), '127.0.0.1')]`))
|
||||
@ -526,7 +494,7 @@ describe('MetaMask', function () {
|
||||
assert.equal(confirmDataText.match(/0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff/))
|
||||
|
||||
const detailsTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Details')]`))
|
||||
detailsTab.click()
|
||||
await detailsTab.click()
|
||||
await delay(regularDelayMs)
|
||||
})
|
||||
|
||||
@ -547,9 +515,15 @@ describe('MetaMask', function () {
|
||||
await driver.switchTo().window(dapp)
|
||||
await delay(regularDelayMs)
|
||||
|
||||
let contractStatus = await driver.findElement(By.css('#contractStatus'))
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deployed/))
|
||||
|
||||
const depositButton = await findElement(driver, By.css('#depositButton'))
|
||||
await depositButton.click()
|
||||
await delay(regularDelayMs)
|
||||
await delay(largeDelayMs)
|
||||
|
||||
contractStatus = await driver.findElement(By.css('#contractStatus'))
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/))
|
||||
|
||||
await driver.switchTo().window(extension)
|
||||
await delay(largeDelayMs)
|
||||
|
@ -6,5 +6,5 @@ set -o pipefail
|
||||
|
||||
export PATH="$PATH:./node_modules/.bin"
|
||||
|
||||
shell-parallel -s 'npm run ganache:start' -x 'sleep 5 && superstatic test/e2e/beta/contract-test/ --port 8080 --host 127.0.0.1' -x 'sleep 5 && mocha test/e2e/beta/metamask-beta-ui.spec'
|
||||
shell-parallel -s 'npm run ganache:start -- -d' -x 'sleep 5 && superstatic test/e2e/beta/contract-test/ --port 8080 --host 127.0.0.1' -x 'sleep 5 && mocha test/e2e/beta/from-import-beta-ui.spec'
|
||||
shell-parallel -s 'npm run ganache:start' -x 'sleep 5 && static-server test/e2e/beta/contract-test/ --port 8080' -x 'sleep 5 && mocha test/e2e/beta/metamask-beta-ui.spec'
|
||||
shell-parallel -s 'npm run ganache:start -- -d' -x 'sleep 5 && static-server test/e2e/beta/contract-test/ --port 8080' -x 'sleep 5 && mocha test/e2e/beta/from-import-beta-ui.spec'
|
||||
|
@ -7,10 +7,11 @@ const PreferencesController = require('../../../../app/scripts/controllers/prefe
|
||||
|
||||
describe('DetectTokensController', () => {
|
||||
const sandbox = sinon.createSandbox()
|
||||
let clock
|
||||
let keyringMemStore
|
||||
before(async () => {
|
||||
let clock, keyringMemStore, network, preferences
|
||||
beforeEach(async () => {
|
||||
keyringMemStore = new ObservableStore({ isUnlocked: false})
|
||||
network = new NetworkController({ provider: { type: 'mainnet' }})
|
||||
preferences = new PreferencesController({ network })
|
||||
})
|
||||
after(() => {
|
||||
sandbox.restore()
|
||||
@ -25,9 +26,7 @@ describe('DetectTokensController', () => {
|
||||
|
||||
it('should be called on every polling period', async () => {
|
||||
clock = sandbox.useFakeTimers()
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = true
|
||||
@ -45,9 +44,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should not check tokens while in test network', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('rinkeby')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = true
|
||||
@ -61,9 +58,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should only check and add tokens while in main network', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = true
|
||||
@ -80,9 +75,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should not detect same token while in main network', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
@ -100,9 +93,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should trigger detect new tokens when change address', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = true
|
||||
@ -112,9 +103,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should trigger detect new tokens when submit password', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.selectedAddress = '0x0'
|
||||
@ -124,9 +113,7 @@ describe('DetectTokensController', () => {
|
||||
})
|
||||
|
||||
it('should not trigger detect new tokens when not open or not unlocked', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = false
|
||||
|
@ -1,11 +1,14 @@
|
||||
const assert = require('assert')
|
||||
const ObservableStore = require('obs-store')
|
||||
const PreferencesController = require('../../../../app/scripts/controllers/preferences')
|
||||
|
||||
describe('preferences controller', function () {
|
||||
let preferencesController
|
||||
let network
|
||||
|
||||
beforeEach(() => {
|
||||
preferencesController = new PreferencesController()
|
||||
network = {providerStore: new ObservableStore({ type: 'mainnet' })}
|
||||
preferencesController = new PreferencesController({ network })
|
||||
})
|
||||
|
||||
describe('setAddresses', function () {
|
||||
@ -28,6 +31,20 @@ describe('preferences controller', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should create account tokens for each account in the store', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
'0x7e57e2',
|
||||
])
|
||||
|
||||
const accountTokens = preferencesController.store.getState().accountTokens
|
||||
|
||||
assert.deepEqual(accountTokens, {
|
||||
'0xda22le': {},
|
||||
'0x7e57e2': {},
|
||||
})
|
||||
})
|
||||
|
||||
it('should replace its list of addresses', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
@ -64,6 +81,17 @@ describe('preferences controller', function () {
|
||||
assert.equal(preferencesController.store.getState().identities['0xda22le'], undefined)
|
||||
})
|
||||
|
||||
it('should remove an address from state and respective tokens', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
'0x7e57e2',
|
||||
])
|
||||
|
||||
preferencesController.removeAddress('0xda22le')
|
||||
|
||||
assert.equal(preferencesController.store.getState().accountTokens['0xda22le'], undefined)
|
||||
})
|
||||
|
||||
it('should switch accounts if the selected address is removed', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
@ -158,6 +186,42 @@ describe('preferences controller', function () {
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
|
||||
})
|
||||
|
||||
it('should add token per account', async function () {
|
||||
const addressFirst = '0xabcdef1234567'
|
||||
const addressSecond = '0xabcdef1234568'
|
||||
const symbolFirst = 'ABBR'
|
||||
const symbolSecond = 'ABBB'
|
||||
const decimals = 5
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(addressFirst, symbolFirst, decimals)
|
||||
const tokensFirstAddress = preferencesController.getTokens()
|
||||
|
||||
await preferencesController.setSelectedAddress('0xda22le')
|
||||
await preferencesController.addToken(addressSecond, symbolSecond, decimals)
|
||||
const tokensSeconAddress = preferencesController.getTokens()
|
||||
|
||||
assert.notEqual(tokensFirstAddress, tokensSeconAddress, 'add different tokens for two account and tokens are equal')
|
||||
})
|
||||
|
||||
it('should add token per network', async function () {
|
||||
const addressFirst = '0xabcdef1234567'
|
||||
const addressSecond = '0xabcdef1234568'
|
||||
const symbolFirst = 'ABBR'
|
||||
const symbolSecond = 'ABBB'
|
||||
const decimals = 5
|
||||
|
||||
network.providerStore.updateState({ type: 'mainnet' })
|
||||
await preferencesController.addToken(addressFirst, symbolFirst, decimals)
|
||||
const tokensFirstAddress = preferencesController.getTokens()
|
||||
|
||||
network.providerStore.updateState({ type: 'rinkeby' })
|
||||
await preferencesController.addToken(addressSecond, symbolSecond, decimals)
|
||||
const tokensSeconAddress = preferencesController.getTokens()
|
||||
|
||||
assert.notEqual(tokensFirstAddress, tokensSeconAddress, 'add different tokens for two networks and tokens are equal')
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeToken', function () {
|
||||
@ -182,6 +246,98 @@ describe('preferences controller', function () {
|
||||
const [token1] = tokens
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||
})
|
||||
|
||||
it('should remove a token from its state on corresponding address', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
const initialTokensSecond = preferencesController.getTokens()
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.removeToken('0xa')
|
||||
|
||||
const tokensFirst = preferencesController.getTokens()
|
||||
assert.equal(tokensFirst.length, 1, 'one token removed in account')
|
||||
|
||||
const [token1] = tokensFirst
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||
const tokensSecond = preferencesController.getTokens()
|
||||
assert.deepEqual(tokensSecond, initialTokensSecond, 'token deleted for account')
|
||||
})
|
||||
|
||||
it('should remove a token from its state on corresponding network', async function () {
|
||||
network.providerStore.updateState({ type: 'mainnet' })
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
network.providerStore.updateState({ type: 'rinkeby' })
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
const initialTokensSecond = preferencesController.getTokens()
|
||||
network.providerStore.updateState({ type: 'mainnet' })
|
||||
await preferencesController.removeToken('0xa')
|
||||
|
||||
const tokensFirst = preferencesController.getTokens()
|
||||
assert.equal(tokensFirst.length, 1, 'one token removed in network')
|
||||
|
||||
const [token1] = tokensFirst
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||
|
||||
network.providerStore.updateState({ type: 'rinkeby' })
|
||||
const tokensSecond = preferencesController.getTokens()
|
||||
assert.deepEqual(tokensSecond, initialTokensSecond, 'token deleted for network')
|
||||
})
|
||||
})
|
||||
|
||||
describe('on setSelectedAddress', function () {
|
||||
it('should update tokens from its state on corresponding address', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||
await preferencesController.addToken('0xa', 'C', 4)
|
||||
await preferencesController.addToken('0xb', 'D', 5)
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
const initialTokensFirst = preferencesController.getTokens()
|
||||
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||
const initialTokensSecond = preferencesController.getTokens()
|
||||
|
||||
assert.notDeepEqual(initialTokensFirst, initialTokensSecond, 'tokens not equal for different accounts and tokens')
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
const tokensFirst = preferencesController.getTokens()
|
||||
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||
const tokensSecond = preferencesController.getTokens()
|
||||
|
||||
assert.deepEqual(tokensFirst, initialTokensFirst, 'tokens equal for same account')
|
||||
assert.deepEqual(tokensSecond, initialTokensSecond, 'tokens equal for same account')
|
||||
})
|
||||
})
|
||||
|
||||
describe('on updateStateNetworkType', function () {
|
||||
it('should remove a token from its state on corresponding network', async function () {
|
||||
network.providerStore.updateState({ type: 'mainnet' })
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
const initialTokensFirst = preferencesController.getTokens()
|
||||
network.providerStore.updateState({ type: 'rinkeby' })
|
||||
await preferencesController.addToken('0xa', 'C', 4)
|
||||
await preferencesController.addToken('0xb', 'D', 5)
|
||||
const initialTokensSecond = preferencesController.getTokens()
|
||||
|
||||
assert.notDeepEqual(initialTokensFirst, initialTokensSecond, 'tokens not equal for different networks and tokens')
|
||||
|
||||
network.providerStore.updateState({ type: 'mainnet' })
|
||||
const tokensFirst = preferencesController.getTokens()
|
||||
network.providerStore.updateState({ type: 'rinkeby' })
|
||||
const tokensSecond = preferencesController.getTokens()
|
||||
assert.deepEqual(tokensFirst, initialTokensFirst, 'tokens equal for same network')
|
||||
assert.deepEqual(tokensSecond, initialTokensSecond, 'tokens equal for same network')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1483,11 +1483,12 @@ function showAccountDetail (address) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
log.debug(`background.setSelectedAddress`)
|
||||
background.setSelectedAddress(address, (err) => {
|
||||
background.setSelectedAddress(address, (err, tokens) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch(updateTokens(tokens))
|
||||
dispatch({
|
||||
type: actions.SHOW_ACCOUNT_DETAIL,
|
||||
value: address,
|
||||
|
@ -130,7 +130,7 @@ class InitializeMenuScreen extends Component {
|
||||
textDecoration: 'underline',
|
||||
marginTop: '32px',
|
||||
},
|
||||
}, 'Use classic interface'),
|
||||
}, this.context.t('classicInterface')),
|
||||
]),
|
||||
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user