From bf5572d44e5f9f84550c857e2ed706d1fecc7ae0 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 2 Oct 2023 16:36:36 +0200 Subject: [PATCH 01/25] feature: implemented edit multisignature feature --- src/locales/en/common.json | 1 - src/modules/account/const/accountMenu.js | 7 +++-- .../components/RegisterMultisigForm/index.js | 26 +++++++++++++++++-- .../RegisterMultisigForm/validators.js | 2 +- .../RegisterMultisigStatus/status.js | 7 +++-- .../RegisterMultisigSummary/Summary.js | 7 ++++- .../components/RegisterMultisigView/index.js | 17 +++++++++--- 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/locales/en/common.json b/src/locales/en/common.json index 4b0591ae12..c827db802c 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -505,7 +505,6 @@ "Redo": "Redo", "Register keys": "Register keys", "Register multisignature": "Register multisignature", - "Register multisignature account": "Register multisignature account", "Register sidechain": "Register sidechain", "Register validator": "Register validator", "Register validator summary": "Register validator summary", diff --git a/src/modules/account/const/accountMenu.js b/src/modules/account/const/accountMenu.js index 98872c12b8..a7a519df92 100644 --- a/src/modules/account/const/accountMenu.js +++ b/src/modules/account/const/accountMenu.js @@ -37,8 +37,11 @@ export const accountMenu = ({ } : {}, icon: 'multiSignatureOutline', - label: 'Register multisignature account', - isHidden: authData?.data?.numberOfSignatures > 0 || hasNetworkError || isLoadingNetwork, + label: `${ + authData?.data?.numberOfSignatures > 0 || hasNetworkError || isLoadingNetwork + ? 'Edit' + : 'Register' + } multisignature account`, }, { component: 'removeSelectedAccount', diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.js b/src/modules/wallet/components/RegisterMultisigForm/index.js index ffec9bf9b2..d126ab9315 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.js @@ -70,7 +70,7 @@ export const validateState = ({ }; // eslint-disable-next-line max-statements -const Form = ({ nextStep, prevState = {}, onNext }) => { +const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { const { t } = useTranslation(); const [numberOfSignatures, setNumberOfSignatures] = useState(() => getInitialSignaturesState(prevState) @@ -145,6 +145,24 @@ const Form = ({ nextStep, prevState = {}, onNext }) => { } }, [numberOfSignatures]); + useEffect(() => { + const numberOfSignaturesOnAccount = authQuery.data?.data?.numberOfSignatures; + + if (authQuery.isFetched && authQuery.data && numberOfSignaturesOnAccount > 1) { + const mandatoryMembers = authQuery.data.data.mandatoryKeys.map((key) => ({ + isMandatory: true, + publicKey: key, + })); + const optionalMembers = authQuery.data.data.optionalKeys.map((key) => ({ + isMandatory: false, + publicKey: key, + })); + + setNumberOfSignatures(numberOfSignaturesOnAccount); + setMembers([...mandatoryMembers, optionalMembers]); + } + }, [authQuery.isFetching]); + const feedback = useMemo( () => validateState({ @@ -173,6 +191,8 @@ const Form = ({ nextStep, prevState = {}, onNext }) => { signatures: initializeDefaultSignatures(mandatoryKeys, optionalKeys), }; + const numberofSignatureOnAccount = authQuery?.data?.data.numberOfSignatures; + return (
{ > <> -

{t('Register multisignature account')}

+

+ {t(`${numberofSignatureOnAccount > 1 ? 'Edit' : 'Register'} multisignature account`)} +

diff --git a/src/modules/wallet/components/RegisterMultisigForm/validators.js b/src/modules/wallet/components/RegisterMultisigForm/validators.js index 6080c321f9..9a7ae811bc 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/validators.js +++ b/src/modules/wallet/components/RegisterMultisigForm/validators.js @@ -14,7 +14,7 @@ const validators = [ }, { pattern: (mandatory, optional, signatures) => - mandatory.length > 0 && optional.length > 0 && signatures <= mandatory.length, + mandatory.length > 0 && optional.length > 0 && signatures < mandatory.length, message: (t, mandatory) => t( t('Number of signatures must be above {{num}}.', { diff --git a/src/modules/wallet/components/RegisterMultisigStatus/status.js b/src/modules/wallet/components/RegisterMultisigStatus/status.js index 8c5e2136da..37a20ffcb6 100644 --- a/src/modules/wallet/components/RegisterMultisigStatus/status.js +++ b/src/modules/wallet/components/RegisterMultisigStatus/status.js @@ -7,15 +7,18 @@ import { selectModuleCommandSchemas } from 'src/redux/selectors'; import ProgressBar from '../RegisterMultisigView/ProgressBar'; import styles from './styles.css'; -const Status = ({ account, transactions, t }) => { +const Status = ({ account, transactions, t, authQuery }) => { const moduleCommandSchemas = useSelector(selectModuleCommandSchemas); const status = getTransactionStatus(account, transactions, { moduleCommandSchemas }); const template = statusMessages(t)[status.code]; + const numberOfSignaturesOnAccount = authQuery.data?.data?.numberOfSignatures; return (
-

{t('Register multisignature account')}

+

+ {t(`${numberOfSignaturesOnAccount > 0 ? 'Edit' : 'Register'} multisignature account`)} +

{ const [sender] = useCurrentAccount(); const { txInitiatorAccount } = useTxInitiatorAccount({ @@ -33,6 +34,8 @@ const Summary = ({ [transactionJSON] ); + const numberOfSignaturesOnAccount = authQuery.data?.data?.numberOfSignatures; + const onConfirmAction = useMemo( () => ({ label: t('Sign'), @@ -90,7 +93,9 @@ const Summary = ({ transactionJSON={transactionJSON} >
-
{t('Register multisignature account')}
+
+ {t(`${numberOfSignaturesOnAccount > 0 ? 'Editi' : 'Register'} multisignature account`)} +
diff --git a/src/modules/wallet/components/RegisterMultisigView/index.js b/src/modules/wallet/components/RegisterMultisigView/index.js index 4a658a2e87..163e6606aa 100644 --- a/src/modules/wallet/components/RegisterMultisigView/index.js +++ b/src/modules/wallet/components/RegisterMultisigView/index.js @@ -4,6 +4,8 @@ import TxSignatureCollector from '@transaction/components/TxSignatureCollector'; import MultiStep from 'src/modules/common/components/OldMultiStep'; import { removeSearchParamsFromUrl } from 'src/utils/searchParams'; import Dialog from 'src/theme/dialog/dialog'; +import { useAuth } from '@auth/hooks/queries'; +import { useCurrentAccount } from '@account/hooks'; import Form from '../RegisterMultisigForm'; import Summary from '../RegisterMultisigSummary'; @@ -19,6 +21,15 @@ const RegisterMultisigView = ({ history }) => { setIsStepTxSignatureCollector(current === 2); }, []); + const [currentAccount] = useCurrentAccount(); + + const currentAccountAddress = currentAccount.metadata?.address; + + const authQuery = useAuth({ + config: { params: { address: currentAccountAddress } }, + options: { enabled: !!currentAccountAddress }, + }); + return ( { className={styles.modal} onChange={onMultiStepChange} > -
- + + - +
); From 1760006a2e288ced98875111247ecfd8053b23ab Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Wed, 4 Oct 2023 23:44:26 +0200 Subject: [PATCH 02/25] wip: resolved signing issue --- .../MultiSignatureReview.js | 28 ++++++++---- .../Multisignature/Multisignature.js | 23 +++++----- .../RegisterMultisignatureGroup.js | 4 +- .../components/TransactionDetails/index.js | 1 + .../TransactionDetails/layoutSchema.js | 10 ++++- ...ransactionSignedAndRemainingMembersList.js | 45 +++++++++++++++++++ .../transaction/configuration/statusConfig.js | 10 +++-- src/modules/transaction/utils/transaction.js | 20 ++++++++- .../components/RegisterMultisigForm/index.js | 9 ++-- .../RegisterMultisigSummary/Summary.js | 2 +- .../components/signMultisigStatus/status.js | 2 + .../components/signMultisigView/helpers.js | 13 +++++- .../wallet/utils/multiSignatureStatus.js | 25 ++++++++++- 13 files changed, 158 insertions(+), 34 deletions(-) create mode 100644 src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js diff --git a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js index 3001bc576b..5de78ab856 100644 --- a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js +++ b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js @@ -58,17 +58,27 @@ const InfoColumn = ({ title, children, className }) => ( ); -const MultiSignatureReview = ({ t, members, fee, numberOfSignatures, token }) => ( +const MultiSignatureReview = ({ + t, + members, + fee, + numberOfSignatures, + token, + isMultisignature, + isRegisterMultisigature, +}) => ( <> -
- - {numberOfSignatures} - - - - -
+ {!isMultisignature && isRegisterMultisigature && ( +
+ + {numberOfSignatures} + + + + +
+ )} ); diff --git a/src/modules/transaction/components/Multisignature/Multisignature.js b/src/modules/transaction/components/Multisignature/Multisignature.js index 61b449d926..05c928a591 100644 --- a/src/modules/transaction/components/Multisignature/Multisignature.js +++ b/src/modules/transaction/components/Multisignature/Multisignature.js @@ -57,7 +57,7 @@ const ErrorActions = ({ t, status, message, network, application }) => ( ); -// eslint-disable-next-line max-statements +// eslint-disable-next-line max-statements, complexity const Multisignature = ({ transactions, title, @@ -107,7 +107,6 @@ const Multisignature = ({ }; useEffect(() => resetTransactionResult, []); - useEffect(() => () => clearTimeout(ref.current), []); return ( @@ -135,17 +134,17 @@ const Multisignature = ({ /> ) : null} {status.code !== txStatusTypes.broadcastSuccess && - status.code !== txStatusTypes.broadcastError ? ( - - - - {t(copied ? 'Copied' : 'Copy')} - - - ) : null} - {status.code === txStatusTypes.multisigSignatureSuccess ? ( + status.code !== txStatusTypes.broadcastError && ( + + + + {t(copied ? 'Copied' : 'Copy')} + + + )} + {(status.code === txStatusTypes.multisigSignatureSuccess) && ( - ) : null} + )} {status.code === txStatusTypes.multisigSignaturePartialSuccess ? ( ) : null} diff --git a/src/modules/transaction/components/RegisterMultisignatureGroup/RegisterMultisignatureGroup.js b/src/modules/transaction/components/RegisterMultisignatureGroup/RegisterMultisignatureGroup.js index fd6625915b..570503e243 100644 --- a/src/modules/transaction/components/RegisterMultisignatureGroup/RegisterMultisignatureGroup.js +++ b/src/modules/transaction/components/RegisterMultisignatureGroup/RegisterMultisignatureGroup.js @@ -2,7 +2,7 @@ import React from 'react'; import { extractAddressFromPublicKey } from '@wallet/utils/account'; import MultiSignatureReview from '../MultiSignatureReview'; -const RegisterMultisignatureGroup = ({ t, transactionJSON, formProps }) => { +const RegisterMultisignatureGroup = ({ t, transactionJSON, formProps, account }) => { const mandatory = transactionJSON.params.mandatoryKeys.map((item) => ({ address: extractAddressFromPublicKey(item), publicKey: item, @@ -21,6 +21,8 @@ const RegisterMultisignatureGroup = ({ t, transactionJSON, formProps }) => { token={formProps.fields.token} members={[...mandatory, ...optional]} numberOfSignatures={transactionJSON.params.numberOfSignatures} + isMultisignature={account.summary.isMultisignature} + isRegisterMultisigature /> ); }; diff --git a/src/modules/transaction/components/TransactionDetails/index.js b/src/modules/transaction/components/TransactionDetails/index.js index 389841e2d8..b0a49d25ac 100644 --- a/src/modules/transaction/components/TransactionDetails/index.js +++ b/src/modules/transaction/components/TransactionDetails/index.js @@ -14,6 +14,7 @@ export { default as Recipient } from './recipient'; export { default as NumberOfSignatures } from './numberOfSignatures'; export { default as Sender } from './sender'; export { default as SignedAndRemainingMembersList } from './signedAndRemainingMembersList'; +export { default as TransactionSignedAndRemainingMembersList } from './transactionSignedAndRemainingMembersList'; export { default as TransactionId } from './transactionId'; export { default as TxDate } from './txDate'; export { default as Stakes } from './stakes'; diff --git a/src/modules/transaction/components/TransactionDetails/layoutSchema.js b/src/modules/transaction/components/TransactionDetails/layoutSchema.js index d567209253..bde4331bfb 100644 --- a/src/modules/transaction/components/TransactionDetails/layoutSchema.js +++ b/src/modules/transaction/components/TransactionDetails/layoutSchema.js @@ -23,6 +23,7 @@ import { Module, Nonce, GenericParams, + TransactionSignedAndRemainingMembersList, } from 'src/modules/transaction/components/TransactionDetails'; import styles from './layoutSchema.css'; @@ -94,7 +95,14 @@ export const LayoutSchema = { className: styles.multiSigLayout, }, [`${registerMultisignature}-preview`]: { - components: [Sender, Members, NumberOfSignatures, Fee, SignedAndRemainingMembersList], + components: [ + Sender, + Members, + NumberOfSignatures, + Fee, + SignedAndRemainingMembersList, + TransactionSignedAndRemainingMembersList, + ], className: styles.multiSigRegisterPreview, }, [unlock]: { diff --git a/src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js new file mode 100644 index 0000000000..2841d7acd5 --- /dev/null +++ b/src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js @@ -0,0 +1,45 @@ +import React, { useMemo, useContext } from 'react'; +import { MODULE_COMMANDS_NAME_MAP } from 'src/modules/transaction/configuration/moduleCommand'; +import { SignedAndRemainingMembers } from '@wallet/components/multisignatureMembers'; +import { calculateRemainingAndSignedMembers } from '@wallet/utils/account'; +import TransactionDetailsContext from '../../context/transactionDetailsContext'; +import styles from './styles.css'; +import { joinModuleAndCommand } from '../../utils'; + +const TransactionSignedAndRemainingMembersList = ({ t }) => { + const { transaction, wallet } = useContext(TransactionDetailsContext); + + const moduleCommand = joinModuleAndCommand(transaction); + const isMultisignatureRegistration = + moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + + const keys = isMultisignatureRegistration + ? { + optionalKeys: transaction.params.optionalKeys, + mandatoryKeys: transaction.params.mandatoryKeys, + numberOfSignatures: transaction.params.numberOfSignatures, + } + : wallet.keys; + + const { signed, remaining } = useMemo( + () => calculateRemainingAndSignedMembers(keys, transaction, isMultisignatureRegistration), + [wallet] + ); + + const required = keys.numberOfSignatures; + + const needed = required - signed.length; + + return ( + + ); +}; + +export default TransactionSignedAndRemainingMembersList; diff --git a/src/modules/transaction/configuration/statusConfig.js b/src/modules/transaction/configuration/statusConfig.js index 8ce132302e..ee3782c060 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -131,24 +131,26 @@ export const getTransactionStatus = (account, transactions, options = {}) => { // signature success if (!isEmpty(transactions.signedTransaction)) { const numberOfSignatures = getNumberOfSignatures(account, transactions.signedTransaction); + const isRegisterMultisignature = + moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + const isMultisignature = account?.summary?.isMultisignature || options.isMultisignature; + let nonEmptySignatures = transactions.signedTransaction.signatures.filter( (sig) => sig.length > 0 ).length; - if (moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature) { + if (isRegisterMultisignature && !isMultisignature) { nonEmptySignatures = transactions.signedTransaction.params.signatures.filter( (sig) => sig.compare(Buffer.alloc(64)) > 0 ).length; } - const isMultisignature = account?.summary?.isMultisignature || options.isMultisignature; - if ( nonEmptySignatures < numberOfSignatures || (isMultisignature && nonEmptySignatures === numberOfSignatures && !options.canSenderSignTx && - moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature) + isRegisterMultisignature) ) { return { code: txStatusTypes.multisigSignaturePartialSuccess }; } diff --git a/src/modules/transaction/utils/transaction.js b/src/modules/transaction/utils/transaction.js index f98b2e77e4..8b1adbb163 100644 --- a/src/modules/transaction/utils/transaction.js +++ b/src/modules/transaction/utils/transaction.js @@ -281,6 +281,7 @@ const signTransactionUsingHW = async ( return { ...signedTransaction, id }; }; +// eslint-disable-next-line max-statements export const sign = async ( wallet, schema, @@ -290,11 +291,28 @@ export const sign = async ( senderAccount, options ) => { + const moduleCommand = joinModuleAndCommand(transaction); if (wallet.metadata?.isHW) { return signTransactionUsingHW(wallet, schema, chainID, transaction, senderAccount, options); } - if (options?.txInitiatorAccount?.numberOfSignatures > 0) { + const isMultiSignatureAccount = options?.txInitiatorAccount?.numberOfSignatures > 0; + const isRegisterMultisignature = + moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + const paramSignatures = transaction.params.signatures; + const areParamsSignaturesFullySigned = + isMultiSignatureAccount && + paramSignatures?.filter((sig) => sig.length !== 64 || Buffer.from(sig).equals(Buffer.alloc(64))) + .length === 0 && + paramSignatures?.length === + transaction.params.mandatoryKeys?.length + transaction.params.optionalKeys?.length; + + const isEditRegisterMultiSignature = isRegisterMultisignature && isMultiSignatureAccount; + + if ( + (isMultiSignatureAccount && !isRegisterMultisignature) || + (isEditRegisterMultiSignature && areParamsSignaturesFullySigned) + ) { return signMultisigUsingPrivateKey( schema, chainID, diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.js b/src/modules/wallet/components/RegisterMultisigForm/index.js index d126ab9315..d3587c8cfb 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.js @@ -159,7 +159,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { })); setNumberOfSignatures(numberOfSignaturesOnAccount); - setMembers([...mandatoryMembers, optionalMembers]); + setMembers([...mandatoryMembers, ...optionalMembers]); } }, [authQuery.isFetching]); @@ -192,6 +192,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { }; const numberofSignatureOnAccount = authQuery?.data?.data.numberOfSignatures; + const isEditMultisignatureMembers = numberofSignatureOnAccount > 1; return (
@@ -204,7 +205,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { <>

- {t(`${numberofSignatureOnAccount > 1 ? 'Edit' : 'Register'} multisignature account`)} + {t(`${isEditMultisignatureMembers ? 'Edit' : 'Register'} multisignature account`)}

@@ -237,7 +238,9 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { t={t} {...member} index={i} - showDeleteIcon={members.length > numberOfSignatures} + showDeleteIcon={ + members.length > numberOfSignatures || isEditMultisignatureMembers + } onChangeMember={changeMember} onDeleteMember={deleteMember} /> diff --git a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js index 44767e94a4..606c7dce9d 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js @@ -94,7 +94,7 @@ const Summary = ({ >
- {t(`${numberOfSignaturesOnAccount > 0 ? 'Editi' : 'Register'} multisignature account`)} + {t(`${numberOfSignaturesOnAccount > 1 ? 'Edit' : 'Register'} multisignature account`)}
diff --git a/src/modules/wallet/components/signMultisigStatus/status.js b/src/modules/wallet/components/signMultisigStatus/status.js index a8b881ae0c..ba361120c1 100644 --- a/src/modules/wallet/components/signMultisigStatus/status.js +++ b/src/modules/wallet/components/signMultisigStatus/status.js @@ -26,7 +26,9 @@ const Status = ({ transactions, t, transactionJSON }) => { transactions.signedTransaction.params?.numberOfSignatures > 0 || numberOfSignatures > 0; const { canSenderSignTx } = useMultiSignatureStatus({ + transactions, transactionJSON, + moduleCommandSchemas, currentAccount, senderAccount: txInitiatorAccount, account: { diff --git a/src/modules/wallet/components/signMultisigView/helpers.js b/src/modules/wallet/components/signMultisigView/helpers.js index 7c09911411..e7b793f794 100644 --- a/src/modules/wallet/components/signMultisigView/helpers.js +++ b/src/modules/wallet/components/signMultisigView/helpers.js @@ -33,8 +33,19 @@ export const getTransactionSignatureStatus = (senderAccount, transaction) => { const paramsSignature = transaction.params.signatures.filter( (s) => s.toString('hex') !== Buffer.alloc(64).toString('hex') ); + const keys = getKeys({ + senderAccount, + transaction, + isRegisterMultisignature: false, + }); + const required = getNumbersOfSignaturesRequired({ + keys, + transaction, + isRegisterMultisignature: false, + }); + const alreadySigned = getNonEmptySignatures(transaction, false).length; - if (paramsSignature.length !== numberOfSignatures) { + if (paramsSignature.length !== numberOfSignatures || required > alreadySigned) { return signatureCollectionStatus.partiallySigned; } if (paramsSignature.length === numberOfSignatures && transaction.signatures.length > 0) { diff --git a/src/modules/wallet/utils/multiSignatureStatus.js b/src/modules/wallet/utils/multiSignatureStatus.js index 7b3b1909b5..f7563e6745 100644 --- a/src/modules/wallet/utils/multiSignatureStatus.js +++ b/src/modules/wallet/utils/multiSignatureStatus.js @@ -1,4 +1,6 @@ import { signatureCollectionStatus } from 'src/modules/transaction/configuration/txStatus'; +import { joinModuleAndCommand, toTransactionJSON } from 'src/modules/transaction/utils'; +import { isEmpty } from 'src/utils/helpers'; import { getTransactionSignatureStatus, showSignButton, @@ -7,14 +9,35 @@ import { /** * Get required statuses for a given multi-signature transaction */ +// eslint-disable-next-line max-statements export const getMultiSignatureStatus = ({ senderAccount, account, - transactionJSON, currentAccount, + // transactionJSON, + moduleCommandSchemas, + transactions, + ...rest }) => { + let transactionJSON = rest.transactionJSON; + + if (!isEmpty(transactions?.signedTransaction) && moduleCommandSchemas) { + const moduleCommand = joinModuleAndCommand(rest.transactionJSON); + const paramSchema = moduleCommandSchemas[moduleCommand]; + transactionJSON = toTransactionJSON(transactions.signedTransaction, paramSchema); + } + const isMember = showSignButton(senderAccount, account, transactionJSON); const signatureStatus = getTransactionSignatureStatus(senderAccount, transactionJSON); + + console.log( + '%%$$$', + moduleCommandSchemas, + transactions, + signatureStatus, + transactionJSON, + currentAccount.metadata.pubkey + ); const canSenderSignTx = transactionJSON.senderPublicKey === currentAccount.metadata.pubkey && signatureStatus === signatureCollectionStatus.fullySigned; From 93c9fe719e9bb5516819dc8282bb221cac56bf1f Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 10:03:49 +0200 Subject: [PATCH 03/25] wip: fixing signatures view --- .../components/TransactionDetails/index.js | 2 +- .../TransactionDetails/layoutSchema.css | 3 +- .../TransactionDetails/layoutSchema.js | 4 +- ....js => signedAndRemainingSignatureList.js} | 26 ++++-------- .../components/TransactionDetails/styles.css | 4 ++ .../components/multisignatureMembers/index.js | 40 +++++++++++-------- .../multisignatureMembers/styles.css | 5 +++ 7 files changed, 44 insertions(+), 40 deletions(-) rename src/modules/transaction/components/TransactionDetails/{transactionSignedAndRemainingMembersList.js => signedAndRemainingSignatureList.js} (50%) diff --git a/src/modules/transaction/components/TransactionDetails/index.js b/src/modules/transaction/components/TransactionDetails/index.js index b0a49d25ac..f2b8a6ae0d 100644 --- a/src/modules/transaction/components/TransactionDetails/index.js +++ b/src/modules/transaction/components/TransactionDetails/index.js @@ -14,7 +14,7 @@ export { default as Recipient } from './recipient'; export { default as NumberOfSignatures } from './numberOfSignatures'; export { default as Sender } from './sender'; export { default as SignedAndRemainingMembersList } from './signedAndRemainingMembersList'; -export { default as TransactionSignedAndRemainingMembersList } from './transactionSignedAndRemainingMembersList'; +export { default as SignedAndRemainingSignatureList } from './signedAndRemainingSignatureList'; export { default as TransactionId } from './transactionId'; export { default as TxDate } from './txDate'; export { default as Stakes } from './stakes'; diff --git a/src/modules/transaction/components/TransactionDetails/layoutSchema.css b/src/modules/transaction/components/TransactionDetails/layoutSchema.css index d735d183e7..ad41df6190 100644 --- a/src/modules/transaction/components/TransactionDetails/layoutSchema.css +++ b/src/modules/transaction/components/TransactionDetails/layoutSchema.css @@ -186,7 +186,8 @@ "sender sender" "numberOfSignatures fee" "members members" - "signedAndRemainingMembersList signedAndRemainingMembersList"; + "signedAndRemainingMembersList signedAndRemainingMembersList" + "signedAndRemainingSignatureList signedAndRemainingSignatureList"; } .reportValidatorMisbehavior { diff --git a/src/modules/transaction/components/TransactionDetails/layoutSchema.js b/src/modules/transaction/components/TransactionDetails/layoutSchema.js index bde4331bfb..2d88403a6a 100644 --- a/src/modules/transaction/components/TransactionDetails/layoutSchema.js +++ b/src/modules/transaction/components/TransactionDetails/layoutSchema.js @@ -23,7 +23,7 @@ import { Module, Nonce, GenericParams, - TransactionSignedAndRemainingMembersList, + SignedAndRemainingSignatureList, } from 'src/modules/transaction/components/TransactionDetails'; import styles from './layoutSchema.css'; @@ -101,7 +101,7 @@ export const LayoutSchema = { NumberOfSignatures, Fee, SignedAndRemainingMembersList, - TransactionSignedAndRemainingMembersList, + SignedAndRemainingSignatureList, ], className: styles.multiSigRegisterPreview, }, diff --git a/src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js similarity index 50% rename from src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js rename to src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js index 2841d7acd5..095f4d565e 100644 --- a/src/modules/transaction/components/TransactionDetails/transactionSignedAndRemainingMembersList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js @@ -1,45 +1,33 @@ import React, { useMemo, useContext } from 'react'; -import { MODULE_COMMANDS_NAME_MAP } from 'src/modules/transaction/configuration/moduleCommand'; import { SignedAndRemainingMembers } from '@wallet/components/multisignatureMembers'; import { calculateRemainingAndSignedMembers } from '@wallet/utils/account'; import TransactionDetailsContext from '../../context/transactionDetailsContext'; import styles from './styles.css'; -import { joinModuleAndCommand } from '../../utils'; -const TransactionSignedAndRemainingMembersList = ({ t }) => { +const SignedAndRemainingSignatureList = ({ t }) => { const { transaction, wallet } = useContext(TransactionDetailsContext); - - const moduleCommand = joinModuleAndCommand(transaction); - const isMultisignatureRegistration = - moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; - - const keys = isMultisignatureRegistration - ? { - optionalKeys: transaction.params.optionalKeys, - mandatoryKeys: transaction.params.mandatoryKeys, - numberOfSignatures: transaction.params.numberOfSignatures, - } - : wallet.keys; + const keys = wallet.keys; const { signed, remaining } = useMemo( - () => calculateRemainingAndSignedMembers(keys, transaction, isMultisignatureRegistration), + () => calculateRemainingAndSignedMembers(keys, transaction, false), [wallet] ); const required = keys.numberOfSignatures; - const needed = required - signed.length; + console.log('>>>>>', signed, remaining, needed, required); + return ( ); }; -export default TransactionSignedAndRemainingMembersList; +export default SignedAndRemainingSignatureList; diff --git a/src/modules/transaction/components/TransactionDetails/styles.css b/src/modules/transaction/components/TransactionDetails/styles.css index ffd1884ed5..884facacfe 100644 --- a/src/modules/transaction/components/TransactionDetails/styles.css +++ b/src/modules/transaction/components/TransactionDetails/styles.css @@ -162,6 +162,10 @@ grid-area: signedAndRemainingMembersList; } +.signedAndRemainingSignatureList { + grid-area: signedAndRemainingSignatureList; +} + .genericParams { grid-area: genericParams; padding-top: var(--vertical-padding-m); diff --git a/src/modules/wallet/components/multisignatureMembers/index.js b/src/modules/wallet/components/multisignatureMembers/index.js index 8feca35c26..44ae2cb43c 100644 --- a/src/modules/wallet/components/multisignatureMembers/index.js +++ b/src/modules/wallet/components/multisignatureMembers/index.js @@ -1,10 +1,9 @@ import React from 'react'; - import Tooltip from '@theme/Tooltip/tooltip'; import WalletVisual from '../walletVisual'; import { truncateAddress } from '../../utils/account'; - import styles from './styles.css'; +import classNames from 'classnames'; const Member = ({ member, i, t, size }) => (
@@ -88,21 +87,28 @@ export const SignedAndRemainingMembers = ({ className, t, }) => ( -
-
-

{t('Signed')}

- {signed.map((member, i) => ( - - ))} -
-
-

- {t('Remaining')} - {` ${needed}/${required}`} -

- {remaining.map((member, i) => ( - - ))} +
+

Transaction root signatures

+
+
+

{t('Signed')}

+ {signed.map((member, i) => ( + + ))} +
+
+

+ {t('Remaining')} + {` ${needed}/${required}`} +

+ {remaining.map((member, i) => ( + + ))} +
); diff --git a/src/modules/wallet/components/multisignatureMembers/styles.css b/src/modules/wallet/components/multisignatureMembers/styles.css index d40676989f..2fb2c5e9a6 100644 --- a/src/modules/wallet/components/multisignatureMembers/styles.css +++ b/src/modules/wallet/components/multisignatureMembers/styles.css @@ -1,5 +1,10 @@ @import '../../../../../setup/react/app/mixins.css'; +.wrapper { + display: flex; + flex-direction: column; +} + .membersContainer { max-height: 440px; overflow-y: auto; From 165554943d3605b96654b67fa0d368b3fe6ffd0a Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 10:06:29 +0200 Subject: [PATCH 04/25] wip: debugging issue with core/service on jenkins --- Jenkinsfile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 0a3f3abb6f..1fab0a2735 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -91,6 +91,13 @@ pipeline { make -C lisk-service build make -C lisk-service up + # logs + cat lisk-core.out + echo "===== core error ====" + cat lisk-core.err + echo "======== service =======" + docker ps + # wait for service to be up and running sleep 10 set -e; while [[ $(curl -s --fail http://127.0.0.1:9901/api/v3/index/status | jq '.data.percentageIndexed') != 100 ]]; do echo waiting; sleep 10; done; set +e From 6959b51d62d34769a50f8b539a902f419ebb7db8 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 14:08:20 +0200 Subject: [PATCH 05/25] fix: Refactored register multi sig flow for an edit multi-sig registration --- src/locales/en/common.json | 2 ++ .../MultiSignatureReview/MultiSignatureReview.js | 2 +- .../signedAndRemainingMembersList.js | 1 + .../signedAndRemainingSignatureList.js | 3 +-- .../components/TransactionInfo/TransactionInfo.js | 2 +- .../wallet/components/multisignatureMembers/index.js | 5 +++-- .../components/multisignatureMembers/styles.css | 1 + .../wallet/components/signMultisigView/helpers.js | 11 ++++++++++- src/modules/wallet/utils/multiSignatureStatus.js | 9 --------- 9 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/locales/en/common.json b/src/locales/en/common.json index c827db802c..0caeea6037 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -232,6 +232,7 @@ "Error retrieving conversion rates.": "Error retrieving conversion rates.", "Events": "Events", "Execution status": "Execution status", + "Existing members": "Existing members", "Expand": "Expand", "Expand sidebar": "Expand sidebar", "Expiry": "Expiry", @@ -510,6 +511,7 @@ "Register validator summary": "Register validator summary", "Registered": "Registered", "Registered validators": "Registered validators", + "Registering members": "Registering members", "Registrant": "Registrant", "Reject": "Reject", "Rejected the pairing request from {{sanitizedName}}": "Rejected the pairing request from {{sanitizedName}}", diff --git a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js index 5de78ab856..2c82aa32c9 100644 --- a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js +++ b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js @@ -31,7 +31,7 @@ const Members = ({ members = [], t }) => { const rightColumn = members.slice(sliceIndex, members.length); return (
-

{t('Members')}

+

{t('Registering members')}

{leftColumn.map((member, i) => ( diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js index 71497b6e70..ad5b0f047d 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js @@ -39,6 +39,7 @@ const SignedAndRemainingMembersList = ({ t }) => { needed={needed} required={required} className={styles.signedAndRemainingMembersList} + title="Multisignature params signature" t={t} /> ); diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js index 095f4d565e..32901c8264 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js @@ -16,8 +16,6 @@ const SignedAndRemainingSignatureList = ({ t }) => { const required = keys.numberOfSignatures; const needed = required - signed.length; - console.log('>>>>>', signed, remaining, needed, required); - return ( { needed={needed} required={required} className={styles.signedAndRemainingSignatureList} + title="Signatures" t={t} /> ); diff --git a/src/modules/transaction/components/TransactionInfo/TransactionInfo.js b/src/modules/transaction/components/TransactionInfo/TransactionInfo.js index 6b6983d617..7630e7c39e 100644 --- a/src/modules/transaction/components/TransactionInfo/TransactionInfo.js +++ b/src/modules/transaction/components/TransactionInfo/TransactionInfo.js @@ -8,7 +8,7 @@ import CustomTransactionInfo from './CustomTransactionInfo'; const Members = ({ members, t }) => (
- +
{members.map((member, i) => (
diff --git a/src/modules/wallet/components/multisignatureMembers/index.js b/src/modules/wallet/components/multisignatureMembers/index.js index 44ae2cb43c..53011f3152 100644 --- a/src/modules/wallet/components/multisignatureMembers/index.js +++ b/src/modules/wallet/components/multisignatureMembers/index.js @@ -1,9 +1,9 @@ import React from 'react'; import Tooltip from '@theme/Tooltip/tooltip'; +import classNames from 'classnames'; import WalletVisual from '../walletVisual'; import { truncateAddress } from '../../utils/account'; import styles from './styles.css'; -import classNames from 'classnames'; const Member = ({ member, i, t, size }) => (
@@ -86,9 +86,10 @@ export const SignedAndRemainingMembers = ({ required, className, t, + title, }) => (
-

Transaction root signatures

+

{title}

{t('Signed')}

diff --git a/src/modules/wallet/components/multisignatureMembers/styles.css b/src/modules/wallet/components/multisignatureMembers/styles.css index 2fb2c5e9a6..cb84eddd5a 100644 --- a/src/modules/wallet/components/multisignatureMembers/styles.css +++ b/src/modules/wallet/components/multisignatureMembers/styles.css @@ -11,6 +11,7 @@ display: flex; flex-direction: row; flex-wrap: wrap; + width: 100%; & p { @mixin contentNormal bold; diff --git a/src/modules/wallet/components/signMultisigView/helpers.js b/src/modules/wallet/components/signMultisigView/helpers.js index e7b793f794..e41dce4f85 100644 --- a/src/modules/wallet/components/signMultisigView/helpers.js +++ b/src/modules/wallet/components/signMultisigView/helpers.js @@ -87,7 +87,16 @@ export const showSignButton = (senderAccount, account, transaction) => { let mandatoryKeys = []; let optionalKeys = []; - if (isRegisterMultisignature) { + const isInitatorAccountMultiSig = senderAccount.numberOfSignatures > 1; + + if (isRegisterMultisignature && isInitatorAccountMultiSig) { + mandatoryKeys = [ + ...new Set([...transaction.params.mandatoryKeys, ...senderAccount.keys?.mandatoryKeys]), + ]; + optionalKeys = [ + ...new Set([...transaction.params.optionalKeys, ...senderAccount.keys?.optionalKeys]), + ]; + } else if (isRegisterMultisignature && !isInitatorAccountMultiSig) { mandatoryKeys = transaction.params.mandatoryKeys; optionalKeys = transaction.params.optionalKeys; } else { diff --git a/src/modules/wallet/utils/multiSignatureStatus.js b/src/modules/wallet/utils/multiSignatureStatus.js index f7563e6745..8bbaf67d8c 100644 --- a/src/modules/wallet/utils/multiSignatureStatus.js +++ b/src/modules/wallet/utils/multiSignatureStatus.js @@ -14,7 +14,6 @@ export const getMultiSignatureStatus = ({ senderAccount, account, currentAccount, - // transactionJSON, moduleCommandSchemas, transactions, ...rest @@ -30,14 +29,6 @@ export const getMultiSignatureStatus = ({ const isMember = showSignButton(senderAccount, account, transactionJSON); const signatureStatus = getTransactionSignatureStatus(senderAccount, transactionJSON); - console.log( - '%%$$$', - moduleCommandSchemas, - transactions, - signatureStatus, - transactionJSON, - currentAccount.metadata.pubkey - ); const canSenderSignTx = transactionJSON.senderPublicKey === currentAccount.metadata.pubkey && signatureStatus === signatureCollectionStatus.fullySigned; From d8958838286a1bc9f84cb0b61100a6d762c749c7 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 15:37:21 +0200 Subject: [PATCH 06/25] fix: resolved deepscan issues --- .../TransactionDetails/signedAndRemainingMembersList.js | 2 +- .../wallet/components/RegisterMultisigForm/index.js | 2 +- src/modules/wallet/components/signMultisigView/helpers.js | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js index ad5b0f047d..0d638cc2df 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js @@ -39,7 +39,7 @@ const SignedAndRemainingMembersList = ({ t }) => { needed={needed} required={required} className={styles.signedAndRemainingMembersList} - title="Multisignature params signature" + title={isMultisignatureRegistration ? 'Multisignature params signature' : 'Members'} t={t} /> ); diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.js b/src/modules/wallet/components/RegisterMultisigForm/index.js index d3587c8cfb..d88d8e90de 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.js @@ -191,7 +191,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { signatures: initializeDefaultSignatures(mandatoryKeys, optionalKeys), }; - const numberofSignatureOnAccount = authQuery?.data?.data.numberOfSignatures; + const numberofSignatureOnAccount = authQuery.data?.data.numberOfSignatures; const isEditMultisignatureMembers = numberofSignatureOnAccount > 1; return ( diff --git a/src/modules/wallet/components/signMultisigView/helpers.js b/src/modules/wallet/components/signMultisigView/helpers.js index e41dce4f85..7af9ce6cbd 100644 --- a/src/modules/wallet/components/signMultisigView/helpers.js +++ b/src/modules/wallet/components/signMultisigView/helpers.js @@ -91,10 +91,13 @@ export const showSignButton = (senderAccount, account, transaction) => { if (isRegisterMultisignature && isInitatorAccountMultiSig) { mandatoryKeys = [ - ...new Set([...transaction.params.mandatoryKeys, ...senderAccount.keys?.mandatoryKeys]), + ...new Set([ + ...transaction.params.mandatoryKeys, + ...(senderAccount.keys?.mandatoryKeys || []), + ]), ]; optionalKeys = [ - ...new Set([...transaction.params.optionalKeys, ...senderAccount.keys?.optionalKeys]), + ...new Set([...transaction.params.optionalKeys, ...(senderAccount.keys?.optionalKeys || [])]), ]; } else if (isRegisterMultisignature && !isInitatorAccountMultiSig) { mandatoryKeys = transaction.params.mandatoryKeys; From fb13deca34115732d8b94d609d6c64c1c1467b16 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 16:50:44 +0200 Subject: [PATCH 07/25] fix: resolved issue with register multi sig form --- .../RegisterMultisigForm/index.test.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.test.js b/src/modules/wallet/components/RegisterMultisigForm/index.test.js index 5d4873f133..66d03ec128 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.test.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.test.js @@ -79,6 +79,17 @@ describe('Multisignature editor component', () => { const props = { account: wallets.genesis, nextStep: jest.fn(), + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 1, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, }; beforeEach(() => { @@ -246,6 +257,21 @@ describe('validateState', () => { }); it('should return error if optional members never get to sign', () => { + const pbk = wallets.genesis.summary.publicKey; + const pbk2 = wallets.mainnet_guy.summary.publicKey; + const pbk3 = wallets.multiSig_candidate.summary.publicKey; + const pbk4 = wallets.validator.summary.publicKey; + const params = { + ...commonParam, + mandatoryKeys: [pbk, pbk2, pbk3,], + optionalKeys: [pbk4], + numberOfSignatures: 2, + }; + const error = 'Number of signatures must be above {{num}}.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if duplicate public key is used', () => { const pbk = wallets.genesis.summary.publicKey; const params = { ...commonParam, @@ -253,7 +279,7 @@ describe('validateState', () => { optionalKeys: [pbk], numberOfSignatures: 3, }; - const error = 'Number of signatures must be above {{num}}.'; + const error = 'Duplicate public keys detected.'; expect(validateState(params).messages).toContain(error); }); From cb9cd635a9222344646d511b44ee25b0d80fc009 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 16:52:45 +0200 Subject: [PATCH 08/25] fix: resolved issue with register multi sig status --- .../RegisterMultisigStatus/status.test.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/modules/wallet/components/RegisterMultisigStatus/status.test.js b/src/modules/wallet/components/RegisterMultisigStatus/status.test.js index 286ab97b04..095d0cf507 100644 --- a/src/modules/wallet/components/RegisterMultisigStatus/status.test.js +++ b/src/modules/wallet/components/RegisterMultisigStatus/status.test.js @@ -16,6 +16,17 @@ describe('Multisignature Status component', () => { txSignatureError: null, signedTransaction: { signatures: ['123', '987'] }, }, + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 1, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, account: accounts.genesis, }; @@ -53,8 +64,7 @@ describe('Multisignature Status component', () => { illustration: 'registerMultisignature', status: { code: 'MULTISIG_SIGNATURE_PARTIAL_SUCCESS' }, title: 'Your signature was successful', - message: - 'You can download or copy the transaction and share it with other members.', + message: 'You can download or copy the transaction and share it with other members.', className: 'content', }); }); From 242ad55f3f5618402a0f1b148f3482ef035ec4aa Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 17:44:14 +0200 Subject: [PATCH 09/25] fix: resolved issue on statusConfig --- src/modules/transaction/configuration/statusConfig.js | 2 +- .../transaction/configuration/statusConfig.test.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/modules/transaction/configuration/statusConfig.js b/src/modules/transaction/configuration/statusConfig.js index ee3782c060..bec5f06d2e 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -144,7 +144,7 @@ export const getTransactionStatus = (account, transactions, options = {}) => { (sig) => sig.compare(Buffer.alloc(64)) > 0 ).length; } - + console.log('>>>', nonEmptySignatures, numberOfSignatures); if ( nonEmptySignatures < numberOfSignatures || (isMultisignature && diff --git a/src/modules/transaction/configuration/statusConfig.test.js b/src/modules/transaction/configuration/statusConfig.test.js index 08178e9123..2f88e799e3 100644 --- a/src/modules/transaction/configuration/statusConfig.test.js +++ b/src/modules/transaction/configuration/statusConfig.test.js @@ -1,4 +1,5 @@ import { mockCommandParametersSchemas } from 'src/modules/common/__fixtures__'; +import wallets from '@tests/constants/wallets'; import { getTransactionStatus } from './statusConfig'; import { txStatusTypes } from './txStatus'; @@ -74,10 +75,13 @@ describe('Transaction signature status', () => { }); it('should return transaction status for fully signed transaction', () => { - const account = {}; + const account = { summary: { isMultisignature: true } }; const transactions = { txSignatureError: null, - signedTransaction, + signedTransaction: { + ...signedTransaction, + signatures: [...signedTransaction.signatures, wallets.genesis.summary.publicKey], + }, }; const isMultisignature = true; const status = getTransactionStatus(account, transactions, { From ca69f3792b084c4130785e812d1782d37182ed29 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 17:52:28 +0200 Subject: [PATCH 10/25] fixed issue with summary test --- .../RegisterMultisigSummary/summary.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js index 14e1f58f87..9604920f84 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js @@ -87,6 +87,17 @@ describe('Multisignature Summary component', () => { moduleCommand: 'auth:registerMultisignature', fields: { token: { ...mockAppsTokens.data[0], availableBalance: '1000000000' } }, }, + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 1, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, }; beforeEach(() => { From 60c2acba9d711c4f75519c09343435efd3511f56 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 19:18:34 +0200 Subject: [PATCH 11/25] fix: resolved coverage on register multi sig summary --- .../AccountManagementDropdown.test.js | 20 +++++++++++++++++++ src/modules/account/const/accountMenu.js | 7 ++----- .../MultiSignatureReview.test.js | 2 ++ .../RegisterMultisigSummary/summary.test.js | 6 ++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/modules/account/components/AccountManagementDropdown/AccountManagementDropdown.test.js b/src/modules/account/components/AccountManagementDropdown/AccountManagementDropdown.test.js index b31cb7d7f3..8406ce8f5c 100644 --- a/src/modules/account/components/AccountManagementDropdown/AccountManagementDropdown.test.js +++ b/src/modules/account/components/AccountManagementDropdown/AccountManagementDropdown.test.js @@ -5,6 +5,7 @@ import { truncateAddress, truncateAccountName } from '@wallet/utils/account'; import { mockHWAccounts } from '@hardwareWallet/__fixtures__'; import { mockAppsTokens } from '@token/fungible/__fixtures__'; import { useTokenBalances } from '@token/fungible/hooks/queries'; +import { useAuth } from '@auth/hooks/queries'; import AccountManagementDropdown from './AccountManagementDropdown'; const mockCurrentAccount = mockSavedAccounts[0]; @@ -14,8 +15,12 @@ jest.mock('../../../account/hooks/useCurrentAccount.js', () => ({ })); jest.mock('@token/fungible/hooks/queries/useTokenBalances'); +jest.mock('@auth/hooks/queries/useAuth'); describe('AccountManagementDropdown', () => { + useAuth.mockReturnValue({ + data: {}, + }); useTokenBalances.mockReturnValue({ data: { data: [{ name: 'Lisk', symbol: 'LSK', availableBalance: 0, ...mockAppsTokens.data[0] }], @@ -76,4 +81,19 @@ describe('AccountManagementDropdown', () => { fireEvent.click(screen.getByText('Backup account')); expect(screen.getByText('Register multisignature account')).toBeVisible(); }); + + it('Should have edit register multisignature enabled', () => { + useAuth.mockReturnValue({ + data: { data: { numberOfSignatures: 3 } }, + }); + + const props = { + currentAccount: mockHWAccounts[0], + onMenuClick: mockOnMenuClick, + }; + renderWithRouterAndQueryClient(AccountManagementDropdown, props); + fireEvent.click(screen.getByAltText('dropdownArrowIcon')); + fireEvent.click(screen.getByText('Backup account')); + expect(screen.getByText('Edit multisignature account')).toBeVisible(); + }); }); diff --git a/src/modules/account/const/accountMenu.js b/src/modules/account/const/accountMenu.js index a7a519df92..caa5e1a437 100644 --- a/src/modules/account/const/accountMenu.js +++ b/src/modules/account/const/accountMenu.js @@ -37,11 +37,8 @@ export const accountMenu = ({ } : {}, icon: 'multiSignatureOutline', - label: `${ - authData?.data?.numberOfSignatures > 0 || hasNetworkError || isLoadingNetwork - ? 'Edit' - : 'Register' - } multisignature account`, + isHidden: hasNetworkError || isLoadingNetwork, + label: `${authData?.data?.numberOfSignatures > 0 ? 'Edit' : 'Register'} multisignature account`, }, { component: 'removeSelectedAccount', diff --git a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js index df9de7e050..dfeb943e01 100644 --- a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js +++ b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js @@ -26,6 +26,8 @@ describe('Multisignature Review component', () => { fee: 2000000, numberOfSignatures: 2, token: { ...mockAppsTokens.data[0], availableBalance: '1000000000' }, + isMultisignature: false, + isRegisterMultisigature: true, }; beforeEach(() => { diff --git a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js index 9604920f84..8cb75fb940 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js @@ -146,6 +146,12 @@ describe('Multisignature Summary component', () => { expect(screen.getByText('0.02 LSK')).toBeInTheDocument(); }); + it('Should be in edit mode', () => { + smartRender(Summary, { ...props, authQuery: { data: { data: { numberOfSignatures: 3 } } } }); + + expect(screen.getByText('Edit multisignature account')); + }); + it('Should not call props.nextStep when signedTransaction is empty', () => { jest.clearAllMocks(); From e7eb8e0b7721487ce4887139e54d446c0743c28c Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Thu, 5 Oct 2023 19:26:13 +0200 Subject: [PATCH 12/25] fix: resolved all unit tests --- .../transaction/configuration/statusConfig.js | 2 +- .../components/RegisterMultisigStatus/status.js | 2 +- .../RegisterMultisigStatus/status.test.js | 15 +++++++++++++++ .../RegisterMultisigSummary/summary.test.js | 3 +-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/modules/transaction/configuration/statusConfig.js b/src/modules/transaction/configuration/statusConfig.js index bec5f06d2e..ee3782c060 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -144,7 +144,7 @@ export const getTransactionStatus = (account, transactions, options = {}) => { (sig) => sig.compare(Buffer.alloc(64)) > 0 ).length; } - console.log('>>>', nonEmptySignatures, numberOfSignatures); + if ( nonEmptySignatures < numberOfSignatures || (isMultisignature && diff --git a/src/modules/wallet/components/RegisterMultisigStatus/status.js b/src/modules/wallet/components/RegisterMultisigStatus/status.js index 37a20ffcb6..ef1c8e5eca 100644 --- a/src/modules/wallet/components/RegisterMultisigStatus/status.js +++ b/src/modules/wallet/components/RegisterMultisigStatus/status.js @@ -17,7 +17,7 @@ const Status = ({ account, transactions, t, authQuery }) => {

- {t(`${numberOfSignaturesOnAccount > 0 ? 'Edit' : 'Register'} multisignature account`)} + {t(`${numberOfSignaturesOnAccount > 1 ? 'Edit' : 'Register'} multisignature account`)}

diff --git a/src/modules/wallet/components/RegisterMultisigStatus/status.test.js b/src/modules/wallet/components/RegisterMultisigStatus/status.test.js index 095d0cf507..426019175c 100644 --- a/src/modules/wallet/components/RegisterMultisigStatus/status.test.js +++ b/src/modules/wallet/components/RegisterMultisigStatus/status.test.js @@ -160,4 +160,19 @@ describe('Multisignature Status component', () => { className: 'content', }); }); + + it('Should be in edit mode', () => { + const customProp = { + ...props, + authQuery: { data: { data: { numberOfSignatures: 3 } } }, + transactions: { + txBroadcastError: null, + txSignatureError: null, + signedTransaction: {}, + }, + }; + + const wrapper = shallow(); + expect(wrapper.find('div.header')).toHaveText('Edit multisignature account'); + }); }); diff --git a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js index 8cb75fb940..99548c465a 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/summary.test.js @@ -148,8 +148,7 @@ describe('Multisignature Summary component', () => { it('Should be in edit mode', () => { smartRender(Summary, { ...props, authQuery: { data: { data: { numberOfSignatures: 3 } } } }); - - expect(screen.getByText('Edit multisignature account')); + expect(screen.getByText('Edit multisignature account')).toBeTruthy(); }); it('Should not call props.nextStep when signedTransaction is empty', () => { From 357f19125e7e9dfed6ec3e3836390a68390a0f7f Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Fri, 6 Oct 2023 13:53:26 +0200 Subject: [PATCH 13/25] fix: resolved issue from manu --- .../MultiSignatureReview.js | 14 ++- .../TransactionInfo/TransactionInfo.js | 118 ++++++++++-------- 2 files changed, 74 insertions(+), 58 deletions(-) diff --git a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js index 2c82aa32c9..a7f6c5fba6 100644 --- a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js +++ b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.js @@ -25,13 +25,16 @@ const Member = ({ member, i, t }) => (
); -const Members = ({ members = [], t }) => { +const Members = ({ members = [], t, isMultisignature, isRegisterMultisigature }) => { const sliceIndex = Math.round(members.length / 2); const leftColumn = members.slice(0, sliceIndex); const rightColumn = members.slice(sliceIndex, members.length); + return (
-

{t('Registering members')}

+

+ {isMultisignature && isRegisterMultisigature ? t('Registering members') : t('Members')} +

{leftColumn.map((member, i) => ( @@ -68,7 +71,12 @@ const MultiSignatureReview = ({ isRegisterMultisigature, }) => ( <> - + {!isMultisignature && isRegisterMultisigature && (
diff --git a/src/modules/transaction/components/TransactionInfo/TransactionInfo.js b/src/modules/transaction/components/TransactionInfo/TransactionInfo.js index 7630e7c39e..86954a39c3 100644 --- a/src/modules/transaction/components/TransactionInfo/TransactionInfo.js +++ b/src/modules/transaction/components/TransactionInfo/TransactionInfo.js @@ -5,10 +5,12 @@ import TokenAmount from '@token/fungible/components/tokenAmount'; import { extractAddressFromPublicKey } from '@wallet/utils/account'; import styles from './TransactionInfo.css'; import CustomTransactionInfo from './CustomTransactionInfo'; +import { joinModuleAndCommand } from '../../utils'; +import { MODULE_COMMANDS_NAME_MAP } from '../../configuration/moduleCommand'; -const Members = ({ members, t }) => ( +const Members = ({ members, t, isRegisterMultisignature }) => (
- +
{members.map((member, i) => (
@@ -35,58 +37,64 @@ const TransactionInfo = ({ date, token, summaryInfo, -}) => ( - <> - - {isMultisignature && ( - <> -
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- ({ - publicKey, - isMandatory: true, - address: extractAddressFromPublicKey(publicKey), - })), - ...account.keys.optionalKeys.map((publicKey) => ({ - publicKey, - isMandatory: false, - address: extractAddressFromPublicKey(publicKey), - })), - ]} - /> - - )} - -); +}) => { + const isRegisterMultisignature = + joinModuleAndCommand(transactionJSON) === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + + return ( + <> + + {isMultisignature && ( + <> +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ ({ + publicKey, + isMandatory: true, + address: extractAddressFromPublicKey(publicKey), + })), + ...account.keys.optionalKeys.map((publicKey) => ({ + publicKey, + isMandatory: false, + address: extractAddressFromPublicKey(publicKey), + })), + ]} + /> + + )} + + ); +}; export default withTranslation()(TransactionInfo); From 8b1d832278631a6ace5ea91e529b215610770cf2 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Fri, 6 Oct 2023 14:59:54 +0200 Subject: [PATCH 14/25] fix: updated text --- .../TransactionDetails/signedAndRemainingMembersList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js index 0d638cc2df..2962967d08 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js @@ -39,7 +39,7 @@ const SignedAndRemainingMembersList = ({ t }) => { needed={needed} required={required} className={styles.signedAndRemainingMembersList} - title={isMultisignatureRegistration ? 'Multisignature params signature' : 'Members'} + title={isMultisignatureRegistration ? 'Multisignature params signatures' : 'Members'} t={t} /> ); From 8936211cce86be05586563ee65ee91c46f82ced1 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Fri, 6 Oct 2023 17:42:44 +0200 Subject: [PATCH 15/25] fix: resolved registration signing from a non multi sig account --- .../TransactionDetails/signedAndRemainingSignatureList.js | 2 ++ src/modules/transaction/configuration/statusConfig.js | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js index 32901c8264..c703863733 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js @@ -16,6 +16,8 @@ const SignedAndRemainingSignatureList = ({ t }) => { const required = keys.numberOfSignatures; const needed = required - signed.length; + if (signed.length === 0 && remaining.length === 0 && required === 0) return null; + return ( { const isRegisterMultisignature = moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; const isMultisignature = account?.summary?.isMultisignature || options.isMultisignature; - + const isInitatorAccountMultiSig = account.numberOfSignatures > 0; let nonEmptySignatures = transactions.signedTransaction.signatures.filter( (sig) => sig.length > 0 ).length; - if (isRegisterMultisignature && !isMultisignature) { + if (isRegisterMultisignature && !isInitatorAccountMultiSig) { nonEmptySignatures = transactions.signedTransaction.params.signatures.filter( (sig) => sig.compare(Buffer.alloc(64)) > 0 ).length; From 065d283645633d99c4c96904f50e9cf30df8da01 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Fri, 6 Oct 2023 17:57:13 +0200 Subject: [PATCH 16/25] fix: resolved test coverage issues --- .../MultiSignatureReview.test.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js index dfeb943e01..f3c5eb0b37 100644 --- a/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js +++ b/src/modules/transaction/components/MultiSignatureReview/MultiSignatureReview.test.js @@ -30,15 +30,22 @@ describe('Multisignature Review component', () => { isRegisterMultisigature: true, }; - beforeEach(() => { - wrapper = mountWithRouter(Review, props); - }); - useTokenBalances.mockReturnValue({ data: mockAppsTokens }); it('Should render properly', () => { + wrapper = mountWithRouter(Review, props); + expect(wrapper).toContainMatchingElements(props.members.length, '.member-info'); expect(wrapper.find('.infoColumn.info-numberOfSignatures')).toHaveText('Required signatures2'); expect(wrapper.find('.infoColumn.info-fee')).toHaveText('Fees0.02 LSK'); }); + + it('Should render properly when editing register multi-signature transaction', () => { + wrapper = mountWithRouter(Review, { + ...props, + isRegisterMultisigature: true, + isMultisignature: true, + }); + expect(wrapper.find('.membersContainer > p:first-child')).toHaveText('Registering members'); + }); }); From 32a770befcb757cb116ab49f6c948085250e2128 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Fri, 6 Oct 2023 17:59:04 +0200 Subject: [PATCH 17/25] fix: resolved deep scan issue --- 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 7e9b67a8ac..36da5bdac3 100644 --- a/src/modules/transaction/configuration/statusConfig.js +++ b/src/modules/transaction/configuration/statusConfig.js @@ -134,7 +134,7 @@ export const getTransactionStatus = (account, transactions, options = {}) => { const isRegisterMultisignature = moduleCommand === MODULE_COMMANDS_NAME_MAP.registerMultisignature; const isMultisignature = account?.summary?.isMultisignature || options.isMultisignature; - const isInitatorAccountMultiSig = account.numberOfSignatures > 0; + const isInitatorAccountMultiSig = account?.numberOfSignatures > 0; let nonEmptySignatures = transactions.signedTransaction.signatures.filter( (sig) => sig.length > 0 ).length; From 6f0f62f67490a7850e6347a94c545cad0fc60429 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 00:33:56 +0200 Subject: [PATCH 18/25] fix: resolved issue with signing if not member --- .../components/RegisterMultisigForm/index.js | 4 ++-- .../RegisterMultisigSummary/Summary.js | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.js b/src/modules/wallet/components/RegisterMultisigForm/index.js index d88d8e90de..a9554138c0 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.js @@ -148,7 +148,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { useEffect(() => { const numberOfSignaturesOnAccount = authQuery.data?.data?.numberOfSignatures; - if (authQuery.isFetched && authQuery.data && numberOfSignaturesOnAccount > 1) { + if (authQuery.isFetched && authQuery.data && numberOfSignaturesOnAccount > 0) { const mandatoryMembers = authQuery.data.data.mandatoryKeys.map((key) => ({ isMandatory: true, publicKey: key, @@ -192,7 +192,7 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { }; const numberofSignatureOnAccount = authQuery.data?.data.numberOfSignatures; - const isEditMultisignatureMembers = numberofSignatureOnAccount > 1; + const isEditMultisignatureMembers = numberofSignatureOnAccount > 0; return (
diff --git a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js index 606c7dce9d..2bb2a8e5d0 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js @@ -1,13 +1,17 @@ import React, { useEffect, useMemo } from 'react'; import { isEmpty } from 'src/utils/helpers'; +import { useDispatch } from 'react-redux'; import { useCurrentAccount } from '@account/hooks'; import { useAuth } from '@auth/hooks/queries'; +import { fromTransactionJSON, joinModuleAndCommand } from '@transaction/utils'; +import actionTypes from '@transaction/store/actionTypes'; import TransactionSummary from '@transaction/manager/transactionSummary'; import useTxInitiatorAccount from '@transaction/hooks/useTxInitiatorAccount'; import { useCommandSchema } from '@network/hooks'; import ProgressBar from '../RegisterMultisigView/ProgressBar'; import styles from './styles.css'; +// eslint-disable-next-line max-statements const Summary = ({ t, prevStep, @@ -19,6 +23,7 @@ const Summary = ({ authQuery, }) => { const [sender] = useCurrentAccount(); + const dispatch = useDispatch(); const { txInitiatorAccount } = useTxInitiatorAccount({ senderPublicKey: transactionJSON.senderPublicKey, }); @@ -53,7 +58,19 @@ const Summary = ({ }); if (!isSenderMember) { - actionFunction(); + dispatch({ + type: actionTypes.transactionSigned, + data: fromTransactionJSON( + transactionJSON, + moduleCommandSchemas[joinModuleAndCommand(transactionJSON)] + ), + }); + nextStep({ + formProps, + transactionJSON, + sender, + actionFunction, + }); } else { nextStep({ formProps, @@ -76,6 +93,7 @@ const Summary = ({ }; useEffect(() => { + console.log('>>>>>', transactions, isSenderMember); if (!isEmpty(transactions.signedTransaction) && !isSenderMember) { nextStep({ formProps, transactionJSON, sender }, 2); } From c9f7ad99e8b380d5ad0eb40fb208c2d24044f4f0 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 01:26:18 +0200 Subject: [PATCH 19/25] fix: resolved issue with previous state retention on reigster multi-sig --- .../wallet/components/RegisterMultisigForm/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.js b/src/modules/wallet/components/RegisterMultisigForm/index.js index a9554138c0..78d7d7bc51 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.js @@ -9,6 +9,7 @@ import TxComposer from '@transaction/components/TxComposer'; import { useCurrentApplication } from '@blockchainApplication/manage/hooks'; import { useTokenBalances } from 'src/modules/token/fungible/hooks/queries'; import { useCurrentAccount } from '@account/hooks'; +import { isEmpty } from 'src/utils/helpers'; import ProgressBar from '../RegisterMultisigView/ProgressBar'; import { MAX_MULTI_SIG_MEMBERS, DEFAULT_SIGNATURE_BYTE_SIZE } from '../../configuration/constants'; @@ -146,6 +147,12 @@ const Form = ({ nextStep, prevState = {}, onNext, authQuery }) => { }, [numberOfSignatures]); useEffect(() => { + if (!isEmpty(getInitialMembersState(prevState))) { + setMembers(getInitialMembersState(prevState)); + setNumberOfSignatures(getInitialSignaturesState(prevState)); + return; + } + const numberOfSignaturesOnAccount = authQuery.data?.data?.numberOfSignatures; if (authQuery.isFetched && authQuery.data && numberOfSignaturesOnAccount > 0) { From 924abc913ff80e49e4e78d27d861e949bc6c2cbe Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 01:54:04 +0200 Subject: [PATCH 20/25] fix: resolved failing unit test --- .../RegisterMultisigForm/index.test.js | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/src/modules/wallet/components/RegisterMultisigForm/index.test.js b/src/modules/wallet/components/RegisterMultisigForm/index.test.js index 66d03ec128..a35567d779 100644 --- a/src/modules/wallet/components/RegisterMultisigForm/index.test.js +++ b/src/modules/wallet/components/RegisterMultisigForm/index.test.js @@ -85,7 +85,7 @@ describe('Multisignature editor component', () => { data: { data: { numberOfSignatures: 1, - mandatoryKeys: [], + mandatoryKeys: [wallets.genesis.summary.publicKey, wallets.mainnet_guy.summary.publicKey], optionalKeys: [], }, }, @@ -137,6 +137,20 @@ describe('Multisignature editor component', () => { }); it('delete icon is only visible if required signatures < members.length', () => { + wrapper = mountWithQueryClient(Form, { + ...props, + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 0, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, + }); expect(wrapper).not.toContainMatchingElement('.delete-icon'); for (let i = 0; i < 3; ++i) { wrapper.find('.add-new-members').at(0).simulate('click'); @@ -153,6 +167,21 @@ describe('Multisignature editor component', () => { }); it('props.nextStep is called when the CTA is clicked', async () => { + wrapper = mountWithQueryClient(Form, { + ...props, + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 0, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, + }); + wrapper .find('input.msign-pk-input') .at(0) @@ -194,6 +223,21 @@ describe('Multisignature editor component', () => { }); it('should be able to change the number of signatures', async () => { + wrapper = mountWithQueryClient(Form, { + ...props, + authQuery: { + isFetching: false, + isFetched: true, + data: { + data: { + numberOfSignatures: 0, + mandatoryKeys: [], + optionalKeys: [], + }, + }, + }, + }); + props.nextStep.mockReset(); wrapper .find('.multisignature-editor-input input') @@ -263,14 +307,14 @@ describe('validateState', () => { const pbk4 = wallets.validator.summary.publicKey; const params = { ...commonParam, - mandatoryKeys: [pbk, pbk2, pbk3,], + mandatoryKeys: [pbk, pbk2, pbk3], optionalKeys: [pbk4], numberOfSignatures: 2, }; const error = 'Number of signatures must be above {{num}}.'; expect(validateState(params).messages).toContain(error); }); - + it('should return error if duplicate public key is used', () => { const pbk = wallets.genesis.summary.publicKey; const params = { From 3cb6ab9afde69d1d0cb9af7cf4ee737d4d97481f Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 18:54:56 +0200 Subject: [PATCH 21/25] fix: refactored ui on params and root signature display --- src/locales/en/common.json | 2 ++ .../signedAndRemainingSignatureList.js | 18 ++++++++++++++- .../transaction/configuration/statusConfig.js | 3 ++- .../RegisterMultisigSummary/Summary.js | 1 - .../components/multisignatureMembers/index.js | 22 +++++++++++++++++-- .../multisignatureMembers/styles.css | 9 ++++++++ 6 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/locales/en/common.json b/src/locales/en/common.json index eb777431e4..a62afd723f 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -367,6 +367,8 @@ "Maxmind": "Maxmind", "Medium": "Medium", "Members": "Members", + "Members have fully signed.": "Members have fully signed.", + "Members have partially signed.": "Members have partially signed.", "Message": "Message", "Message (Optional)": "Message (Optional)", "Message Fee": "Message Fee", diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js index c703863733..dc8b568d83 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingSignatureList.js @@ -4,9 +4,20 @@ import { calculateRemainingAndSignedMembers } from '@wallet/utils/account'; import TransactionDetailsContext from '../../context/transactionDetailsContext'; import styles from './styles.css'; +// eslint-disable-next-line max-statements const SignedAndRemainingSignatureList = ({ t }) => { const { transaction, wallet } = useContext(TransactionDetailsContext); const keys = wallet.keys; + const transactionKeys = { + optionalKeys: transaction.params.optionalKeys, + mandatoryKeys: transaction.params.mandatoryKeys, + numberOfSignatures: transaction.params.numberOfSignatures, + }; + + const { remaining: remainingTxParamMembers } = useMemo( + () => calculateRemainingAndSignedMembers(transactionKeys, transaction, true), + [wallet] + ); const { signed, remaining } = useMemo( () => calculateRemainingAndSignedMembers(keys, transaction, false), @@ -16,7 +27,12 @@ const SignedAndRemainingSignatureList = ({ t }) => { const required = keys.numberOfSignatures; const needed = required - signed.length; - if (signed.length === 0 && remaining.length === 0 && required === 0) return null; + if ( + (signed.length === 0 && remaining.length === 0 && required === 0) || + remainingTxParamMembers.length > 0 + ) { + return null; + } return ( { (isMultisignature && nonEmptySignatures === numberOfSignatures && !options.canSenderSignTx && - isRegisterMultisignature) + isRegisterMultisignature && + !isInitatorAccountMultiSig) ) { return { code: txStatusTypes.multisigSignaturePartialSuccess }; } diff --git a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js index 2bb2a8e5d0..90c1f1b776 100644 --- a/src/modules/wallet/components/RegisterMultisigSummary/Summary.js +++ b/src/modules/wallet/components/RegisterMultisigSummary/Summary.js @@ -93,7 +93,6 @@ const Summary = ({ }; useEffect(() => { - console.log('>>>>>', transactions, isSenderMember); if (!isEmpty(transactions.signedTransaction) && !isSenderMember) { nextStep({ formProps, transactionJSON, sender }, 2); } diff --git a/src/modules/wallet/components/multisignatureMembers/index.js b/src/modules/wallet/components/multisignatureMembers/index.js index 53011f3152..432ffd6d7e 100644 --- a/src/modules/wallet/components/multisignatureMembers/index.js +++ b/src/modules/wallet/components/multisignatureMembers/index.js @@ -1,6 +1,7 @@ import React from 'react'; import Tooltip from '@theme/Tooltip/tooltip'; import classNames from 'classnames'; +import Icon from 'src/theme/Icon'; import WalletVisual from '../walletVisual'; import { truncateAddress } from '../../utils/account'; import styles from './styles.css'; @@ -89,8 +90,25 @@ export const SignedAndRemainingMembers = ({ title, }) => (
-

{title}

-
+

+ {title} + } + > +

+ {remaining.length === 0 + ? t('Members have fully signed.') + : t('Members have partially signed.')} +

+ +

+

{t('Signed')}

{signed.map((member, i) => ( diff --git a/src/modules/wallet/components/multisignatureMembers/styles.css b/src/modules/wallet/components/multisignatureMembers/styles.css index cb84eddd5a..5af47e942e 100644 --- a/src/modules/wallet/components/multisignatureMembers/styles.css +++ b/src/modules/wallet/components/multisignatureMembers/styles.css @@ -3,6 +3,11 @@ .wrapper { display: flex; flex-direction: column; + + & > p:first-child > div:first-child { + margin-bottom: -4px; + margin-left: 7px; + } } .membersContainer { @@ -13,6 +18,10 @@ flex-wrap: wrap; width: 100%; + &.fullySigned { + opacity: 0.5; + } + & p { @mixin contentNormal bold; From 1e1a2e6e6555d54cf17a20744001baf1e4176c20 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 19:37:07 +0200 Subject: [PATCH 22/25] fix: resolved issue with account details not showing --- .../account/components/AccountMenuListing/AccountMenuListing.js | 1 + src/modules/account/const/accountMenu.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/modules/account/components/AccountMenuListing/AccountMenuListing.js b/src/modules/account/components/AccountMenuListing/AccountMenuListing.js index cc7765b0ff..9b230a0a7a 100644 --- a/src/modules/account/components/AccountMenuListing/AccountMenuListing.js +++ b/src/modules/account/components/AccountMenuListing/AccountMenuListing.js @@ -38,6 +38,7 @@ const AccountMenuListing = ({ className, onItemClicked }) => { {accountMenu({ authData, isHW, + address, hasNetworkError, isLoadingNetwork, hasAvailableTokenBalance: tokenBalances.data?.data?.some( diff --git a/src/modules/account/const/accountMenu.js b/src/modules/account/const/accountMenu.js index caa5e1a437..d7fa014c84 100644 --- a/src/modules/account/const/accountMenu.js +++ b/src/modules/account/const/accountMenu.js @@ -7,11 +7,13 @@ export const accountMenu = ({ hasNetworkError, isLoadingNetwork, hasAvailableTokenBalance, + address, }) => [ { component: 'accountDetails', icon: 'profileOutline', label: 'Account details', + data: { address }, }, { component: 'switchAccount', From 2c9d2d021516bb3c5b98908c0c0b7684005c62f9 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Mon, 9 Oct 2023 20:21:58 +0200 Subject: [PATCH 23/25] fix: resolved issue with memeber not in params memeber --- .../components/signMultisigSummary/summary.js | 12 ++++-- .../wallet/utils/multiSignatureStatus.js | 39 +++++++++++++++++-- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/modules/wallet/components/signMultisigSummary/summary.js b/src/modules/wallet/components/signMultisigSummary/summary.js index 5169e85a7f..55e3b65557 100644 --- a/src/modules/wallet/components/signMultisigSummary/summary.js +++ b/src/modules/wallet/components/signMultisigSummary/summary.js @@ -25,7 +25,7 @@ const Summary = ({ t, transactionJSON, formProps, account, nextStep, history, ne senderPublicKey: transactionJSON.senderPublicKey, }); - const { isMember, signatureStatus, canSenderSignTx } = useMultiSignatureStatus({ + const { signatureStatus, canSenderSignTx, canCurrentMemberSign } = useMultiSignatureStatus({ transactionJSON, account, currentAccount, @@ -47,7 +47,7 @@ const Summary = ({ t, transactionJSON, formProps, account, nextStep, history, ne }; const showFeedback = - !(isMember || canSenderSignTx) || + !(canCurrentMemberSign || canSenderSignTx) || (signatureStatus === signatureCollectionStatus.fullySigned && !canSenderSignTx) || (signatureStatus === signatureCollectionStatus.occupiedByOptionals && !canSenderSignTx); @@ -85,13 +85,17 @@ const Summary = ({ t, transactionJSON, formProps, account, nextStep, history, ne - {((isMember && + {((canCurrentMemberSign && signatureStatus !== signatureCollectionStatus.fullySigned && signatureStatus !== signatureCollectionStatus.occupiedByOptionals) || canSenderSignTx) && } {showFeedback ? ( - + ) : null} ); diff --git a/src/modules/wallet/utils/multiSignatureStatus.js b/src/modules/wallet/utils/multiSignatureStatus.js index 8bbaf67d8c..4ce3dbf33b 100644 --- a/src/modules/wallet/utils/multiSignatureStatus.js +++ b/src/modules/wallet/utils/multiSignatureStatus.js @@ -1,10 +1,12 @@ -import { signatureCollectionStatus } from 'src/modules/transaction/configuration/txStatus'; -import { joinModuleAndCommand, toTransactionJSON } from 'src/modules/transaction/utils'; +import { signatureCollectionStatus } from '@transaction/configuration/txStatus'; +import { MODULE_COMMANDS_NAME_MAP } from '@transaction/configuration/moduleCommand'; +import { joinModuleAndCommand, toTransactionJSON } from '@transaction/utils'; import { isEmpty } from 'src/utils/helpers'; import { getTransactionSignatureStatus, showSignButton, } from '../components/signMultisigView/helpers'; +import { calculateRemainingAndSignedMembers } from './account'; /** * Get required statuses for a given multi-signature transaction @@ -33,5 +35,36 @@ export const getMultiSignatureStatus = ({ transactionJSON.senderPublicKey === currentAccount.metadata.pubkey && signatureStatus === signatureCollectionStatus.fullySigned; - return { isMember, signatureStatus, canSenderSignTx }; + // eslint-disable-next-line max-statements + const canCurrentMemberSign = () => { + const isRegisterMultisignature = + joinModuleAndCommand(transactionJSON) === MODULE_COMMANDS_NAME_MAP.registerMultisignature; + + const isInitatorAccountMultiSig = senderAccount.numberOfSignatures > 1; + + const transactionKeys = { + optionalKeys: transactionJSON.params.optionalKeys, + mandatoryKeys: transactionJSON.params.mandatoryKeys, + numberOfSignatures: transactionJSON.params.numberOfSignatures, + }; + const { remaining: paramsTxSignaturesRemaining } = calculateRemainingAndSignedMembers( + transactionKeys, + transactionJSON, + true + ); + + if (isRegisterMultisignature && isInitatorAccountMultiSig && paramsTxSignaturesRemaining.length > 0) { + const { optionalKeys, mandatoryKeys } = transactionJSON.params; + return [...optionalKeys, ...mandatoryKeys].includes(account.summary.publicKey); + } + + return isMember; + }; + + return { + isMember, + signatureStatus, + canSenderSignTx, + canCurrentMemberSign: canCurrentMemberSign(), + }; }; From 4853f130d9474d7add9ec3a0453143407b722fa7 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Tue, 10 Oct 2023 08:52:32 +0200 Subject: [PATCH 24/25] fix: resolved summary unit test --- src/modules/wallet/utils/multiSignatureStatus.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/modules/wallet/utils/multiSignatureStatus.js b/src/modules/wallet/utils/multiSignatureStatus.js index 4ce3dbf33b..ae61898dd9 100644 --- a/src/modules/wallet/utils/multiSignatureStatus.js +++ b/src/modules/wallet/utils/multiSignatureStatus.js @@ -47,13 +47,16 @@ export const getMultiSignatureStatus = ({ mandatoryKeys: transactionJSON.params.mandatoryKeys, numberOfSignatures: transactionJSON.params.numberOfSignatures, }; - const { remaining: paramsTxSignaturesRemaining } = calculateRemainingAndSignedMembers( - transactionKeys, - transactionJSON, - true - ); - if (isRegisterMultisignature && isInitatorAccountMultiSig && paramsTxSignaturesRemaining.length > 0) { + if (isRegisterMultisignature && isInitatorAccountMultiSig) { + const { remaining: paramsTxSignaturesRemaining } = calculateRemainingAndSignedMembers( + transactionKeys, + transactionJSON, + true + ); + + if (paramsTxSignaturesRemaining.length === 0) return isMember; + const { optionalKeys, mandatoryKeys } = transactionJSON.params; return [...optionalKeys, ...mandatoryKeys].includes(account.summary.publicKey); } From b68bdd066accbe4d2890c52d523f774a6a608369 Mon Sep 17 00:00:00 2001 From: Eniola Olatunji Date: Tue, 10 Oct 2023 10:03:40 +0200 Subject: [PATCH 25/25] fix: resolved failing unit test --- src/locales/en/common.json | 1 + .../Multisignature/Multisignature.js | 20 ++++---- .../signedAndRemainingMembersList.js | 2 +- .../wallet/utils/multiSignatureStatus.test.js | 47 ++++++++++++++++++- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/locales/en/common.json b/src/locales/en/common.json index a62afd723f..86538fb190 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -385,6 +385,7 @@ "Monthly": "Monthly", "More filters": "More filters", "Multisignature details": "Multisignature details", + "Multisignature params signatures": "Multisignature params signatures", "My validator profile": "My validator profile", "Name": "Name", "Network": "Network", diff --git a/src/modules/transaction/components/Multisignature/Multisignature.js b/src/modules/transaction/components/Multisignature/Multisignature.js index 05c928a591..cbe3d31403 100644 --- a/src/modules/transaction/components/Multisignature/Multisignature.js +++ b/src/modules/transaction/components/Multisignature/Multisignature.js @@ -134,17 +134,17 @@ const Multisignature = ({ /> ) : null} {status.code !== txStatusTypes.broadcastSuccess && - status.code !== txStatusTypes.broadcastError && ( - - - - {t(copied ? 'Copied' : 'Copy')} - - - )} - {(status.code === txStatusTypes.multisigSignatureSuccess) && ( + status.code !== txStatusTypes.broadcastError ? ( + + + + {t(copied ? 'Copied' : 'Copy')} + + + ) : null} + {status.code === txStatusTypes.multisigSignatureSuccess ? ( - )} + ) : null} {status.code === txStatusTypes.multisigSignaturePartialSuccess ? ( ) : null} diff --git a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js index 2962967d08..45e94c8860 100644 --- a/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js +++ b/src/modules/transaction/components/TransactionDetails/signedAndRemainingMembersList.js @@ -39,7 +39,7 @@ const SignedAndRemainingMembersList = ({ t }) => { needed={needed} required={required} className={styles.signedAndRemainingMembersList} - title={isMultisignatureRegistration ? 'Multisignature params signatures' : 'Members'} + title={isMultisignatureRegistration ? t('Multisignature params signatures') : t('Members')} t={t} /> ); diff --git a/src/modules/wallet/utils/multiSignatureStatus.test.js b/src/modules/wallet/utils/multiSignatureStatus.test.js index 04387a5aaa..854c202725 100644 --- a/src/modules/wallet/utils/multiSignatureStatus.test.js +++ b/src/modules/wallet/utils/multiSignatureStatus.test.js @@ -1,6 +1,7 @@ import mockSavedAccounts from '@tests/fixtures/accounts'; import accounts from '@tests/constants/wallets'; import { getMultiSignatureStatus } from './multiSignatureStatus'; +import * as accountUtils from './account'; const mockCurrentAccount = mockSavedAccounts[0]; @@ -13,8 +14,8 @@ describe('TxSignatureCollector', () => { nonce: '1', signatures: [''], params: { - mandatoryKeys: ['mandatory-1'], - optionalKeys: ['public-1'], + mandatoryKeys: [accounts.genesis.publicKey], + optionalKeys: [accounts.multiSig.summary.publicKey], signatures: [], }, }; @@ -69,4 +70,46 @@ describe('TxSignatureCollector', () => { expect(canSenderSignTx).toBeTruthy(); }); + + it('should return canCurrentMemberSign as false if there are remaning memebers to sign', () => { + const currentAccount = { + ...mockCurrentAccount, + metadata: { pubkey: transactionJSON.senderPublicKey }, + }; + transactionJSON.params.signatures = ['', '']; + + jest.spyOn(accountUtils, 'calculateRemainingAndSignedMembers').mockReturnValue({ + remaining: [''], + }); + + const { canCurrentMemberSign } = getMultiSignatureStatus({ + senderAccount: { ...senderAccount, numberOfSignatures: 2 }, + account, + transactionJSON, + currentAccount, + }); + + expect(canCurrentMemberSign).toBeFalsy(); + }); + + it('should return canCurrentMemberSign as false if there are no remaning memebers to sign', () => { + const currentAccount = { + ...mockCurrentAccount, + metadata: { pubkey: transactionJSON.senderPublicKey }, + }; + transactionJSON.params.signatures = ['', '']; + + jest.spyOn(accountUtils, 'calculateRemainingAndSignedMembers').mockReturnValue({ + remaining: [], + }); + + const { canCurrentMemberSign } = getMultiSignatureStatus({ + senderAccount: { ...senderAccount, numberOfSignatures: 2 }, + account, + transactionJSON, + currentAccount, + }); + + expect(canCurrentMemberSign).toBeFalsy(); + }); });