mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
background - move pojo migrator to outside of metamask controller
This commit is contained in:
parent
2019c02fc0
commit
3bc996878b
@ -1,41 +1,57 @@
|
||||
const urlUtil = require('url')
|
||||
const extend = require('xtend')
|
||||
const Dnode = require('dnode')
|
||||
const eos = require('end-of-stream')
|
||||
const Migrator = require('pojo-migrator')
|
||||
const migrations = require('./lib/migrations')
|
||||
const LocalStorageStore = require('./lib/observable/local-storage')
|
||||
const PortStream = require('./lib/port-stream.js')
|
||||
const notification = require('./lib/notifications.js')
|
||||
const messageManager = require('./lib/message-manager')
|
||||
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||
const MetamaskController = require('./metamask-controller')
|
||||
const extension = require('./lib/extension')
|
||||
const firstTimeState = require('./first-time-state')
|
||||
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
|
||||
var popupIsOpen = false
|
||||
let popupIsOpen = false
|
||||
|
||||
|
||||
//
|
||||
// State and Persistence
|
||||
//
|
||||
|
||||
// state persistence
|
||||
|
||||
let dataStore = new LocalStorageStore({ storageKey: STORAGE_KEY })
|
||||
// initial state for first time users
|
||||
if (!dataStore.get()) {
|
||||
dataStore.put({ meta: { version: 0 }, data: firstTimeState })
|
||||
}
|
||||
|
||||
// migrations
|
||||
|
||||
let migrator = new Migrator({
|
||||
migrations,
|
||||
// Data persistence methods
|
||||
loadData: () => dataStore.get(),
|
||||
setData: (newState) => dataStore.put(newState),
|
||||
})
|
||||
|
||||
//
|
||||
// MetaMask Controller
|
||||
//
|
||||
|
||||
const controller = new MetamaskController({
|
||||
// User confirmation callbacks:
|
||||
showUnconfirmedMessage: triggerUi,
|
||||
unlockAccountMessage: triggerUi,
|
||||
showUnapprovedTx: triggerUi,
|
||||
// initial state
|
||||
initState: loadData(),
|
||||
initState: migrator.getData(),
|
||||
})
|
||||
// setup state persistence
|
||||
controller.store.subscribe(setData)
|
||||
|
||||
const txManager = controller.txManager
|
||||
function triggerUi () {
|
||||
if (!popupIsOpen) notification.show()
|
||||
}
|
||||
// On first install, open a window to MetaMask website to how-it-works.
|
||||
|
||||
extension.runtime.onInstalled.addListener(function (details) {
|
||||
if ((details.reason === 'install') && (!METAMASK_DEBUG)) {
|
||||
extension.tabs.create({url: 'https://metamask.io/#how-it-works'})
|
||||
}
|
||||
})
|
||||
controller.store.subscribe((newState) => migrator.saveData(newState))
|
||||
|
||||
//
|
||||
// connect to other contexts
|
||||
@ -94,11 +110,23 @@ function setupControllerConnection (stream) {
|
||||
}
|
||||
|
||||
//
|
||||
// plugin badge text
|
||||
// User Interface setup
|
||||
//
|
||||
|
||||
txManager.on('updateBadge', updateBadge)
|
||||
// popup trigger
|
||||
function triggerUi () {
|
||||
if (!popupIsOpen) notification.show()
|
||||
}
|
||||
|
||||
// On first install, open a window to MetaMask website to how-it-works.
|
||||
extension.runtime.onInstalled.addListener(function (details) {
|
||||
if ((details.reason === 'install') && (!METAMASK_DEBUG)) {
|
||||
extension.tabs.create({url: 'https://metamask.io/#how-it-works'})
|
||||
}
|
||||
})
|
||||
|
||||
// plugin badge text
|
||||
controller.txManager.on('updateBadge', updateBadge)
|
||||
function updateBadge () {
|
||||
var label = ''
|
||||
var unapprovedTxCount = controller.txManager.unapprovedTxCount
|
||||
@ -111,33 +139,3 @@ function updateBadge () {
|
||||
extension.browserAction.setBadgeText({ text: label })
|
||||
extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
|
||||
}
|
||||
|
||||
// data :: setters/getters
|
||||
|
||||
function loadData () {
|
||||
let defaultData = {
|
||||
meta: {
|
||||
version: 0,
|
||||
},
|
||||
data: {
|
||||
config: {
|
||||
provider: {
|
||||
type: 'testnet',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var persisted
|
||||
try {
|
||||
persisted = JSON.parse(window.localStorage[STORAGE_KEY])
|
||||
} catch (err) {
|
||||
persisted = null
|
||||
}
|
||||
|
||||
return extend(defaultData, persisted)
|
||||
}
|
||||
|
||||
function setData (data) {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(data)
|
||||
}
|
||||
|
11
app/scripts/first-time-state.js
Normal file
11
app/scripts/first-time-state.js
Normal file
@ -0,0 +1,11 @@
|
||||
//
|
||||
// The default state of MetaMask
|
||||
//
|
||||
|
||||
module.exports = {
|
||||
config: {
|
||||
provider: {
|
||||
type: 'testnet',
|
||||
},
|
||||
},
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
const Migrator = require('pojo-migrator')
|
||||
const MetamaskConfig = require('../config.js')
|
||||
const migrations = require('./migrations')
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const normalize = require('./sig-util').normalize
|
||||
|
||||
@ -20,38 +18,17 @@ function ConfigManager (opts) {
|
||||
// ConfigManager is observable and will emit updates
|
||||
this._subs = []
|
||||
this.store = opts.store
|
||||
|
||||
/* The migrator exported on the config-manager
|
||||
* has two methods the user should be concerned with:
|
||||
*
|
||||
* getData(), which returns the app-consumable data object
|
||||
* saveData(), which persists the app-consumable data object.
|
||||
*/
|
||||
this.migrator = new Migrator({
|
||||
|
||||
// Migrations must start at version 1 or later.
|
||||
// They are objects with a `version` number
|
||||
// and a `migrate` function.
|
||||
//
|
||||
// The `migrate` function receives the previous
|
||||
// config data format, and returns the new one.
|
||||
migrations: migrations,
|
||||
|
||||
// Data persistence methods
|
||||
loadData: () => this.store.get(),
|
||||
setData: (value) => this.store.put(value),
|
||||
})
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setConfig = function (config) {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
data.config = config
|
||||
this.setData(data)
|
||||
this._emitUpdates(config)
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getConfig = function () {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
if ('config' in data) {
|
||||
return data.config
|
||||
} else {
|
||||
@ -94,15 +71,15 @@ ConfigManager.prototype.getProvider = function () {
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setData = function (data) {
|
||||
this.migrator.saveData(data)
|
||||
this.store.put(data)
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getData = function () {
|
||||
return this.migrator.getData()
|
||||
return this.store.get()
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setWallet = function (wallet) {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
data.wallet = wallet
|
||||
this.setData(data)
|
||||
}
|
||||
@ -119,11 +96,11 @@ ConfigManager.prototype.getVault = function () {
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getKeychains = function () {
|
||||
return this.migrator.getData().keychains || []
|
||||
return this.store.get().keychains || []
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setKeychains = function (keychains) {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
data.keychains = keychains
|
||||
this.setData(data)
|
||||
}
|
||||
@ -140,19 +117,19 @@ ConfigManager.prototype.setSelectedAccount = function (address) {
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getWallet = function () {
|
||||
return this.migrator.getData().wallet
|
||||
return this.store.get().wallet
|
||||
}
|
||||
|
||||
// Takes a boolean
|
||||
ConfigManager.prototype.setShowSeedWords = function (should) {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
data.showSeedWords = should
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
|
||||
ConfigManager.prototype.getShouldShowSeedWords = function () {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
return data.showSeedWords
|
||||
}
|
||||
|
||||
@ -187,7 +164,7 @@ ConfigManager.prototype.getCurrentRpcAddress = function () {
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setData = function (data) {
|
||||
this.migrator.saveData(data)
|
||||
this.store.put(data)
|
||||
}
|
||||
|
||||
//
|
||||
@ -195,7 +172,7 @@ ConfigManager.prototype.setData = function (data) {
|
||||
//
|
||||
|
||||
ConfigManager.prototype.getTxList = function () {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
if (data.transactions !== undefined) {
|
||||
return data.transactions
|
||||
} else {
|
||||
@ -204,7 +181,7 @@ ConfigManager.prototype.getTxList = function () {
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setTxList = function (txList) {
|
||||
var data = this.migrator.getData()
|
||||
var data = this.store.get()
|
||||
data.transactions = txList
|
||||
this.setData(data)
|
||||
}
|
||||
|
@ -1,3 +1,16 @@
|
||||
/* The migrator has two methods the user should be concerned with:
|
||||
*
|
||||
* getData(), which returns the app-consumable data object
|
||||
* saveData(), which persists the app-consumable data object.
|
||||
*/
|
||||
|
||||
// Migrations must start at version 1 or later.
|
||||
// They are objects with a `version` number
|
||||
// and a `migrate` function.
|
||||
//
|
||||
// The `migrate` function receives the previous
|
||||
// config data format, and returns the new one.
|
||||
|
||||
module.exports = [
|
||||
require('../migrations/002'),
|
||||
require('../migrations/003'),
|
||||
|
@ -12,14 +12,14 @@ class HostStore extends ObservableStore {
|
||||
|
||||
constructor (initState, opts) {
|
||||
super(initState)
|
||||
this.opts = opts || {}
|
||||
this._opts = opts || {}
|
||||
}
|
||||
|
||||
createStream () {
|
||||
const self = this
|
||||
// setup remotely exposed api
|
||||
let remoteApi = {}
|
||||
if (!self.opts.readOnly) {
|
||||
if (!self._opts.readOnly) {
|
||||
remoteApi.put = (newState) => self.put(newState)
|
||||
}
|
||||
// listen for connection to remote
|
||||
|
@ -7,22 +7,30 @@ class ObservableStore extends EventEmitter {
|
||||
this._state = initialState
|
||||
}
|
||||
|
||||
// wrapper around internal get
|
||||
get () {
|
||||
return this._state
|
||||
}
|
||||
|
||||
|
||||
// wrapper around internal put
|
||||
put (newState) {
|
||||
this._put(newState)
|
||||
}
|
||||
|
||||
// subscribe to changes
|
||||
subscribe (handler) {
|
||||
this.on('update', handler)
|
||||
}
|
||||
|
||||
// unsubscribe to changes
|
||||
unsubscribe (handler) {
|
||||
this.removeListener('update', handler)
|
||||
}
|
||||
|
||||
//
|
||||
// private
|
||||
//
|
||||
|
||||
_put (newState) {
|
||||
this._state = newState
|
||||
this.emit('update', newState)
|
||||
|
37
app/scripts/lib/observable/local-storage.js
Normal file
37
app/scripts/lib/observable/local-storage.js
Normal file
@ -0,0 +1,37 @@
|
||||
const ObservableStore = require('./index')
|
||||
|
||||
//
|
||||
// LocalStorageStore
|
||||
//
|
||||
// uses localStorage instead of a cache
|
||||
//
|
||||
|
||||
class LocalStorageStore extends ObservableStore {
|
||||
|
||||
constructor (opts) {
|
||||
super()
|
||||
delete this._state
|
||||
|
||||
this._opts = opts || {}
|
||||
if (!this._opts.storageKey) {
|
||||
throw new Error('LocalStorageStore - no "storageKey" specified')
|
||||
}
|
||||
this._storageKey = this._opts.storageKey
|
||||
}
|
||||
|
||||
get() {
|
||||
try {
|
||||
return JSON.parse(global.localStorage[this._storageKey])
|
||||
} catch (err) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
_put(newState) {
|
||||
global.localStorage[this._storageKey] = JSON.stringify(newState)
|
||||
this.emit('update', newState)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = LocalStorageStore
|
@ -12,7 +12,7 @@ class RemoteStore extends ObservableStore {
|
||||
|
||||
constructor (initState, opts) {
|
||||
super(initState)
|
||||
this.opts = opts || {}
|
||||
this._opts = opts || {}
|
||||
this._remote = null
|
||||
}
|
||||
|
||||
|
24
app/scripts/lib/observable/util/sync.js
Normal file
24
app/scripts/lib/observable/util/sync.js
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
//
|
||||
// synchronizeStore(inStore, outStore, stateTransform)
|
||||
//
|
||||
// keeps outStore synchronized with inStore, via an optional stateTransform
|
||||
//
|
||||
|
||||
module.exports = synchronizeStore
|
||||
|
||||
|
||||
function synchronizeStore(inStore, outStore, stateTransform) {
|
||||
stateTransform = stateTransform || transformNoop
|
||||
const initState = stateTransform(inStore.get())
|
||||
outStore.put(initState)
|
||||
inStore.subscribe((inState) => {
|
||||
const outState = stateTransform(inState)
|
||||
outStore.put(outState)
|
||||
})
|
||||
return outStore
|
||||
}
|
||||
|
||||
function transformNoop(state) {
|
||||
return state
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
|
||||
module.exports = transformStore
|
||||
|
||||
|
||||
function transformStore(inStore, outStore, stateTransform) {
|
||||
const initState = stateTransform(inStore.get())
|
||||
outStore.put(initState)
|
||||
inStore.subscribe((inState) => {
|
||||
const outState = stateTransform(inState)
|
||||
outStore.put(outState)
|
||||
})
|
||||
return outStore
|
||||
}
|
@ -14,7 +14,7 @@ const nodeify = require('./lib/nodeify')
|
||||
const IdStoreMigrator = require('./lib/idStore-migrator')
|
||||
const ObservableStore = require('./lib/observable/')
|
||||
const HostStore = require('./lib/observable/host')
|
||||
const transformStore = require('./lib/observable/util/transform')
|
||||
const synchronizeStore = require('./lib/observable/util/sync')
|
||||
const version = require('../manifest.json').version
|
||||
|
||||
module.exports = class MetamaskController extends EventEmitter {
|
||||
@ -244,12 +244,12 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
var publicConfigStore = new HostStore(initPublicState, { readOnly: true })
|
||||
|
||||
// sync publicConfigStore with transform
|
||||
transformStore(this.store, publicConfigStore, selectPublicState)
|
||||
synchronizeStore(this.store, publicConfigStore, selectPublicState)
|
||||
|
||||
function selectPublicState(state) {
|
||||
let result = { selectedAccount: undefined }
|
||||
try {
|
||||
result.selectedAccount = state.data.config.selectedAccount
|
||||
result.selectedAccount = state.config.selectedAccount
|
||||
} catch (err) {
|
||||
console.warn('Error in "selectPublicState": ' + err.message)
|
||||
}
|
||||
|
96
mock-dev.js
96
mock-dev.js
@ -12,6 +12,9 @@
|
||||
* To use, run `npm run mock`.
|
||||
*/
|
||||
|
||||
// pollyfill localStorage for non-browser environments
|
||||
if (!global.localStorage) global.localStorage
|
||||
|
||||
const extend = require('xtend')
|
||||
const render = require('react-dom').render
|
||||
const h = require('react-hyperscript')
|
||||
@ -21,93 +24,62 @@ const actions = require('./ui/app/actions')
|
||||
const states = require('./development/states')
|
||||
const Selector = require('./development/selector')
|
||||
const MetamaskController = require('./app/scripts/metamask-controller')
|
||||
const firstTimeState = require('./app/scripts/first-time-state')
|
||||
const LocalStorageStore = require('./app/scripts/lib/observable/local-storage')
|
||||
const synchronizeStore = require('./app/scripts/lib/observable/util/sync')
|
||||
const extension = require('./development/mockExtension')
|
||||
const noop = function () {}
|
||||
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
|
||||
//
|
||||
// Query String
|
||||
//
|
||||
|
||||
const qs = require('qs')
|
||||
let queryString = qs.parse(window.location.href.split('#')[1])
|
||||
let selectedView = queryString.view || 'first time'
|
||||
const firstState = states[selectedView]
|
||||
updateQueryParams(selectedView)
|
||||
|
||||
// CSS
|
||||
const MetaMaskUiCss = require('./ui/css')
|
||||
const injectCss = require('inject-css')
|
||||
|
||||
|
||||
function updateQueryParams(newView) {
|
||||
queryString.view = newView
|
||||
const params = qs.stringify(queryString)
|
||||
window.location.href = window.location.href.split('#')[0] + `#${params}`
|
||||
}
|
||||
|
||||
const noop = function () {}
|
||||
//
|
||||
// CSS
|
||||
//
|
||||
|
||||
const MetaMaskUiCss = require('./ui/css')
|
||||
const injectCss = require('inject-css')
|
||||
|
||||
//
|
||||
// MetaMask Controller
|
||||
//
|
||||
|
||||
let dataStore = new LocalStorageStore({ storageKey: STORAGE_KEY })
|
||||
// initial state for first time users
|
||||
if (!dataStore.get()) {
|
||||
dataStore.put(firstTimeState)
|
||||
}
|
||||
|
||||
const controller = new MetamaskController({
|
||||
// User confirmation callbacks:
|
||||
showUnconfirmedMessage: noop,
|
||||
unlockAccountMessage: noop,
|
||||
showUnapprovedTx: noop,
|
||||
// initial state
|
||||
initState: loadData(),
|
||||
initState: dataStore.get(),
|
||||
})
|
||||
|
||||
// setup state persistence
|
||||
controller.store.subscribe(setData)
|
||||
synchronizeStore(controller.store, dataStore)
|
||||
|
||||
// Stub out localStorage for non-browser environments
|
||||
if (!window.localStorage) {
|
||||
window.localStorage = {}
|
||||
}
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
function loadData () {
|
||||
var oldData = getOldStyleData()
|
||||
var newData
|
||||
try {
|
||||
newData = JSON.parse(window.localStorage[STORAGE_KEY])
|
||||
} catch (e) {}
|
||||
|
||||
var data = extend({
|
||||
meta: {
|
||||
version: 0,
|
||||
},
|
||||
data: {
|
||||
config: {
|
||||
provider: {
|
||||
type: 'testnet',
|
||||
},
|
||||
},
|
||||
},
|
||||
}, oldData || null, newData || null)
|
||||
return data
|
||||
}
|
||||
|
||||
function setData (data) {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(data)
|
||||
}
|
||||
|
||||
function getOldStyleData () {
|
||||
var config, wallet, seedWords
|
||||
|
||||
var result = {
|
||||
meta: { version: 0 },
|
||||
data: {},
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(window.localStorage['config'])
|
||||
result.data.config = config
|
||||
} catch (e) {}
|
||||
try {
|
||||
wallet = JSON.parse(window.localStorage['lightwallet'])
|
||||
result.data.wallet = wallet
|
||||
} catch (e) {}
|
||||
try {
|
||||
seedWords = window.localStorage['seedWords']
|
||||
result.data.seedWords = seedWords
|
||||
} catch (e) {}
|
||||
|
||||
return result
|
||||
}
|
||||
//
|
||||
// User Interface
|
||||
//
|
||||
|
||||
actions._setBackgroundConnection(controller.getApi())
|
||||
actions.update = function(stateName) {
|
||||
|
@ -4,8 +4,8 @@ const IdStoreMigrator = require('../../../app/scripts/lib/idStore-migrator')
|
||||
const SimpleKeyring = require('../../../app/scripts/keyrings/simple')
|
||||
const normalize = require('../../../app/scripts/lib/sig-util').normalize
|
||||
|
||||
const oldStyleVault = require('../mocks/oldVault.json')
|
||||
const badStyleVault = require('../mocks/badVault.json')
|
||||
const oldStyleVault = require('../mocks/oldVault.json').data
|
||||
const badStyleVault = require('../mocks/badVault.json').data
|
||||
|
||||
const PASSWORD = '12345678'
|
||||
const FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase()
|
||||
@ -14,15 +14,10 @@ const SEED = 'fringe damage bounce extend tunnel afraid alert sound all soldier
|
||||
|
||||
QUnit.module('Old Style Vaults', {
|
||||
beforeEach: function () {
|
||||
let store = new ObservableStore(oldStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
store: store,
|
||||
})
|
||||
|
||||
this.migrator = new IdStoreMigrator({
|
||||
configManager: this.configManager,
|
||||
})
|
||||
let managers = managersFromInitState(oldStyleVault)
|
||||
|
||||
this.configManager = managers.configManager
|
||||
this.migrator = managers.migrator
|
||||
}
|
||||
})
|
||||
|
||||
@ -35,6 +30,7 @@ QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
|
||||
this.migrator.migratedVaultForPassword(PASSWORD)
|
||||
.then((result) => {
|
||||
assert.ok(result, 'migratedVaultForPassword returned result')
|
||||
const { serialized, lostAccounts } = result
|
||||
assert.equal(serialized.data.mnemonic, SEED, 'seed phrase recovered')
|
||||
assert.equal(lostAccounts.length, 0, 'no lost accounts')
|
||||
@ -44,15 +40,10 @@ QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
|
||||
QUnit.module('Old Style Vaults with bad HD seed', {
|
||||
beforeEach: function () {
|
||||
let store = new ObservableStore(badStyleVault)
|
||||
|
||||
this.configManager = new ConfigManager({
|
||||
store: store,
|
||||
})
|
||||
|
||||
this.migrator = new IdStoreMigrator({
|
||||
configManager: this.configManager,
|
||||
})
|
||||
let managers = managersFromInitState(badStyleVault)
|
||||
|
||||
this.configManager = managers.configManager
|
||||
this.migrator = managers.migrator
|
||||
}
|
||||
})
|
||||
|
||||
@ -61,6 +52,7 @@ QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
|
||||
this.migrator.migratedVaultForPassword(PASSWORD)
|
||||
.then((result) => {
|
||||
assert.ok(result, 'migratedVaultForPassword returned result')
|
||||
const { serialized, lostAccounts } = result
|
||||
|
||||
assert.equal(lostAccounts.length, 1, 'one lost account')
|
||||
@ -86,3 +78,15 @@ QUnit.test('migrator:migratedVaultForPassword', function (assert) {
|
||||
})
|
||||
})
|
||||
|
||||
function managersFromInitState(initState){
|
||||
|
||||
let configManager = new ConfigManager({
|
||||
store: new ObservableStore(initState),
|
||||
})
|
||||
|
||||
let migrator = new IdStoreMigrator({
|
||||
configManager: configManager,
|
||||
})
|
||||
|
||||
return { configManager, migrator }
|
||||
}
|
@ -1,61 +1,11 @@
|
||||
const ConfigManager = require('../../app/scripts/lib/config-manager')
|
||||
const ObservableStore = require('../../app/scripts/lib/observable/')
|
||||
const LocalStorageStore = require('../../app/scripts/lib/observable/local-storage')
|
||||
const firstTimeState = require('../../app/scripts/first-time-state')
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
const extend = require('xtend')
|
||||
|
||||
module.exports = function() {
|
||||
let store = new ObservableStore(loadData())
|
||||
store.subscribe(setData)
|
||||
return new ConfigManager({ store })
|
||||
}
|
||||
|
||||
function loadData () {
|
||||
var oldData = getOldStyleData()
|
||||
var newData
|
||||
|
||||
try {
|
||||
newData = JSON.parse(window.localStorage[STORAGE_KEY])
|
||||
} catch (e) {}
|
||||
|
||||
var data = extend({
|
||||
meta: {
|
||||
version: 0,
|
||||
},
|
||||
data: {
|
||||
config: {
|
||||
provider: {
|
||||
type: 'testnet',
|
||||
},
|
||||
},
|
||||
},
|
||||
}, oldData || null, newData || null)
|
||||
return data
|
||||
}
|
||||
|
||||
function getOldStyleData () {
|
||||
var config, wallet, seedWords
|
||||
|
||||
var result = {
|
||||
meta: { version: 0 },
|
||||
data: {},
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(window.localStorage['config'])
|
||||
result.data.config = config
|
||||
} catch (e) {}
|
||||
try {
|
||||
wallet = JSON.parse(window.localStorage['lightwallet'])
|
||||
result.data.wallet = wallet
|
||||
} catch (e) {}
|
||||
try {
|
||||
seedWords = window.localStorage['seedWords']
|
||||
result.data.seedWords = seedWords
|
||||
} catch (e) {}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function setData (data) {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(data)
|
||||
}
|
||||
let dataStore = new LocalStorageStore({ storageKey: STORAGE_KEY })
|
||||
// initial state for first time users
|
||||
if (!dataStore.get()) dataStore.put(firstTimeState)
|
||||
return new ConfigManager({ store: dataStore })
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
// polyfill fetch
|
||||
global.fetch = global.fetch || require('isomorphic-fetch')
|
||||
// pollyfill localStorage support into JSDom
|
||||
global.localStorage = global.localStorage || polyfillLocalStorage()
|
||||
|
||||
const assert = require('assert')
|
||||
const extend = require('xtend')
|
||||
const rp = require('request-promise')
|
||||
@ -11,7 +14,7 @@ describe('config-manager', function() {
|
||||
var configManager
|
||||
|
||||
beforeEach(function() {
|
||||
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||
global.localStorage.clear()
|
||||
configManager = configManagerGen()
|
||||
})
|
||||
|
||||
@ -132,7 +135,6 @@ describe('config-manager', function() {
|
||||
})
|
||||
|
||||
describe('#setConfig', function() {
|
||||
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||
|
||||
it('should set the config key', function () {
|
||||
var testConfig = {
|
||||
@ -238,3 +240,7 @@ describe('config-manager', function() {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function polyfillLocalStorage(){
|
||||
return Object.create({ clear: function(){ global.localStorage = polyfillLocalStorage() } })
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user