diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js
index 61606f13..1424cfb2 100644
--- a/embark-ui/src/actions/index.js
+++ b/embark-ui/src/actions/index.js
@@ -104,11 +104,18 @@ export const contractProfile = {
failure: (error) => action(CONTRACT_PROFILE[FAILURE], {error})
};
-export const MESSAGE_VERSION = createRequestTypes('MESSAGE_VERSION');
-export const messageVersion = {
- request: () => action(MESSAGE_VERSION[REQUEST]),
- success: (messageVersion) => action(MESSAGE_VERSION[SUCCESS], {messageVersion}),
- failure: (error) => action(MESSAGE_VERSION[FAILURE], {error})
+export const VERSIONS = createRequestTypes('VERSIONS');
+export const versions = {
+ request: () => action(VERSIONS[REQUEST]),
+ success: (versions) => action(VERSIONS[SUCCESS], {versions}),
+ failure: (error) => action(VERSIONS[FAILURE], {error})
+};
+
+export const PLUGINS = createRequestTypes('PLUGINS');
+export const plugins = {
+ request: () => action(PLUGINS[REQUEST]),
+ success: (plugins) => action(PLUGINS[SUCCESS], {plugins}),
+ failure: (error) => action(PLUGINS[FAILURE], {error})
};
export const MESSAGE_SEND = createRequestTypes('MESSAGE_SEND');
diff --git a/embark-ui/src/api/index.js b/embark-ui/src/api/index.js
index d2a17e75..4dc9dc2d 100644
--- a/embark-ui/src/api/index.js
+++ b/embark-ui/src/api/index.js
@@ -68,8 +68,12 @@ export function fetchContract(payload) {
return get(`/contract/${payload.contractName}`);
}
-export function communicationVersion() {
- return get(`/communication/version`);
+export function fetchVersions() {
+ return get('/versions');
+}
+
+export function fetchPlugins() {
+ return get('/plugins');
}
export function sendMessage(payload) {
diff --git a/embark-ui/src/components/ExplorerLayout.js b/embark-ui/src/components/ExplorerLayout.js
index e98f7586..0ad2a318 100644
--- a/embark-ui/src/components/ExplorerLayout.js
+++ b/embark-ui/src/components/ExplorerLayout.js
@@ -10,9 +10,18 @@ import AccountsContainer from '../containers/AccountsContainer';
import AccountContainer from '../containers/AccountContainer';
import BlocksContainer from '../containers/BlocksContainer';
import BlockContainer from '../containers/BlockContainer';
-import CommunicationContainer from '../containers/CommunicationContainer';
import TransactionsContainer from '../containers/TransactionsContainer';
import TransactionContainer from '../containers/TransactionContainer';
+import CommunicationContainer from '../containers/CommunicationContainer';
+import ENSContainer from '../containers/ENSContainer';
+
+const groupItems = [
+ {to: "/embark/explorer/accounts", icon: "users", value: "Accounts"},
+ {to: "/embark/explorer/blocks", icon: "book-open", value: "Blocks"},
+ {to: "/embark/explorer/transactions", icon: "activity", value: "Transactions"},
+ {to: "/embark/explorer/communication", icon: "phone-call", value: "Communication"},
+ {to: "/embark/explorer/ens", icon: "disc", value: "ENS"}
+];
const className = "d-flex align-items-center";
@@ -22,38 +31,16 @@ const ExplorerLayout = () => (
Explorer
-
- Accounts
-
-
- Blocks
-
-
- Transactions
-
-
- Communication
-
+ {groupItems.map((groupItem) => (
+
+ {groupItem.value}
+
+ ))}
@@ -63,9 +50,10 @@ const ExplorerLayout = () => (
-
+
+
diff --git a/embark-ui/src/containers/AppContainer.js b/embark-ui/src/containers/AppContainer.js
index 47a47d9d..5f1e7317 100644
--- a/embark-ui/src/containers/AppContainer.js
+++ b/embark-ui/src/containers/AppContainer.js
@@ -6,13 +6,22 @@ import React, {Component} from 'react';
import history from '../history';
import Layout from '../components/Layout';
import routes from '../routes';
-import {contracts as contractsAction, initBlockHeader, processes as processesAction} from '../actions';
+
+import {
+ initBlockHeader,
+ contracts as contractsAction,
+ processes as processesAction,
+ versions as versionsAction,
+ plugins as pluginsAction
+} from '../actions';
class AppContainer extends Component {
componentDidMount() {
this.props.initBlockHeader();
this.props.fetchProcesses();
this.props.fetchContracts();
+ this.props.fetchVersions();
+ this.props.fetchPlugins();
}
render() {
@@ -29,7 +38,9 @@ class AppContainer extends Component {
AppContainer.propTypes = {
initBlockHeader: PropTypes.func,
fetchContracts: PropTypes.func,
- fetchProcesses: PropTypes.func
+ fetchProcesses: PropTypes.func,
+ fetchPlugins: PropTypes.func,
+ fetchVersions: PropTypes.func
};
export default connect(
@@ -37,6 +48,8 @@ export default connect(
{
initBlockHeader,
fetchProcesses: processesAction.request,
- fetchContracts: contractsAction.request
+ fetchContracts: contractsAction.request,
+ fetchVersions: versionsAction.request,
+ fetchPlugins: pluginsAction.request
},
)(AppContainer);
diff --git a/embark-ui/src/containers/CommunicationContainer.js b/embark-ui/src/containers/CommunicationContainer.js
index 389c23dc..57a125cf 100644
--- a/embark-ui/src/containers/CommunicationContainer.js
+++ b/embark-ui/src/containers/CommunicationContainer.js
@@ -2,16 +2,11 @@ import PropTypes from "prop-types";
import React, {Component} from 'react';
import connect from "react-redux/es/connect/connect";
import {Alert, Loader, Page} from 'tabler-react';
-import {messageSend, messageListen, messageVersion} from "../actions";
+import {messageSend, messageListen} from "../actions";
import Communication from "../components/Communication";
-import Loading from "../components/Loading";
-import {getMessageVersion, getMessages, getMessageChannels} from "../reducers/selectors";
+import {getMessages, getMessageChannels} from "../reducers/selectors";
class CommunicationContainer extends Component {
- componentDidMount() {
- this.props.communicationVersion();
- }
-
sendMessage(topic, message) {
this.props.messageSend({topic, message});
}
@@ -31,9 +26,6 @@ class CommunicationContainer extends Component {
isEnabledMessage = The node uses an unsupported version of Whisper;
}
- if (!this.props.messages) {
- return ;
- }
return (
{isEnabledMessage}
@@ -49,8 +41,7 @@ class CommunicationContainer extends Component {
CommunicationContainer.propTypes = {
messageSend: PropTypes.func,
messageListen: PropTypes.func,
- communicationVersion: PropTypes.func,
- messageVersion: PropTypes.number,
+ isWhisperEnabled: PropTypes.bool,
messages: PropTypes.object,
messageChannels: PropTypes.array
};
@@ -59,7 +50,7 @@ function mapStateToProps(state) {
return {
messages: getMessages(state),
messageChannels: getMessageChannels(state),
- messageVersion: getMessageVersion(state)
+ isWhisperEnabled: isWhisperEnabled(state)
};
}
@@ -68,7 +59,6 @@ export default connect(
{
messageSend: messageSend.request,
messageListen: messageListen.request,
- communicationVersion: messageVersion.request
}
)(CommunicationContainer);
diff --git a/embark-ui/src/containers/ENSContainer.js b/embark-ui/src/containers/ENSContainer.js
new file mode 100644
index 00000000..da118914
--- /dev/null
+++ b/embark-ui/src/containers/ENSContainer.js
@@ -0,0 +1,67 @@
+import PropTypes from "prop-types";
+import React, {Component} from 'react';
+import connect from "react-redux/es/connect/connect";
+import {Alert, Loader, Page} from 'tabler-react';
+import {messageSend, messageListen, messageVersion} from "../actions";
+import Communication from "../components/Communication";
+import Loading from "../components/Loading";
+import {getMessages, getMessageChannels} from "../reducers/selectors";
+
+class CommunicationContainer extends Component {
+ sendMessage(topic, message) {
+ this.props.messageSend({topic, message});
+ }
+
+ listenToChannel(channel) {
+ this.props.messageListen(channel);
+ }
+
+ render() {
+ let isEnabledMessage = '';
+ if (this.props.messageVersion === undefined || this.props.messageVersion === null) {
+ isEnabledMessage =
+ Checking Whisper support, please wait;
+ } else if (!this.props.messageVersion) {
+ isEnabledMessage = The node you are using does not support Whisper;
+ } else if (this.props.messageVersion === -1) {
+ isEnabledMessage = The node uses an unsupported version of Whisper;
+ }
+
+ if (!this.props.messages) {
+ return ;
+ }
+ return (
+
+ {isEnabledMessage}
+ this.listenToChannel(channel)}
+ sendMessage={(channel, message) => this.sendMessage(channel, message)}
+ channels={this.props.messages}
+ subscriptions={this.props.messageChannels}/>
+
+ );
+ }
+}
+
+CommunicationContainer.propTypes = {
+ messageSend: PropTypes.func,
+ messageListen: PropTypes.func,
+ messageVersion: PropTypes.number,
+ messages: PropTypes.object,
+ messageChannels: PropTypes.array
+};
+
+function mapStateToProps(state) {
+ return {
+ messages: getMessages(state),
+ messageChannels: getMessageChannels(state)
+ };
+}
+
+export default connect(
+ mapStateToProps,
+ {
+ messageSend: messageSend.request,
+ messageListen: messageListen.request
+ }
+)(CommunicationContainer);
+
diff --git a/embark-ui/src/reducers/index.js b/embark-ui/src/reducers/index.js
index 2e7ca707..315ce094 100644
--- a/embark-ui/src/reducers/index.js
+++ b/embark-ui/src/reducers/index.js
@@ -15,8 +15,9 @@ const entitiesDefaultState = {
commands: [],
messages: [],
messageChannels: [],
- messageVersion: null,
- fiddle: null
+ fiddle: null,
+ versions: [],
+ plugins: []
};
const sorter = {
@@ -61,10 +62,7 @@ function entities(state = entitiesDefaultState, action) {
for (let name of Object.keys(state)) {
let filter = filtrer[name] || (() => true);
let sort = sorter[name] || (() => true);
- if (action[name] && !Array.isArray(action[name])) {
- return {...state, [name]: action[name]};
- }
- if (action[name] && (!Array.isArray(action[name]) || action[name].length > 1)) {
+ if (action[name] && action[name].length > 1) {
return {...state, [name]: [...action[name], ...state[name]].filter(filter).sort(sort)};
}
if (action[name] && action[name].length === 1) {
diff --git a/embark-ui/src/sagas/index.js b/embark-ui/src/sagas/index.js
index 78a0e0e0..74b0348b 100644
--- a/embark-ui/src/sagas/index.js
+++ b/embark-ui/src/sagas/index.js
@@ -4,8 +4,7 @@ import {eventChannel} from 'redux-saga';
import {all, call, fork, put, takeEvery, take} from 'redux-saga/effects';
const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs,
- contracts, contract, contractProfile, messageSend, messageVersion, messageListen, contractLogs,
- fiddle} = actions;
+ contracts, contract, contractProfile, messageSend, versions, plugins, messageListen, fiddle} = actions;
function *doRequest(entity, apiFn, payload) {
const {response, error} = yield call(apiFn, payload);
@@ -16,6 +15,8 @@ function *doRequest(entity, apiFn, payload) {
}
}
+export const fetchPlugins = doRequest.bind(null, plugins, api.fetchPlugins);
+export const fetchVersions = doRequest.bind(null, versions, api.fetchVersions);
export const fetchAccount = doRequest.bind(null, account, api.fetchAccount);
export const fetchBlock = doRequest.bind(null, block, api.fetchBlock);
export const fetchTransaction = doRequest.bind(null, transaction, api.fetchTransaction);
@@ -30,6 +31,7 @@ export const fetchContracts = doRequest.bind(null, contracts, api.fetchContracts
export const fetchContract = doRequest.bind(null, contract, api.fetchContract);
export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile);
export const fetchFiddle = doRequest.bind(null, fiddle, api.fetchFiddle);
+export const sendMessage = doRequest.bind(null, messageSend, api.sendMessage);
export function *watchFetchTransaction() {
yield takeEvery(actions.TRANSACTION[actions.REQUEST], fetchTransaction);
@@ -83,6 +85,18 @@ export function *watchFetchContractProfile() {
yield takeEvery(actions.CONTRACT_PROFILE[actions.REQUEST], fetchContractProfile);
}
+export function *watchFetchVersions() {
+ yield takeEvery(actions.VERSIONS[actions.REQUEST], fetchVersions);
+}
+
+export function *watchFetchPlugins() {
+ yield takeEvery(actions.PLUGINS[actions.REQUEST], fetchPlugins);
+}
+
+export function *watchSendMessage() {
+ yield takeEvery(actions.MESSAGE_SEND[actions.REQUEST], sendMessage);
+}
+
function createChannel(socket) {
return eventChannel(emit => {
socket.onmessage = ((message) => {
@@ -134,8 +148,6 @@ export function *watchListenToContractLogs() {
yield takeEvery(actions.WATCH_NEW_CONTRACT_LOGS, listenToContractLogs);
}
-export const sendMessage = doRequest.bind(null, messageSend, api.sendMessage);
-
export function *watchSendMessage() {
yield takeEvery(actions.MESSAGE_SEND[actions.REQUEST], sendMessage);
}
@@ -153,16 +165,11 @@ export function *watchListenToMessages() {
yield takeEvery(actions.MESSAGE_LISTEN[actions.REQUEST], listenToMessages);
}
-export const fetchCommunicationVersion = doRequest.bind(null, messageVersion, api.communicationVersion);
-
-export function *watchCommunicationVersion() {
- yield takeEvery(actions.MESSAGE_VERSION[actions.REQUEST], fetchCommunicationVersion);
-}
-
export function *watchFetchFiddle() {
yield takeEvery(actions.FIDDLE[actions.REQUEST], fetchFiddle);
}
+
export default function *root() {
yield all([
fork(watchInitBlockHeader),
@@ -176,7 +183,8 @@ export default function *root() {
fork(watchFetchBlock),
fork(watchFetchTransactions),
fork(watchPostCommand),
- fork(watchCommunicationVersion),
+ fork(watchFetchVersions),
+ fork(watchFetchPlugins),
fork(watchFetchBlocks),
fork(watchFetchContracts),
fork(watchListenToMessages),
@@ -187,4 +195,3 @@ export default function *root() {
fork(watchFetchFiddle)
]);
}
-
diff --git a/lib/core/plugins.js b/lib/core/plugins.js
index de7bc2ea..5df5bccb 100644
--- a/lib/core/plugins.js
+++ b/lib/core/plugins.js
@@ -15,21 +15,19 @@ var Plugins = function(options) {
};
Plugins.prototype.loadPlugins = function() {
- var pluginConfig;
- for (var pluginName in this.pluginList) {
- pluginConfig = this.pluginList[pluginName];
+ for (let pluginName in this.pluginList) {
+ let pluginConfig = this.pluginList[pluginName];
this.loadPlugin(pluginName, pluginConfig);
}
};
Plugins.prototype.listPlugins = function() {
- const list = [];
- this.plugins.forEach(plugin => {
+ return this.plugins.reduce((list, plugin) => {
if (plugin.loaded) {
list.push(plugin.name);
}
- });
- return list;
+ return list;
+ }, []);
};
// for services that act as a plugin but have core functionality
diff --git a/lib/modules/library_manager/index.js b/lib/modules/library_manager/index.js
index 032d643e..a366e97d 100644
--- a/lib/modules/library_manager/index.js
+++ b/lib/modules/library_manager/index.js
@@ -11,6 +11,7 @@ class LibraryManager {
this.determineVersions();
this.registerCommands();
+ this.registerAPICommands();
this.listenToCommandsToGetVersions();
this.listenToCommandsToGetLibrary();
}
@@ -51,6 +52,18 @@ class LibraryManager {
});
}
+ registerAPICommands() {
+ const self = this;
+ self.embark.registerAPICall(
+ 'get',
+ '/embark-api/versions',
+ (req, res) => {
+ const versions = Object.keys(self.versions).map((name) => ({value: self.versions[name], name}));
+ res.send(versions);
+ }
+ );
+ }
+
listenToCommandsToGetVersions() {
const self = this;
for (let libName in this.versions) {
diff --git a/lib/modules/webserver/server.js b/lib/modules/webserver/server.js
index 07f1a919..94001961 100644
--- a/lib/modules/webserver/server.js
+++ b/lib/modules/webserver/server.js
@@ -85,6 +85,13 @@ class Server {
if (self.plugins) {
let apiCalls = self.plugins.getPluginsProperty("apiCalls", "apiCalls");
+
+ app.get('/embark-api/plugins', function(req, res) {
+ res.send(JSON.stringify(self.plugins.plugins.map((plugin) => {
+ return {name: plugin.name};
+ })));
+ });
+
for (let apiCall of apiCalls) {
console.dir("adding " + apiCall.method + " " + apiCall.endpoint);
app[apiCall.method].apply(app, [apiCall.endpoint, apiCall.cb]);
diff --git a/lib/modules/whisper/index.js b/lib/modules/whisper/index.js
index 394b6cee..4baafa3c 100644
--- a/lib/modules/whisper/index.js
+++ b/lib/modules/whisper/index.js
@@ -199,14 +199,6 @@ class Whisper {
ws.send(JSON.stringify(result));
});
});
-
- self.embark.registerAPICall(
- 'get',
- '/embark-api/communication/version',
- (req, res) => {
- res.send(self.isOldWeb3 ? -1 : self.version || 0);
- }
- );
});
}
}