From 0dddc1e071a859802b33a293634e1d978d6ad05e Mon Sep 17 00:00:00 2001 From: Oskar Fransson Date: Fri, 13 Oct 2023 12:55:26 +0200 Subject: [PATCH 1/4] move transaction string to be stored in url state instead of url params state because bigger size is allowed in url state --- src/modules/account/hooks/useCurrentAccount.js | 15 +++++++++++++-- .../components/Multisignature/Multisignature.js | 10 +++++++--- .../wallet/components/signMultisigView/index.js | 3 +-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/modules/account/hooks/useCurrentAccount.js b/src/modules/account/hooks/useCurrentAccount.js index 3df938a30a..015bd8fc16 100644 --- a/src/modules/account/hooks/useCurrentAccount.js +++ b/src/modules/account/hooks/useCurrentAccount.js @@ -19,7 +19,8 @@ export function useCurrentAccount() { (stake) => stake.confirmed !== stake.unconfirmed ); - const setAccount = (encryptedAccount, referrer, redirect = true) => { + // eslint-disable-next-line max-statements + const setAccount = (encryptedAccount, referrer, redirect = true, urlState) => { // clear stakes list during login or accounts switch if (pendingStakes.length) { const onCancel = /* istanbul ignore next */ () => @@ -40,7 +41,17 @@ export function useCurrentAccount() { } else { dispatch(setCurrentAccount(encryptedAccount)); if (redirect) { - history.push(referrer || routes.wallet.path); + if (urlState) { + const relativeUrlPath = referrer || routes.wallet.path; + const { pathname, search } = new URL(relativeUrlPath, window.location.origin); + history.push({ + pathname, + search, + state: urlState, + }); + } else { + history.push(referrer || routes.wallet.path); + } } } }; diff --git a/src/modules/transaction/components/Multisignature/Multisignature.js b/src/modules/transaction/components/Multisignature/Multisignature.js index 4949cd4ef0..aa81c2fbb4 100644 --- a/src/modules/transaction/components/Multisignature/Multisignature.js +++ b/src/modules/transaction/components/Multisignature/Multisignature.js @@ -17,6 +17,7 @@ import WarningNotification from '@common/components/warningNotification'; import AccountRow from '@account/components/AccountRow'; import classNames from 'classnames'; import { getNextAccountToSign } from '@transaction/utils/multisignatureUtils'; +import generateUniqueId from 'src/utils/generateUniqueId'; import getIllustration from '../TxBroadcaster/illustrationsMap'; import styles from './Multisignature.css'; import useTxInitiatorAccount from '../../hooks/useTxInitiatorAccount'; @@ -28,15 +29,18 @@ export const PartiallySignedActions = ({ transactionJSON, reset, }) => { - const [, setCurrentAccount] = useCurrentAccount(); + const [currentAccount, setCurrentAccount] = useCurrentAccount(); const handleSwitchAccount = () => { const stringifiedTransaction = encodeURIComponent(JSON.stringify(transactionJSON)); + const uniqueUrlIdToPreventHashError = generateUniqueId(); setCurrentAccount( nextAccountToSign, - `/wallet?modal=signMultiSignTransaction&stringifiedTransaction=${stringifiedTransaction}`, + `/wallet?modal=signMultiSignTransaction&prevAccount=${currentAccount.metadata.address}&uniqueId=${uniqueUrlIdToPreventHashError}`, true, - { stringifiedTransaction } + { + stringifiedTransaction, + } ); reset?.(); }; diff --git a/src/modules/wallet/components/signMultisigView/index.js b/src/modules/wallet/components/signMultisigView/index.js index 755899a623..7b22871ee6 100644 --- a/src/modules/wallet/components/signMultisigView/index.js +++ b/src/modules/wallet/components/signMultisigView/index.js @@ -16,8 +16,7 @@ import Status from '../signMultisigStatus'; const SignMultisigView = ({ history }) => { const [currentStep, setCurrentStep] = useState(); const location = useLocation(); - const queryParams = new URLSearchParams(location.search); - const stringifiedTransaction = queryParams.get('stringifiedTransaction'); + const stringifiedTransaction = location.state?.stringifiedTransaction; const onMultiStepChange = useCallback(({ step: { current } }) => { setCurrentStep(current); From 2fc8bdf701442fd62b814617d98ae0df7865b9d6 Mon Sep 17 00:00:00 2001 From: Oskar Fransson Date: Fri, 13 Oct 2023 14:38:08 +0200 Subject: [PATCH 2/4] Prevent an account from sending an incomplete transaction --- .../transaction/configuration/statusConfig.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/modules/transaction/configuration/statusConfig.js b/src/modules/transaction/configuration/statusConfig.js index de1e56064b..90b02411a3 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -2,6 +2,7 @@ import { transactions as LiskTransaction } from '@liskhq/lisk-client'; import { isEmpty } from 'src/utils/helpers'; import { txStatusTypes } from '@transaction/configuration/txStatus'; +import { calculateRemainingAndSignedMembers } from '@wallet/utils/account'; import { getNumberOfSignatures, joinModuleAndCommand, toTransactionJSON } from '../utils'; import { MODULE_COMMANDS_NAME_MAP } from './moduleCommand'; @@ -85,6 +86,24 @@ const getErrorMessage = (transaction, paramSchema, errorMessage) => { }; }; +function getHasRemainingMandatorySignatures(signedTransaction, walletKeys) { + const transactionSignaturesAsStrings = signedTransaction.signatures.map((signature) => + signature.toString('hex') + ); + + const moduleCommand = joinModuleAndCommand(signedTransaction); + const isMultisignatureRegistration = + moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + + const { remaining } = calculateRemainingAndSignedMembers( + walletKeys, + { ...signedTransaction, signatures: transactionSignaturesAsStrings }, + isMultisignatureRegistration + ); + + return remaining.some(({ mandatory }) => mandatory); +} + /** * Defines the Status of the broadcasted tx. */ @@ -135,6 +154,12 @@ export const getTransactionStatus = (account, transactions, options = {}) => { moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; const isMultisignature = account?.summary?.isMultisignature || options.isMultisignature; const isInitatorAccountMultiSig = account?.numberOfSignatures > 0; + + const hasRemainingMandatorySignatures = getHasRemainingMandatorySignatures( + transactions.signedTransaction, + account.keys + ); + let nonEmptySignatures = transactions.signedTransaction.signatures.filter( (sig) => sig.length > 0 ).length; @@ -146,6 +171,7 @@ export const getTransactionStatus = (account, transactions, options = {}) => { } if ( + hasRemainingMandatorySignatures || nonEmptySignatures < numberOfSignatures || (isMultisignature && nonEmptySignatures === numberOfSignatures && From d2ee1003abc4dba4c448349acac12c34a174072d Mon Sep 17 00:00:00 2001 From: Oskar Fransson Date: Fri, 13 Oct 2023 14:42:22 +0200 Subject: [PATCH 3/4] fixed deep scan --- src/modules/transaction/configuration/statusConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/transaction/configuration/statusConfig.js b/src/modules/transaction/configuration/statusConfig.js index 90b02411a3..ec73ce8b31 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -157,7 +157,7 @@ export const getTransactionStatus = (account, transactions, options = {}) => { const hasRemainingMandatorySignatures = getHasRemainingMandatorySignatures( transactions.signedTransaction, - account.keys + account?.keys ); let nonEmptySignatures = transactions.signedTransaction.signatures.filter( From fa978d61ed568140b6278649b4b35e9c4bca4330 Mon Sep 17 00:00:00 2001 From: Oskar Fransson Date: Mon, 16 Oct 2023 16:08:44 +0200 Subject: [PATCH 4/4] Created a named constant of a var that is used in multiple places --- src/modules/account/hooks/useCurrentAccount.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/account/hooks/useCurrentAccount.js b/src/modules/account/hooks/useCurrentAccount.js index 015bd8fc16..b7cd9edbd6 100644 --- a/src/modules/account/hooks/useCurrentAccount.js +++ b/src/modules/account/hooks/useCurrentAccount.js @@ -22,6 +22,8 @@ export function useCurrentAccount() { // eslint-disable-next-line max-statements const setAccount = (encryptedAccount, referrer, redirect = true, urlState) => { // clear stakes list during login or accounts switch + const relativeUrlPath = referrer || routes.wallet.path; + if (pendingStakes.length) { const onCancel = /* istanbul ignore next */ () => removeSearchParamsFromUrl(history, ['modal']); @@ -29,7 +31,7 @@ export function useCurrentAccount() { dispatch(setCurrentAccount(encryptedAccount)); dispatch(stakesReset()); - history.push(referrer || routes.wallet.path); + history.push(relativeUrlPath); }; const state = createConfirmSwitchState({ mode: 'pendingStakes', @@ -42,7 +44,6 @@ export function useCurrentAccount() { dispatch(setCurrentAccount(encryptedAccount)); if (redirect) { if (urlState) { - const relativeUrlPath = referrer || routes.wallet.path; const { pathname, search } = new URL(relativeUrlPath, window.location.origin); history.push({ pathname, @@ -50,7 +51,7 @@ export function useCurrentAccount() { state: urlState, }); } else { - history.push(referrer || routes.wallet.path); + history.push(relativeUrlPath); } } }