From f71beb6ce2f67a61ec6b729c8c81726695e36e62 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Tue, 30 Nov 2021 11:06:58 +0100 Subject: [PATCH 01/17] Close the dropdown when an item is selected --- src/components/toolbox/dropdown/dropdown.js | 12 ++++++++++-- src/components/toolbox/dropdownButton/index.js | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/toolbox/dropdown/dropdown.js b/src/components/toolbox/dropdown/dropdown.js index bd3882f6d3..aa0db032f4 100644 --- a/src/components/toolbox/dropdown/dropdown.js +++ b/src/components/toolbox/dropdown/dropdown.js @@ -5,7 +5,7 @@ import styles from './dropdown.css'; import Separator from './separator'; const Dropdown = ({ - showDropdown, className, showArrow, active, children, align, + showDropdown, className, showArrow, active, children, align, toggleDropdown, }) => { const isSelectionList = children && Array.isArray(children); @@ -31,7 +31,15 @@ const Dropdown = ({ isSelectionList ? flattenArray(children).map((child, key) => ( child.type === Separator ? child - : React.cloneElement(child, { className: ` ${styles.option} ${active === key ? styles.active : ''} ${child.props.className || ''}`, key }) + : React.cloneElement(child, { + className: ` ${styles.option} ${active === key ? styles.active : ''} ${child.props.className || ''}`, + key, + onClick: (...rest) => { + console.log(); + toggleDropdown(); + if (child.props.onClick) child.props.onClick(...rest); + }, + }) )) : children } diff --git a/src/components/toolbox/dropdownButton/index.js b/src/components/toolbox/dropdownButton/index.js index 29bdac5425..33ac6c80ea 100644 --- a/src/components/toolbox/dropdownButton/index.js +++ b/src/components/toolbox/dropdownButton/index.js @@ -45,6 +45,7 @@ class DropdownButton extends React.Component { From c281a3f66fd2a0f4664963e2c3b6e6a43b5f22ba Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Tue, 30 Nov 2021 16:12:21 +0100 Subject: [PATCH 02/17] Improve registration validator --- .../screens/multiSignature/form/form.js | 67 +++++++++++--- .../screens/multiSignature/form/form.test.js | 88 ++++++++++++++++++- 2 files changed, 140 insertions(+), 15 deletions(-) diff --git a/src/components/screens/multiSignature/form/form.js b/src/components/screens/multiSignature/form/form.js index 2cc08031a0..7dd1b63e3d 100644 --- a/src/components/screens/multiSignature/form/form.js +++ b/src/components/screens/multiSignature/form/form.js @@ -25,22 +25,61 @@ const placeholderMember = { const getInitialMembersState = (prevState) => prevState.members ?? [placeholderMember]; const getInitialSignaturesState = (prevState) => prevState.numberOfSignatures ?? 2; -const validateState = ({ +const validators = [ + { + pattern: (_, optional) => optional.length === 1, + message: t => t('Either change the optional member to mandatory or define more optional members.'), + }, + { + pattern: (mandatory, optional) => mandatory.length === 0 && optional.length > 0, + message: t => t('All members can not be optional. Consider changing them to mandatory.'), + }, + { + pattern: (mandatory, optional, signatures) => + mandatory.length > 0 && optional.length === 0 && signatures !== mandatory.length, + message: t => t('Number of signatures must be equal to the number of members.'), + }, + { + pattern: (mandatory, optional, signatures) => + mandatory.length > 0 && optional.length > 0 && signatures <= mandatory.length, + message: (t, mandatory) => t(t('Number of signatures must be above {{num}}.', { num: mandatory.length })), + }, + { + pattern: (mandatory, optional, signatures) => + mandatory.length > 0 && optional.length > 0 + && signatures === mandatory.length + optional.length, + message: t => t('Either change the optional member to mandatory or reduce the number of signatures.'), + }, + { + pattern: (mandatory, optional, signatures) => + mandatory.length > 0 && optional.length > 0 + && signatures > mandatory.length + optional.length, + message: (t, mandatory, optional) => t('Number of signatures must be lower than {{num}}.', { num: mandatory.length + optional.length }), + }, + { + pattern: (mandatory, optional) => mandatory.length + optional.length > MAX_MULTI_SIG_MEMBERS, + message: t => t('Maximum number of members is {{MAX_MULTI_SIG_MEMBERS}}.', { MAX_MULTI_SIG_MEMBERS }), + }, + { + pattern: (mandatory, optional) => + mandatory.some(item => !regex.publicKey.test(item)) + || optional.some(item => !regex.publicKey.test(item)), + message: t => t('Please enter a valid public key for each member.'), + }, +]; + +export const validateState = ({ mandatoryKeys, optionalKeys, requiredSignatures, t, }) => { - const messages = []; - if (requiredSignatures > MAX_MULTI_SIG_MEMBERS) { - messages.push(t('Maximum number of members is {{MAX_MULTI_SIG_MEMBERS}}.', { MAX_MULTI_SIG_MEMBERS })); - } - if (requiredSignatures > mandatoryKeys.length + optionalKeys.length) { - messages.push(t('Number of signatures must be lower than or equal to the number of members.')); - } - if ( - mandatoryKeys.some(item => !regex.publicKey.test(item)) - || optionalKeys.some(item => !regex.publicKey.test(item)) - ) { - messages.push(t('Please enter a valid public key for each member.')); - } + const messages = validators + .map((scenario) => { + if (scenario.pattern(mandatoryKeys, optionalKeys, requiredSignatures)) { + return scenario.message(t, mandatoryKeys, optionalKeys); + } + return null; + }) + .filter(item => !!item); + return { error: (mandatoryKeys.length + optionalKeys.length) ? messages.length : -1, messages, diff --git a/src/components/screens/multiSignature/form/form.test.js b/src/components/screens/multiSignature/form/form.test.js index 9ca4e556ae..4cbd645d7b 100644 --- a/src/components/screens/multiSignature/form/form.test.js +++ b/src/components/screens/multiSignature/form/form.test.js @@ -7,7 +7,7 @@ import useTransactionFeeCalculation from '@shared/transactionPriority/useTransac import { fromRawLsk } from '@utils/lsk'; import accounts from '../../../../../test/constants/accounts'; -import Form from './form'; +import Form, { validateState } from './form'; jest.mock('@shared/transactionPriority/useTransactionFeeCalculation'); jest.mock('@api/transaction'); @@ -98,3 +98,89 @@ describe('Multisignature editor component', () => { expect(props.nextStep).toHaveBeenCalledTimes(1); }); }); + +describe('validateState', () => { + it('should return error if signature are less than mandatory members', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [pbk, pbk, pbk], + optionalKeys: [], + requiredSignatures: 2, + t: str => str, + }; + const error = 'Number of signatures must be equal to the number of members.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if signatures are more than all members', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [pbk, pbk, pbk], + optionalKeys: [], + requiredSignatures: 5, + t: str => str, + }; + const error = 'Number of signatures must be equal to the number of members.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if optional members are practically mandatory', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [pbk, pbk, pbk], + optionalKeys: [pbk], + requiredSignatures: 4, + t: str => str, + }; + const error = 'Either change the optional member to mandatory or define more optional members.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if optional members never get to sign', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [pbk, pbk, pbk], + optionalKeys: [pbk], + requiredSignatures: 3, + t: str => str, + }; + const error = 'Either change the optional member to mandatory or define more optional members.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if there are only optional members', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [], + optionalKeys: [pbk, pbk, pbk], + requiredSignatures: 3, + t: str => str, + }; + const error = 'All members can not be optional. Consider changing them to mandatory.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if the number of signature is equal to optional and mandatory members', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: [pbk, pbk, pbk], + optionalKeys: [pbk, pbk, pbk], + requiredSignatures: 6, + t: str => str, + }; + const error = 'Either change the optional member to mandatory or reduce the number of signatures.'; + expect(validateState(params).messages).toContain(error); + }); + + it('should return error if there are more than 64 members', () => { + const pbk = accounts.genesis.summary.publicKey; + const params = { + mandatoryKeys: new Array(65).fill(pbk), + optionalKeys: [], + requiredSignatures: 65, + t: str => str, + }; + const error = 'Maximum number of members is {{MAX_MULTI_SIG_MEMBERS}}.'; + expect(validateState(params).messages).toContain(error); + }); +}); From 33b6b845e1f9e7befb9ee588b17bdf245541fcd4 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Tue, 30 Nov 2021 16:12:52 +0100 Subject: [PATCH 03/17] Add new i18n labels --- i18n/locales/en/common.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 7583a9526b..f59adfc7d5 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -34,6 +34,7 @@ "All": "All", "All accounts": "All accounts", "All blocks": "All blocks", + "All members can not be optional. Consider changing them to mandatory.": "All members can not be optional. Consider changing them to mandatory.", "All transactions": "All transactions", "All types": "All types", "All you need to do:": "All you need to do:", @@ -154,6 +155,8 @@ "Edit bookmark": "Edit bookmark", "Edit transaction": "Edit transaction", "Edit vote": "Edit vote", + "Either change the optional member to mandatory or define more optional members.": "Either change the optional member to mandatory or define more optional members.", + "Either change the optional member to mandatory or reduce the number of signatures.": "Either change the optional member to mandatory or reduce the number of signatures.", "Empty": "Empty", "Empty/Not empty": "Empty/Not empty", "Enable dark mode": "Enable dark mode", @@ -245,7 +248,7 @@ "Lisk Website": "Lisk Website", "Lisk accounts on {{WalletModel}}": "Lisk accounts on {{WalletModel}}", "Lisk counts your message in bytes, so keep in mind\n that the length of your message may vary in different languages.\n Different characters may consume a varying amount of bytes.": "Lisk counts your message in bytes, so keep in mind\n that the length of your message may vary in different languages.\n Different characters may consume a varying amount of bytes.", - "Lisk currently supports Ledger Nano S, Ledger Nano X, Trezor One and Trezor Model T wallets": "Lisk currently supports Ledger Nano S, Ledger Nano X, Trezor One and Trezor Model T wallets", + "Lisk currently supports Ledger Nano S, Ledger Nano X wallets": "Lisk currently supports Ledger Nano S, Ledger Nano X wallets", "Lisk currently supports Ledger Nano S, Ledger Nano X, Trezor One and Trezor T wallets.": "Lisk currently supports Ledger Nano S, Ledger Nano X, Trezor One and Trezor T wallets.", "Lisk has now been enhanced even further": "Lisk has now been enhanced even further", "Lisk {{version}}": "Lisk {{version}}", @@ -306,7 +309,9 @@ "Nothing has been found. Make sure to double check the ID you typed.": "Nothing has been found. Make sure to double check the ID you typed.", "Now you can send it to the blockchain. You may also copy or download it, if you wish to send the transaction using another device later.": "Now you can send it to the blockchain. You may also copy or download it, if you wish to send the transaction using another device later.", "Number": "Number", - "Number of signatures must be lower than or equal to the number of members.": "Number of signatures must be lower than or equal to the number of members.", + "Number of signatures must be above {{num}}.": "Number of signatures must be above {{num}}.", + "Number of signatures must be equal to the number of members.": "Number of signatures must be equal to the number of members.", + "Number of signatures must be lower than {{num}}.": "Number of signatures must be lower than {{num}}.", "Official guidelines": "Official guidelines", "Ok": "Ok", "Old account": "Old account", From 14cd2ee9a7a0f31ce9fac5019e248d0b2353a684 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 09:35:59 +0100 Subject: [PATCH 04/17] Improve signature status helper --- .../screens/signMultiSignTransaction/helpers.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/screens/signMultiSignTransaction/helpers.js b/src/components/screens/signMultiSignTransaction/helpers.js index f3e2a7425a..a206fb82d9 100644 --- a/src/components/screens/signMultiSignTransaction/helpers.js +++ b/src/components/screens/signMultiSignTransaction/helpers.js @@ -26,7 +26,7 @@ export const findNonEmptySignatureIndices = (signatures) => { }; // eslint-disable-next-line max-statements -export const isTransactionFullySigned = (senderAccount, transaction) => { +export const getTransactionSignatureStatus = (senderAccount, transaction) => { const moduleAssetId = transaction.moduleAssetId || joinModuleAndAssetIds(transaction); const isGroupRegistration = moduleAssetId === MODULE_ASSETS_NAME_ID_MAP.registerMultisignatureGroup; @@ -39,8 +39,20 @@ export const isTransactionFullySigned = (senderAccount, transaction) => { }); const alreadySigned = getNonEmptySignatures(transaction.signatures).length; + const mandatorySignatures = getNonEmptySignatures( + transaction.signatures.slice(0, keys.mandatoryKeys.length + 1), + ).length; - return (required === alreadySigned); + if (required > alreadySigned) { + return 'partiallySigned'; + } + if (required === alreadySigned && mandatorySignatures === keys.mandatoryKeys.length + 1) { + return 'fullySigned'; + } + if (required === alreadySigned && mandatorySignatures < keys.mandatoryKeys.length + 1) { + return 'occupiedByOptionals'; + } + return 'overSigned'; }; // eslint-disable-next-line max-statements From 9a203d932c55b391493c76de6d0f3f68e549634d Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 09:36:27 +0100 Subject: [PATCH 05/17] Show relevant messages --- .../screens/signMultiSignTransaction/styles.css | 4 ++++ .../signMultiSignTransaction/summary/footer.js | 11 +++++++---- .../signMultiSignTransaction/summary/summary.js | 12 ++++++------ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/components/screens/signMultiSignTransaction/styles.css b/src/components/screens/signMultiSignTransaction/styles.css index 40cef72258..4797bd98ab 100644 --- a/src/components/screens/signMultiSignTransaction/styles.css +++ b/src/components/screens/signMultiSignTransaction/styles.css @@ -19,6 +19,10 @@ & > .footer { padding-top: 20px; + + & + footer { + padding-top: 0; + } } & .feedback { diff --git a/src/components/screens/signMultiSignTransaction/summary/footer.js b/src/components/screens/signMultiSignTransaction/summary/footer.js index 9f336ec481..c69ebb92a7 100644 --- a/src/components/screens/signMultiSignTransaction/summary/footer.js +++ b/src/components/screens/signMultiSignTransaction/summary/footer.js @@ -28,14 +28,17 @@ export const ActionBar = ({ ); export const Feedback = ({ - t, isMember, isFullySigned, + t, isMember, signatureStatus, }) => { let feedback = 'Unknown error'; + const statusMessages = { + fullySigned: t('Transaction is already fully signed.'), + occupiedByOptionals: t('Your signature will replace one optional signature.'), + }; if (!isMember) { feedback = t('Only members of the group can sign the transaction.'); - } - if (isFullySigned) { - feedback = t('Transaction is already fully signed.'); + } else { + feedback = statusMessages[signatureStatus]; } return ( diff --git a/src/components/screens/signMultiSignTransaction/summary/summary.js b/src/components/screens/signMultiSignTransaction/summary/summary.js index 27fb09acda..144fe5fd33 100644 --- a/src/components/screens/signMultiSignTransaction/summary/summary.js +++ b/src/components/screens/signMultiSignTransaction/summary/summary.js @@ -5,7 +5,7 @@ import Box from '@toolbox/box'; import TransactionDetails from '@screens/transactionDetails/transactionDetails'; import ProgressBar from '../progressBar'; -import { showSignButton, isTransactionFullySigned } from '../helpers'; +import { showSignButton, getTransactionSignatureStatus } from '../helpers'; import { ActionBar, Feedback } from './footer'; import styles from '../styles.css'; @@ -25,9 +25,9 @@ const Summary = ({ return null; }, [senderAccount.data]); - const isFullySigned = useMemo(() => { + const signatureStatus = useMemo(() => { if (senderAccount.data.keys) { - return isTransactionFullySigned(senderAccount.data, transaction); + return getTransactionSignatureStatus(senderAccount.data, transaction); } return null; }, [senderAccount.data]); @@ -40,11 +40,11 @@ const Summary = ({ }; const nextButton = { - title: isFullySigned ? t('Continue') : t('Sign'), + title: signatureStatus === 'fullySigned' ? t('Continue') : t('Sign'), onClick, }; - const showFeedback = !isMember || isFullySigned; + const showFeedback = !isMember || signatureStatus === 'fullySigned' || signatureStatus === 'occupiedByOptionals'; if (isEmpty(senderAccount.data)) { return
; @@ -84,7 +84,7 @@ const Summary = ({ ) : null } From 98288d2dee50836da83b9d2d7318b53bc96c2a13 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 09:36:38 +0100 Subject: [PATCH 06/17] Add new titles to i18n --- i18n/locales/en/common.json | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index f59adfc7d5..b8cb6a8783 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -605,6 +605,7 @@ "Your multisignatures groups": "Your multisignatures groups", "Your session will be timed out in {{time}} if no network activity occurs.": "Your session will be timed out in {{time}} if no network activity occurs.", "Your signature was successful": "Your signature was successful", + "Your signature will replace one optional signature.": "Your signature will replace one optional signature.", "Your tokens and passphrase are safe.": "Your tokens and passphrase are safe.", "Your transaction has been submitted and will appear in sender account's wallet after confirmation.": "Your transaction has been submitted and will appear in sender account's wallet after confirmation.", "Your transaction has been submitted and will be confirmed in a few moments.": "Your transaction has been submitted and will be confirmed in a few moments.", From 42015c1be5ef8ced02ca83713a18da1079086af3 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 12:25:54 +0100 Subject: [PATCH 07/17] Replace the first optional with the current mandatory --- src/store/actions/transactions.js | 6 +++--- src/utils/transaction.js | 36 ++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/store/actions/transactions.js b/src/store/actions/transactions.js index a5c8475a0f..8776e2439f 100644 --- a/src/store/actions/transactions.js +++ b/src/store/actions/transactions.js @@ -7,7 +7,7 @@ import { isEmpty } from '@utils/helpers'; import { getTransactions, create, broadcast } from '@api/transaction'; import { selectActiveTokenAccount, selectNetworkIdentifier } from '@store/selectors'; import { signTransaction, transformTransaction } from '@utils/transaction'; -import { isTransactionFullySigned } from '@screens/signMultiSignTransaction/helpers'; +import { getTransactionSignatureStatus } from '@screens/signMultiSignTransaction/helpers'; import { timerReset } from './account'; import { loadingStarted, loadingFinished } from './loading'; @@ -234,14 +234,14 @@ export const multisigTransactionSigned = ({ hwInfo: account.hwInfo, }; // @todo move isTransactionFullySigned to a generic location - const isFullySigned = isTransactionFullySigned(sender.data, rawTransaction); + const txStatus = getTransactionSignatureStatus(sender.data, rawTransaction); const [tx, error] = signTransaction( rawTransaction, activeAccount.passphrase, networkIdentifier, sender, - isFullySigned, + txStatus, network, ); diff --git a/src/utils/transaction.js b/src/utils/transaction.js index c658a51c72..df27dffb54 100644 --- a/src/utils/transaction.js +++ b/src/utils/transaction.js @@ -377,6 +377,29 @@ const downloadJSON = (data, name) => { anchor.setAttribute('download', `${name}.json`); anchor.click(); }; + +/** + * Removes the excess signatures from optional members + * to open up room for the mandatory ones + * + * @param {array} signatures - The transaction signatures array + * @param {number} mandatoryKeysNo - Number of mandatory keys + * @param {boolean} hasSenderSignature - Defines if the signatures list has + * an extra sender signature at the beginning. + * @returns {array} the trimmed array of signatures + */ +const removeExcessSignatures = (signatures, mandatoryKeysNo, hasSenderSignature) => { + const skip = hasSenderSignature ? 1 : 0; + const firstOptional = skip + mandatoryKeysNo; + const trimmedSignatures = signatures.map((item, index) => { + if (index === firstOptional) { + return Buffer.from(''); + } + return item; + }); + return trimmedSignatures; +}; + /** * Signs a given multisignature tx with a given passphrase * @@ -395,7 +418,7 @@ const signTransaction = ( passphrase, networkIdentifier, senderAccount, - isFullySigned, + txStatus, network, ) => { let signedTransaction; @@ -419,6 +442,13 @@ const signTransaction = ( === MODULE_ASSETS_NAME_ID_MAP.registerMultisignatureGroup; try { + // remove excess optionals + if (txStatus === 'occupiedByOptionals') { + transactionObject.signatures = removeExcessSignatures( + transactionObject.signatures, keys.mandatoryKeys.length, includeSender, + ); + } + signedTransaction = transactions.signMultiSignatureTransaction( network.networks.LSK.moduleAssetSchemas[transaction.moduleAssetId], transactionObject, @@ -429,8 +459,8 @@ const signTransaction = ( ); // remove unnecessary signatures - if (isFullySigned) { - const emptySignatureIndices = findNonEmptySignatureIndices(transaction.signatures); + if (txStatus === 'fullySigned' || txStatus === 'occupiedByOptionals') { + const emptySignatureIndices = findNonEmptySignatureIndices(signedTransaction.signatures); emptySignatureIndices.forEach(index => { signedTransaction.signatures[index] = Buffer.from(''); }); From ce2a5a9de7954fef4cfb08a843679ab7507bd2b5 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 12:33:58 +0100 Subject: [PATCH 08/17] Fix styles --- .../screens/signMultiSignTransaction/styles.css | 9 ++++++++- .../screens/signMultiSignTransaction/summary/footer.js | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/screens/signMultiSignTransaction/styles.css b/src/components/screens/signMultiSignTransaction/styles.css index 4797bd98ab..95a1ece253 100644 --- a/src/components/screens/signMultiSignTransaction/styles.css +++ b/src/components/screens/signMultiSignTransaction/styles.css @@ -33,13 +33,20 @@ & > span { width: 100%; - background: var(--error-background-color); color: var(--color-strong-white); border-radius: var(--border-radius-standard); display: block; padding: var(--vertical-padding-s) var(--horizontal-padding-m); box-sizing: border-box; } + + &.error > span { + background: var(--error-background-color); + } + + &.warning > span { + background: var(--color-danger); + } } } diff --git a/src/components/screens/signMultiSignTransaction/summary/footer.js b/src/components/screens/signMultiSignTransaction/summary/footer.js index c69ebb92a7..6147238e05 100644 --- a/src/components/screens/signMultiSignTransaction/summary/footer.js +++ b/src/components/screens/signMultiSignTransaction/summary/footer.js @@ -30,7 +30,7 @@ export const ActionBar = ({ export const Feedback = ({ t, isMember, signatureStatus, }) => { - let feedback = 'Unknown error'; + let feedback; const statusMessages = { fullySigned: t('Transaction is already fully signed.'), occupiedByOptionals: t('Your signature will replace one optional signature.'), @@ -46,7 +46,7 @@ export const Feedback = ({ direction="horizontal" className={styles.footer} > -
+
{feedback}
From 42ca6cecafc3af5b75e01677fbef4271737b50c1 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 12:34:17 +0100 Subject: [PATCH 09/17] Null check the parameters --- src/components/toolbox/dropdown/dropdown.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/toolbox/dropdown/dropdown.js b/src/components/toolbox/dropdown/dropdown.js index aa0db032f4..b9e3b4af0f 100644 --- a/src/components/toolbox/dropdown/dropdown.js +++ b/src/components/toolbox/dropdown/dropdown.js @@ -35,8 +35,7 @@ const Dropdown = ({ className: ` ${styles.option} ${active === key ? styles.active : ''} ${child.props.className || ''}`, key, onClick: (...rest) => { - console.log(); - toggleDropdown(); + if (typeof toggleDropdown === 'function') toggleDropdown(); if (child.props.onClick) child.props.onClick(...rest); }, }) From 2d0070fe0cf21b8d360fe418b4d3d992c6ed9f09 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 20:17:18 +0100 Subject: [PATCH 10/17] Remove redundant sanitization --- src/utils/transaction.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/utils/transaction.js b/src/utils/transaction.js index df27dffb54..4f4ae6d0fb 100644 --- a/src/utils/transaction.js +++ b/src/utils/transaction.js @@ -457,14 +457,6 @@ const signTransaction = ( keys, includeSender, ); - - // remove unnecessary signatures - if (txStatus === 'fullySigned' || txStatus === 'occupiedByOptionals') { - const emptySignatureIndices = findNonEmptySignatureIndices(signedTransaction.signatures); - emptySignatureIndices.forEach(index => { - signedTransaction.signatures[index] = Buffer.from(''); - }); - } } catch (e) { // eslint-disable-next-line no-console console.error(e); From 4e0e61f032f2800abe9b6ca91bb56e8a8ee3c88e Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 20:17:30 +0100 Subject: [PATCH 11/17] Update i18n files --- i18n/locales/en/common.json | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 0c4f5b58ae..2a0788d170 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -282,6 +282,7 @@ "Min": "Min", "Minimize": "Minimize", "Missed slot": "Missed slot", + "Modify recovery phrase derivation path": "Modify recovery phrase derivation path", "More filters": "More filters", "Multisignature account details": "Multisignature account details", "Multisignatures": "Multisignatures", From 32fb2f6879c8b37e2f1ba5f7d4c8eb742a5b9eea Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 22:11:25 +0100 Subject: [PATCH 12/17] Fix randomly signed multisigs --- .../signMultiSignTransaction/helpers.js | 20 ++++++++++--------- src/constants/index.js | 1 + src/constants/txStatus.js | 17 ++++++++++++++++ src/utils/transaction.js | 13 ++++++++---- 4 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 src/constants/txStatus.js diff --git a/src/components/screens/signMultiSignTransaction/helpers.js b/src/components/screens/signMultiSignTransaction/helpers.js index a206fb82d9..91866f2d4b 100644 --- a/src/components/screens/signMultiSignTransaction/helpers.js +++ b/src/components/screens/signMultiSignTransaction/helpers.js @@ -1,4 +1,4 @@ -import { MODULE_ASSETS_NAME_ID_MAP } from '@constants'; +import { MODULE_ASSETS_NAME_ID_MAP, signatureCollectionStatus } from '@constants'; import { joinModuleAndAssetIds } from '@utils/moduleAssets'; import { getKeys } from '@utils/account'; @@ -39,20 +39,22 @@ export const getTransactionSignatureStatus = (senderAccount, transaction) => { }); const alreadySigned = getNonEmptySignatures(transaction.signatures).length; - const mandatorySignatures = getNonEmptySignatures( - transaction.signatures.slice(0, keys.mandatoryKeys.length + 1), + const registrationExtra = isGroupRegistration ? 1 : 0; + const mandatorySigs = keys.mandatoryKeys.length + registrationExtra; + const nonEmptyMandatorySigs = getNonEmptySignatures( + transaction.signatures.slice(0, mandatorySigs), ).length; if (required > alreadySigned) { - return 'partiallySigned'; + return signatureCollectionStatus.partiallySigned; } - if (required === alreadySigned && mandatorySignatures === keys.mandatoryKeys.length + 1) { - return 'fullySigned'; + if (required === alreadySigned && nonEmptyMandatorySigs === mandatorySigs) { + return signatureCollectionStatus.fullySigned; } - if (required === alreadySigned && mandatorySignatures < keys.mandatoryKeys.length + 1) { - return 'occupiedByOptionals'; + if (required === alreadySigned && nonEmptyMandatorySigs < mandatorySigs) { + return signatureCollectionStatus.occupiedByOptionals; } - return 'overSigned'; + return signatureCollectionStatus.overSigned; }; // eslint-disable-next-line max-statements diff --git a/src/constants/index.js b/src/constants/index.js index bc33f6e9b1..3861fcb18d 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -1,6 +1,7 @@ export { default as loginTypes } from './loginTypes'; export { default as keyCodes } from './keyCodes'; export * from './moduleAssets'; +export { txStatusTypes, signatureCollectionStatus } from './txStatus'; export { DEFAULT_LIMIT } from './monitor'; export { default as networks, networkKeys } from './networks'; export { default as piwikOptions } from './piwik'; diff --git a/src/constants/txStatus.js b/src/constants/txStatus.js new file mode 100644 index 0000000000..5b824852be --- /dev/null +++ b/src/constants/txStatus.js @@ -0,0 +1,17 @@ +export const txStatusTypes = { + multisigSignaturePartialSuccess: 'MULTISIG_SIGNATURE_PARTIAL_SUCCESS', + multisigSignatureSuccess: 'MULTISIG_SIGNATURE_SUCCESS', + signatureSuccess: 'SIGNATURE_SUCCESS', + multisigBroadcastSuccess: 'MULTISIG_BROADCAST_SUCCESS', + broadcastSuccess: 'BROADCAST_SUCCESS', + signatureError: 'SIGNATURE_ERROR', + broadcastError: 'BROADCAST_ERROR', + hwRejected: 'HW_REJECTED', +}; + +export const signatureCollectionStatus = { + partiallySigned: 'partiallySigned', + fullySigned: 'fullySigned', + occupiedByOptionals: 'occupiedByOptionals', + overSigned: 'overSigned', +}; diff --git a/src/utils/transaction.js b/src/utils/transaction.js index 4f4ae6d0fb..88c32839e5 100644 --- a/src/utils/transaction.js +++ b/src/utils/transaction.js @@ -1,6 +1,10 @@ /* eslint-disable max-lines */ import { transactions } from '@liskhq/lisk-client'; -import { DEFAULT_NUMBER_OF_SIGNATURES, MODULE_ASSETS_NAME_ID_MAP } from '@constants'; +import { + DEFAULT_NUMBER_OF_SIGNATURES, + MODULE_ASSETS_NAME_ID_MAP, + signatureCollectionStatus, +} from '@constants'; import { extractAddressFromPublicKey, getBase32AddressFromAddress, @@ -10,7 +14,6 @@ import { import { transformStringDateToUnixTimestamp } from '@utils/datetime'; import { toRawLsk } from '@utils/lsk'; import { splitModuleAndAssetIds, joinModuleAndAssetIds } from '@utils/moduleAssets'; -import { findNonEmptySignatureIndices } from '@screens/signMultiSignTransaction/helpers'; const { transfer, voteDelegate, registerDelegate, unlockToken, reclaimLSK, registerMultisignatureGroup, @@ -391,8 +394,10 @@ const downloadJSON = (data, name) => { const removeExcessSignatures = (signatures, mandatoryKeysNo, hasSenderSignature) => { const skip = hasSenderSignature ? 1 : 0; const firstOptional = skip + mandatoryKeysNo; + let cleared = false; const trimmedSignatures = signatures.map((item, index) => { - if (index === firstOptional) { + if (index >= firstOptional && item.length && !cleared) { + cleared = true; return Buffer.from(''); } return item; @@ -443,7 +448,7 @@ const signTransaction = ( try { // remove excess optionals - if (txStatus === 'occupiedByOptionals') { + if (txStatus === signatureCollectionStatus.occupiedByOptionals) { transactionObject.signatures = removeExcessSignatures( transactionObject.signatures, keys.mandatoryKeys.length, includeSender, ); From cfef991299377a5aaf87c84885d4cd0e1369360c Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 22:15:03 +0100 Subject: [PATCH 13/17] Moved txStatusTypes to constants --- .../screens/registerDelegate/status/status.js | 3 ++- .../registerDelegate/status/statusMessages.js | 3 ++- src/components/screens/send/status/status.js | 3 ++- .../screens/votingQueue/status/statusMessages.js | 4 ++-- .../shared/transactionResult/illustrations.js | 2 +- .../shared/transactionResult/multisignature.js | 3 +-- src/components/shared/transactionResult/regular.js | 3 +-- .../shared/transactionResult/statusConfig.js | 12 +----------- .../shared/transactionResult/transactionResult.js | 2 +- 9 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/components/screens/registerDelegate/status/status.js b/src/components/screens/registerDelegate/status/status.js index e2b853e24a..916d382be1 100644 --- a/src/components/screens/registerDelegate/status/status.js +++ b/src/components/screens/registerDelegate/status/status.js @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import TransactionResult from '@shared/transactionResult'; -import { getTransactionStatus, txStatusTypes } from '@shared/transactionResult/statusConfig'; +import { txStatusTypes } from '@constants'; +import { getTransactionStatus } from '@shared/transactionResult/statusConfig'; import DelegateAnimation from '../animations/delegateAnimation'; import statusMessages from './statusMessages'; import styles from './status.css'; diff --git a/src/components/screens/registerDelegate/status/statusMessages.js b/src/components/screens/registerDelegate/status/statusMessages.js index 7805c71462..a30511946b 100644 --- a/src/components/screens/registerDelegate/status/statusMessages.js +++ b/src/components/screens/registerDelegate/status/statusMessages.js @@ -1,5 +1,6 @@ /* istanbul ignore file */ -import { statusMessages, txStatusTypes } from '@shared/transactionResult/statusConfig'; +import { statusMessages } from '@shared/transactionResult/statusConfig'; +import { txStatusTypes } from '@constants'; const registerDelegatesMessages = t => ({ ...statusMessages(t), diff --git a/src/components/screens/send/status/status.js b/src/components/screens/send/status/status.js index 6281bd5b9f..fc9c17adb5 100644 --- a/src/components/screens/send/status/status.js +++ b/src/components/screens/send/status/status.js @@ -1,8 +1,9 @@ import React, { useEffect } from 'react'; import { isEmpty } from '@utils/helpers'; +import { txStatusTypes } from '@constants'; import { PrimaryButton } from '@toolbox/buttons'; import TransactionResult from '@shared/transactionResult'; -import { getTransactionStatus, txStatusTypes, statusMessages } from '@shared/transactionResult/statusConfig'; +import { getTransactionStatus, statusMessages } from '@shared/transactionResult/statusConfig'; import DialogLink from '@toolbox/dialog/link'; import styles from './status.css'; diff --git a/src/components/screens/votingQueue/status/statusMessages.js b/src/components/screens/votingQueue/status/statusMessages.js index 39ac2a4102..613e377bc4 100644 --- a/src/components/screens/votingQueue/status/statusMessages.js +++ b/src/components/screens/votingQueue/status/statusMessages.js @@ -1,7 +1,7 @@ /* istanbul ignore file */ import React from 'react'; -import { statusMessages, txStatusTypes } from '@shared/transactionResult/statusConfig'; - +import { txStatusTypes } from '@constants'; +import { statusMessages } from '@shared/transactionResult/statusConfig'; import LiskAmount from '@shared/liskAmount'; import styles from './styles.css'; diff --git a/src/components/shared/transactionResult/illustrations.js b/src/components/shared/transactionResult/illustrations.js index 5a43a57098..3ee4fbce7d 100644 --- a/src/components/shared/transactionResult/illustrations.js +++ b/src/components/shared/transactionResult/illustrations.js @@ -1,4 +1,4 @@ -import { txStatusTypes } from './statusConfig'; +import { txStatusTypes } from '@constants'; const getDeviceType = (deviceModel = '') => { if (/ledger/i.test(deviceModel)) { diff --git a/src/components/shared/transactionResult/multisignature.js b/src/components/shared/transactionResult/multisignature.js index 6d448d83ef..ac9b9b09fd 100644 --- a/src/components/shared/transactionResult/multisignature.js +++ b/src/components/shared/transactionResult/multisignature.js @@ -5,12 +5,11 @@ import { } from '@toolbox/buttons'; import Illustration from '@toolbox/illustration'; import { transactionToJSON, downloadJSON } from '@utils/transaction'; -import { routes } from '@constants'; +import { routes, txStatusTypes } from '@constants'; import copyToClipboard from 'copy-to-clipboard'; import Icon from '@toolbox/icon'; import getIllustration from './illustrations'; -import { txStatusTypes } from './statusConfig'; import styles from './transactionResult.css'; const PartiallySignedActions = ({ onDownload, t }) => ( diff --git a/src/components/shared/transactionResult/regular.js b/src/components/shared/transactionResult/regular.js index b737dc6d64..68bcd1450e 100644 --- a/src/components/shared/transactionResult/regular.js +++ b/src/components/shared/transactionResult/regular.js @@ -2,10 +2,9 @@ import React, { useEffect } from 'react'; import { getErrorReportMailto, isEmpty } from '@utils/helpers'; import { TertiaryButton, PrimaryButton } from '@toolbox/buttons'; -import { routes } from '@constants'; +import { routes, txStatusTypes } from '@constants'; import Illustration from '@toolbox/illustration'; import getIllustration from './illustrations'; -import { txStatusTypes } from './statusConfig'; import styles from './transactionResult.css'; const errorTypes = [ diff --git a/src/components/shared/transactionResult/statusConfig.js b/src/components/shared/transactionResult/statusConfig.js index cc23949b28..806ebe4a6d 100644 --- a/src/components/shared/transactionResult/statusConfig.js +++ b/src/components/shared/transactionResult/statusConfig.js @@ -1,16 +1,6 @@ import { transactionToJSON, getNumberOfSignatures } from '@utils/transaction'; import { isEmpty } from '@utils/helpers'; - -export const txStatusTypes = { - multisigSignaturePartialSuccess: 'MULTISIG_SIGNATURE_PARTIAL_SUCCESS', - multisigSignatureSuccess: 'MULTISIG_SIGNATURE_SUCCESS', - signatureSuccess: 'SIGNATURE_SUCCESS', - multisigBroadcastSuccess: 'MULTISIG_BROADCAST_SUCCESS', - broadcastSuccess: 'BROADCAST_SUCCESS', - signatureError: 'SIGNATURE_ERROR', - broadcastError: 'BROADCAST_ERROR', - hwRejected: 'HW_REJECTED', -}; +import { txStatusTypes } from '@constants'; export const statusMessages = t => ({ [txStatusTypes.multisigSignaturePartialSuccess]: { diff --git a/src/components/shared/transactionResult/transactionResult.js b/src/components/shared/transactionResult/transactionResult.js index 89b3242ad7..2985ed331b 100644 --- a/src/components/shared/transactionResult/transactionResult.js +++ b/src/components/shared/transactionResult/transactionResult.js @@ -1,7 +1,7 @@ /* eslint-disable complexity */ import React, { useEffect, useState } from 'react'; +import { txStatusTypes } from '@constants'; import Regular from './regular'; -import { txStatusTypes } from './statusConfig'; import Multisignature from './multisignature'; const TransactionResult = (props) => { From 6a09a901b2397f098ae1840255bc0bf8be4cf8e1 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Wed, 1 Dec 2021 22:23:24 +0100 Subject: [PATCH 14/17] Add unit tests --- src/utils/transaction.js | 2 +- src/utils/transaction.test.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/utils/transaction.js b/src/utils/transaction.js index 88c32839e5..0c1c6d0563 100644 --- a/src/utils/transaction.js +++ b/src/utils/transaction.js @@ -391,7 +391,7 @@ const downloadJSON = (data, name) => { * an extra sender signature at the beginning. * @returns {array} the trimmed array of signatures */ -const removeExcessSignatures = (signatures, mandatoryKeysNo, hasSenderSignature) => { +export const removeExcessSignatures = (signatures, mandatoryKeysNo, hasSenderSignature) => { const skip = hasSenderSignature ? 1 : 0; const firstOptional = skip + mandatoryKeysNo; let cleared = false; diff --git a/src/utils/transaction.test.js b/src/utils/transaction.test.js index f2b2707de5..631f8c54e4 100644 --- a/src/utils/transaction.test.js +++ b/src/utils/transaction.test.js @@ -7,6 +7,7 @@ import { containsTransactionType, createTransactionObject, transactionToJSON, + removeExcessSignatures, } from './transaction'; import accounts from '../../test/constants/accounts'; @@ -321,4 +322,18 @@ describe('API: LSK Transactions', () => { expect(json).toMatchSnapshot(); }); }); + + describe('removeExcessSignatures', () => { + it('should remove optional signature considering the sender signature', () => { + const nonEmpty = Buffer.from(accounts.genesis.summary.publicKey, 'hex'); + const empty = Buffer.from(''); + const mandatoryKeysNo = 2; + const hasSenderSignature = true; + const signatures = [nonEmpty, nonEmpty, empty, nonEmpty]; + const expectSignatures = [nonEmpty, nonEmpty, empty, empty]; + expect( + removeExcessSignatures(signatures, mandatoryKeysNo, hasSenderSignature), + ).toEqual(expectSignatures); + }); + }); }); From f7710d795f4c9568f687693c042c707e0a8a3ec7 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Thu, 2 Dec 2021 09:54:56 +0100 Subject: [PATCH 15/17] Use signatureCollectionStatus constants --- .../screens/signMultiSignTransaction/summary/footer.js | 3 ++- .../screens/signMultiSignTransaction/summary/summary.js | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/screens/signMultiSignTransaction/summary/footer.js b/src/components/screens/signMultiSignTransaction/summary/footer.js index 6147238e05..9e608f9fd5 100644 --- a/src/components/screens/signMultiSignTransaction/summary/footer.js +++ b/src/components/screens/signMultiSignTransaction/summary/footer.js @@ -1,4 +1,5 @@ import React from 'react'; +import { signatureCollectionStatus } from '@constants'; import { useTheme } from '@utils/theme'; import { removeSearchParamsFromUrl } from '@utils/searchParams'; import { PrimaryButton, SecondaryButton } from '@toolbox/buttons'; @@ -46,7 +47,7 @@ export const Feedback = ({ direction="horizontal" className={styles.footer} > -
+
{feedback}
diff --git a/src/components/screens/signMultiSignTransaction/summary/summary.js b/src/components/screens/signMultiSignTransaction/summary/summary.js index 144fe5fd33..92cf469dee 100644 --- a/src/components/screens/signMultiSignTransaction/summary/summary.js +++ b/src/components/screens/signMultiSignTransaction/summary/summary.js @@ -1,5 +1,6 @@ import React, { useMemo } from 'react'; import { isEmpty } from '@utils/helpers'; +import { signatureCollectionStatus } from '@constants'; import BoxContent from '@toolbox/box/content'; import Box from '@toolbox/box'; import TransactionDetails from '@screens/transactionDetails/transactionDetails'; @@ -40,11 +41,13 @@ const Summary = ({ }; const nextButton = { - title: signatureStatus === 'fullySigned' ? t('Continue') : t('Sign'), + title: signatureStatus === signatureCollectionStatus.fullySigned ? t('Continue') : t('Sign'), onClick, }; - const showFeedback = !isMember || signatureStatus === 'fullySigned' || signatureStatus === 'occupiedByOptionals'; + const showFeedback = !isMember + || signatureStatus === signatureCollectionStatus.fullySigned + || signatureStatus === signatureCollectionStatus.occupiedByOptionals; if (isEmpty(senderAccount.data)) { return
; From 86cf6d7337f5bfdc77fe056e6a34ebb5c7a340eb Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Thu, 2 Dec 2021 16:19:53 +0100 Subject: [PATCH 16/17] Fix import routes --- src/components/screens/reclaimBalance/modal/status/status.js | 4 ++-- .../shared/transactionResult/multisignature.test.js | 3 +-- src/components/shared/transactionResult/regular.test.js | 3 +-- .../shared/transactionResult/transactionResult.test.js | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/screens/reclaimBalance/modal/status/status.js b/src/components/screens/reclaimBalance/modal/status/status.js index 1f1cabee49..1c23cc3d42 100644 --- a/src/components/screens/reclaimBalance/modal/status/status.js +++ b/src/components/screens/reclaimBalance/modal/status/status.js @@ -1,9 +1,9 @@ import React from 'react'; import TransactionResult from '@shared/transactionResult'; -import { statusMessages, getTransactionStatus, txStatusTypes } from '@shared/transactionResult/statusConfig'; +import { statusMessages, getTransactionStatus } from '@shared/transactionResult/statusConfig'; import LiskAmount from '@shared/liskAmount'; import { PrimaryButton } from '@toolbox/buttons'; -import { tokenMap } from '@constants'; +import { tokenMap, txStatusTypes } from '@constants'; import Spinner from '@toolbox/spinner'; import styles from './status.css'; diff --git a/src/components/shared/transactionResult/multisignature.test.js b/src/components/shared/transactionResult/multisignature.test.js index 98ad091f16..89c4a86872 100644 --- a/src/components/shared/transactionResult/multisignature.test.js +++ b/src/components/shared/transactionResult/multisignature.test.js @@ -2,9 +2,8 @@ import React from 'react'; import { mount } from 'enzyme'; import copyToClipboard from 'copy-to-clipboard'; import * as txUtils from '@utils/transaction'; -import { routes } from '@constants'; +import { routes, txStatusTypes } from '@constants'; import Multisignature, { FullySignedActions, PartiallySignedActions } from './multisignature'; -import { txStatusTypes } from './statusConfig'; import accounts from '../../../../test/constants/accounts'; jest.mock('copy-to-clipboard'); diff --git a/src/components/shared/transactionResult/regular.test.js b/src/components/shared/transactionResult/regular.test.js index 8ea55e984e..02d4426a1f 100644 --- a/src/components/shared/transactionResult/regular.test.js +++ b/src/components/shared/transactionResult/regular.test.js @@ -1,8 +1,7 @@ import React from 'react'; import { mount } from 'enzyme'; -import { routes } from '@constants'; +import { routes, txStatusTypes } from '@constants'; import Regular from './regular'; -import { txStatusTypes } from './statusConfig'; import accounts from '../../../../test/constants/accounts'; describe('TransactionResult Regular', () => { diff --git a/src/components/shared/transactionResult/transactionResult.test.js b/src/components/shared/transactionResult/transactionResult.test.js index 13882cf11a..8f41e1dde0 100644 --- a/src/components/shared/transactionResult/transactionResult.test.js +++ b/src/components/shared/transactionResult/transactionResult.test.js @@ -1,9 +1,9 @@ import React from 'react'; import { mount } from 'enzyme'; +import { txStatusTypes } from '@constants'; import TransactionResult from './transactionResult'; import Regular from './regular'; import Multisignature from './multisignature'; -import { txStatusTypes } from './statusConfig'; import accounts from '../../../../test/constants/accounts'; describe('TransactionResult', () => { From 731174bee4bde26f3ef28447e1eb745b4772b9d1 Mon Sep 17 00:00:00 2001 From: Ali Haghighatkhah Date: Fri, 3 Dec 2021 09:30:38 +0100 Subject: [PATCH 17/17] Revert dropdown action call changes --- src/components/toolbox/dropdown/dropdown.js | 11 ++--------- src/components/toolbox/dropdownButton/index.js | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/components/toolbox/dropdown/dropdown.js b/src/components/toolbox/dropdown/dropdown.js index b9e3b4af0f..bd3882f6d3 100644 --- a/src/components/toolbox/dropdown/dropdown.js +++ b/src/components/toolbox/dropdown/dropdown.js @@ -5,7 +5,7 @@ import styles from './dropdown.css'; import Separator from './separator'; const Dropdown = ({ - showDropdown, className, showArrow, active, children, align, toggleDropdown, + showDropdown, className, showArrow, active, children, align, }) => { const isSelectionList = children && Array.isArray(children); @@ -31,14 +31,7 @@ const Dropdown = ({ isSelectionList ? flattenArray(children).map((child, key) => ( child.type === Separator ? child - : React.cloneElement(child, { - className: ` ${styles.option} ${active === key ? styles.active : ''} ${child.props.className || ''}`, - key, - onClick: (...rest) => { - if (typeof toggleDropdown === 'function') toggleDropdown(); - if (child.props.onClick) child.props.onClick(...rest); - }, - }) + : React.cloneElement(child, { className: ` ${styles.option} ${active === key ? styles.active : ''} ${child.props.className || ''}`, key }) )) : children }
diff --git a/src/components/toolbox/dropdownButton/index.js b/src/components/toolbox/dropdownButton/index.js index 33ac6c80ea..29bdac5425 100644 --- a/src/components/toolbox/dropdownButton/index.js +++ b/src/components/toolbox/dropdownButton/index.js @@ -45,7 +45,6 @@ class DropdownButton extends React.Component {