// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . import { action, computed, observable, transaction } from 'mobx'; // TODO: We need to move this to a generic location, it should most probably be // merged with the other valitation errors. Import here better than duplication. import ERRORS from '~/views/Accounts/CreateAccount/errors'; let instance; export default class Store { @observable isBusyAccounts = false; @observable isBusyCreate = false; @observable isBusyLoad = false; @observable isBusyLock = false; @observable isBusyMeta = false; @observable isBusyUnlock = false; @observable isModalAccountsOpen = false; @observable isModalCreateOpen = false; @observable isModalLockOpen = false; @observable isModalMetaOpen = false; @observable isModalUnlockOpen = false; @observable selectedAccounts = {}; @observable vault = null; @observable vaults = []; @observable vaultsOpened = []; @observable vaultNames = []; @observable vaultName = ''; @observable vaultNameError = ERRORS.noName; @observable vaultDescription = ''; @observable vaultPassword = ''; @observable vaultPasswordHint = ''; @observable vaultPasswordOld = ''; @observable vaultPasswordRepeat = ''; @observable vaultTags = []; constructor (api) { this._api = api; } @computed get vaultPasswordRepeatError () { return this.vaultPassword === this.vaultPasswordRepeat ? null : ERRORS.noMatchPassword; } @action clearVaultFields = () => { transaction(() => { this.setVaultName(''); this.setVaultDescription(''); this.setVaultPassword(''); this.setVaultPasswordHint(''); this.setVaultPasswordOld(''); this.setVaultPasswordRepeat(''); this.setVaultTags([]); }); } @action setBusyAccounts = (isBusy) => { this.isBusyAccounts = isBusy; } @action setBusyCreate = (isBusy) => { this.isBusyCreate = isBusy; } @action setBusyLoad = (isBusy) => { this.isBusyLoad = isBusy; } @action setBusyLock = (isBusy) => { this.isBusyLock = isBusy; } @action setBusyMeta = (isBusy) => { this.isBusyMeta = isBusy; } @action setBusyUnlock = (isBusy) => { this.isBusyUnlock = isBusy; } @action setModalAccountsOpen = (isOpen) => { transaction(() => { this.setBusyAccounts(false); this.isModalAccountsOpen = isOpen; }); } @action setModalCreateOpen = (isOpen) => { transaction(() => { this.setBusyCreate(false); this.isModalCreateOpen = isOpen; }); } @action setModalLockOpen = (isOpen) => { transaction(() => { this.setBusyLock(false); this.isModalLockOpen = isOpen; }); } @action setModalMetaOpen = (isOpen) => { transaction(() => { this.setBusyMeta(false); this.isModalMetaOpen = isOpen; }); } @action setModalUnlockOpen = (isOpen) => { transaction(() => { this.setBusyUnlock(false); this.setVaultPassword(''); this.isModalUnlockOpen = isOpen; }); } @action setSelectedAccounts = (selectedAccounts) => { this.selectedAccounts = selectedAccounts; } @action setVaults = (allVaults, openedVaults, metaData) => { transaction(() => { this.vaultNames = allVaults.map((name) => name.toLowerCase()); this.vaults = allVaults.map((name, index) => { return { meta: metaData[index] || {}, name, isOpen: openedVaults.includes(name) }; }); this.vaultsOpened = this.vaults.filter((vault) => vault.isOpen); }); } @action setVaultDescription = (description) => { this.vaultDescription = description; } @action setVaultName = (name) => { let nameError = null; if (!name || !name.trim().length) { nameError = ERRORS.noName; } else { const lowerName = name.toLowerCase(); if (this.vaultNames.includes(lowerName)) { nameError = ERRORS.duplicateName; } } transaction(() => { this.vault = this.vaults.find((vault) => vault.name === name); this.vaultName = name; this.vaultNameError = nameError; }); } @action setVaultPassword = (password) => { this.vaultPassword = password; } @action setVaultPasswordHint = (hint) => { this.vaultPasswordHint = hint; } @action setVaultPasswordOld = (password) => { this.vaultPasswordOld = password; } @action setVaultPasswordRepeat = (password) => { this.vaultPasswordRepeat = password; } @action setVaultTags = (tags) => { this.vaultTags = tags; } @action toggleSelectedAccount = (address) => { this.setSelectedAccounts(Object.assign({}, this.selectedAccounts, { [address]: !this.selectedAccounts[address] }) ); } closeAccountsModal () { this.setModalAccountsOpen(false); } closeCreateModal () { this.setModalCreateOpen(false); } closeLockModal () { this.setModalLockOpen(false); } closeMetaModal () { this.setModalMetaOpen(false); } closeUnlockModal () { this.setModalUnlockOpen(false); } openAccountsModal (name) { transaction(() => { this.setVaultName(name); this.setSelectedAccounts({}); this.setModalAccountsOpen(true); }); } openCreateModal () { transaction(() => { this.clearVaultFields(); this.setModalCreateOpen(true); }); } openLockModal (name) { transaction(() => { this.setVaultName(name); this.setModalLockOpen(true); }); } openMetaModal (name) { transaction(() => { this.clearVaultFields(); this.setVaultName(name); if (this.vault && this.vault.meta) { this.setVaultDescription(this.vault.meta.description); this.setVaultPasswordHint(this.vault.meta.passwordHint); } this.setModalMetaOpen(true); }); } openUnlockModal (name) { transaction(() => { this.setVaultName(name); this.setModalUnlockOpen(true); }); } loadVaults = () => { this.setBusyLoad(true); return Promise .all([ this._api.parity.listVaults(), this._api.parity.listOpenedVaults() ]) .then(([allVaults, openedVaults]) => { return Promise .all(allVaults.map((name) => this._api.parity.getVaultMeta(name))) .then((metaData) => { transaction(() => { this.setBusyLoad(false); this.setVaults(allVaults, openedVaults, metaData); }); }); }) .catch((error) => { console.warn('loadVaults', error); this.setBusyLoad(false); }); } closeVault () { this.setBusyLock(true); return this._api.parity .closeVault(this.vaultName) .then(this.loadVaults) .then(() => { this.setBusyLock(false); }) .catch((error) => { console.error('closeVault', error); this.setBusyLock(false); throw error; }); } createVault () { if (this.vaultNameError || this.vaultPasswordRepeatError) { return Promise.reject(); } this.setBusyCreate(true); return this._api.parity .newVault(this.vaultName, this.vaultPassword) .then(() => { return this._api.parity.setVaultMeta(this.vaultName, { description: this.vaultDescription, passwordHint: this.vaultPasswordHint, tags: this.vaultTags }); }) .then(this.loadVaults) .then(() => { this.setBusyCreate(false); }) .catch((error) => { console.error('createVault', error); this.setBusyCreate(false); throw error; }); } editVaultMeta () { this.setBusyMeta(true); return this._api.parity .setVaultMeta(this.vaultName, { description: this.vaultDescription, passwordHint: this.vaultPasswordHint, tags: this.vaultTags }) .then(this.loadVaults) .then(() => { this.setBusyMeta(false); }) .catch((error) => { console.error('editVaultMeta', error); this.setBusyMeta(false); throw error; }); } editVaultPassword () { this.setBusyMeta(true); return this._api.parity .closeVault(this.vaultName) .then(() => { return this._api.parity.openVault(this.vaultName, this.vaultPasswordOld); }) .then(() => { return this._api.parity.changeVaultPassword(this.vaultName, this.vaultPassword); }) .then(() => { this.setBusyMeta(false); }) .catch((error) => { console.error('editVaultPassword', error); this.loadVaults(); this.setBusyMeta(false); throw new Error('Unable to change the vault password'); }); } openVault () { this.setBusyUnlock(true); return this._api.parity .openVault(this.vaultName, this.vaultPassword) .then(this.loadVaults) .then(() => { this.setBusyUnlock(false); }) .catch((error) => { console.error('openVault', error); this.setBusyUnlock(false); throw error; }); } moveAccounts (vaultName, inAccounts, outAccounts) { this.setBusyAccounts(true); return Promise .all([ inAccounts.map((address) => this._api.parity.changeVault(address, vaultName)), outAccounts.map((address) => this._api.parity.changeVault(address, '')) ]) .then(this.loadVaults) .then(() => { this.setBusyAccounts(false); }) .catch((error) => { console.error('moveAccounts', error); this.setBusyAccounts(false); throw error; }); } moveAccount (vaultName, address) { this.setBusyAccounts(true); return this._api.parity .changeVault(address, vaultName) .then(this.loadVaults) .then(() => { this.setBusyAccounts(false); }) .catch((error) => { console.error('moveAccount', error); this.setBusyAccounts(false); throw error; }); } static get (api) { if (!instance) { instance = new Store(api); } return instance; } }