Merge pull request #999 from MetaMask/obs-store2
background - introduce ObservableStore (mark II)feature/default_network_editable
commit
d30612a216
@ -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, |
||||
}) |
||||
|
||||
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
|
||||
//
|
||||
let popupIsOpen = false |
||||
|
||||
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')) |
||||
} |
||||
// state persistence
|
||||
const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) |
||||
|
||||
function setupTrustedCommunication (connectionStream, originDomain) { |
||||
// setup multiplexing
|
||||
var mx = setupMultiplex(connectionStream) |
||||
// connect features
|
||||
setupControllerConnection(mx.createStream('controller')) |
||||
controller.setupProviderConnection(mx.createStream('provider'), originDomain) |
||||
} |
||||
// initialization flow
|
||||
asyncQ.waterfall([ |
||||
() => loadStateFromPersistence(), |
||||
(initState) => setupController(initState), |
||||
]) |
||||
.then(() => console.log('MetaMask initialization complete.')) |
||||
.catch((err) => { console.error(err) }) |
||||
|
||||
//
|
||||
// remote features
|
||||
// State and Persistence
|
||||
//
|
||||
|
||||
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 |
||||
}) |
||||
}) |
||||
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), |
||||
]) |
||||
} |
||||
|
||||
//
|
||||
// plugin badge text
|
||||
//
|
||||
function setupController (initState) { |
||||
|
||||
//
|
||||
// MetaMask Controller
|
||||
//
|
||||
|
||||
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) |
||||
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 |
||||
} |
||||
extension.browserAction.setBadgeText({ text: label }) |
||||
extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' }) |
||||
} |
||||
|
||||
// data :: setters/getters
|
||||
//
|
||||
// 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 loadData () { |
||||
var oldData = getOldStyleData() |
||||
var newData |
||||
try { |
||||
newData = JSON.parse(window.localStorage[STORAGE_KEY]) |
||||
} catch (e) {} |
||||
function setupUntrustedCommunication (connectionStream, originDomain) { |
||||
// setup multiplexing
|
||||
var mx = setupMultiplex(connectionStream) |
||||
// connect features
|
||||
controller.setupProviderConnection(mx.createStream('provider'), originDomain) |
||||
controller.setupPublicConfig(mx.createStream('publicConfig')) |
||||
} |
||||
|
||||
var data = extend({ |
||||
meta: { |
||||
version: 0, |
||||
}, |
||||
data: { |
||||
config: { |
||||
provider: { |
||||
type: 'testnet', |
||||
}, |
||||
}, |
||||
}, |
||||
}, oldData || null, newData || null) |
||||
return data |
||||
} |
||||
function setupTrustedCommunication (connectionStream, originDomain) { |
||||
// setup multiplexing
|
||||
var mx = setupMultiplex(connectionStream) |
||||
// connect features
|
||||
setupControllerConnection(mx.createStream('controller')) |
||||
controller.setupProviderConnection(mx.createStream('provider'), originDomain) |
||||
} |
||||
|
||||
function getOldStyleData () { |
||||
var config, wallet, seedWords |
||||
//
|
||||
// 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 |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
var result = { |
||||
meta: { version: 0 }, |
||||
data: {}, |
||||
//
|
||||
// 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' }) |
||||
} |
||||
|
||||
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 |
||||
return Promise.resolve() |
||||
|
||||
} |
||||
|
||||
function setData (data) { |
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(data) |
||||
//
|
||||
// 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'}) |
||||
} |
||||
}) |
@ -0,0 +1,11 @@ |
||||
//
|
||||
// The default state of MetaMask
|
||||
//
|
||||
|
||||
module.exports = { |
||||
config: { |
||||
provider: { |
||||
type: 'testnet', |
||||
}, |
||||
}, |
||||
} |
@ -1,5 +0,0 @@ |
||||
module.exports = [ |
||||
require('../migrations/002'), |
||||
require('../migrations/003'), |
||||
require('../migrations/004'), |
||||
] |
@ -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 |
@ -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) |
||||
} |
@ -1,13 +1,16 @@ |
||||
const version = 2 |
||||
|
||||
module.exports = { |
||||
version: 2, |
||||
version, |
||||
|
||||
migrate: function (data) { |
||||
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) |
||||
}, |
||||
} |
||||
|
@ -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) |
||||
}, |
||||
} |
||||
|
@ -1,22 +1,25 @@ |
||||
const version = 4 |
||||
|
||||
module.exports = { |
||||
version: 4, |
||||
version,
|
||||
|
||||
migrate: function (data) { |
||||
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) |
||||
}, |
||||
} |
||||
|
@ -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) |
||||
}) |
||||
}) |
||||
|
||||
}, |
||||
} |
@ -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'), |
||||
] |
@ -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 }) |
||||
} |
@ -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')) |
||||
|
||||
describe('wallet1 is migrated successfully', function() { |
||||
const oldTestRpc = 'https://rawtestrpc.metamask.io/' |
||||
const newTestRpc = 'https://testrpc.metamask.io/' |
||||
|
||||
it('should convert providers', function(done) { |
||||
describe('wallet1 is migrated successfully', function() { |
||||
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') |
||||
}) |
||||
|
||||
}) |
||||
}) |
||||
|
||||
|
Loading…
Reference in new issue