diff --git a/js/src/redux/providers/signerMiddleware.js b/js/src/redux/providers/signerMiddleware.js
index 869a7d802..282e93601 100644
--- a/js/src/redux/providers/signerMiddleware.js
+++ b/js/src/redux/providers/signerMiddleware.js
@@ -103,6 +103,12 @@ export default class SignerMiddleware {
return this.confirmRawRequest(store, id, signature);
}
+ confirmDecryptedMsg (store, id, decrypted) {
+ const { msg } = decrypted;
+
+ return this.confirmRawRequest(store, id, msg);
+ }
+
confirmSignedTransaction (store, id, txSigned) {
const { netVersion } = store.getState().nodeStatus;
const { signature, tx } = txSigned;
@@ -153,7 +159,7 @@ export default class SignerMiddleware {
}
onConfirmStart = (store, action) => {
- const { condition, gas = 0, gasPrice = 0, id, password, payload, txSigned, dataSigned, wallet } = action.payload;
+ const { condition, gas = 0, gasPrice = 0, id, password, payload, txSigned, dataSigned, decrypted, wallet } = action.payload;
const handlePromise = this._createConfirmPromiseHandler(store, id);
const transaction = payload.sendTransaction || payload.signTransaction;
@@ -176,10 +182,14 @@ export default class SignerMiddleware {
}
}
- // TODO [ToDr] Support eth_sign for external wallet (wallet && !transction)
+ // TODO [ToDr] Support eth_sign for external wallet (wallet && dataSigned)
if (dataSigned) {
return this.confirmSignedData(store, id, dataSigned);
}
+ // TODO [ToDr] Support parity_decrypt for external wallet (wallet && decrypted)
+ if (decrypted) {
+ return this.confirmDecryptedMsg(store, id, decrypted);
+ }
return handlePromise(this._api.signer.confirmRequest(id, { gas, gasPrice, condition }, password));
}
diff --git a/js/src/util/qrscan.js b/js/src/util/qrscan.js
index da73d5b8f..97fa70c84 100644
--- a/js/src/util/qrscan.js
+++ b/js/src/util/qrscan.js
@@ -121,6 +121,16 @@ export function generateDataQr (data) {
});
}
+export function generateDecryptQr (data) {
+ return Promise.resolve({
+ decrypt: data,
+ value: JSON.stringify({
+ action: 'decrypt',
+ data
+ })
+ });
+}
+
export function generateTxQr (api, netVersion, transaction) {
return createUnsignedTx(api, netVersion, transaction)
.then((qr) => {
diff --git a/js/src/views/Signer/components/DecryptRequest/decryptRequest.js b/js/src/views/Signer/components/DecryptRequest/decryptRequest.js
index f4626c755..703582c9e 100644
--- a/js/src/views/Signer/components/DecryptRequest/decryptRequest.js
+++ b/js/src/views/Signer/components/DecryptRequest/decryptRequest.js
@@ -114,7 +114,7 @@ class DecryptRequest extends Component {
}
renderActions () {
- const { accounts, address, focus, isFinished, status } = this.props;
+ const { accounts, address, focus, isFinished, status, data } = this.props;
const account = accounts[address];
if (isFinished) {
@@ -153,15 +153,16 @@ class DecryptRequest extends Component {
onConfirm={ this.onConfirm }
onReject={ this.onReject }
className={ styles.actions }
+ dataToSign={ { decrypt: data } }
/>
);
}
onConfirm = (data) => {
const { id } = this.props;
- const { password } = data;
+ const { password, decrypted, wallet } = data;
- this.props.onConfirm({ id, password });
+ this.props.onConfirm({ id, password, decrypted, wallet });
}
onReject = () => {
diff --git a/js/src/views/Signer/components/RequestPending/requestPending.spec.js b/js/src/views/Signer/components/RequestPending/requestPending.spec.js
index 130a9d319..3c2d29cf0 100644
--- a/js/src/views/Signer/components/RequestPending/requestPending.spec.js
+++ b/js/src/views/Signer/components/RequestPending/requestPending.spec.js
@@ -40,6 +40,12 @@ const PAYLOAD_SIGN = {
const PAYLOAD_SIGNTX = {
signTransaction: TRANSACTION
};
+const PAYLOAD_DECRYPT = {
+ decrypt: {
+ address: ADDRESS,
+ msg: 'testing'
+ }
+};
let component;
let onConfirm;
@@ -109,4 +115,18 @@ describe('views/Signer/RequestPending', () => {
expect(component.find('Connect(TransactionPending)')).to.have.length(1);
});
});
+
+ describe('decrypt', () => {
+ beforeEach(() => {
+ render(PAYLOAD_DECRYPT);
+ });
+
+ it('renders defaults', () => {
+ expect(component).to.be.ok;
+ });
+
+ it('renders DecryptRequest component', () => {
+ expect(component.find('Connect(DecryptRequest)')).to.have.length(1);
+ });
+ });
});
diff --git a/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingFormConfirm/transactionPendingFormConfirm.js b/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingFormConfirm/transactionPendingFormConfirm.js
index 8d4e4a9cc..f6c4883a8 100644
--- a/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingFormConfirm/transactionPendingFormConfirm.js
+++ b/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingFormConfirm/transactionPendingFormConfirm.js
@@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl';
import ReactTooltip from 'react-tooltip';
import { Form, Input, IdentityIcon, QrCode, QrScan } from '~/ui';
-import { generateTxQr, generateDataQr } from '~/util/qrscan';
+import { generateTxQr, generateDataQr, generateDecryptQr } from '~/util/qrscan';
import styles from './transactionPendingFormConfirm.css';
@@ -352,7 +352,7 @@ export default class TransactionPendingFormConfirm extends Component {
return (
);
}
@@ -404,8 +404,8 @@ export default class TransactionPendingFormConfirm extends Component {
);
}
- onScanTx = (signature) => {
- const { chainId, rlp, tx, data } = this.state.qr;
+ onScan = (signature) => {
+ const { chainId, rlp, tx, data, decrypt } = this.state.qr;
if (signature && signature.substr(0, 2) !== '0x') {
signature = `0x${signature}`;
@@ -425,6 +425,16 @@ export default class TransactionPendingFormConfirm extends Component {
return;
}
+ if (decrypt) {
+ this.props.onConfirm({
+ decrypted: {
+ decrypt,
+ msg: signature
+ }
+ });
+ return;
+ }
+
this.props.onConfirm({
dataSigned: {
data,
@@ -499,7 +509,7 @@ export default class TransactionPendingFormConfirm extends Component {
generateQr = () => {
const { api } = this.context;
const { netVersion, dataToSign } = this.props;
- const { transaction, data } = dataToSign;
+ const { transaction, data, decrypt } = dataToSign;
const setState = qr => {
this.setState({ qr });
};
@@ -509,6 +519,11 @@ export default class TransactionPendingFormConfirm extends Component {
return;
}
+ if (decrypt) {
+ generateDecryptQr(decrypt).then(setState);
+ return;
+ }
+
generateDataQr(data).then(setState);
}
@@ -547,7 +562,7 @@ export default class TransactionPendingFormConfirm extends Component {
const { account, dataToSign } = this.props;
const { qr } = this.state;
- if (dataToSign.data && qr && !qr.value) {
+ if ((dataToSign.data || dataToSign.decrypt) && qr && !qr.value) {
this.generateQr();
return;
}
diff --git a/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js b/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js
index e176b97e9..e7248e1ab 100644
--- a/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js
+++ b/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js
@@ -40,6 +40,9 @@ export default class TransactionPendingForm extends Component {
}),
PropTypes.shape({
data: PropTypes.string.isRequired
+ }),
+ PropTypes.shape({
+ decrypt: PropTypes.string.isRequired
})
]).isRequired
};
diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs
index 569d9f4db..0e09d1db2 100644
--- a/rpc/src/v1/impls/signer.rs
+++ b/rpc/src/v1/impls/signer.rs
@@ -201,8 +201,10 @@ impl Signer for SignerClient {
Err(err) => Err(errors::invalid_params("Invalid signature received.", err)),
}
},
- // TODO [ToDr]: Decrypt - pass through?
- _ => Err(errors::unimplemented(Some("Non-transaction requests does not support RAW signing yet.".into()))),
+ ConfirmationPayload::Decrypt(_address, _data) => {
+ // TODO [ToDr]: Decrypt can we verify if the answer is correct?
+ Ok(ConfirmationResponse::Decrypt(bytes))
+ },
};
if let Ok(ref response) = result {
signer.request_confirmed(id, Ok(response.clone()));
diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs
index c0cc7ef3e..d9f7b96a9 100644
--- a/rpc/src/v1/tests/mocked/signer.rs
+++ b/rpc/src/v1/tests/mocked/signer.rs
@@ -28,7 +28,7 @@ use jsonrpc_core::IoHandler;
use v1::{SignerClient, Signer, Origin};
use v1::metadata::Metadata;
use v1::tests::helpers::TestMinerService;
-use v1::types::H520;
+use v1::types::{Bytes as RpcBytes, H520};
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
use v1::helpers::dispatch::{FullDispatcher, eth_data_hash};
@@ -479,7 +479,6 @@ fn should_confirm_sign_transaction_with_rlp() {
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
}
-
#[test]
fn should_confirm_data_sign_with_signature() {
// given
@@ -510,6 +509,34 @@ fn should_confirm_data_sign_with_signature() {
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
}
+#[test]
+fn should_confirm_decrypt_with_phrase() {
+ // given
+ let tester = signer_tester();
+ let address = tester.accounts.new_account("test").unwrap();
+ tester.signer.add_request(ConfirmationPayload::Decrypt(
+ address,
+ vec![1, 2, 3, 4].into(),
+ ), Origin::Unknown).unwrap();
+ assert_eq!(tester.signer.requests().len(), 1);
+
+ let decrypted = serde_json::to_string(&RpcBytes::new(b"phrase".to_vec())).unwrap();
+
+ // when
+ let request = r#"{
+ "jsonrpc":"2.0",
+ "method":"signer_confirmRequestRaw",
+ "params":["0x1", "#.to_owned() + &decrypted + r#"],
+ "id":1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"#.to_owned() + &decrypted + r#","id":1}"#;
+
+ // then
+ assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
+ assert_eq!(tester.signer.requests().len(), 0);
+ assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
+}
+
#[test]
fn should_generate_new_token() {
// given