Merge pull request #2 from MetaMask/master

update
feature/default_network_editable
Orange 7 years ago committed by GitHub
commit 95742596e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitignore
  2. 6
      CHANGELOG.md
  3. 1
      app/manifest.json
  4. 35
      app/scripts/background.js
  5. 38
      app/scripts/lib/local-store.js
  6. 6
      app/scripts/lib/tx-gas-utils.js
  7. 13
      old-ui/app/keychains/hd/restore-vault.js
  8. 1
      package.json
  9. 13
      ui/app/keychains/hd/restore-vault.js

1
.gitignore vendored

@ -1,5 +1,6 @@
npm-debug.log npm-debug.log
node_modules node_modules
yarn.lock
app/bower_components app/bower_components
test/bower_components test/bower_components

@ -1,13 +1,17 @@
# Changelog # Changelog
## Current Master ## Current Master
- Add ability for internationalization.
- Will now throw an error if the `to` field in txParams is not valid.
- Will strip null values from the `to` field.
- Fix flashing to Log in screen after logging in or restoring from seed phrase. - Fix flashing to Log in screen after logging in or restoring from seed phrase.
- Increase tap areas for menu buttons on mobile - Increase tap areas for menu buttons on mobile
- Change all fonts in new-ui onboarding to Roboto, size 400 - Change all fonts in new-ui onboarding to Roboto, size 400
- Add a welcome screen to new-ui onboarding flow - Add a welcome screen to new-ui onboarding flow
- Make new-ui create password screen responsive - Make new-ui create password screen responsive
- Hide network dropdown before account is initialized - Hide network dropdown before account is initialized
- Add ability for internationalization. - Fix bug that could prevent MetaMask from saving the latest vault.
## 4.2.0 Tue Mar 06 2018 ## 4.2.0 Tue Mar 06 2018

@ -56,6 +56,7 @@
], ],
"permissions": [ "permissions": [
"storage", "storage",
"unlimitedStorage",
"clipboardWrite", "clipboardWrite",
"http://localhost:8545/", "http://localhost:8545/",
"https://*.infura.io/" "https://*.infura.io/"

@ -1,9 +1,11 @@
const urlUtil = require('url') const urlUtil = require('url')
const endOfStream = require('end-of-stream') const endOfStream = require('end-of-stream')
const pump = require('pump') const pump = require('pump')
const debounce = require('debounce-stream')
const log = require('loglevel') const log = require('loglevel')
const extension = require('extensionizer') const extension = require('extensionizer')
const LocalStorageStore = require('obs-store/lib/localStorage') const LocalStorageStore = require('obs-store/lib/localStorage')
const LocalStore = require('./lib/local-store')
const storeTransform = require('obs-store/lib/transform') const storeTransform = require('obs-store/lib/transform')
const asStream = require('obs-store/lib/asStream') const asStream = require('obs-store/lib/asStream')
const ExtensionPlatform = require('./platforms/extension') const ExtensionPlatform = require('./platforms/extension')
@ -44,6 +46,8 @@ let openMetamaskTabsIDs = {}
// state persistence // state persistence
const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY })
const localStore = new LocalStore()
let versionedData
// initialization flow // initialization flow
initialize().catch(log.error) initialize().catch(log.error)
@ -64,12 +68,23 @@ async function initialize () {
async function loadStateFromPersistence () { async function loadStateFromPersistence () {
// migrations // migrations
const migrator = new Migrator({ migrations }) const migrator = new Migrator({ migrations })
// read from disk // read from disk
let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) // first from preferred, async API:
versionedData = (await localStore.get()) ||
diskStore.getState() ||
migrator.generateInitialState(firstTimeState)
// migrate data // migrate data
versionedData = await migrator.migrateData(versionedData) versionedData = await migrator.migrateData(versionedData)
if (!versionedData) {
throw new Error('MetaMask - migrator returned undefined')
}
// write to disk // write to disk
if (localStore.isSupported) localStore.set(versionedData)
diskStore.putState(versionedData) diskStore.putState(versionedData)
// return just the data // return just the data
return versionedData.data return versionedData.data
} }
@ -102,16 +117,30 @@ function setupController (initState) {
// setup state persistence // setup state persistence
pump( pump(
asStream(controller.store), asStream(controller.store),
debounce(1000),
storeTransform(versionifyData), storeTransform(versionifyData),
asStream(diskStore) storeTransform(syncDataWithExtension),
asStream(diskStore),
(error) => {
log.error('pump hit error', error)
}
) )
function versionifyData (state) { function versionifyData (state) {
const versionedData = diskStore.getState()
versionedData.data = state versionedData.data = state
return versionedData return versionedData
} }
function syncDataWithExtension(state) {
if (localStore.isSupported) {
localStore.set(state)
.catch((err) => {
log.error('error setting state in local store:', err)
})
}
return state
}
// //
// connect to other contexts // connect to other contexts
// //

@ -0,0 +1,38 @@
// We should not rely on local storage in an extension!
// We should use this instead!
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local
const extension = require('extensionizer')
const { promisify } = require('util')
module.exports = class ExtensionStore {
constructor() {
this.isSupported = !!(extension.storage.local)
if (!this.isSupported) {
log.error('Storage local API not available.')
}
const local = extension.storage.local
this._get = promisify(local.get).bind(local)
this._set = promisify(local.set).bind(local)
}
async get() {
if (!this.isSupported) return undefined
const result = await this._get()
// extension.storage.local always returns an obj
// if the object is empty, treat it as undefined
if (isEmpty(result)) {
return undefined
} else {
return result
}
}
async set(state) {
return this._set(state)
}
}
function isEmpty(obj) {
return Object.keys(obj).length === 0
}

@ -4,7 +4,7 @@ const {
BnMultiplyByFraction, BnMultiplyByFraction,
bnToHex, bnToHex,
} = require('./util') } = require('./util')
const addHexPrefix = require('ethereumjs-util').addHexPrefix const { addHexPrefix, isValidAddress } = require('ethereumjs-util')
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
/* /*
@ -113,12 +113,14 @@ module.exports = class TxGasUtil {
} }
} }
validateRecipient (txParams) { validateRecipient (txParams) {
if (txParams.to === '0x') { if (txParams.to === '0x' || txParams.to === null ) {
if (txParams.data) { if (txParams.data) {
delete txParams.to delete txParams.to
} else { } else {
throw new Error('Invalid recipient address') throw new Error('Invalid recipient address')
} }
} else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) {
throw new Error('Invalid recipient address')
} }
return txParams return txParams
} }

@ -140,6 +140,19 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () {
// check seed // check seed
var seedBox = document.querySelector('textarea.twelve-word-phrase') var seedBox = document.querySelector('textarea.twelve-word-phrase')
var seed = seedBox.value.trim() var seed = seedBox.value.trim()
// true if the string has more than a space between words.
if (seed.split(' ').length > 1) {
this.warning = 'there can only be a space between words'
this.props.dispatch(actions.displayWarning(this.warning))
return
}
// true if seed contains a character that is not between a-z or a space
if (!seed.match(/^[a-z ]+$/)) {
this.warning = 'seed words only have lowercase characters'
this.props.dispatch(actions.displayWarning(this.warning))
return
}
if (seed.split(' ').length !== 12) { if (seed.split(' ').length !== 12) {
this.warning = 'seed phrases are 12 words long' this.warning = 'seed phrases are 12 words long'
this.props.dispatch(actions.displayWarning(this.warning)) this.props.dispatch(actions.displayWarning(this.warning))

@ -72,6 +72,7 @@
"clone": "^2.1.1", "clone": "^2.1.1",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"debounce": "^1.0.0", "debounce": "^1.0.0",
"debounce-stream": "^2.0.0",
"deep-extend": "^0.5.0", "deep-extend": "^0.5.0",
"detect-node": "^2.0.3", "detect-node": "^2.0.3",
"disc": "^1.3.2", "disc": "^1.3.2",

@ -144,6 +144,19 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () {
// check seed // check seed
var seedBox = document.querySelector('textarea.twelve-word-phrase') var seedBox = document.querySelector('textarea.twelve-word-phrase')
var seed = seedBox.value.trim() var seed = seedBox.value.trim()
// true if the string has more than a space between words.
if (seed.split(' ').length > 1) {
this.warning = 'there can only a space between words'
this.props.dispatch(actions.displayWarning(this.warning))
return
}
// true if seed contains a character that is not between a-z or a space
if (!seed.match(/^[a-z ]+$/)) {
this.warning = 'seed words only have lowercase characters'
this.props.dispatch(actions.displayWarning(this.warning))
return
}
if (seed.split(' ').length !== 12) { if (seed.split(' ').length !== 12) {
this.warning = 'seed phrases are 12 words long' this.warning = 'seed phrases are 12 words long'
this.props.dispatch(actions.displayWarning(this.warning)) this.props.dispatch(actions.displayWarning(this.warning))

Loading…
Cancel
Save