diff --git a/app/scripts/background.js b/app/scripts/background.js
index f3837a028..18882e5d5 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -1,162 +1,181 @@
 const urlUtil = require('url')
-const extend = require('xtend')
 const Dnode = require('dnode')
 const eos = require('end-of-stream')
+const asyncQ = require('async-q')
+const pipe = require('pump')
+const LocalStorageStore = require('obs-store/lib/localStorage')
+const storeTransform = require('obs-store/lib/transform')
+const Migrator = require('./lib/migrator/')
+const migrations = require('./migrations/')
 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
 
-const controller = new MetamaskController({
-  // User confirmation callbacks:
-  showUnconfirmedMessage: triggerUi,
-  unlockAccountMessage: triggerUi,
-  showUnapprovedTx: triggerUi,
-  // Persistence Methods:
-  setData,
-  loadData,
-})
+let popupIsOpen = false
 
+// state persistence
+const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY })
+
+// initialization flow
+asyncQ.waterfall([
+  () => loadStateFromPersistence(),
+  (initState) => setupController(initState),
+])
+.then(() => console.log('MetaMask initialization complete.'))
+.catch((err) => { console.error(err) })
+
+//
+// State and Persistence
+//
+
+function loadStateFromPersistence() {
+  // migrations
+  let migrator = new Migrator({ migrations })
+  let initialState = migrator.generateInitialState(firstTimeState)
+  return asyncQ.waterfall([
+    // read from disk
+    () => Promise.resolve(diskStore.getState() || initialState),
+    // migrate data
+    (versionedData) => migrator.migrateData(versionedData),
+    // write to disk
+    (versionedData) => {
+      diskStore.putState(versionedData)
+      return Promise.resolve(versionedData)
+    },
+    // resolve to just data
+    (versionedData) => Promise.resolve(versionedData.data),
+  ])
+}
+
+function setupController (initState) {
+
+  //
+  // MetaMask Controller
+  //
+
+  const controller = new MetamaskController({
+    // User confirmation callbacks:
+    showUnconfirmedMessage: triggerUi,
+    unlockAccountMessage: triggerUi,
+    showUnapprovedTx: triggerUi,
+    // initial state
+    initState,
+  })
+  global.metamaskController = controller
+
+  // setup state persistence
+  pipe(
+    controller.store,
+    storeTransform(versionifyData),
+    diskStore
+  )
+
+  function versionifyData(state) {
+    let versionedData = diskStore.getState()
+    versionedData.data = state
+    return versionedData
+  }
+
+  //
+  // connect to other contexts
+  //
+
+  extension.runtime.onConnect.addListener(connectRemote)
+  function connectRemote (remotePort) {
+    var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification'
+    var portStream = new PortStream(remotePort)
+    if (isMetaMaskInternalProcess) {
+      // communication with popup
+      popupIsOpen = remotePort.name === 'popup'
+      setupTrustedCommunication(portStream, 'MetaMask', remotePort.name)
+    } else {
+      // communication with page
+      var originDomain = urlUtil.parse(remotePort.sender.url).hostname
+      setupUntrustedCommunication(portStream, originDomain)
+    }
+  }
+
+  function setupUntrustedCommunication (connectionStream, originDomain) {
+    // setup multiplexing
+    var mx = setupMultiplex(connectionStream)
+    // connect features
+    controller.setupProviderConnection(mx.createStream('provider'), originDomain)
+    controller.setupPublicConfig(mx.createStream('publicConfig'))
+  }
+
+  function setupTrustedCommunication (connectionStream, originDomain) {
+    // setup multiplexing
+    var mx = setupMultiplex(connectionStream)
+    // connect features
+    setupControllerConnection(mx.createStream('controller'))
+    controller.setupProviderConnection(mx.createStream('provider'), originDomain)
+  }
+
+  //
+  // remote features
+  //
+
+  function setupControllerConnection (stream) {
+    controller.stream = stream
+    var api = controller.getApi()
+    var dnode = Dnode(api)
+    stream.pipe(dnode).pipe(stream)
+    dnode.on('remote', (remote) => {
+      // push updates to popup
+      var sendUpdate = remote.sendUpdate.bind(remote)
+      controller.on('update', sendUpdate)
+      // teardown on disconnect
+      eos(stream, () => {
+        controller.removeListener('update', sendUpdate)
+        popupIsOpen = false
+      })
+    })
+  }
+
+  //
+  // User Interface setup
+  //
+
+  updateBadge()
+  controller.txManager.on('updateBadge', updateBadge)
+
+  // plugin badge text
+  function updateBadge () {
+    var label = ''
+    var unapprovedTxCount = controller.txManager.unapprovedTxCount
+    var unconfMsgs = messageManager.unconfirmedMsgs()
+    var unconfMsgLen = Object.keys(unconfMsgs).length
+    var count = unapprovedTxCount + unconfMsgLen
+    if (count) {
+      label = String(count)
+    }
+    extension.browserAction.setBadgeText({ text: label })
+    extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
+  }
+
+  return Promise.resolve()
+
+}
+
+//
+// Etc...
+//
+
+// 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'})
   }
-})
-
-//
-// connect to other contexts
-//
-
-extension.runtime.onConnect.addListener(connectRemote)
-function connectRemote (remotePort) {
-  var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification'
-  var portStream = new PortStream(remotePort)
-  if (isMetaMaskInternalProcess) {
-    // communication with popup
-    popupIsOpen = remotePort.name === 'popup'
-    setupTrustedCommunication(portStream, 'MetaMask', remotePort.name)
-  } else {
-    // communication with page
-    var originDomain = urlUtil.parse(remotePort.sender.url).hostname
-    setupUntrustedCommunication(portStream, originDomain)
-  }
-}
-
-function setupUntrustedCommunication (connectionStream, originDomain) {
-  // setup multiplexing
-  var mx = setupMultiplex(connectionStream)
-  // connect features
-  controller.setupProviderConnection(mx.createStream('provider'), originDomain)
-  controller.setupPublicConfig(mx.createStream('publicConfig'))
-}
-
-function setupTrustedCommunication (connectionStream, originDomain) {
-  // setup multiplexing
-  var mx = setupMultiplex(connectionStream)
-  // connect features
-  setupControllerConnection(mx.createStream('controller'))
-  controller.setupProviderConnection(mx.createStream('provider'), originDomain)
-}
-
-//
-// remote features
-//
-
-function setupControllerConnection (stream) {
-  controller.stream = stream
-  var api = controller.getApi()
-  var dnode = Dnode(api)
-  stream.pipe(dnode).pipe(stream)
-  dnode.on('remote', (remote) => {
-    // push updates to popup
-    var sendUpdate = remote.sendUpdate.bind(remote)
-    controller.on('update', sendUpdate)
-    // teardown on disconnect
-    eos(stream, () => {
-      controller.removeListener('update', sendUpdate)
-      popupIsOpen = false
-    })
-  })
-}
-
-//
-// plugin badge text
-//
-
-controller.txManager.on('updateBadge', updateBadge)
-updateBadge()
-
-function updateBadge () {
-  var label = ''
-  var unapprovedTxCount = controller.txManager.unapprovedTxCount
-  var unconfMsgs = messageManager.unconfirmedMsgs()
-  var unconfMsgLen = Object.keys(unconfMsgs).length
-  var count = unapprovedTxCount + unconfMsgLen
-  if (count) {
-    label = String(count)
-  }
-  extension.browserAction.setBadgeText({ text: label })
-  extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
-}
-
-// data :: setters/getters
-
-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)
-}
+})
\ No newline at end of file
diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js
new file mode 100644
index 000000000..3196981ba
--- /dev/null
+++ b/app/scripts/first-time-state.js
@@ -0,0 +1,11 @@
+//
+// The default state of MetaMask
+//
+
+module.exports = {
+  config: {
+    provider: {
+      type: 'testnet',
+    },
+  },
+}
\ No newline at end of file
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index e927c78ec..6d088906c 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -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
 
@@ -19,41 +17,18 @@ module.exports = ConfigManager
 function ConfigManager (opts) {
   // ConfigManager is observable and will emit updates
   this._subs = []
-
-  /* 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,
-
-    // How to load initial config.
-    // Includes step on migrating pre-pojo-migrator data.
-    loadData: opts.loadData,
-
-    // How to persist migrated config.
-    setData: opts.setData,
-  })
+  this.store = opts.store
 }
 
 ConfigManager.prototype.setConfig = function (config) {
-  var data = this.migrator.getData()
+  var data = this.getData()
   data.config = config
   this.setData(data)
   this._emitUpdates(config)
 }
 
 ConfigManager.prototype.getConfig = function () {
-  var data = this.migrator.getData()
+  var data = this.getData()
   if ('config' in data) {
     return data.config
   } else {
@@ -96,15 +71,15 @@ ConfigManager.prototype.getProvider = function () {
 }
 
 ConfigManager.prototype.setData = function (data) {
-  this.migrator.saveData(data)
+  this.store.putState(data)
 }
 
 ConfigManager.prototype.getData = function () {
-  return this.migrator.getData()
+  return this.store.getState()
 }
 
 ConfigManager.prototype.setWallet = function (wallet) {
-  var data = this.migrator.getData()
+  var data = this.getData()
   data.wallet = wallet
   this.setData(data)
 }
@@ -121,11 +96,11 @@ ConfigManager.prototype.getVault = function () {
 }
 
 ConfigManager.prototype.getKeychains = function () {
-  return this.migrator.getData().keychains || []
+  return this.getData().keychains || []
 }
 
 ConfigManager.prototype.setKeychains = function (keychains) {
-  var data = this.migrator.getData()
+  var data = this.getData()
   data.keychains = keychains
   this.setData(data)
 }
@@ -142,19 +117,19 @@ ConfigManager.prototype.setSelectedAccount = function (address) {
 }
 
 ConfigManager.prototype.getWallet = function () {
-  return this.migrator.getData().wallet
+  return this.getData().wallet
 }
 
 // Takes a boolean
 ConfigManager.prototype.setShowSeedWords = function (should) {
-  var data = this.migrator.getData()
+  var data = this.getData()
   data.showSeedWords = should
   this.setData(data)
 }
 
 
 ConfigManager.prototype.getShouldShowSeedWords = function () {
-  var data = this.migrator.getData()
+  var data = this.getData()
   return data.showSeedWords
 }
 
@@ -166,7 +141,7 @@ ConfigManager.prototype.setSeedWords = function (words) {
 
 ConfigManager.prototype.getSeedWords = function () {
   var data = this.getData()
-  return ('seedWords' in data) && data.seedWords
+  return data.seedWords
 }
 
 ConfigManager.prototype.getCurrentRpcAddress = function () {
@@ -188,16 +163,12 @@ ConfigManager.prototype.getCurrentRpcAddress = function () {
   }
 }
 
-ConfigManager.prototype.setData = function (data) {
-  this.migrator.saveData(data)
-}
-
 //
 // Tx
 //
 
 ConfigManager.prototype.getTxList = function () {
-  var data = this.migrator.getData()
+  var data = this.getData()
   if (data.transactions !== undefined) {
     return data.transactions
   } else {
@@ -206,7 +177,7 @@ ConfigManager.prototype.getTxList = function () {
 }
 
 ConfigManager.prototype.setTxList = function (txList) {
-  var data = this.migrator.getData()
+  var data = this.getData()
   data.transactions = txList
   this.setData(data)
 }
@@ -239,7 +210,7 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) {
 
 ConfigManager.prototype.getSalt = function () {
   var data = this.getData()
-  return ('salt' in data) && data.salt
+  return data.salt
 }
 
 ConfigManager.prototype.setSalt = function (salt) {
@@ -273,7 +244,7 @@ ConfigManager.prototype.setConfirmedDisclaimer = function (confirmed) {
 
 ConfigManager.prototype.getConfirmedDisclaimer = function () {
   var data = this.getData()
-  return ('isDisclaimerConfirmed' in data) && data.isDisclaimerConfirmed
+  return data.isDisclaimerConfirmed
 }
 
 ConfigManager.prototype.setTOSHash = function (hash) {
@@ -284,7 +255,7 @@ ConfigManager.prototype.setTOSHash = function (hash) {
 
 ConfigManager.prototype.getTOSHash = function () {
   var data = this.getData()
-  return ('TOSHash' in data) && data.TOSHash
+  return data.TOSHash
 }
 
 ConfigManager.prototype.setCurrentFiat = function (currency) {
@@ -295,7 +266,7 @@ ConfigManager.prototype.setCurrentFiat = function (currency) {
 
 ConfigManager.prototype.getCurrentFiat = function () {
   var data = this.getData()
-  return ('fiatCurrency' in data) && data.fiatCurrency
+  return data.fiatCurrency
 }
 
 ConfigManager.prototype.updateConversionRate = function () {
@@ -326,12 +297,12 @@ ConfigManager.prototype.setConversionDate = function (datestring) {
 
 ConfigManager.prototype.getConversionRate = function () {
   var data = this.getData()
-  return (('conversionRate' in data) && data.conversionRate) || 0
+  return (data.conversionRate) || 0
 }
 
 ConfigManager.prototype.getConversionDate = function () {
   var data = this.getData()
-  return (('conversionDate' in data) && data.conversionDate) || 'N/A'
+  return (data.conversionDate) || 'N/A'
 }
 
 ConfigManager.prototype.getShapeShiftTxList = function () {
@@ -370,7 +341,7 @@ ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositTy
 
 ConfigManager.prototype.getGasMultiplier = function () {
   var data = this.getData()
-  return ('gasMultiplier' in data) && data.gasMultiplier
+  return data.gasMultiplier
 }
 
 ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) {
diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js
index 11bd5cc3a..066916b4d 100644
--- a/app/scripts/lib/inpage-provider.js
+++ b/app/scripts/lib/inpage-provider.js
@@ -1,7 +1,7 @@
-const Streams = require('mississippi')
+const pipe = require('pump')
 const StreamProvider = require('web3-stream-provider')
+const LocalStorageStore = require('obs-store')
 const ObjectMultiplex = require('./obj-multiplex')
-const RemoteStore = require('./remote-store.js').RemoteStore
 const createRandomId = require('./random-id')
 
 module.exports = MetamaskInpageProvider
@@ -10,33 +10,30 @@ function MetamaskInpageProvider (connectionStream) {
   const self = this
 
   // setup connectionStream multiplexing
-  var multiStream = ObjectMultiplex()
-  Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
-    let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask'
-    if (err) warningMsg += '\n' + err.stack
-    console.warn(warningMsg)
-  })
-  self.multiStream = multiStream
+  var multiStream = self.multiStream = ObjectMultiplex()
+  pipe(
+    connectionStream,
+    multiStream,
+    connectionStream,
+    (err) => logStreamDisconnectWarning('MetaMask', err)
+  )
 
-  // subscribe to metamask public config
-  var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config')
-  var storeStream = publicConfigStore.createStream()
-  Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
-    let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask publicConfig'
-    if (err) warningMsg += '\n' + err.stack
-    console.warn(warningMsg)
-  })
-  self.publicConfigStore = publicConfigStore
+  // subscribe to metamask public config (one-way)
+  self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' })
+  pipe(
+    multiStream.createStream('publicConfig'),
+    self.publicConfigStore,
+    (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err)
+  )
 
   // connect to async provider
-  var asyncProvider = new StreamProvider()
-  Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
-    let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask provider'
-    if (err) warningMsg += '\n' + err.stack
-    console.warn(warningMsg)
-  })
-  asyncProvider.on('error', console.error.bind(console))
-  self.asyncProvider = asyncProvider
+  const asyncProvider = self.asyncProvider = new StreamProvider()
+  pipe(
+    asyncProvider,
+    multiStream.createStream('provider'),
+    asyncProvider,
+    (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err)
+  )
 
   self.idMap = {}
   // handle sendAsync requests via asyncProvider
@@ -72,13 +69,13 @@ MetamaskInpageProvider.prototype.send = function (payload) {
 
     case 'eth_accounts':
       // read from localStorage
-      selectedAccount = self.publicConfigStore.get('selectedAccount')
+      selectedAccount = self.publicConfigStore.getState().selectedAccount
       result = selectedAccount ? [selectedAccount] : []
       break
 
     case 'eth_coinbase':
       // read from localStorage
-      selectedAccount = self.publicConfigStore.get('selectedAccount')
+      selectedAccount = self.publicConfigStore.getState().selectedAccount
       result = selectedAccount || '0x0000000000000000000000000000000000000000'
       break
 
@@ -115,18 +112,6 @@ MetamaskInpageProvider.prototype.isMetaMask = true
 
 // util
 
-function remoteStoreWithLocalStorageCache (storageKey) {
-  // read local cache
-  var initState = JSON.parse(localStorage[storageKey] || '{}')
-  var store = new RemoteStore(initState)
-  // cache the latest state locally
-  store.subscribe(function (state) {
-    localStorage[storageKey] = JSON.stringify(state)
-  })
-
-  return store
-}
-
 function eachJsonMessage (payload, transformFn) {
   if (Array.isArray(payload)) {
     return payload.map(transformFn)
@@ -135,4 +120,10 @@ function eachJsonMessage (payload, transformFn) {
   }
 }
 
+function logStreamDisconnectWarning(remoteLabel, err){
+  let warningMsg = `MetamaskInpageProvider - lost connection to ${remoteLabel}`
+  if (err) warningMsg += '\n' + err.stack
+  console.warn(warningMsg)
+}
+
 function noop () {}
diff --git a/app/scripts/lib/migrations.js b/app/scripts/lib/migrations.js
deleted file mode 100644
index f026cbe53..000000000
--- a/app/scripts/lib/migrations.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = [
-  require('../migrations/002'),
-  require('../migrations/003'),
-  require('../migrations/004'),
-]
diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js
new file mode 100644
index 000000000..ab5a757b3
--- /dev/null
+++ b/app/scripts/lib/migrator/index.js
@@ -0,0 +1,40 @@
+const asyncQ = require('async-q')
+
+class Migrator {
+
+  constructor (opts = {}) {
+    let migrations = opts.migrations || []
+    this.migrations = migrations.sort((a, b) => a.version - b.version)
+    let lastMigration = this.migrations.slice(-1)[0]
+    // use specified defaultVersion or highest migration version
+    this.defaultVersion = opts.defaultVersion || (lastMigration && lastMigration.version) || 0
+  }
+
+  // run all pending migrations on meta in place
+  migrateData (versionedData = this.generateInitialState()) {
+    let remaining = this.migrations.filter(migrationIsPending)
+    
+    return (
+      asyncQ.eachSeries(remaining, (migration) => migration.migrate(versionedData))
+      .then(() => versionedData)
+    )
+
+    // migration is "pending" if hit has a higher
+    // version number than currentVersion
+    function migrationIsPending(migration) {
+      return migration.version > versionedData.meta.version
+    }
+  }
+
+  generateInitialState (initState) {
+    return {
+      meta: {
+        version: this.defaultVersion,
+      },
+      data: initState,
+    }
+  }
+
+}
+
+module.exports = Migrator
diff --git a/app/scripts/lib/remote-store.js b/app/scripts/lib/remote-store.js
deleted file mode 100644
index fbfab7bad..000000000
--- a/app/scripts/lib/remote-store.js
+++ /dev/null
@@ -1,97 +0,0 @@
-const Dnode = require('dnode')
-const inherits = require('util').inherits
-
-module.exports = {
-  HostStore: HostStore,
-  RemoteStore: RemoteStore,
-}
-
-function BaseStore (initState) {
-  this._state = initState || {}
-  this._subs = []
-}
-
-BaseStore.prototype.set = function (key, value) {
-  throw Error('Not implemented.')
-}
-
-BaseStore.prototype.get = function (key) {
-  return this._state[key]
-}
-
-BaseStore.prototype.subscribe = function (fn) {
-  this._subs.push(fn)
-  var unsubscribe = this.unsubscribe.bind(this, fn)
-  return unsubscribe
-}
-
-BaseStore.prototype.unsubscribe = function (fn) {
-  var index = this._subs.indexOf(fn)
-  if (index !== -1) this._subs.splice(index, 1)
-}
-
-BaseStore.prototype._emitUpdates = function (state) {
-  this._subs.forEach(function (handler) {
-    handler(state)
-  })
-}
-
-//
-// host
-//
-
-inherits(HostStore, BaseStore)
-function HostStore (initState, opts) {
-  BaseStore.call(this, initState)
-}
-
-HostStore.prototype.set = function (key, value) {
-  this._state[key] = value
-  process.nextTick(this._emitUpdates.bind(this, this._state))
-}
-
-HostStore.prototype.createStream = function () {
-  var dnode = Dnode({
-    // update: this._didUpdate.bind(this),
-  })
-  dnode.on('remote', this._didConnect.bind(this))
-  return dnode
-}
-
-HostStore.prototype._didConnect = function (remote) {
-  this.subscribe(function (state) {
-    remote.update(state)
-  })
-  remote.update(this._state)
-}
-
-//
-// remote
-//
-
-inherits(RemoteStore, BaseStore)
-function RemoteStore (initState, opts) {
-  BaseStore.call(this, initState)
-  this._remote = null
-}
-
-RemoteStore.prototype.set = function (key, value) {
-  this._remote.set(key, value)
-}
-
-RemoteStore.prototype.createStream = function () {
-  var dnode = Dnode({
-    update: this._didUpdate.bind(this),
-  })
-  dnode.once('remote', this._didConnect.bind(this))
-  return dnode
-}
-
-RemoteStore.prototype._didConnect = function (remote) {
-  this._remote = remote
-}
-
-RemoteStore.prototype._didUpdate = function (state) {
-  this._state = state
-  this._emitUpdates(state)
-}
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 5c663255a..8f157a45e 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -1,13 +1,15 @@
 const EventEmitter = require('events')
 const extend = require('xtend')
 const promiseToCallback = require('promise-to-callback')
+const pipe = require('pump')
+const ObservableStore = require('obs-store')
+const storeTransform = require('obs-store/lib/transform')
 const EthStore = require('./lib/eth-store')
 const MetaMaskProvider = require('web3-provider-engine/zero.js')
 const KeyringController = require('./keyring-controller')
 const NoticeController = require('./notice-controller')
 const messageManager = require('./lib/message-manager')
 const TxManager = require('./transaction-manager')
-const HostStore = require('./lib/remote-store.js').HostStore
 const Web3 = require('web3')
 const ConfigManager = require('./lib/config-manager')
 const extension = require('./lib/extension')
@@ -15,19 +17,30 @@ const autoFaucet = require('./lib/auto-faucet')
 const nodeify = require('./lib/nodeify')
 const IdStoreMigrator = require('./lib/idStore-migrator')
 const accountImporter = require('./account-import-strategies')
+
 const version = require('../manifest.json').version
 
 module.exports = class MetamaskController extends EventEmitter {
 
   constructor (opts) {
     super()
-    this.state = { network: 'loading' }
     this.opts = opts
-    this.configManager = new ConfigManager(opts)
+    this.state = { network: 'loading' }
+
+    // observable state store
+    this.store = new ObservableStore(opts.initState)
+    // config manager
+    this.configManager = new ConfigManager({
+      store: this.store,
+    })
+    // key mgmt
     this.keyringController = new KeyringController({
       configManager: this.configManager,
       getNetwork: this.getStateNetwork.bind(this),
     })
+    this.keyringController.on('newAccount', (account) => {
+      autoFaucet(account)
+    })
     // notices
     this.noticeController = new NoticeController({
       configManager: this.configManager,
@@ -245,29 +258,23 @@ module.exports = class MetamaskController extends EventEmitter {
 
   initPublicConfigStore () {
     // get init state
-    var initPublicState = configToPublic(this.configManager.getConfig())
-    var publicConfigStore = new HostStore(initPublicState)
+    const publicConfigStore = new ObservableStore()
 
-    // subscribe to changes
-    this.configManager.subscribe(function (state) {
-      storeSetFromObj(publicConfigStore, configToPublic(state))
-    })
+    // sync publicConfigStore with transform
+    pipe(
+      this.store,
+      storeTransform(selectPublicState),
+      publicConfigStore
+    )
 
-    this.keyringController.on('newAccount', (account) => {
-      autoFaucet(account)
-    })
-
-    // config substate
-    function configToPublic (state) {
-      return {
-        selectedAccount: state.selectedAccount,
+    function selectPublicState(state) {
+      const result = { selectedAccount: undefined }
+      try {
+        result.selectedAccount = state.config.selectedAccount
+      } catch (_) {
+        // thats fine, im sure it will be there next time...
       }
-    }
-    // dump obj into store
-    function storeSetFromObj (store, obj) {
-      Object.keys(obj).forEach(function (key) {
-        store.set(key, obj[key])
-      })
+      return result
     }
 
     return publicConfigStore
@@ -310,9 +317,11 @@ module.exports = class MetamaskController extends EventEmitter {
     this.opts.showUnconfirmedMessage(msgParams, msgId)
   }
 
-  setupPublicConfig (stream) {
-    var storeStream = this.publicConfigStore.createStream()
-    stream.pipe(storeStream).pipe(stream)
+  setupPublicConfig (outStream) {
+    pipe(
+      this.publicConfigStore,
+      outStream
+    )
   }
 
   // Log blocks
diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js
index 0b654f825..476b0a43a 100644
--- a/app/scripts/migrations/002.js
+++ b/app/scripts/migrations/002.js
@@ -1,13 +1,16 @@
-module.exports = {
-  version: 2,
+const version = 2
 
-  migrate: function (data) {
+module.exports = {
+  version,
+
+  migrate: function (versionedData) {
+    versionedData.meta.version = version
     try {
-      if (data.config.provider.type === 'etherscan') {
-        data.config.provider.type = 'rpc'
-        data.config.provider.rpcTarget = 'https://rpc.metamask.io/'
+      if (versionedData.data.config.provider.type === 'etherscan') {
+        versionedData.data.config.provider.type = 'rpc'
+        versionedData.data.config.provider.rpcTarget = 'https://rpc.metamask.io/'
       }
     } catch (e) {}
-    return data
+    return Promise.resolve(versionedData)
   },
 }
diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js
index 617c55c09..eceaeaa4b 100644
--- a/app/scripts/migrations/003.js
+++ b/app/scripts/migrations/003.js
@@ -1,15 +1,17 @@
-var oldTestRpc = 'https://rawtestrpc.metamask.io/'
-var newTestRpc = 'https://testrpc.metamask.io/'
+const version = 3
+const oldTestRpc = 'https://rawtestrpc.metamask.io/'
+const newTestRpc = 'https://testrpc.metamask.io/'
 
 module.exports = {
-  version: 3,
+  version,
 
-  migrate: function (data) {
+  migrate: function (versionedData) {
+    versionedData.meta.version = version
     try {
-      if (data.config.provider.rpcTarget === oldTestRpc) {
-        data.config.provider.rpcTarget = newTestRpc
+      if (versionedData.data.config.provider.rpcTarget === oldTestRpc) {
+        versionedData.data.config.provider.rpcTarget = newTestRpc
       }
     } catch (e) {}
-    return data
+    return Promise.resolve(versionedData)
   },
 }
diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js
index 1329a1eed..0f9850208 100644
--- a/app/scripts/migrations/004.js
+++ b/app/scripts/migrations/004.js
@@ -1,22 +1,25 @@
-module.exports = {
-  version: 4,
+const version = 4
 
-  migrate: function (data) {
+module.exports = {
+  version,  
+
+  migrate: function (versionedData) {
+    versionedData.meta.version = version
     try {
-      if (data.config.provider.type !== 'rpc') return data
-      switch (data.config.provider.rpcTarget) {
+      if (versionedData.data.config.provider.type !== 'rpc') return Promise.resolve(versionedData)
+      switch (versionedData.data.config.provider.rpcTarget) {
         case 'https://testrpc.metamask.io/':
-          data.config.provider = {
+          versionedData.data.config.provider = {
             type: 'testnet',
           }
           break
         case 'https://rpc.metamask.io/':
-          data.config.provider = {
+          versionedData.data.config.provider = {
             type: 'mainnet',
           }
           break
       }
     } catch (_) {}
-    return data
+    return Promise.resolve(versionedData)
   },
 }
diff --git a/app/scripts/migrations/_multi-keyring.js b/app/scripts/migrations/_multi-keyring.js
new file mode 100644
index 000000000..04c966d4d
--- /dev/null
+++ b/app/scripts/migrations/_multi-keyring.js
@@ -0,0 +1,51 @@
+const version = 5
+
+/*
+
+This is an incomplete migration bc it requires post-decrypted data
+which we dont have access to at the time of this writing.
+
+*/
+
+const ObservableStore = require('obs-store')
+const ConfigManager = require('../../app/scripts/lib/config-manager')
+const IdentityStoreMigrator = require('../../app/scripts/lib/idStore-migrator')
+const KeyringController = require('../../app/scripts/lib/keyring-controller')
+
+const password = 'obviously not correct'
+
+module.exports = {
+  version,  
+
+  migrate: function (versionedData) {
+    versionedData.meta.version = version
+
+    let store = new ObservableStore(versionedData.data)
+    let configManager = new ConfigManager({ store })
+    let idStoreMigrator = new IdentityStoreMigrator({ configManager })
+    let keyringController = new KeyringController({
+      configManager: configManager,
+    })
+
+    // attempt to migrate to multiVault
+    return idStoreMigrator.migratedVaultForPassword(password)
+    .then((result) => {
+      // skip if nothing to migrate
+      if (!result) return Promise.resolve(versionedData)
+      delete versionedData.data.wallet
+      // create new keyrings
+      const privKeys = result.lostAccounts.map(acct => acct.privateKey)
+      return Promise.all([
+        keyringController.restoreKeyring(result.serialized),
+        keyringController.restoreKeyring({ type: 'Simple Key Pair', data: privKeys }),
+      ]).then(() => {
+        return keyringController.persistAllKeyrings(password)
+      }).then(() => {
+        // copy result on to state object
+        versionedData.data = store.get()
+        return Promise.resolve(versionedData)
+      })
+    })
+
+  },
+}
diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js
new file mode 100644
index 000000000..d2ac221b9
--- /dev/null
+++ b/app/scripts/migrations/index.js
@@ -0,0 +1,18 @@
+/* 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('./002'),
+  require('./003'),
+  require('./004'),
+]
diff --git a/mock-dev.js b/mock-dev.js
index 283bc2c79..bd3a1ad77 100644
--- a/mock-dev.js
+++ b/mock-dev.js
@@ -15,97 +15,71 @@
 const extend = require('xtend')
 const render = require('react-dom').render
 const h = require('react-hyperscript')
+const pipe = require('mississippi').pipe
+const LocalStorageStore = require('obs-store/lib/localStorage')
 const Root = require('./ui/app/root')
 const configureStore = require('./ui/app/store')
 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 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.getState()) {
+  dataStore.putState(firstTimeState)
+}
+
 const controller = new MetamaskController({
   // User confirmation callbacks:
   showUnconfirmedMessage: noop,
   unlockAccountMessage: noop,
   showUnapprovedTx: noop,
-  // Persistence Methods:
-  setData,
-  loadData,
+  // initial state
+  initState: dataStore.getState(),
 })
 
-// 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) {}
+// setup state persistence
+pipe(
+  controller.store,
+  dataStore
+)
 
-  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) {
diff --git a/package.json b/package.json
index 569cab2a0..67bd3b209 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
   },
   "dependencies": {
     "async": "^1.5.2",
+    "async-q": "^0.3.1",
     "bip39": "^2.2.0",
     "browser-passworder": "^2.0.3",
     "browserify-derequire": "^0.9.4",
@@ -69,6 +70,7 @@
     "mississippi": "^1.2.0",
     "mkdirp": "^0.5.1",
     "multiplex": "^6.7.0",
+    "obs-store": "^2.2.3",
     "once": "^1.3.3",
     "ping-pong-stream": "^1.0.0",
     "pojo-migrator": "^2.1.0",
@@ -76,6 +78,7 @@
     "post-message-stream": "^1.0.0",
     "promise-filter": "^1.1.0",
     "promise-to-callback": "^1.0.0",
+    "pump": "^1.0.2",
     "pumpify": "^1.3.4",
     "qrcode-npm": "0.0.3",
     "react": "^15.0.2",
diff --git a/test/integration/lib/idStore-migrator-test.js b/test/integration/lib/idStore-migrator-test.js
index 4ae30411d..f2a437a7c 100644
--- a/test/integration/lib/idStore-migrator-test.js
+++ b/test/integration/lib/idStore-migrator-test.js
@@ -1,30 +1,23 @@
-var ConfigManager = require('../../../app/scripts/lib/config-manager')
-var IdStoreMigrator = require('../../../app/scripts/lib/idStore-migrator')
-var SimpleKeyring = require('../../../app/scripts/keyrings/simple')
-var normalize = require('../../../app/scripts/lib/sig-util').normalize
+const ObservableStore = require('obs-store')
+const ConfigManager = require('../../../app/scripts/lib/config-manager')
+const IdStoreMigrator = require('../../../app/scripts/lib/idStore-migrator')
+const SimpleKeyring = require('../../../app/scripts/keyrings/simple')
+const normalize = require('../../../app/scripts/lib/sig-util').normalize
 
-var oldStyleVault = require('../mocks/oldVault.json')
-var badStyleVault = require('../mocks/badVault.json')
+const oldStyleVault = require('../mocks/oldVault.json').data
+const badStyleVault = require('../mocks/badVault.json').data
 
-var STORAGE_KEY = 'metamask-config'
-var PASSWORD = '12345678'
-var FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase()
-var SEED = 'fringe damage bounce extend tunnel afraid alert sound all soldier all dinner'
-
-var BAD_STYLE_FIRST_ADDRESS = '0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9'
+const PASSWORD = '12345678'
+const FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase()
+const BAD_STYLE_FIRST_ADDRESS = '0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9'
+const SEED = 'fringe damage bounce extend tunnel afraid alert sound all soldier all dinner'
 
 QUnit.module('Old Style Vaults', {
   beforeEach: function () {
-    window.localStorage[STORAGE_KEY] = JSON.stringify(oldStyleVault)
-
-    this.configManager = new ConfigManager({
-      loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
-      setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
-    })
-
-    this.migrator = new IdStoreMigrator({
-      configManager: this.configManager,
-    })
+    let managers = managersFromInitState(oldStyleVault)
+    
+    this.configManager = managers.configManager
+    this.migrator = managers.migrator
   }
 })
 
@@ -37,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')
@@ -46,16 +40,10 @@ QUnit.test('migrator:migratedVaultForPassword', function (assert) {
 
 QUnit.module('Old Style Vaults with bad HD seed', {
   beforeEach: function () {
-    window.localStorage[STORAGE_KEY] = JSON.stringify(badStyleVault)
-
-    this.configManager = new ConfigManager({
-      loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) },
-      setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) },
-    })
-
-    this.migrator = new IdStoreMigrator({
-      configManager: this.configManager,
-    })
+    let managers = managersFromInitState(badStyleVault)
+    
+    this.configManager = managers.configManager
+    this.migrator = managers.migrator
   }
 })
 
@@ -64,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')
@@ -89,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 }
+}
\ No newline at end of file
diff --git a/test/lib/mock-config-manager.js b/test/lib/mock-config-manager.js
index b79f63090..72be86ed1 100644
--- a/test/lib/mock-config-manager.js
+++ b/test/lib/mock-config-manager.js
@@ -1,58 +1,10 @@
-var ConfigManager = require('../../app/scripts/lib/config-manager')
+const ObservableStore = require('obs-store')
+const clone = require('clone')
+const ConfigManager = require('../../app/scripts/lib/config-manager')
+const firstTimeState = require('../../app/scripts/first-time-state')
 const STORAGE_KEY = 'metamask-config'
-const extend = require('xtend')
 
 module.exports = function() {
-  return new ConfigManager({ loadData, setData })
-}
-
-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 store = new ObservableStore(clone(firstTimeState))
+  return new ConfigManager({ store })
+}
\ No newline at end of file
diff --git a/test/unit/config-manager-test.js b/test/unit/config-manager-test.js
index 77d431d5f..fa3929599 100644
--- a/test/unit/config-manager-test.js
+++ b/test/unit/config-manager-test.js
@@ -1,24 +1,23 @@
 // polyfill fetch
 global.fetch = global.fetch || require('isomorphic-fetch')
+
 const assert = require('assert')
 const extend = require('xtend')
 const rp = require('request-promise')
 const nock = require('nock')
 const configManagerGen = require('../lib/mock-config-manager')
-const STORAGE_KEY = 'metamask-persistance-key'
 
 describe('config-manager', function() {
   var configManager
 
   beforeEach(function() {
-    window.localStorage = {} // Hacking localStorage support into JSDom
     configManager = configManagerGen()
   })
 
   describe('currency conversions', function() {
 
     describe('#getCurrentFiat', function() {
-      it('should return false if no previous key exists', function() {
+      it('should return undefined if no previous key exists', function() {
         var result = configManager.getCurrentFiat()
         assert.ok(!result)
       })
@@ -26,14 +25,14 @@ describe('config-manager', function() {
 
     describe('#setCurrentFiat', function() {
       it('should make getCurrentFiat return true once set', function() {
-        assert.equal(configManager.getCurrentFiat(), false)
+        assert.equal(configManager.getCurrentFiat(), undefined)
         configManager.setCurrentFiat('USD')
         var result = configManager.getCurrentFiat()
         assert.equal(result, 'USD')
       })
 
       it('should work with other currencies as well', function() {
-        assert.equal(configManager.getCurrentFiat(), false)
+        assert.equal(configManager.getCurrentFiat(), undefined)
         configManager.setCurrentFiat('JPY')
         var result = configManager.getCurrentFiat()
         assert.equal(result, 'JPY')
@@ -41,7 +40,7 @@ describe('config-manager', function() {
     })
 
     describe('#getConversionRate', function() {
-      it('should return false if non-existent', function() {
+      it('should return undefined if non-existent', function() {
         var result = configManager.getConversionRate()
         assert.ok(!result)
       })
@@ -54,7 +53,7 @@ describe('config-manager', function() {
           .get('/api/ticker/eth-USD')
           .reply(200, '{"ticker":{"base":"ETH","target":"USD","price":"11.02456145","volume":"44948.91745289","change":"-0.01472534"},"timestamp":1472072136,"success":true,"error":""}')
 
-        assert.equal(configManager.getConversionRate(), false)
+        assert.equal(configManager.getConversionRate(), 0)
         var promise = new Promise(
           function (resolve, reject) {
             configManager.setCurrentFiat('USD')
@@ -75,7 +74,7 @@ describe('config-manager', function() {
 
       it('should work for JPY as well.', function() {
         this.timeout(15000)
-        assert.equal(configManager.getConversionRate(), false)
+        assert.equal(configManager.getConversionRate(), 0)
 
         var jpyMock = nock('https://www.cryptonator.com')
           .get('/api/ticker/eth-JPY')
@@ -103,7 +102,7 @@ describe('config-manager', function() {
   describe('confirmation', function() {
 
     describe('#getConfirmedDisclaimer', function() {
-      it('should return false if no previous key exists', function() {
+      it('should return undefined if no previous key exists', function() {
         var result = configManager.getConfirmedDisclaimer()
         assert.ok(!result)
       })
@@ -111,16 +110,16 @@ describe('config-manager', function() {
 
     describe('#setConfirmedDisclaimer', function() {
       it('should make getConfirmedDisclaimer return true once set', function() {
-        assert.equal(configManager.getConfirmedDisclaimer(), false)
+        assert.equal(configManager.getConfirmedDisclaimer(), undefined)
         configManager.setConfirmedDisclaimer(true)
         var result = configManager.getConfirmedDisclaimer()
         assert.equal(result, true)
       })
 
-      it('should be able to set false', function() {
-        configManager.setConfirmedDisclaimer(false)
+      it('should be able to set undefined', function() {
+        configManager.setConfirmedDisclaimer(undefined)
         var result = configManager.getConfirmedDisclaimer()
-        assert.equal(result, false)
+        assert.equal(result, undefined)
       })
 
       it('should persist to local storage', function() {
@@ -132,7 +131,6 @@ describe('config-manager', function() {
   })
 
   describe('#setConfig', function() {
-    window.localStorage = {} // Hacking localStorage support into JSDom
 
     it('should set the config key', function () {
       var testConfig = {
diff --git a/test/unit/idStore-migration-test.js b/test/unit/idStore-migration-test.js
index 54f38fb2f..38667fc3e 100644
--- a/test/unit/idStore-migration-test.js
+++ b/test/unit/idStore-migration-test.js
@@ -1,5 +1,6 @@
 const async = require('async')
 const assert = require('assert')
+const ObservableStore = require('obs-store')
 const ethUtil = require('ethereumjs-util')
 const BN = ethUtil.BN
 const ConfigManager = require('../../app/scripts/lib/config-manager')
@@ -42,10 +43,9 @@ describe('IdentityStore to KeyringController migration', function() {
   beforeEach(function(done) {
     this.sinon = sinon.sandbox.create()
     window.localStorage = {} // Hacking localStorage support into JSDom
-    configManager = new ConfigManager({
-      loadData,
-      setData: (d) => { window.localStorage = d }
-    })
+    let store = new ObservableStore(loadData())
+    store.subscribe(setData)
+    configManager = new ConfigManager({ store })
 
 
     idStore = new IdentityStore({
diff --git a/test/unit/metamask-controller-test.js b/test/unit/metamask-controller-test.js
index a6164c9a0..24d9ddd67 100644
--- a/test/unit/metamask-controller-test.js
+++ b/test/unit/metamask-controller-test.js
@@ -10,9 +10,11 @@ describe('MetaMaskController', function() {
     showUnconfirmedMessage: noop,
     unlockAccountMessage: noop,
     showUnapprovedTx: noop,
-    setData,
-    loadData,
+    // initial state
+    initState: loadData(),
   })
+  // setup state persistence
+  controller.store.subscribe(setData)
 
   beforeEach(function() {
     // sinon allows stubbing methods that are easily verified
diff --git a/test/unit/migrations-test.js b/test/unit/migrations-test.js
index 9ea8d5c5a..715a5feb0 100644
--- a/test/unit/migrations-test.js
+++ b/test/unit/migrations-test.js
@@ -1,34 +1,34 @@
-var assert = require('assert')
-var path = require('path')
+const assert = require('assert')
+const path = require('path')
 
-var wallet1 = require(path.join('..', 'lib', 'migrations', '001.json'))
+const wallet1 = require(path.join('..', 'lib', 'migrations', '001.json'))
 
-var migration2 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '002'))
-var migration3 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '003'))
-var migration4 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '004'))
+const migration2 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '002'))
+const migration3 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '003'))
+const migration4 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '004'))
+
+const oldTestRpc = 'https://rawtestrpc.metamask.io/'
+const newTestRpc = 'https://testrpc.metamask.io/'
 
 describe('wallet1 is migrated successfully', function() {
-
-  it('should convert providers', function(done) {
+  it('should convert providers', function() {
 
     wallet1.data.config.provider = { type: 'etherscan', rpcTarget: null }
 
-    var firstResult = migration2.migrate(wallet1.data)
-    assert.equal(firstResult.config.provider.type, 'rpc', 'provider should be rpc')
-    assert.equal(firstResult.config.provider.rpcTarget, 'https://rpc.metamask.io/', 'main provider should be our rpc')
-
-    var oldTestRpc = 'https://rawtestrpc.metamask.io/'
-    var newTestRpc = 'https://testrpc.metamask.io/'
-    firstResult.config.provider.rpcTarget = oldTestRpc
-
-    var secondResult = migration3.migrate(firstResult)
-    assert.equal(secondResult.config.provider.rpcTarget, newTestRpc)
-
-    var thirdResult = migration4.migrate(secondResult)
-    assert.equal(secondResult.config.provider.rpcTarget, null)
-    assert.equal(secondResult.config.provider.type, 'testnet')
-
-    done()
+    return migration2.migrate(wallet1)
+    .then((firstResult) => {
+      assert.equal(firstResult.data.config.provider.type, 'rpc', 'provider should be rpc')
+      assert.equal(firstResult.data.config.provider.rpcTarget, 'https://rpc.metamask.io/', 'main provider should be our rpc')
+      firstResult.data.config.provider.rpcTarget = oldTestRpc
+      return migration3.migrate(firstResult)
+    }).then((secondResult) => {
+      assert.equal(secondResult.data.config.provider.rpcTarget, newTestRpc)
+      return migration4.migrate(secondResult)
+    }).then((thirdResult) => {
+      assert.equal(thirdResult.data.config.provider.rpcTarget, null)
+      assert.equal(thirdResult.data.config.provider.type, 'testnet')
+    })
+    
   })
 })