openethereum/js/src/views/Dapps/dappsStore.js

284 lines
7.1 KiB
JavaScript
Raw Normal View History

2016-12-11 19:30:54 +01:00
// Copyright 2015, 2016 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';
2016-11-14 17:02:45 +01:00
import store from 'store';
import Contracts from '~/contracts';
import {
fetchBuiltinApps, fetchLocalApps,
fetchRegistryAppIds, fetchRegistryApp,
subscribeToChanges
} from '~/util/dapps';
2016-11-14 17:02:45 +01:00
const LS_KEY_DISPLAY = 'displayApps';
2016-11-16 13:08:08 +01:00
const LS_KEY_EXTERNAL_ACCEPT = 'acceptExternal';
const BUILTIN_APPS_KEY = 'BUILTIN_APPS_KEY';
let instance = null;
export default class DappsStore {
@observable apps = [];
2016-11-14 17:02:45 +01:00
@observable displayApps = {};
@observable modalOpen = false;
2016-11-16 13:08:08 +01:00
@observable externalOverlayVisible = true;
_api = null;
_subscriptions = {};
_cachedApps = {};
_manifests = {};
_registryAppsIds = null;
constructor (api) {
this._api = api;
this.readDisplayApps();
2016-11-16 13:08:08 +01:00
this.loadExternalOverlay();
this.subscribeToChanges();
}
/**
* Try to find the app from the local (local or builtin)
* apps, else fetch from the node
*/
loadApp (id) {
const { dappReg } = Contracts.get();
return this
.loadLocalApps()
.then(() => {
const app = this.apps.find((app) => app.id === id);
if (app) {
return app;
}
return this.fetchRegistryApp(dappReg, id, true);
});
}
loadLocalApps () {
return Promise
2016-11-14 17:02:45 +01:00
.all([
this.fetchBuiltinApps().then((apps) => this.addApps(apps)),
this.fetchLocalApps().then((apps) => this.addApps(apps))
]);
}
loadAllApps () {
const { dappReg } = Contracts.get();
return Promise
.all([
this.loadLocalApps(),
this.fetchRegistryApps(dappReg).then((apps) => this.addApps(apps))
2016-11-14 17:02:45 +01:00
])
2016-11-14 21:57:28 +01:00
.then(this.writeDisplayApps);
}
static get (api) {
if (!instance) {
instance = new DappsStore(api);
}
return instance;
}
subscribeToChanges () {
const { dappReg } = Contracts.get();
// Unsubscribe from previous subscriptions, if any
if (this._subscriptions.block) {
this._api.unsubscribe(this._subscriptions.block);
}
if (this._subscriptions.filter) {
this._api.eth.uninstallFilter(this._subscriptions.filter);
}
// Subscribe to dapps reg changes
subscribeToChanges(this._api, dappReg, (appIds) => {
const updates = appIds.map((appId) => {
return this.fetchRegistryApp(dappReg, appId, true);
});
Promise
.all(updates)
.then((apps) => {
this.addApps(apps);
});
}).then((subscriptions) => {
this._subscriptions = subscriptions;
});
}
fetchBuiltinApps (force = false) {
if (!force && this._cachedApps[BUILTIN_APPS_KEY] !== undefined) {
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
}
this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps()
.then((apps) => {
this._cachedApps[BUILTIN_APPS_KEY] = apps;
return apps;
});
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
}
fetchLocalApps () {
return fetchLocalApps(this._api);
}
fetchRegistryAppIds (force = false) {
if (!force && this._registryAppsIds) {
return Promise.resolve(this._registryAppsIds);
}
this._registryAppsIds = fetchRegistryAppIds()
.then((appIds) => {
this._registryAppsIds = appIds;
return this._registryAppsIds;
});
return Promise.resolve(this._registryAppsIds);
}
fetchRegistryApp (dappReg, appId, force = false) {
if (!force && this._cachedApps[appId] !== undefined) {
return Promise.resolve(this._cachedApps[appId]);
}
this._cachedApps[appId] = fetchRegistryApp(this._api, dappReg, appId)
.then((dapp) => {
this._cachedApps[appId] = dapp;
return dapp;
});
return Promise.resolve(this._cachedApps[appId]);
}
fetchRegistryApps (dappReg) {
return this
.fetchRegistryAppIds()
.then((appIds) => {
const promises = appIds.map((appId) => {
// Fetch the Dapp and display it ASAP
return this
.fetchRegistryApp(dappReg, appId)
.then((app) => {
if (app) {
this.addApps([ app ]);
}
return app;
});
});
return Promise.all(promises);
});
}
2016-11-14 21:57:28 +01:00
@computed get sortedBuiltin () {
return this.apps.filter((app) => app.type === 'builtin');
}
@computed get sortedLocal () {
return this.apps.filter((app) => app.type === 'local');
}
@computed get sortedNetwork () {
return this.apps.filter((app) => app.type === 'network');
2016-11-14 17:02:45 +01:00
}
@computed get visibleApps () {
2016-11-14 21:57:28 +01:00
return this.apps.filter((app) => this.displayApps[app.id] && this.displayApps[app.id].visible);
}
2016-11-16 12:36:15 +01:00
@computed get visibleBuiltin () {
return this.visibleApps.filter((app) => app.type === 'builtin');
}
@computed get visibleLocal () {
return this.visibleApps.filter((app) => app.type === 'local');
}
@computed get visibleNetwork () {
return this.visibleApps.filter((app) => app.type === 'network');
}
@action openModal = () => {
this.modalOpen = true;
}
@action closeModal = () => {
this.modalOpen = false;
}
2016-11-16 13:08:08 +01:00
@action closeExternalOverlay = () => {
this.externalOverlayVisible = false;
store.set(LS_KEY_EXTERNAL_ACCEPT, true);
}
@action loadExternalOverlay () {
this.externalOverlayVisible = !(store.get(LS_KEY_EXTERNAL_ACCEPT) || false);
}
@action hideApp = (id) => {
2016-11-14 21:57:28 +01:00
this.displayApps = Object.assign({}, this.displayApps, { [id]: { visible: false } });
this.writeDisplayApps();
}
@action showApp = (id) => {
2016-11-14 21:57:28 +01:00
this.displayApps = Object.assign({}, this.displayApps, { [id]: { visible: true } });
this.writeDisplayApps();
}
2016-11-14 17:02:45 +01:00
2016-11-14 21:57:28 +01:00
@action readDisplayApps = () => {
this.displayApps = store.get(LS_KEY_DISPLAY) || {};
2016-11-14 17:02:45 +01:00
}
2016-11-14 21:57:28 +01:00
@action writeDisplayApps = () => {
store.set(LS_KEY_DISPLAY, this.displayApps);
2016-11-14 17:02:45 +01:00
}
Backporting to beta (#4152) * Fix broken transfer total balance (#4127) * Add proper label to method decoding inputs (#4136) * Another minor estimation fix (#4133) * Return 0 instead of error with out of gas on estimate_gas * Fix stuff up. * Another estimate gas fix. * Alter balance to maximum possible rather than GP=0. * Only increase to amount strictly necessary. * Get rid of unsafe code in ethkey, propagate incorrect Secret errors. (#4119) * Implementing secret * Fixing tests * Refactor VoteCollector (#4101) * dir * simple validator list * stub validator contract * make the engine hold Weak<Client> instead of IoChannel * validator set factory * register weak client with ValidatorContract * check chain security * add address array to generator * register provider contract * update validator set on notify * add validator contract spec * simple list test * split update and contract test * contract change * use client in tendermint * fix deadlock * step duration in params * adapt tendermint tests * add storage fields to test spec * constructor spec * execute under wrong address * create under correct address * revert * validator contract constructor * move genesis block lookup * add removal ability to contract * validator contract adding validators * fix basic authority * validator changing test * more docs * update sync tests * remove env_logger * another env_logger * cameltoe * hold EngineClient instead of Client * return error on misbehaviour * nicer return * sprinkle docs * Reenable mainnet update server. (#4137) * basic tests for subscribeToEvents (#4115) * subscribeToEvent fixtures :white_check_mark: * subscribeToEvent tests :white_check_mark: * temporarily skip failing test (#4138) * Improvements and optimisations to estimate_gas (#4142) * Return 0 instead of error with out of gas on estimate_gas * Fix stuff up. * Another estimate gas fix. * Alter balance to maximum possible rather than GP=0. * Only increase to amount strictly necessary. * Improvements and optimisations to estimate_gas. - Introduce proper error type - Avoid building costly traces * Fix tests. * Actually fix testsActually fix tests * Use estimateGas error (as per updated implementation) (#4131) * Use estimateGas error (as per updated implementation) * EXCEPTION_ERROR as per #4142 * Better error log reporting & handling (#4128) * Don't pop-up notifications after network switch (#4076) * Better notifications * Don't pollute with notifs if switched networks * Better connection close/open events / No more notifs on change network * PR Grumbles * Add close and open events to HTTP // Add tests * Fix tests * WIP Signer Fix * Fix Signer // Better reconnection handling * PR Grumbles * PR Grumbles * Fixes wrong fetching of balances + Notifications * Secure API WIP * Updated Secure API Connection + Status * Linting * Linting * Updated Secure API Logic * Proper handling of token updates // Fixing poping notifications * PR Grumbles * PR Grumbles * Fixing tests * Trim spaces from InputAddress (#4126) * Trim spaces for addresses * onSubmit has only value, not event * onSubmit (again) * Length check on trimmed value * Remove bindActionCreators({}, dispatch) (empty) (#4135)
2017-01-12 17:06:15 +01:00
@action addApps = (_apps = []) => {
2016-11-14 17:02:45 +01:00
transaction(() => {
const apps = _apps.filter((app) => app);
// Get new apps IDs if available
const newAppsIds = apps
.map((app) => app.id)
.filter((id) => id);
2016-11-14 21:57:28 +01:00
this.apps = this.apps
.filter((app) => !app.id || !newAppsIds.includes(app.id))
2016-11-14 21:57:28 +01:00
.concat(apps || [])
.sort((a, b) => a.name.localeCompare(b.name));
const visibility = {};
apps.forEach((app) => {
if (!this.displayApps[app.id]) {
visibility[app.id] = { visible: app.visible };
}
});
2016-11-14 17:02:45 +01:00
2016-11-14 21:57:28 +01:00
this.displayApps = Object.assign({}, this.displayApps, visibility);
2016-11-14 17:02:45 +01:00
});
}
}