From a25540ce589bef2d01a0513c03690883b1217249 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 10 Aug 2023 23:07:58 +0400 Subject: [PATCH 01/12] APL-2337: add transactions offline --- package.json | 2 +- src/helpers/transactions/index.js | 51 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/helpers/transactions/index.js diff --git a/package.json b/package.json index c87c60e92..53b253ec3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@fortawesome/fontawesome-free": "5.13.0", - "apl-web-crypto": "^1.0.2", + "apl-web-crypto": "^1.0.29", "axios": "0.19.2", "bignumber.js": "9.1.0", "bootstrap": "4.4.1", diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js new file mode 100644 index 000000000..800f99a61 --- /dev/null +++ b/src/helpers/transactions/index.js @@ -0,0 +1,51 @@ +import { Crypto, Transaction } from 'apl-web-crypto'; +import { ONE_APL } from 'constants/constants'; + +export const sendMoneyOfflineTransaction = async ({ + secretPhrase, + amountATM, + feeATM, + deadline = 1440, + recipient, +}) => { + const publicKey = Crypto.getPublicKey(secretPhrase); + + const data = { + publicKey, + requestType: 'sendMoney', + amountATM: amountATM * ONE_APL, + feeATM: feeATM * ONE_APL, + deadline, + recipient, + secretPhrase + }; + + const signedResponse = await Transaction.sendWithOfflineSign(data) + + const dataTransaction = { + requestType: 'broadcastTransaction', + transactionBytes: signedResponse.transactionBytes, + } + return await Transaction.send(dataTransaction); +} + +export const sendCurrencyTransferOffline = async ({secretPhrase, feeATM,...initialData}) => { + const publicKey = Crypto.getPublicKey(secretPhrase); + + const data = { + ...initialData, + publicKey, + requestType: 'transferCurrency', + deadline: 1440, + feeATM: feeATM * ONE_APL, + secretPhrase, + }; + + const signedResponse = await Transaction.sendWithOfflineSign(data) + + const dataTransaction = { + requestType: 'broadcastTransaction', + transactionBytes: signedResponse.transactionBytes, + } + return await Transaction.send(dataTransaction); +} \ No newline at end of file From a62d8d363eb8f53db9be3183c0ce0a294446625a Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 10 Aug 2023 23:20:25 +0400 Subject: [PATCH 02/12] APL-2337: add offline transactions to the flow submit --- .../handle-form-submit/index.js | 5 ++- src/containers/modals/send-apollo/index.jsx | 39 +++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js index a79df376a..d21167e8e 100644 --- a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js +++ b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js @@ -1,7 +1,7 @@ import { NotificationManager } from 'react-notifications'; import { setBodyModalParamsAction } from 'modules/modals'; -import submitForm from 'helpers/forms/forms'; import { setModalProcessingTrueAction, setModalProcessingFalseAction } from 'actions/modals'; +import { sendCurrencyTransferOffline } from 'helpers/transactions'; export const handleFormSubmit = ({decimals, ...values}) => async dispatch => { const data = { @@ -11,7 +11,8 @@ export const handleFormSubmit = ({decimals, ...values}) => async dispatch => { dispatch(setModalProcessingTrueAction()) - const res = await dispatch(submitForm.submitForm(data, 'transferCurrency')); + const res = await sendCurrencyTransferOffline(data); + if (res && res.errorCode) { dispatch(setModalProcessingFalseAction()) NotificationManager.error(res.errorDescription, 'Error', 5000); diff --git a/src/containers/modals/send-apollo/index.jsx b/src/containers/modals/send-apollo/index.jsx index 45e9f08a9..2e9c7c5f5 100644 --- a/src/containers/modals/send-apollo/index.jsx +++ b/src/containers/modals/send-apollo/index.jsx @@ -16,6 +16,8 @@ import { import ModalBody from 'containers/components/modals/modal-body'; import {PrivateTransactionConfirm} from './PrivateTransactionConfirm/PrivateTransactionConfirm'; import SendApolloForm from './form'; +import { sendMoneyOfflineTransaction } from 'helpers/transactions'; +import { setModalProcessingFalseAction, setModalProcessingTrueAction } from 'actions/modals'; export default function SendApollo({ closeModal, processForm }) { const [ isShowNotification, setIsShowNotification ] = useState(false); @@ -33,6 +35,8 @@ export default function SendApollo({ closeModal, processForm }) { return; } + dispatch(setModalProcessingTrueAction()) + if (values.doNotSign) { data.publicKey = await crypto.getPublicKeyAPL(account, true); delete data.secretPhrase; @@ -46,18 +50,31 @@ export default function SendApollo({ closeModal, processForm }) { data.recipient = values.alias; } - processForm({ decimals, ...data }, 'sendMoney', 'Transaction has been submitted!', res => { - if (res.broadcasted === false) { - dispatch(setBodyModalParamsAction('RAW_TRANSACTION_DETAILS', { - request: data, - result: res, - })); - } else { - closeModal(); - } - - NotificationManager.success('Transaction has been submitted!', null, 5000); + const res = await sendMoneyOfflineTransaction({ + recipient: data.recipient, + secretPhrase: data.secretPhrase, + amountATM: data.amountATM, + feeATM: data.feeATM, + deadline: data.deadline, }); + + dispatch(setModalProcessingFalseAction()); + + if (res && res.errorCode) { + NotificationManager.error(res.errorDescription, 'Error', 5000); + return; + } + + if (res.broadcasted === false) { + dispatch(setBodyModalParamsAction('RAW_TRANSACTION_DETAILS', { + request: data, + result: res, + })); + } else { + closeModal(); + } + + NotificationManager.success('Transaction has been submitted!', null, 5000); }, [account, closeModal, decimals, dispatch, processForm]); const handleShowNotification = (value) => () => { From 75b4896a8f9d79e9056949ddbbb0492ced75493a Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Fri, 11 Aug 2023 14:52:45 +0400 Subject: [PATCH 03/12] APL-2337: add validation to sendMoney transaction --- src/containers/modals/send-apollo/index.jsx | 69 ++++++++++----------- src/helpers/transactions/index.js | 53 ++++++++++++---- 2 files changed, 74 insertions(+), 48 deletions(-) diff --git a/src/containers/modals/send-apollo/index.jsx b/src/containers/modals/send-apollo/index.jsx index 2e9c7c5f5..5414fa3e2 100644 --- a/src/containers/modals/send-apollo/index.jsx +++ b/src/containers/modals/send-apollo/index.jsx @@ -8,9 +8,11 @@ import { useSelector, useDispatch, shallowEqual } from 'react-redux'; import { NotificationManager } from 'react-notifications'; import { setBodyModalParamsAction } from 'modules/modals'; import { + getAccountRsSelector, getAccountSelector, getDecimalsSelector, getModalDataSelector, + getPassPhraseSelector, getTickerSelector } from 'selectors'; import ModalBody from 'containers/components/modals/modal-body'; @@ -24,7 +26,8 @@ export default function SendApollo({ closeModal, processForm }) { const dispatch = useDispatch(); const modalData = useSelector(getModalDataSelector, shallowEqual); - const account = useSelector(getAccountSelector); + const accountRS = useSelector(getAccountRsSelector); + const passPhrase = useSelector(getPassPhraseSelector); const ticker = useSelector(getTickerSelector); const decimals = useSelector(getDecimalsSelector); @@ -37,45 +40,41 @@ export default function SendApollo({ closeModal, processForm }) { dispatch(setModalProcessingTrueAction()) - if (values.doNotSign) { - data.publicKey = await crypto.getPublicKeyAPL(account, true); - delete data.secretPhrase; - } - - if (values.phasingFinishHeight) { - data.phased = true; - } - if (values.alias) { data.recipient = values.alias; } - const res = await sendMoneyOfflineTransaction({ - recipient: data.recipient, - secretPhrase: data.secretPhrase, - amountATM: data.amountATM, - feeATM: data.feeATM, - deadline: data.deadline, - }); - - dispatch(setModalProcessingFalseAction()); - - if (res && res.errorCode) { - NotificationManager.error(res.errorDescription, 'Error', 5000); - return; - } - - if (res.broadcasted === false) { - dispatch(setBodyModalParamsAction('RAW_TRANSACTION_DETAILS', { - request: data, - result: res, - })); - } else { - closeModal(); + try { + const res = await sendMoneyOfflineTransaction({ + recipient: data.recipient, + secretPhrase: data.secretPhrase, + amountATM: data.amountATM, + feeATM: data.feeATM, + deadline: data.deadline, + }, accountRS, passPhrase); + + dispatch(setModalProcessingFalseAction()); + + if (res && res.errorCode) { + NotificationManager.error(res.errorDescription, 'Error', 5000); + return; + } + + if (res.broadcasted === false) { + dispatch(setBodyModalParamsAction('RAW_TRANSACTION_DETAILS', { + request: data, + result: res, + })); + } else { + closeModal(); + } + + NotificationManager.success('Transaction has been submitted!', null, 5000); + } catch (e) { + dispatch(setModalProcessingFalseAction()); + NotificationManager.error(e.message, 'Error', 5000); } - - NotificationManager.success('Transaction has been submitted!', null, 5000); - }, [account, closeModal, decimals, dispatch, processForm]); + }, [closeModal, decimals, dispatch, passPhrase, accountRS]); const handleShowNotification = (value) => () => { setIsShowNotification(value); diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index 800f99a61..365fd0edd 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -1,15 +1,41 @@ import { Crypto, Transaction } from 'apl-web-crypto'; import { ONE_APL } from 'constants/constants'; -export const sendMoneyOfflineTransaction = async ({ - secretPhrase, - amountATM, - feeATM, - deadline = 1440, - recipient, -}) => { +// check user secretPhase and compare account RS from publicKey and from request +// return publicKey +const checkAccountForOfflineSignAndPublicKey = (secretPhrase, accountRS, appPassPhraseFromStore) => { + + if (!secretPhrase) throw new Error('Secret phrase is empty'); + + if (!accountRS) throw new Error('Set sender account'); + + if(appPassPhraseFromStore && secretPhrase !== appPassPhraseFromStore) { + throw new Error('Incorrect secret phrase') + } + const publicKey = Crypto.getPublicKey(secretPhrase); + const userFromPublicKey = Crypto.getAccountIdFromPublicKey(publicKey, true); + + if (accountRS !== userFromPublicKey) { + throw new Error('Incorrect secret phrase') + } + return publicKey; +} + +export const sendMoneyOfflineTransaction = async ( + { + secretPhrase, + amountATM, + feeATM, + deadline = 1440, + recipient, + }, + accountRS, + appPassPhraseFromStore +) => { + const publicKey = checkAccountForOfflineSignAndPublicKey(secretPhrase, accountRS, appPassPhraseFromStore); + const data = { publicKey, requestType: 'sendMoney', @@ -17,10 +43,11 @@ export const sendMoneyOfflineTransaction = async ({ feeATM: feeATM * ONE_APL, deadline, recipient, - secretPhrase }; - const signedResponse = await Transaction.sendWithOfflineSign(data) + const unsignedTransactionData = await Transaction.sendNotSign(data); + const sendData = {secretPhrase: secretPhrase }; + const signedResponse = await Transaction.processOfflineSign(sendData, unsignedTransactionData); const dataTransaction = { requestType: 'broadcastTransaction', @@ -32,16 +59,16 @@ export const sendMoneyOfflineTransaction = async ({ export const sendCurrencyTransferOffline = async ({secretPhrase, feeATM,...initialData}) => { const publicKey = Crypto.getPublicKey(secretPhrase); - const data = { + const unsignedTransactionData = await Transaction.sendNotSign({ ...initialData, publicKey, requestType: 'transferCurrency', deadline: 1440, feeATM: feeATM * ONE_APL, - secretPhrase, - }; + }); - const signedResponse = await Transaction.sendWithOfflineSign(data) + const sendData = {secretPhrase: secretPhrase }; + const signedResponse = await Transaction.processOfflineSign(sendData, unsignedTransactionData); const dataTransaction = { requestType: 'broadcastTransaction', From ebe3461a7965b67d3254fd5b572e2696fa166472 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Fri, 11 Aug 2023 15:30:12 +0400 Subject: [PATCH 04/12] APL-2337: add check secretPhrase to transferCurrency --- .../handle-form-submit/index.js | 33 ++++++++++++------- src/helpers/transactions/index.js | 8 +++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js index d21167e8e..2f9daf874 100644 --- a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js +++ b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js @@ -2,23 +2,34 @@ import { NotificationManager } from 'react-notifications'; import { setBodyModalParamsAction } from 'modules/modals'; import { setModalProcessingTrueAction, setModalProcessingFalseAction } from 'actions/modals'; import { sendCurrencyTransferOffline } from 'helpers/transactions'; +import { getAccountRsSelector, getPassPhraseSelector } from 'selectors'; + +export const handleFormSubmit = ({decimals, ...values}) => async (dispatch, getState) => { + const state = getState(); + const accountRS = getAccountRsSelector(state); + const passPhrase = getPassPhraseSelector(state); -export const handleFormSubmit = ({decimals, ...values}) => async dispatch => { const data = { ...values, units: values.units * (10 ** (decimals || 0)), }; - dispatch(setModalProcessingTrueAction()) - - const res = await sendCurrencyTransferOffline(data); + dispatch(setModalProcessingTrueAction()); - if (res && res.errorCode) { - dispatch(setModalProcessingFalseAction()) - NotificationManager.error(res.errorDescription, 'Error', 5000); - } else { - dispatch(setModalProcessingFalseAction()) - dispatch(setBodyModalParamsAction()); - NotificationManager.success('Transfer currency request has been submitted!', null, 5000); + try { + const res = await sendCurrencyTransferOffline(data, accountRS, passPhrase); + + if (res && res.errorCode) { + dispatch(setModalProcessingFalseAction()) + NotificationManager.error(res.errorDescription, 'Error', 5000); + } else { + dispatch(setModalProcessingFalseAction()) + dispatch(setBodyModalParamsAction()); + NotificationManager.success('Transfer currency request has been submitted!', null, 5000); + } + } catch (e) { + dispatch(setModalProcessingFalseAction()); + NotificationManager.error(e.message, 'Error', 5000); } + }; diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index 365fd0edd..16bab26d6 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -56,8 +56,12 @@ export const sendMoneyOfflineTransaction = async ( return await Transaction.send(dataTransaction); } -export const sendCurrencyTransferOffline = async ({secretPhrase, feeATM,...initialData}) => { - const publicKey = Crypto.getPublicKey(secretPhrase); +export const sendCurrencyTransferOffline = async ( + {secretPhrase, feeATM,...initialData}, + accountRS, + appPassPhraseFromStore +) => { + const publicKey = checkAccountForOfflineSignAndPublicKey(secretPhrase, accountRS, appPassPhraseFromStore); const unsignedTransactionData = await Transaction.sendNotSign({ ...initialData, From 2871e10ba6670a0f0c281dc33702598e006969d5 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Fri, 11 Aug 2023 17:53:07 +0400 Subject: [PATCH 05/12] APL-2334: add message to offline sign --- .../form-components/MessageInputs/index.jsx | 2 +- src/containers/modals/send-apollo/index.jsx | 17 ++++++++++------- src/helpers/transactions/index.js | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/containers/components/form-components/MessageInputs/index.jsx b/src/containers/components/form-components/MessageInputs/index.jsx index c4cbda6bc..6f190c037 100644 --- a/src/containers/components/form-components/MessageInputs/index.jsx +++ b/src/containers/components/form-components/MessageInputs/index.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { useFormikContext } from 'formik'; import CheckboxWithFormik from 'containers/components/check-button-input/CheckboxWithFormik'; -import CustomTextArea from '../TextArea'; +import CustomTextArea from '../TextArea/TextAreaWithFormik'; export const MessageInputs = ({ idGroup }) => { const { values } = useFormikContext(); diff --git a/src/containers/modals/send-apollo/index.jsx b/src/containers/modals/send-apollo/index.jsx index 5414fa3e2..4a7dbf781 100644 --- a/src/containers/modals/send-apollo/index.jsx +++ b/src/containers/modals/send-apollo/index.jsx @@ -32,6 +32,7 @@ export default function SendApollo({ closeModal, processForm }) { const decimals = useSelector(getDecimalsSelector); const handleFormSubmit = useCallback(async values => { + console.log("🚀 ~ file: index.jsx:35 ~ handleFormSubmit ~ values:", values) const { privateTransaction, ...data } = values; if (!values.secretPhrase || values.secretPhrase.length === 0) { NotificationManager.error('Secret Phrase is required.', 'Error', 5000); @@ -44,14 +45,16 @@ export default function SendApollo({ closeModal, processForm }) { data.recipient = values.alias; } + // const sendedData = { + // recipient: data.recipient, + // secretPhrase: data.secretPhrase, + // amountATM: data.amountATM, + // feeATM: data.feeATM, + // deadline: data.deadline, + // }; + try { - const res = await sendMoneyOfflineTransaction({ - recipient: data.recipient, - secretPhrase: data.secretPhrase, - amountATM: data.amountATM, - feeATM: data.feeATM, - deadline: data.deadline, - }, accountRS, passPhrase); + const res = await sendMoneyOfflineTransaction(data, accountRS, passPhrase); dispatch(setModalProcessingFalseAction()); diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index 16bab26d6..c6bcfb434 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -30,6 +30,10 @@ export const sendMoneyOfflineTransaction = async ( feeATM, deadline = 1440, recipient, + add_message, + encrypt_message, + permanent_message, + message, }, accountRS, appPassPhraseFromStore @@ -45,6 +49,18 @@ export const sendMoneyOfflineTransaction = async ( recipient, }; + if (add_message && encrypt_message) { + data.messageToEncrypt = message; + } + + if (add_message) { + data.message = message; + } + + if (add_message && permanent_message) { + data.permanent_message = permanent_message; + } + const unsignedTransactionData = await Transaction.sendNotSign(data); const sendData = {secretPhrase: secretPhrase }; const signedResponse = await Transaction.processOfflineSign(sendData, unsignedTransactionData); From 2a298ffc2abdd93508905e13a03fa3b6d2ddc738 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Wed, 16 Aug 2023 22:57:07 +0400 Subject: [PATCH 06/12] APL-2334: add encrypting for message --- src/helpers/transactions/check.js | 87 +++++++++++++++++++++++++++++++ src/helpers/transactions/index.js | 19 ++++++- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/helpers/transactions/check.js diff --git a/src/helpers/transactions/check.js b/src/helpers/transactions/check.js new file mode 100644 index 000000000..324495dac --- /dev/null +++ b/src/helpers/transactions/check.js @@ -0,0 +1,87 @@ +NRS.encryptNote = function(message, options, secretPhrase) { + try { + options = NRS.getEncryptionKeys(options, secretPhrase); + var encrypted = encryptData(converters.stringToByteArray(message), options); + return { + "message": converters.byteArrayToHexString(encrypted.data), + "nonce": converters.byteArrayToHexString(encrypted.nonce) + }; + } catch (err) { + if (err.errorCode && err.errorCode < 5) { + throw err; + } else { + throw { + "message": $.t("error_message_encryption"), + "errorCode": 5 + }; + } + } +}; + + +NRS.getEncryptionKeys = function (options, secretPhrase){ + if (!options.sharedKey) { + if (!options.privateKey) { + if (!secretPhrase) { + if (NRS.rememberPassword) { + secretPhrase = _password; + } else { + throw { + "message": $.t("error_encryption_passphrase_required"), + "errorCode": 1 + }; + } + } + + options.privateKey = converters.hexStringToByteArray(NRS.getPrivateKey(secretPhrase)); + } + + if (!options.publicKey) { + if (!options.account) { + throw { + "message": $.t("error_account_id_not_specified"), + "errorCode": 2 + }; + } + + try { + options.publicKey = converters.hexStringToByteArray(NRS.getPublicKey(options.account, true)); + } catch (err) { + var nxtAddress = new NxtAddress(); + + if (!nxtAddress.set(options.account)) { + throw { + "message": $.t("error_invalid_account_id"), + "errorCode": 3 + }; + } else { + throw { + "message": $.t("error_public_key_not_specified"), + "errorCode": 4 + }; + } + } + } else if (typeof options.publicKey == "string") { + options.publicKey = converters.hexStringToByteArray(options.publicKey); + } + } + return options; +}; + + +function encryptData(plaintext, options) { + options.nonce = getRandomBytes(32); + if (!options.sharedKey) { + options.sharedKey = getSharedSecret(options.privateKey, options.publicKey); + } + var compressedPlaintext = pako.gzip(new Uint8Array(plaintext)); + var data = aesEncrypt(compressedPlaintext, options); + return { + "nonce": options.nonce, + "data": data + }; +} + +function getSharedSecret(key1, key2) { + return converters.shortArrayToByteArray(curve25519_(converters.byteArrayToShortArray(key1), converters.byteArrayToShortArray(key2), null)); +} \ No newline at end of file diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index c6bcfb434..4a9d4f993 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -1,5 +1,7 @@ import { Crypto, Transaction } from 'apl-web-crypto'; import { ONE_APL } from 'constants/constants'; +import LocalCrypto from '../crypto/crypto'; +import converters from '../converters'; // check user secretPhase and compare account RS from publicKey and from request // return publicKey @@ -49,8 +51,23 @@ export const sendMoneyOfflineTransaction = async ( recipient, }; + if (add_message && encrypt_message) { - data.messageToEncrypt = message; + const privateKey = Crypto.getPrivateKey(secretPhrase); + + const encrypted = LocalCrypto.encryptDataAPL(converters.stringToByteArray(message), { + privateKey, + publicKey, + }) + + data.encryptedMessageData = converters.byteArrayToHexString(encrypted.data); + data.encryptedMessageNonce = converters.byteArrayToHexString(encrypted.nonce); + + if (recipient === accountRS) { + data.messageToEncryptToSelfIsText = "true" + } else { + data.messageToEncryptIsText = "true" + } } if (add_message) { From 98f1aafd4649dd5f3ad676af58ddbefd89906fe3 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 15:04:17 +0400 Subject: [PATCH 07/12] APL-2334: add condition send sendMoney request for vault and standart wallets --- src/containers/modals/send-apollo/index.jsx | 31 +++++++++++++-------- src/helpers/transactions/index.js | 8 +++++- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/containers/modals/send-apollo/index.jsx b/src/containers/modals/send-apollo/index.jsx index 4a7dbf781..38f6899a9 100644 --- a/src/containers/modals/send-apollo/index.jsx +++ b/src/containers/modals/send-apollo/index.jsx @@ -9,7 +9,6 @@ import { NotificationManager } from 'react-notifications'; import { setBodyModalParamsAction } from 'modules/modals'; import { getAccountRsSelector, - getAccountSelector, getDecimalsSelector, getModalDataSelector, getPassPhraseSelector, @@ -18,7 +17,7 @@ import { import ModalBody from 'containers/components/modals/modal-body'; import {PrivateTransactionConfirm} from './PrivateTransactionConfirm/PrivateTransactionConfirm'; import SendApolloForm from './form'; -import { sendMoneyOfflineTransaction } from 'helpers/transactions'; +import { sendMoneyOfflineTransaction, checkIsVaultWallet } from 'helpers/transactions'; import { setModalProcessingFalseAction, setModalProcessingTrueAction } from 'actions/modals'; export default function SendApollo({ closeModal, processForm }) { @@ -45,13 +44,23 @@ export default function SendApollo({ closeModal, processForm }) { data.recipient = values.alias; } - // const sendedData = { - // recipient: data.recipient, - // secretPhrase: data.secretPhrase, - // amountATM: data.amountATM, - // feeATM: data.feeATM, - // deadline: data.deadline, - // }; + const isVaultWallet = checkIsVaultWallet(data.secretPhrase, accountRS); + + if (isVaultWallet) { + processForm({ decimals, ...data }, 'sendMoney', 'Transaction has been submitted!', res => { + if (res.broadcasted === false) { + dispatch(setBodyModalParamsAction('RAW_TRANSACTION_DETAILS', { + request: data, + result: res, + })); + } else { + closeModal(); + } + + NotificationManager.success('Transaction has been submitted!', null, 5000); + }); + return; + } try { const res = await sendMoneyOfflineTransaction(data, accountRS, passPhrase); @@ -75,9 +84,9 @@ export default function SendApollo({ closeModal, processForm }) { NotificationManager.success('Transaction has been submitted!', null, 5000); } catch (e) { dispatch(setModalProcessingFalseAction()); - NotificationManager.error(e.message, 'Error', 5000); + NotificationManager.error('Transaction error', 'Error', 5000); } - }, [closeModal, decimals, dispatch, passPhrase, accountRS]); + }, [closeModal, decimals, dispatch, passPhrase, accountRS, processForm]); const handleShowNotification = (value) => () => { setIsShowNotification(value); diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index 4a9d4f993..3ae1e3734 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -3,6 +3,12 @@ import { ONE_APL } from 'constants/constants'; import LocalCrypto from '../crypto/crypto'; import converters from '../converters'; +export const checkIsVaultWallet = (secretPhrase, accountRS) => { + const publicKey = Crypto.getPublicKey(secretPhrase); + const userFromPublicKey = Crypto.getAccountIdFromPublicKey(publicKey, true); + return accountRS !== userFromPublicKey; +} + // check user secretPhase and compare account RS from publicKey and from request // return publicKey const checkAccountForOfflineSignAndPublicKey = (secretPhrase, accountRS, appPassPhraseFromStore) => { @@ -20,7 +26,7 @@ const checkAccountForOfflineSignAndPublicKey = (secretPhrase, accountRS, appPass const userFromPublicKey = Crypto.getAccountIdFromPublicKey(publicKey, true); if (accountRS !== userFromPublicKey) { - throw new Error('Incorrect secret phrase') + throw new Error('Incorrect secret phrase'); } return publicKey; } From 02c2e6197cd96e7c038d56956b50f76cdbb50d32 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 15:23:12 +0400 Subject: [PATCH 08/12] APL-2334: add condition send currency transfer for vault and standart wallets --- .../handle-form-submit/index.js | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js index 2f9daf874..61fbbcf57 100644 --- a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js +++ b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js @@ -1,8 +1,9 @@ import { NotificationManager } from 'react-notifications'; import { setBodyModalParamsAction } from 'modules/modals'; import { setModalProcessingTrueAction, setModalProcessingFalseAction } from 'actions/modals'; -import { sendCurrencyTransferOffline } from 'helpers/transactions'; +import { sendCurrencyTransferOffline, checkIsVaultWallet } from 'helpers/transactions'; import { getAccountRsSelector, getPassPhraseSelector } from 'selectors'; +import submitForm from 'helpers/forms/forms'; export const handleFormSubmit = ({decimals, ...values}) => async (dispatch, getState) => { const state = getState(); @@ -16,20 +17,33 @@ export const handleFormSubmit = ({decimals, ...values}) => async (dispatch, getS dispatch(setModalProcessingTrueAction()); - try { - const res = await sendCurrencyTransferOffline(data, accountRS, passPhrase); - + const isVaultWallet = checkIsVaultWallet(data.secretPhrase, accountRS); + let res = null; + + if (isVaultWallet) { + res = await dispatch(submitForm.submitForm(data, 'transferCurrency')); if (res && res.errorCode) { dispatch(setModalProcessingFalseAction()) NotificationManager.error(res.errorDescription, 'Error', 5000); } else { dispatch(setModalProcessingFalseAction()) dispatch(setBodyModalParamsAction()); - NotificationManager.success('Transfer currency request has been submitted!', null, 5000); } - } catch (e) { - dispatch(setModalProcessingFalseAction()); - NotificationManager.error(e.message, 'Error', 5000); + } else { + try { + res = await sendCurrencyTransferOffline(data, accountRS, passPhrase); + } catch (e) { + dispatch(setModalProcessingFalseAction()); + NotificationManager.error(e.message, 'Error', 5000); + } } + if (res && res.errorCode) { + dispatch(setModalProcessingFalseAction()) + NotificationManager.error(res.errorDescription, 'Error', 5000); + } else { + dispatch(setModalProcessingFalseAction()) + dispatch(setBodyModalParamsAction()); + NotificationManager.success('Transfer currency request has been submitted!', null, 5000); + } }; From 23a2a46dcf3c17f8dbb76906335ac0ae7a567a9a Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 15:28:37 +0400 Subject: [PATCH 09/12] APL-2334: edit sending params to back --- src/helpers/transactions/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/helpers/transactions/index.js b/src/helpers/transactions/index.js index 3ae1e3734..765840e68 100644 --- a/src/helpers/transactions/index.js +++ b/src/helpers/transactions/index.js @@ -69,11 +69,11 @@ export const sendMoneyOfflineTransaction = async ( data.encryptedMessageData = converters.byteArrayToHexString(encrypted.data); data.encryptedMessageNonce = converters.byteArrayToHexString(encrypted.nonce); - if (recipient === accountRS) { - data.messageToEncryptToSelfIsText = "true" - } else { - data.messageToEncryptIsText = "true" - } + // if (recipient === accountRS) { + // data.messageToEncryptToSelfIsText = "true" + // } else { + data.messageToEncryptIsText = "true" + // } } if (add_message) { From b10429dab6da63adbb8f291d0c703c1abc4a91e6 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 15:31:42 +0400 Subject: [PATCH 10/12] remove unused file --- src/helpers/transactions/check.js | 87 ------------------------------- 1 file changed, 87 deletions(-) delete mode 100644 src/helpers/transactions/check.js diff --git a/src/helpers/transactions/check.js b/src/helpers/transactions/check.js deleted file mode 100644 index 324495dac..000000000 --- a/src/helpers/transactions/check.js +++ /dev/null @@ -1,87 +0,0 @@ -NRS.encryptNote = function(message, options, secretPhrase) { - try { - options = NRS.getEncryptionKeys(options, secretPhrase); - var encrypted = encryptData(converters.stringToByteArray(message), options); - return { - "message": converters.byteArrayToHexString(encrypted.data), - "nonce": converters.byteArrayToHexString(encrypted.nonce) - }; - } catch (err) { - if (err.errorCode && err.errorCode < 5) { - throw err; - } else { - throw { - "message": $.t("error_message_encryption"), - "errorCode": 5 - }; - } - } -}; - - -NRS.getEncryptionKeys = function (options, secretPhrase){ - if (!options.sharedKey) { - if (!options.privateKey) { - if (!secretPhrase) { - if (NRS.rememberPassword) { - secretPhrase = _password; - } else { - throw { - "message": $.t("error_encryption_passphrase_required"), - "errorCode": 1 - }; - } - } - - options.privateKey = converters.hexStringToByteArray(NRS.getPrivateKey(secretPhrase)); - } - - if (!options.publicKey) { - if (!options.account) { - throw { - "message": $.t("error_account_id_not_specified"), - "errorCode": 2 - }; - } - - try { - options.publicKey = converters.hexStringToByteArray(NRS.getPublicKey(options.account, true)); - } catch (err) { - var nxtAddress = new NxtAddress(); - - if (!nxtAddress.set(options.account)) { - throw { - "message": $.t("error_invalid_account_id"), - "errorCode": 3 - }; - } else { - throw { - "message": $.t("error_public_key_not_specified"), - "errorCode": 4 - }; - } - } - } else if (typeof options.publicKey == "string") { - options.publicKey = converters.hexStringToByteArray(options.publicKey); - } - } - return options; -}; - - -function encryptData(plaintext, options) { - options.nonce = getRandomBytes(32); - if (!options.sharedKey) { - options.sharedKey = getSharedSecret(options.privateKey, options.publicKey); - } - var compressedPlaintext = pako.gzip(new Uint8Array(plaintext)); - var data = aesEncrypt(compressedPlaintext, options); - return { - "nonce": options.nonce, - "data": data - }; -} - -function getSharedSecret(key1, key2) { - return converters.shortArrayToByteArray(curve25519_(converters.byteArrayToShortArray(key1), converters.byteArrayToShortArray(key2), null)); -} \ No newline at end of file From a0ac0b924031d9bc124b163d1bb34bb1ef179a6d Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 15:33:19 +0400 Subject: [PATCH 11/12] up ui version to 3.0.10 --- VERSION | 2 +- package.json | 2 +- packaging/pkg-apollo-web-ui.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 489200c52..f1cb5ae0c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.9 \ No newline at end of file +3.0.10 \ No newline at end of file diff --git a/package.json b/package.json index 53b253ec3..b177168c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "apollo-web-wallet", - "version": "3.0.9", + "version": "3.0.10", "private": true, "dependencies": { "@fortawesome/fontawesome-free": "5.13.0", diff --git a/packaging/pkg-apollo-web-ui.json b/packaging/pkg-apollo-web-ui.json index 3b47577ce..696c24bcb 100644 --- a/packaging/pkg-apollo-web-ui.json +++ b/packaging/pkg-apollo-web-ui.json @@ -1,6 +1,6 @@ { "name": "apollo-web-ui", "description": "Apollo blockchain web UI", - "version": "3.0.9", + "version": "3.0.10", "dependencies": [ ] } From d824e3fbd73194b43890401f22968c575c262297 Mon Sep 17 00:00:00 2001 From: Roman Gavrylenko Date: Thu, 17 Aug 2023 17:23:32 +0400 Subject: [PATCH 12/12] clean up and edit submit form for transfer currency --- .../handle-form-submit/index.js | 23 ++++++------------- src/containers/modals/send-apollo/index.jsx | 1 - 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js index 61fbbcf57..65aa656a9 100644 --- a/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js +++ b/src/containers/modals/currencies/transfer-currency/handle-form-submit/index.js @@ -20,22 +20,13 @@ export const handleFormSubmit = ({decimals, ...values}) => async (dispatch, getS const isVaultWallet = checkIsVaultWallet(data.secretPhrase, accountRS); let res = null; - if (isVaultWallet) { - res = await dispatch(submitForm.submitForm(data, 'transferCurrency')); - if (res && res.errorCode) { - dispatch(setModalProcessingFalseAction()) - NotificationManager.error(res.errorDescription, 'Error', 5000); - } else { - dispatch(setModalProcessingFalseAction()) - dispatch(setBodyModalParamsAction()); - } - } else { - try { - res = await sendCurrencyTransferOffline(data, accountRS, passPhrase); - } catch (e) { - dispatch(setModalProcessingFalseAction()); - NotificationManager.error(e.message, 'Error', 5000); - } + try { + res = isVaultWallet ? + await dispatch(submitForm.submitForm(data, 'transferCurrency')) : await sendCurrencyTransferOffline(data, accountRS, passPhrase); + } catch (e) { + dispatch(setModalProcessingFalseAction()); + NotificationManager.error(e.message, 'Error', 5000); + return; } if (res && res.errorCode) { diff --git a/src/containers/modals/send-apollo/index.jsx b/src/containers/modals/send-apollo/index.jsx index 38f6899a9..0eafc4901 100644 --- a/src/containers/modals/send-apollo/index.jsx +++ b/src/containers/modals/send-apollo/index.jsx @@ -31,7 +31,6 @@ export default function SendApollo({ closeModal, processForm }) { const decimals = useSelector(getDecimalsSelector); const handleFormSubmit = useCallback(async values => { - console.log("🚀 ~ file: index.jsx:35 ~ handleFormSubmit ~ values:", values) const { privateTransaction, ...data } = values; if (!values.secretPhrase || values.secretPhrase.length === 0) { NotificationManager.error('Secret Phrase is required.', 'Error', 5000);