2017-02-20 16:40:01 +01:00
|
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
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.
|
2017-07-21 15:46:53 +02:00
|
|
|
import ERRORS from '@parity/dapp-accounts/CreateAccount/errors';
|
2017-02-20 16:40:01 +01:00
|
|
|
|
|
|
|
let instance;
|
|
|
|
|
|
|
|
export default class Store {
|
|
|
|
@observable isBusyAccounts = false;
|
|
|
|
@observable isBusyCreate = false;
|
|
|
|
@observable isBusyLoad = false;
|
|
|
|
@observable isBusyLock = false;
|
2017-02-24 18:05:04 +01:00
|
|
|
@observable isBusyMeta = false;
|
2017-02-20 16:40:01 +01:00
|
|
|
@observable isBusyUnlock = false;
|
|
|
|
@observable isModalAccountsOpen = false;
|
|
|
|
@observable isModalCreateOpen = false;
|
|
|
|
@observable isModalLockOpen = false;
|
2017-02-24 18:05:04 +01:00
|
|
|
@observable isModalMetaOpen = false;
|
2017-02-20 16:40:01 +01:00
|
|
|
@observable isModalUnlockOpen = false;
|
|
|
|
@observable selectedAccounts = {};
|
|
|
|
@observable vault = null;
|
|
|
|
@observable vaults = [];
|
2017-03-03 19:50:54 +01:00
|
|
|
@observable vaultsOpened = [];
|
2017-02-20 16:40:01 +01:00
|
|
|
@observable vaultNames = [];
|
|
|
|
@observable vaultName = '';
|
|
|
|
@observable vaultNameError = ERRORS.noName;
|
|
|
|
@observable vaultDescription = '';
|
|
|
|
@observable vaultPassword = '';
|
|
|
|
@observable vaultPasswordHint = '';
|
2017-02-24 18:05:04 +01:00
|
|
|
@observable vaultPasswordOld = '';
|
2017-02-20 16:40:01 +01:00
|
|
|
@observable vaultPasswordRepeat = '';
|
2017-02-24 18:05:04 +01:00
|
|
|
@observable vaultTags = [];
|
2017-02-20 16:40:01 +01:00
|
|
|
|
|
|
|
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('');
|
2017-02-24 18:05:04 +01:00
|
|
|
this.setVaultPasswordOld('');
|
2017-02-20 16:40:01 +01:00
|
|
|
this.setVaultPasswordRepeat('');
|
2017-02-24 18:05:04 +01:00
|
|
|
this.setVaultTags([]);
|
2017-02-20 16:40:01 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@action setBusyAccounts = (isBusy) => {
|
|
|
|
this.isBusyAccounts = isBusy;
|
|
|
|
}
|
|
|
|
|
|
|
|
@action setBusyCreate = (isBusy) => {
|
|
|
|
this.isBusyCreate = isBusy;
|
|
|
|
}
|
|
|
|
|
|
|
|
@action setBusyLoad = (isBusy) => {
|
|
|
|
this.isBusyLoad = isBusy;
|
|
|
|
}
|
|
|
|
|
|
|
|
@action setBusyLock = (isBusy) => {
|
|
|
|
this.isBusyLock = isBusy;
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
@action setBusyMeta = (isBusy) => {
|
|
|
|
this.isBusyMeta = isBusy;
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
@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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
@action setModalMetaOpen = (isOpen) => {
|
|
|
|
transaction(() => {
|
|
|
|
this.setBusyMeta(false);
|
|
|
|
this.isModalMetaOpen = isOpen;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
@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)
|
|
|
|
};
|
|
|
|
});
|
2017-03-03 19:50:54 +01:00
|
|
|
this.vaultsOpened = this.vaults.filter((vault) => vault.isOpen);
|
2017-02-20 16:40:01 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@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;
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
@action setVaultPasswordOld = (password) => {
|
|
|
|
this.vaultPasswordOld = password;
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
@action setVaultPasswordRepeat = (password) => {
|
|
|
|
this.vaultPasswordRepeat = password;
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
@action setVaultTags = (tags) => {
|
|
|
|
this.vaultTags = tags;
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
@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);
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
closeMetaModal () {
|
|
|
|
this.setModalMetaOpen(false);
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
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,
|
2017-02-24 18:05:04 +01:00
|
|
|
passwordHint: this.vaultPasswordHint,
|
|
|
|
tags: this.vaultTags
|
2017-02-20 16:40:01 +01:00
|
|
|
});
|
|
|
|
})
|
|
|
|
.then(this.loadVaults)
|
|
|
|
.then(() => {
|
|
|
|
this.setBusyCreate(false);
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
console.error('createVault', error);
|
|
|
|
this.setBusyCreate(false);
|
|
|
|
throw error;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-24 18:05:04 +01:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:40:01 +01:00
|
|
|
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)
|
2017-02-24 18:05:04 +01:00
|
|
|
.then(() => {
|
|
|
|
this.setBusyAccounts(false);
|
|
|
|
})
|
2017-02-20 16:40:01 +01:00
|
|
|
.catch((error) => {
|
|
|
|
console.error('moveAccounts', error);
|
2017-02-24 18:05:04 +01:00
|
|
|
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);
|
2017-02-20 16:40:01 +01:00
|
|
|
throw error;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static get (api) {
|
|
|
|
if (!instance) {
|
|
|
|
instance = new Store(api);
|
|
|
|
}
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
}
|