1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Add migration on 3box imports and remove feature flag (#7209)

* Delete unused code

* Run threebox imports through migrations

* Remove 3box feature flag

* Remove unnecessary use of 'type' in threebox._updatePlugin

* Fix threebox controller getLastUpdated

* Turn off threebox by default

* Rename restoredFromThreeBox to showRestorePrompt

* Remove accientally added method from threebox controller

* Restore from threebox on import from unlock screen

* Throw on non 404 errors from Box.getconfig in new3Box
This commit is contained in:
Dan J Miller 2019-09-26 03:24:52 -04:00 committed by GitHub
parent e1efb4d7ac
commit 970e90ea70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 192 additions and 191 deletions

View File

@ -42,7 +42,6 @@ class PreferencesController {
// perform sensitive operations.
featureFlags: {
showIncomingTransactions: true,
threeBox: false,
},
knownMethodData: {},
participateInMetaMetrics: null,

View File

@ -2,9 +2,9 @@ const ObservableStore = require('obs-store')
const Box = process.env.IN_TEST
? require('../../../development/mock-3box')
: require('3box')
// const Box = require(process.env.IN_TEST ? '../lib/mock-3box' : '3box/dist/3box.min')
const log = require('loglevel')
const migrations = require('../migrations/')
const Migrator = require('../lib/migrator')
const JsonRpcEngine = require('json-rpc-engine')
const providerFromEngine = require('eth-json-rpc-middleware/providerFromEngine')
const createMetamaskMiddleware = require('./network/createMetamaskMiddleware')
@ -48,8 +48,9 @@ class ThreeBoxController {
})
const initState = {
threeBoxSyncingAllowed: true,
restoredFromThreeBox: null,
threeBoxSyncingAllowed: false,
showRestorePrompt: true,
threeBoxLastUpdated: 0,
...opts.initState,
threeBoxAddress: null,
threeBoxSynced: false,
@ -57,10 +58,9 @@ class ThreeBoxController {
}
this.store = new ObservableStore(initState)
this.registeringUpdates = false
this.lastMigration = migrations.sort((a, b) => a.version - b.version).slice(-1)[0]
const threeBoxFeatureFlagTurnedOn = this.preferencesController.getFeatureFlags().threeBox
if (threeBoxFeatureFlagTurnedOn) {
if (initState.threeBoxSyncingAllowed) {
this.init()
}
}
@ -73,12 +73,19 @@ class ThreeBoxController {
}
}
async _update3Box ({ type }, newState) {
async _update3Box () {
try {
const { threeBoxSyncingAllowed, threeBoxSynced } = this.store.getState()
if (threeBoxSyncingAllowed && threeBoxSynced) {
await this.space.private.set('lastUpdated', Date.now())
await this.space.private.set(type, JSON.stringify(newState))
const newState = {
preferences: this.preferencesController.store.getState(),
addressBook: this.addressBookController.state,
lastUpdated: Date.now(),
lastMigration: this.lastMigration,
}
await this.space.private.set('metamaskBackup', JSON.stringify(newState))
await this.setShowRestorePromptToFalse()
}
} catch (error) {
console.error(error)
@ -105,11 +112,20 @@ class ThreeBoxController {
async new3Box () {
const accounts = await this.keyringController.getAccounts()
const address = accounts[0]
if (this.getThreeBoxSyncingState()) {
this.address = await this.keyringController.getAppKeyAddress(accounts[0], 'wallet://3box.metamask.io')
let backupExists
try {
const threeBoxConfig = await Box.getConfig(this.address)
backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask
} catch (e) {
if (e.message.match(/^Error: Invalid response (404)/)) {
backupExists = false
} else {
throw e
}
}
if (this.getThreeBoxSyncingState() || backupExists) {
this.store.updateState({ threeBoxSynced: false })
this.address = await this.keyringController.getAppKeyAddress(address, 'wallet://3box.metamask.io')
let timedOut = false
const syncTimeout = setTimeout(() => {
@ -121,13 +137,13 @@ class ThreeBoxController {
})
}, SYNC_TIMEOUT)
try {
this.box = await Box.openBox(address, this.provider)
this.box = await Box.openBox(this.address, this.provider)
await this._waitForOnSyncDone()
this.space = await this.box.openSpace('metamask', {
onSyncDone: async () => {
const stateUpdate = {
threeBoxSynced: true,
threeBoxAddress: address,
threeBoxAddress: this.address,
}
if (timedOut) {
log.info(`3Box sync completed after timeout; no longer disabled`)
@ -136,6 +152,7 @@ class ThreeBoxController {
clearTimeout(syncTimeout)
this.store.updateState(stateUpdate)
log.debug('3Box space sync done')
},
})
@ -147,15 +164,36 @@ class ThreeBoxController {
}
async getLastUpdated () {
return await this.space.private.get('lastUpdated')
const res = await this.space.private.get('metamaskBackup')
const parsedRes = JSON.parse(res || '{}')
return parsedRes.lastUpdated
}
async migrateBackedUpState (backedUpState) {
const migrator = new Migrator({ migrations })
const formattedStateBackup = {
PreferencesController: backedUpState.preferences,
AddressBookController: backedUpState.addressBook,
}
const initialMigrationState = migrator.generateInitialState(formattedStateBackup)
const migratedState = await migrator.migrateData(initialMigrationState)
return {
preferences: migratedState.PreferencesController,
addressBook: migratedState.AddressBookController,
}
}
async restoreFromThreeBox () {
this.setRestoredFromThreeBoxToTrue()
const backedUpPreferences = await this.space.private.get('preferences')
backedUpPreferences && this.preferencesController.store.updateState(JSON.parse(backedUpPreferences))
const backedUpAddressBook = await this.space.private.get('addressBook')
backedUpAddressBook && this.addressBookController.update(JSON.parse(backedUpAddressBook), true)
const backedUpState = await this.space.private.get('metamaskBackup')
const {
preferences,
addressBook,
} = await this.migrateBackedUpState(backedUpState)
this.store.updateState({ threeBoxLastUpdated: backedUpState.lastUpdated })
preferences && this.preferencesController.store.updateState(JSON.parse(preferences))
addressBook && this.addressBookController.update(JSON.parse(addressBook), true)
this.setShowRestorePromptToFalse()
}
turnThreeBoxSyncingOn () {
@ -166,12 +204,8 @@ class ThreeBoxController {
this.box.logout()
}
setRestoredFromThreeBoxToTrue () {
this.store.updateState({ restoredFromThreeBox: true })
}
setRestoredFromThreeBoxToFalse () {
this.store.updateState({ restoredFromThreeBox: false })
setShowRestorePromptToFalse () {
this.store.updateState({ showRestorePrompt: false })
}
setThreeBoxSyncingPermission (newThreeboxSyncingState) {
@ -201,9 +235,9 @@ class ThreeBoxController {
_registerUpdates () {
if (!this.registeringUpdates) {
const updatePreferences = this._update3Box.bind(this, { type: 'preferences' })
const updatePreferences = this._update3Box.bind(this)
this.preferencesController.store.subscribe(updatePreferences)
const updateAddressBook = this._update3Box.bind(this, { type: 'addressBook' })
const updateAddressBook = this._update3Box.bind(this)
this.addressBookController.subscribe(updateAddressBook)
this.registeringUpdates = true
}

View File

@ -543,7 +543,7 @@ module.exports = class MetamaskController extends EventEmitter {
// 3Box
setThreeBoxSyncingPermission: nodeify(threeBoxController.setThreeBoxSyncingPermission, threeBoxController),
restoreFromThreeBox: nodeify(threeBoxController.restoreFromThreeBox, threeBoxController),
setRestoredFromThreeBoxToFalse: nodeify(threeBoxController.setRestoredFromThreeBoxToFalse, threeBoxController),
setShowRestorePromptToFalse: nodeify(threeBoxController.setShowRestorePromptToFalse, threeBoxController),
getThreeBoxLastUpdated: nodeify(threeBoxController.getLastUpdated, threeBoxController),
turnThreeBoxSyncingOn: nodeify(threeBoxController.turnThreeBoxSyncingOn, threeBoxController),
initializeThreeBox: nodeify(this.initializeThreeBox, this),
@ -752,16 +752,12 @@ module.exports = class MetamaskController extends EventEmitter {
await this.preferencesController.syncAddresses(accounts)
await this.txController.pendingTxTracker.updatePendingTxs()
const threeBoxFeatureFlagTurnedOn = this.preferencesController.getFeatureFlags().threeBox
if (threeBoxFeatureFlagTurnedOn) {
const threeBoxSyncingAllowed = this.threeBoxController.getThreeBoxSyncingState()
if (threeBoxSyncingAllowed && !this.threeBoxController.box) {
await this.threeBoxController.new3Box()
this.threeBoxController.turnThreeBoxSyncingOn()
} else if (threeBoxSyncingAllowed && this.threeBoxController.box) {
this.threeBoxController.turnThreeBoxSyncingOn()
}
const threeBoxSyncingAllowed = this.threeBoxController.getThreeBoxSyncingState()
if (threeBoxSyncingAllowed && !this.threeBoxController.box) {
await this.threeBoxController.new3Box()
this.threeBoxController.turnThreeBoxSyncingOn()
} else if (threeBoxSyncingAllowed && this.threeBoxController.box) {
this.threeBoxController.turnThreeBoxSyncingOn()
}
return this.keyringController.fullUpdate()
@ -1714,7 +1710,7 @@ module.exports = class MetamaskController extends EventEmitter {
}
async initializeThreeBox () {
await this.threeBoxController.new3Box()
await this.threeBoxController.init()
}
/**

View File

@ -55,6 +55,13 @@ class Mock3Box {
logout: () => {},
})
}
static async getConfig (address) {
const backup = await loadFromMock3Box(`${address}-metamask-metamaskBackup`)
return backup
? { spaces: { metamask: {} } }
: {}
}
}
module.exports = Mock3Box

View File

@ -51,12 +51,6 @@ describe('MetaMask', function () {
describe('set up data to be restored by 3box', () => {
describe('First time flow starting from an existing seed phrase', () => {
it('turns on the threebox feature flag', async () => {
await delay(largeDelayMs)
await driver.executeScript('window.metamask.setFeatureFlag("threeBox", true)')
await delay(largeDelayMs)
})
it('clicks the continue button on the welcome screen', async () => {
await findElement(driver, By.css('.welcome-page__header'))
const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
@ -108,7 +102,7 @@ describe('MetaMask', function () {
})
})
describe('updates settings and address book', () => {
describe('turns on threebox syncing', () => {
it('goes to the settings screen', async () => {
await driver.findElement(By.css('.account-menu__icon')).click()
await delay(regularDelayMs)
@ -117,6 +111,23 @@ describe('MetaMask', function () {
settingsButton.click()
})
it('turns on threebox syncing', async () => {
const advancedButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Advanced')]`))
await advancedButton.click()
const threeBoxToggle = await findElements(driver, By.css('.toggle-button'))
const threeBoxToggleButton = await threeBoxToggle[3].findElement(By.css('div'))
await threeBoxToggleButton.click()
})
})
describe('updates settings and address book', () => {
it('adds an address to the contact list', async () => {
const generalButton = await findElement(driver, By.xpath(`//div[contains(text(), 'General')]`))
await generalButton.click()
})
it('turns on use of blockies', async () => {
const toggleButton = await findElement(driver, By.css('.toggle-button > div'))
await toggleButton.click()
@ -163,12 +174,6 @@ describe('MetaMask', function () {
})
describe('First time flow starting from an existing seed phrase', () => {
it('turns on the threebox feature flag', async () => {
await delay(largeDelayMs)
await driver2.executeScript('window.metamask.setFeatureFlag("threeBox", true)')
await delay(largeDelayMs)
})
it('clicks the continue button on the welcome screen', async () => {
await findElement(driver2, By.css('.welcome-page__header'))
const welcomeScreenBtn = await findElement(driver2, By.css('.first-time-flow__button'))

View File

@ -129,14 +129,7 @@ describe('MetaMaskController', function () {
})
})
it('gets does not instantiate 3box if the feature flag is false', async () => {
await metamaskController.submitPassword(password)
assert(threeBoxSpies.new3Box.notCalled)
assert(threeBoxSpies.turnThreeBoxSyncingOn.notCalled)
})
it('gets the address from threebox and creates a new 3box instance if the feature flag is true', async () => {
metamaskController.preferencesController.setFeatureFlag('threeBox', true)
it('gets the address from threebox and creates a new 3box instance', async () => {
await metamaskController.submitPassword(password)
assert(threeBoxSpies.new3Box.calledOnce)
assert(threeBoxSpies.turnThreeBoxSyncingOn.calledOnce)

View File

@ -38,12 +38,11 @@ export default class Home extends PureComponent {
threeBoxSynced: PropTypes.bool,
setupThreeBox: PropTypes.func,
turnThreeBoxSyncingOn: PropTypes.func,
restoredFromThreeBox: PropTypes.bool,
showRestorePrompt: PropTypes.bool,
selectedAddress: PropTypes.string,
restoreFromThreeBox: PropTypes.func,
setRestoredFromThreeBoxToFalse: PropTypes.func,
setShowRestorePromptToFalse: PropTypes.func,
threeBoxLastUpdated: PropTypes.string,
threeBoxFeatureFlagIsTrue: PropTypes.bool,
}
componentWillMount () {
@ -73,10 +72,10 @@ export default class Home extends PureComponent {
const {
threeBoxSynced,
setupThreeBox,
restoredFromThreeBox,
showRestorePrompt,
threeBoxLastUpdated,
} = this.props
if (threeBoxSynced && restoredFromThreeBox === null && threeBoxLastUpdated === null) {
if (threeBoxSynced && showRestorePrompt && threeBoxLastUpdated === null) {
setupThreeBox()
}
}
@ -94,10 +93,9 @@ export default class Home extends PureComponent {
selectedAddress,
restoreFromThreeBox,
turnThreeBoxSyncingOn,
setRestoredFromThreeBoxToFalse,
restoredFromThreeBox,
setShowRestorePromptToFalse,
showRestorePrompt,
threeBoxLastUpdated,
threeBoxFeatureFlagIsTrue,
} = this.props
if (forgottenPassword) {
@ -155,7 +153,7 @@ export default class Home extends PureComponent {
/>,
},
{
shouldBeRendered: threeBoxFeatureFlagIsTrue && threeBoxLastUpdated && restoredFromThreeBox === null,
shouldBeRendered: threeBoxLastUpdated && showRestorePrompt,
component: <HomeNotification
descriptionText={t('restoreWalletPreferences', [ formatDate(parseInt(threeBoxLastUpdated), 'M/d/y') ])}
acceptText={t('restore')}
@ -168,7 +166,7 @@ export default class Home extends PureComponent {
})
}}
onIgnore={() => {
setRestoredFromThreeBoxToFalse()
setShowRestorePromptToFalse()
}}
key="home-privacyModeDefault"
/>,

View File

@ -9,7 +9,7 @@ import {
restoreFromThreeBox,
turnThreeBoxSyncingOn,
getThreeBoxLastUpdated,
setRestoredFromThreeBoxToFalse,
setShowRestorePromptToFalse,
} from '../../store/actions'
import { setThreeBoxLastUpdated } from '../../ducks/app/app'
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
@ -24,9 +24,8 @@ const mapStateToProps = state => {
seedPhraseBackedUp,
tokens,
threeBoxSynced,
restoredFromThreeBox,
showRestorePrompt,
selectedAddress,
featureFlags,
} = metamask
const accountBalance = getCurrentEthBalance(state)
const { forgottenPassword, threeBoxLastUpdated } = appState
@ -42,10 +41,9 @@ const mapStateToProps = state => {
shouldShowSeedPhraseReminder: !seedPhraseBackedUp && (parseInt(accountBalance, 16) > 0 || tokens.length > 0),
isPopup,
threeBoxSynced,
restoredFromThreeBox,
showRestorePrompt,
selectedAddress,
threeBoxLastUpdated,
threeBoxFeatureFlagIsTrue: featureFlags.threeBox,
}
}
@ -58,13 +56,13 @@ const mapDispatchToProps = (dispatch) => ({
if (lastUpdated) {
dispatch(setThreeBoxLastUpdated(lastUpdated))
} else {
dispatch(setRestoredFromThreeBoxToFalse())
dispatch(setShowRestorePromptToFalse())
dispatch(turnThreeBoxSyncingOn())
}
})
},
restoreFromThreeBox: (address) => dispatch(restoreFromThreeBox(address)),
setRestoredFromThreeBoxToFalse: () => dispatch(setRestoredFromThreeBoxToFalse()),
setShowRestorePromptToFalse: () => dispatch(setShowRestorePromptToFalse()),
})
export default compose(

View File

@ -4,6 +4,7 @@ import {connect} from 'react-redux'
import {
createNewVaultAndRestore,
unMarkPasswordForgotten,
initializeThreeBox,
} from '../../store/actions'
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
import TextField from '../../components/ui/text-field'
@ -21,6 +22,7 @@ class RestoreVaultPage extends Component {
leaveImportSeedScreenState: PropTypes.func,
history: PropTypes.object,
isLoading: PropTypes.bool,
initializeThreeBox: PropTypes.func,
};
state = {
@ -81,6 +83,7 @@ class RestoreVaultPage extends Component {
createNewVaultAndRestore,
leaveImportSeedScreenState,
history,
initializeThreeBox,
} = this.props
leaveImportSeedScreenState()
@ -93,6 +96,7 @@ class RestoreVaultPage extends Component {
name: 'onboardingRestoredVault',
},
})
initializeThreeBox()
history.push(DEFAULT_ROUTE)
})
}
@ -194,5 +198,6 @@ export default connect(
dispatch(unMarkPasswordForgotten())
},
createNewVaultAndRestore: (pw, seed) => dispatch(createNewVaultAndRestore(pw, seed)),
initializeThreeBox: () => dispatch(initializeThreeBox()),
})
)(RestoreVaultPage)

View File

@ -30,7 +30,6 @@ export default class AdvancedTab extends PureComponent {
threeBoxSyncingAllowed: PropTypes.bool.isRequired,
setThreeBoxSyncingPermission: PropTypes.func.isRequired,
threeBoxDisabled: PropTypes.bool.isRequired,
threeBoxFeatureFlag: PropTypes.bool.isRequired,
}
state = { autoLogoutTimeLimit: this.props.autoLogoutTimeLimit }
@ -301,7 +300,7 @@ export default class AdvancedTab extends PureComponent {
}
renderContent () {
const { warning, threeBoxFeatureFlag } = this.props
const { warning } = this.props
return (
<div className="settings-page__body">
@ -313,7 +312,7 @@ export default class AdvancedTab extends PureComponent {
{ this.renderHexDataOptIn() }
{ this.renderShowConversionInTestnets() }
{ this.renderAutoLogoutTimeLimit() }
{ threeBoxFeatureFlag ? this.renderThreeBoxControl() : null }
{ this.renderThreeBoxControl() }
</div>
)
}

View File

@ -10,6 +10,7 @@ import {
setShowFiatConversionOnTestnetsPreference,
setAutoLogoutTimeLimit,
setThreeBoxSyncingPermission,
turnThreeBoxSyncingOnAndInitialize,
} from '../../../store/actions'
import {preferencesSelector} from '../../../selectors/selectors'
@ -19,7 +20,6 @@ export const mapStateToProps = state => {
featureFlags: {
sendHexData,
advancedInlineGas,
threeBox,
} = {},
threeBoxSyncingAllowed,
threeBoxDisabled,
@ -34,7 +34,6 @@ export const mapStateToProps = state => {
autoLogoutTimeLimit,
threeBoxSyncingAllowed,
threeBoxDisabled,
threeBoxFeatureFlag: threeBox,
}
}
@ -51,7 +50,13 @@ export const mapDispatchToProps = dispatch => {
setAutoLogoutTimeLimit: value => {
return dispatch(setAutoLogoutTimeLimit(value))
},
setThreeBoxSyncingPermission: newThreeBoxSyncingState => dispatch(setThreeBoxSyncingPermission(newThreeBoxSyncingState)),
setThreeBoxSyncingPermission: newThreeBoxSyncingState => {
if (newThreeBoxSyncingState) {
dispatch(turnThreeBoxSyncingOnAndInitialize())
} else {
dispatch(setThreeBoxSyncingPermission(newThreeBoxSyncingState))
}
},
}
}

View File

@ -6,7 +6,7 @@ import AdvancedTab from '../advanced-tab.component'
import TextField from '../../../../components/ui/text-field'
describe('AdvancedTab Component', () => {
it('should render correctly when threeBoxFeatureFlag is false', () => {
it('should render correctly when threeBoxFeatureFlag', () => {
const root = shallow(
<AdvancedTab />,
{
@ -16,19 +16,6 @@ describe('AdvancedTab Component', () => {
}
)
assert.equal(root.find('.settings-page__content-row').length, 7)
})
it('should render correctly threeBoxFeatureFlag is true', () => {
const root = shallow(
<AdvancedTab threeBoxFeatureFlag={true} />,
{
context: {
t: s => `_${s}`,
},
}
)
assert.equal(root.find('.settings-page__content-row').length, 8)
})

View File

@ -9,7 +9,6 @@ const defaultState = {
featureFlags: {
sendHexData: false,
advancedInlineGas: false,
threeBox: false,
},
preferences: {
autoLogoutTimeLimit: 0,
@ -32,7 +31,6 @@ describe('AdvancedTab Container', () => {
autoLogoutTimeLimit: 0,
threeBoxSyncingAllowed: false,
threeBoxDisabled: false,
threeBoxFeatureFlag: false,
}
assert.deepEqual(props, expected)

View File

@ -16,7 +16,6 @@ const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enum
const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util')
const gasDuck = require('../ducks/gas/gas.duck')
const WebcamUtils = require('../../lib/webcam-utils')
const { getFeatureFlags } = require('../selectors/selectors')
var actions = {
_setBackgroundConnection: _setBackgroundConnection,
@ -382,8 +381,9 @@ var actions = {
restoreFromThreeBox,
getThreeBoxLastUpdated,
setThreeBoxSyncingPermission,
setRestoredFromThreeBoxToFalse,
setShowRestorePromptToFalse,
turnThreeBoxSyncingOn,
turnThreeBoxSyncingOnAndInitialize,
}
module.exports = actions
@ -2798,116 +2798,93 @@ function hideSeedPhraseBackupAfterOnboarding () {
}
function initializeThreeBox () {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.initializeThreeBox((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
return (dispatch) => {
return new Promise((resolve, reject) => {
background.initializeThreeBox((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
} else {
return Promise.resolve()
}
})
}
}
function setRestoredFromThreeBoxToFalse () {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.setRestoredFromThreeBoxToFalse((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
function setShowRestorePromptToFalse () {
return (dispatch) => {
return new Promise((resolve, reject) => {
background.setShowRestorePromptToFalse((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
} else {
return Promise.resolve()
}
})
}
}
function turnThreeBoxSyncingOn () {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.turnThreeBoxSyncingOn((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
return (dispatch) => {
return new Promise((resolve, reject) => {
background.turnThreeBoxSyncingOn((err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
} else {
return Promise.resolve()
}
})
}
}
function restoreFromThreeBox (accountAddress) {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.restoreFromThreeBox(accountAddress, (err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
return (dispatch) => {
return new Promise((resolve, reject) => {
background.restoreFromThreeBox(accountAddress, (err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
} else {
return Promise.resolve()
}
})
}
}
function getThreeBoxLastUpdated () {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.getThreeBoxLastUpdated((err, lastUpdated) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve(lastUpdated)
})
return (dispatch) => {
return new Promise((resolve, reject) => {
background.getThreeBoxLastUpdated((err, lastUpdated) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve(lastUpdated)
})
} else {
return Promise.resolve()
}
})
}
}
function setThreeBoxSyncingPermission (threeBoxSyncingAllowed) {
return (dispatch, getState) => {
const state = getState()
if (getFeatureFlags(state).threeBox) {
return new Promise((resolve, reject) => {
background.setThreeBoxSyncingPermission(threeBoxSyncingAllowed, (err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
return (dispatch) => {
return new Promise((resolve, reject) => {
background.setThreeBoxSyncingPermission(threeBoxSyncingAllowed, (err) => {
if (err) {
dispatch(actions.displayWarning(err.message))
return reject(err)
}
resolve()
})
} else {
return Promise.resolve()
}
})
}
}
function turnThreeBoxSyncingOnAndInitialize () {
return async (dispatch) => {
await dispatch(setThreeBoxSyncingPermission(true))
await dispatch(turnThreeBoxSyncingOn())
await dispatch(initializeThreeBox(true))
}
}