aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts/lib')
-rw-r--r--app/scripts/lib/config-manager.js10
-rw-r--r--app/scripts/lib/inpage-provider.js18
-rw-r--r--app/scripts/lib/observable/host.js50
-rw-r--r--app/scripts/lib/observable/index.js33
-rw-r--r--app/scripts/lib/observable/remote.js51
-rw-r--r--app/scripts/lib/observable/util/transform.js13
-rw-r--r--app/scripts/lib/remote-store.js97
7 files changed, 163 insertions, 109 deletions
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index 3a1f12ac0..01e6ccc3c 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -19,6 +19,7 @@ module.exports = ConfigManager
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:
@@ -36,12 +37,9 @@ function ConfigManager (opts) {
// 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,
+ // Data persistence methods
+ loadData: () => this.store.get(),
+ setData: (value) => this.store.put(value),
})
}
diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js
index 11bd5cc3a..64301be78 100644
--- a/app/scripts/lib/inpage-provider.js
+++ b/app/scripts/lib/inpage-provider.js
@@ -1,7 +1,7 @@
const Streams = require('mississippi')
const StreamProvider = require('web3-stream-provider')
const ObjectMultiplex = require('./obj-multiplex')
-const RemoteStore = require('./remote-store.js').RemoteStore
+const RemoteStore = require('./observable/remote')
const createRandomId = require('./random-id')
module.exports = MetamaskInpageProvider
@@ -72,13 +72,13 @@ MetamaskInpageProvider.prototype.send = function (payload) {
case 'eth_accounts':
// read from localStorage
- selectedAccount = self.publicConfigStore.get('selectedAccount')
+ selectedAccount = self.publicConfigStore.get().selectedAccount
result = selectedAccount ? [selectedAccount] : []
break
case 'eth_coinbase':
// read from localStorage
- selectedAccount = self.publicConfigStore.get('selectedAccount')
+ selectedAccount = self.publicConfigStore.get().selectedAccount
result = selectedAccount || '0x0000000000000000000000000000000000000000'
break
@@ -117,9 +117,15 @@ MetamaskInpageProvider.prototype.isMetaMask = true
function remoteStoreWithLocalStorageCache (storageKey) {
// read local cache
- var initState = JSON.parse(localStorage[storageKey] || '{}')
- var store = new RemoteStore(initState)
- // cache the latest state locally
+ let initState
+ try {
+ initState = JSON.parse(localStorage[storageKey] || '{}')
+ } catch (err) {
+ initState = {}
+ }
+ // intialize store
+ const store = new RemoteStore(initState)
+ // write local cache
store.subscribe(function (state) {
localStorage[storageKey] = JSON.stringify(state)
})
diff --git a/app/scripts/lib/observable/host.js b/app/scripts/lib/observable/host.js
new file mode 100644
index 000000000..69f674be8
--- /dev/null
+++ b/app/scripts/lib/observable/host.js
@@ -0,0 +1,50 @@
+const Dnode = require('dnode')
+const ObservableStore = require('./index')
+const endOfStream = require('end-of-stream')
+
+//
+// HostStore
+//
+// plays host to many RemoteStores and sends its state over a stream
+//
+
+class HostStore extends ObservableStore {
+
+ constructor (initState, opts) {
+ super(initState)
+ this.opts = opts || {}
+ }
+
+ createStream () {
+ const self = this
+ // setup remotely exposed api
+ let remoteApi = {}
+ if (!self.opts.readOnly) {
+ remoteApi.put = (newState) => self.put(newState)
+ }
+ // listen for connection to remote
+ const dnode = Dnode(remoteApi)
+ dnode.on('remote', (remote) => {
+ // setup update subscription lifecycle
+ const updateHandler = (state) => remote.put(state)
+ self._onConnect(updateHandler)
+ endOfStream(dnode, () => self._onDisconnect(updateHandler))
+ })
+ return dnode
+ }
+
+ _onConnect (updateHandler) {
+ // subscribe to updates
+ this.subscribe(updateHandler)
+ // send state immediately
+ updateHandler(this.get())
+ }
+
+ _onDisconnect (updateHandler) {
+ // unsubscribe to updates
+ this.unsubscribe(updateHandler)
+ }
+
+}
+
+module.exports = HostStore
diff --git a/app/scripts/lib/observable/index.js b/app/scripts/lib/observable/index.js
new file mode 100644
index 000000000..d193e5554
--- /dev/null
+++ b/app/scripts/lib/observable/index.js
@@ -0,0 +1,33 @@
+const EventEmitter = require('events').EventEmitter
+
+class ObservableStore extends EventEmitter {
+
+ constructor (initialState) {
+ super()
+ this._state = initialState
+ }
+
+ get () {
+ return this._state
+ }
+
+ put (newState) {
+ this._put(newState)
+ }
+
+ subscribe (handler) {
+ this.on('update', handler)
+ }
+
+ unsubscribe (handler) {
+ this.removeListener('update', handler)
+ }
+
+ _put (newState) {
+ this._state = newState
+ this.emit('update', newState)
+ }
+
+}
+
+module.exports = ObservableStore
diff --git a/app/scripts/lib/observable/remote.js b/app/scripts/lib/observable/remote.js
new file mode 100644
index 000000000..b5a3254a2
--- /dev/null
+++ b/app/scripts/lib/observable/remote.js
@@ -0,0 +1,51 @@
+const Dnode = require('dnode')
+const ObservableStore = require('./index')
+const endOfStream = require('end-of-stream')
+
+//
+// RemoteStore
+//
+// connects to a HostStore and receives its latest state
+//
+
+class RemoteStore extends ObservableStore {
+
+ constructor (initState, opts) {
+ super(initState)
+ this.opts = opts || {}
+ this._remote = null
+ }
+
+ put (newState) {
+ if (!this._remote) throw new Error('RemoteStore - "put" called before connection to HostStore')
+ this._put(newState)
+ this._remote.put(newState)
+ }
+
+ createStream () {
+ const self = this
+ const dnode = Dnode({
+ put: (newState) => self._put(newState),
+ })
+ // listen for connection to remote
+ dnode.once('remote', (remote) => {
+ // setup connection lifecycle
+ self._onConnect(remote)
+ endOfStream(dnode, () => self._onDisconnect())
+ })
+ return dnode
+ }
+
+ _onConnect (remote) {
+ this._remote = remote
+ this.emit('connected')
+ }
+
+ _onDisconnect () {
+ this._remote = null
+ this.emit('disconnected')
+ }
+
+}
+
+module.exports = RemoteStore \ No newline at end of file
diff --git a/app/scripts/lib/observable/util/transform.js b/app/scripts/lib/observable/util/transform.js
new file mode 100644
index 000000000..87946f402
--- /dev/null
+++ b/app/scripts/lib/observable/util/transform.js
@@ -0,0 +1,13 @@
+
+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
+} \ No newline at end of file
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)
-}