diff --git a/js/src/Status/SignerPending/EtherValue/etherValue.js b/js/src/Status/SignerPending/EtherValue/etherValue.js
new file mode 100644
index 000000000..bc5b79c90
--- /dev/null
+++ b/js/src/Status/SignerPending/EtherValue/etherValue.js
@@ -0,0 +1,39 @@
+// 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 React from 'react';
+import PropTypes from 'prop-types';
+
+const EtherValue = ({ value }, { api }) => {
+ const ether = api.util.fromWei(value);
+
+ return (
+
+ {ether.toFormat(5)}
+ ETH
+
+ );
+};
+
+EtherValue.propTypes = {
+ value: PropTypes.object.isRequired
+};
+
+EtherValue.contextTypes = {
+ api: PropTypes.object.isRequired
+};
+
+export default EtherValue;
diff --git a/js/src/Status/SignerPending/EtherValue/index.js b/js/src/Status/SignerPending/EtherValue/index.js
new file mode 100644
index 000000000..eb8fcffa8
--- /dev/null
+++ b/js/src/Status/SignerPending/EtherValue/index.js
@@ -0,0 +1,17 @@
+// 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 .
+
+export default from './etherValue';
diff --git a/js/src/Status/SignerPending/RequestItem/index.js b/js/src/Status/SignerPending/RequestItem/index.js
new file mode 100644
index 000000000..c6a73a370
--- /dev/null
+++ b/js/src/Status/SignerPending/RequestItem/index.js
@@ -0,0 +1,17 @@
+// 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 .
+
+export default from './requestItem';
diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.css b/js/src/Status/SignerPending/RequestItem/requestItem.css
new file mode 100644
index 000000000..5d1a2e9b6
--- /dev/null
+++ b/js/src/Status/SignerPending/RequestItem/requestItem.css
@@ -0,0 +1,24 @@
+/* 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 .
+*/
+
+.listDescription {
+ display: flex !important;
+}
+
+.toAvatar {
+ margin-left: 3px;
+}
diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.js b/js/src/Status/SignerPending/RequestItem/requestItem.js
new file mode 100644
index 000000000..13cddea0f
--- /dev/null
+++ b/js/src/Status/SignerPending/RequestItem/requestItem.js
@@ -0,0 +1,188 @@
+// 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 React, { Component } from 'react';
+import { connect } from 'react-redux';
+import { observer } from 'mobx-react';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from 'react-intl';
+
+import MethodDecodingStore from '@parity/ui/lib/MethodDecoding/methodDecodingStore';
+import { TOKEN_METHODS } from '@parity/ui/lib/MethodDecoding/constants';
+import TokenValue from '@parity/ui/lib/MethodDecoding/tokenValue';
+import IdentityIcon from '@parity/ui/lib/IdentityIcon';
+import Image from 'semantic-ui-react/dist/commonjs/elements/Image';
+import List from 'semantic-ui-react/dist/commonjs/elements/List';
+
+import EtherValue from '../EtherValue';
+import styles from './requestItem.css';
+
+@observer
+@connect(({ tokens }, { transaction }) => ({
+ token: Object.values(tokens).find(({ address }) => address === transaction.to)
+}))
+class RequestItem extends Component {
+ static propTypes = {
+ onClick: PropTypes.func.isRequired,
+ transaction: PropTypes.object.isRequired,
+ token: PropTypes.object
+ };
+
+ static contextTypes = {
+ api: PropTypes.object.isRequired
+ };
+
+ state = {
+ decoded: null // Decoded transaction
+ };
+
+ methodDecodingStore = MethodDecodingStore.get(this.context.api);
+
+ componentWillMount () {
+ const { transaction } = this.props;
+
+ // Decode the transaction and put it into the state
+ this.methodDecodingStore
+ .lookup(transaction.from, transaction)
+ .then(lookup => this.setState({
+ decoded: lookup
+ }));
+ }
+
+ renderDescription = () => {
+ // Decide what to display in the description, depending
+ // on what type of transaction we're dealing with
+ const { token } = this.props;
+ const {
+ inputs,
+ signature,
+ contract,
+ deploy
+ } = this.state.decoded;
+
+ if (deploy) {
+ return this.renderDeploy();
+ }
+
+ if (contract && signature) {
+ if (token && TOKEN_METHODS[signature] && inputs) {
+ return this.renderTokenTransfer();
+ }
+ return this.renderContractMethod();
+ }
+
+ return this.renderValueTransfer();
+ }
+
+ renderDeploy = () => {
+ return (
+
+ );
+ };
+
+ renderContractMethod = () => {
+ const { transaction } = this.props;
+
+ return (
+
+
+ {this.renderRecipient(transaction.to)}
+
+ );
+ };
+
+ renderTokenTransfer = () => {
+ const { token } = this.props;
+ const { inputs } = this.state.decoded;
+ const valueInput = inputs.find(({ name }) => name === '_value');
+ const toInput = inputs.find(({ name }) => name === '_to');
+
+ return (
+
+
+ )
+ }
+ }
+ />
+ {this.renderRecipient(toInput.value)}
+
+ );
+ };
+
+ renderValueTransfer = () => {
+ const { transaction } = this.props;
+
+ return (
+
+
+ }
+ }
+ />
+ {this.renderRecipient(transaction.to)}
+
+ );
+ };
+
+ renderRecipient = address => (
+
+ );
+
+ render () {
+ const { transaction, onClick } = this.props;
+
+ if (!this.state.decoded) { return null; }
+
+ return (
+
+
+
+
+
+
+
+
+ {this.renderDescription()}
+
+
+ );
+ }
+}
+
+export default RequestItem;
diff --git a/js/src/Status/SignerPending/index.js b/js/src/Status/SignerPending/index.js
new file mode 100644
index 000000000..b172c419a
--- /dev/null
+++ b/js/src/Status/SignerPending/index.js
@@ -0,0 +1,17 @@
+// 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 .
+
+export default from './signerPending';
diff --git a/js/src/Status/SignerPending/signerPending.css b/js/src/Status/SignerPending/signerPending.css
new file mode 100644
index 000000000..3fcc9ae7d
--- /dev/null
+++ b/js/src/Status/SignerPending/signerPending.css
@@ -0,0 +1,30 @@
+/* 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 .
+*/
+
+.signerPending {
+ margin-top: 4px !important;
+ position: relative;
+ cursor: pointer;
+}
+
+.label {
+ font-size: 0.65rem !important;
+}
+
+.noRequest {
+ min-width: 280px;
+}
diff --git a/js/src/Status/SignerPending/signerPending.js b/js/src/Status/SignerPending/signerPending.js
new file mode 100644
index 000000000..7c8283f40
--- /dev/null
+++ b/js/src/Status/SignerPending/signerPending.js
@@ -0,0 +1,128 @@
+// 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 React, { Component } from 'react';
+import { observer } from 'mobx-react';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from 'react-intl';
+
+import Container from 'semantic-ui-react/dist/commonjs/elements/Container';
+import Header from 'semantic-ui-react/dist/commonjs/elements/Header';
+import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon';
+import Label from 'semantic-ui-react/dist/commonjs/elements/Label';
+import List from 'semantic-ui-react/dist/commonjs/elements/List';
+import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
+
+import Store from './store';
+import ParityBarStore from '../../ParityBar/store';
+import RequestItem from './RequestItem';
+import styles from './signerPending.css';
+
+@observer
+class SignerPending extends Component {
+ static propTypes = {};
+
+ static contextTypes = {
+ api: PropTypes.object.isRequired
+ };
+
+ state = {
+ isOpen: false
+ };
+
+ store = Store.get(this.context.api);
+ parityBarStore = ParityBarStore.get();
+
+ handleRequestClick = () => {
+ this.parityBarStore.toggleOpenSigner();
+ this.handleClose();
+ };
+
+ handleOpen = () => {
+ this.setState({ isOpen: true });
+ };
+
+ handleClose = () => {
+ this.setState({ isOpen: false });
+ };
+
+ renderPopupContent = () => (
+
+ );
+
+ render () {
+ return (
+
+ 0 ? 'bell' : 'bell outline' }
+ />
+ {this.store.pending.length > 0 && (
+
+ )}
+
+ }
+ content={ this.renderPopupContent() }
+ offset={ 8 } // Empirically looks better
+ on='click'
+ hideOnScroll
+ open={ this.state.isOpen }
+ onClose={ this.handleClose }
+ onOpen={ this.handleOpen }
+ position='bottom right'
+ />
+ );
+ }
+}
+
+export default SignerPending;
diff --git a/js/src/Status/SignerPending/store.js b/js/src/Status/SignerPending/store.js
new file mode 100644
index 000000000..c2dad5351
--- /dev/null
+++ b/js/src/Status/SignerPending/store.js
@@ -0,0 +1,50 @@
+// 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, observable } from 'mobx';
+
+let instance;
+
+export default class Store {
+ @observable pending = [];
+
+ constructor (api) {
+ this._api = api;
+ this.startSubscription();
+ }
+
+ @action setPending = (pending = []) => {
+ this.pending = pending;
+ }
+
+ startSubscription () {
+ this._api.subscribe('signer_requestsToConfirm', (error, pending) => {
+ if (error) {
+ return;
+ }
+
+ this.setPending(pending);
+ });
+ }
+
+ static get (api) {
+ if (!instance) {
+ instance = new Store(api);
+ }
+
+ return instance;
+ }
+}
diff --git a/js/src/Status/status.css b/js/src/Status/status.css
index e38792f9e..110d2f3c8 100644
--- a/js/src/Status/status.css
+++ b/js/src/Status/status.css
@@ -75,10 +75,6 @@ $textColor: #ccc;
opacity: 0.75;
}
- .signerPending {
- cursor: pointer;
- }
-
.health {
> span {
margin: -0.5rem 0 0.2rem 0 !important;
diff --git a/js/src/Status/status.js b/js/src/Status/status.js
index 24513304b..947a09739 100644
--- a/js/src/Status/status.js
+++ b/js/src/Status/status.js
@@ -25,21 +25,19 @@ import GradientBg from '@parity/ui/lib/GradientBg';
import { HomeIcon } from '@parity/ui/lib/Icons';
import NetChain from '@parity/ui/lib/NetChain';
import NetPeers from '@parity/ui/lib/NetPeers';
-import SignerPending from '@parity/ui/lib/SignerPending';
import StatusIndicator from '@parity/ui/lib/StatusIndicator';
import Consensus from './Consensus';
import DefaultAccount from './DefaultAccount';
import AccountStore from '../ParityBar/accountStore';
-import ParityBarStore from '../ParityBar/store';
import SyncWarning from '../SyncWarning';
import PluginStore from './pluginStore';
+import SignerPending from './SignerPending';
import Upgrade from './Upgrade';
import styles from './status.css';
const pluginStore = PluginStore.get();
-const parityBarStore = ParityBarStore.get();
function Status ({ className = '', upgradeStore }, { api }) {
const accountStore = AccountStore.get(api);
@@ -63,10 +61,6 @@ function Status ({ className = '', upgradeStore }, { api }) {
))
}
-
+
+