diff --git a/explorer/frontend/__tests__/test-utils/transactions.js b/explorer/frontend/__tests__/test-utils/transactions.js index 159da7d93..21a4a823f 100644 --- a/explorer/frontend/__tests__/test-utils/transactions.js +++ b/explorer/frontend/__tests__/test-utils/transactions.js @@ -153,9 +153,11 @@ export const transactionPageResponse = [ deadline: '2024-03-29 14:06:21', embeddedTransactions: [ { + fee: 0.13, initiator: 'ND2RSOCXYGMABR6LESAW5ENC22Z34G3IL63ABALN', signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' @@ -179,6 +181,7 @@ export const transactionPageResponse = [ deadline: '2024-03-29 14:06:29', embeddedTransactions: [ { + fee: 0.13, initiator: 'ND2RSOCXYGMABR6LESAW5ENC22Z34G3IL63ABALN', message: { is_plain: 1, @@ -190,6 +193,7 @@ export const transactionPageResponse = [ }, signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' @@ -746,7 +750,7 @@ export const transactionPageResult = { signature: '7A4F8F82B6A144E568F5B33DE055D35E9F8D3EE2FC200F0DE9D2571DF5957FF942B8E5A99ED1726D3F459218CF9F27EA3F264011B04122BB9E3E391E72EE930D', - fee: 0.15, + fee: 0.45, value: [ { id: 'nem.xem', @@ -763,10 +767,29 @@ export const transactionPageResult = { ], signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' } + ], + feesBreakdown: [ + { + type: 'multisigFee', + amount: 0.15 + }, + { + type: 'embeddedTransactionsFee', + amount: 0.13 + }, + { + type: 'signaturesFee', + amount: 0.17 + }, + { + type: 'totalFee', + amount: 0.45 + } ] }, { @@ -785,7 +808,7 @@ export const transactionPageResult = { signature: '7A4F8F82B6A144E568F5B33DE055D35E9F8D3EE2FC200F0DE9D2571DF5957FF942B8E5A99ED1726D3F459218CF9F27EA3F264011B04122BB9E3E391E72EE930D', - fee: 0.15, + fee: 0.45, amount: 13200, value: [ { @@ -814,10 +837,29 @@ export const transactionPageResult = { ], signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' } + ], + feesBreakdown: [ + { + type: 'multisigFee', + amount: 0.15 + }, + { + type: 'embeddedTransactionsFee', + amount: 0.13 + }, + { + type: 'signaturesFee', + amount: 0.17 + }, + { + type: 'totalFee', + amount: 0.45 + } ] }, { @@ -1612,7 +1654,7 @@ export const transactionAccountPageResult = { height: 4694401, signature: '7A4F8F82B6A144E568F5B33DE055D35E9F8D3EE2FC200F0DE9D2571DF5957FF942B8E5A99ED1726D3F459218CF9F27EA3F264011B04122BB9E3E391E72EE930D', - fee: 0.15, + fee: 0.45, value: [ { id: 'nem.xem', @@ -1629,10 +1671,29 @@ export const transactionAccountPageResult = { ], signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' } + ], + feesBreakdown: [ + { + type: 'multisigFee', + amount: 0.15 + }, + { + type: 'embeddedTransactionsFee', + amount: 0.13 + }, + { + type: 'signaturesFee', + amount: 0.17 + }, + { + type: 'totalFee', + amount: 0.45 + } ] }, { @@ -1649,7 +1710,7 @@ export const transactionAccountPageResult = { height: 4694401, signature: '7A4F8F82B6A144E568F5B33DE055D35E9F8D3EE2FC200F0DE9D2571DF5957FF942B8E5A99ED1726D3F459218CF9F27EA3F264011B04122BB9E3E391E72EE930D', - fee: 0.15, + fee: 0.45, amount: 13200, value: [ { @@ -1678,10 +1739,29 @@ export const transactionAccountPageResult = { ], signatures: [ { + fee: 0.17, signature: '7D79A1ECFC4BE173BFFF9D54DCD0B0DED43C8F56E875E6BEF1E9EFFC32091E98A3BF0D7C4F66BDA9874A3120D1CB233C8D3A9EB963946100D776C8181F07EF01', signer: 'NDIVJFQIJR3VWXJRDSNFK6U37HM4DZNORXI3IRTV' } + ], + feesBreakdown: [ + { + type: 'multisigFee', + amount: 0.15 + }, + { + type: 'embeddedTransactionsFee', + amount: 0.13 + }, + { + type: 'signaturesFee', + amount: 0.17 + }, + { + type: 'totalFee', + amount: 0.45 + } ] }, { @@ -2205,6 +2285,7 @@ export const transactionInfoResponse = { deadline: '2024-03-29 19:13:31', embeddedTransactions: [ { + fee: 0.13, initiator: 'NANEWEN4LPV4CSDLFW3OPFUC57LQQDEFY5QDLHAG', message: { is_plain: 1, @@ -2216,6 +2297,7 @@ export const transactionInfoResponse = { }, signatures: [ { + fee: 0.17, signature: '8869F54E0B9CF93BFE2811982428799428656B3A18D73EB9B56C68D7FA64D5403860DA00EEF9EF3E63E0C6331D8CCF85078225E9888EEA50520A640C4A102709', signer: 'NCQME4TROE2LM2SE53WYZMECOQZEPPKMQ27TZEN2' @@ -2252,7 +2334,7 @@ export const transactionInfoResult = { signature: '84FC7751D87ED49EACDA60EE2D5F4B5F8020A32D7593A2E268054BCCC919FCD6DB4F66B35B60E1E0DF8E229B9510090C6A203D7426A7E6F595AEABE98EA3820F', - fee: 0.15, + fee: 0.45, amount: 7, value: [ { @@ -2281,11 +2363,30 @@ export const transactionInfoResult = { ], signatures: [ { + fee: 0.17, signature: '8869F54E0B9CF93BFE2811982428799428656B3A18D73EB9B56C68D7FA64D5403860DA00EEF9EF3E63E0C6331D8CCF85078225E9888EEA50520A640C4A102709', signer: 'NCQME4TROE2LM2SE53WYZMECOQZEPPKMQ27TZEN2' } ], + feesBreakdown: [ + { + type: 'multisigFee', + amount: 0.15 + }, + { + type: 'embeddedTransactionsFee', + amount: 0.13 + }, + { + type: 'signaturesFee', + amount: 0.17 + }, + { + type: 'totalFee', + amount: 0.45 + } + ], accountStateChange: [ { address: 'NB2CCC4ZKHX32CF4QU4X22S6LOS765W5A6LDKLJ2', diff --git a/explorer/frontend/__tests__/utils/server.test.js b/explorer/frontend/__tests__/utils/server.test.js index 06ac9471c..89105b03e 100644 --- a/explorer/frontend/__tests__/utils/server.test.js +++ b/explorer/frontend/__tests__/utils/server.test.js @@ -39,13 +39,13 @@ describe('utils/server', () => { it('throws error if function throws error with no 404 status', async () => { // Arrange: const error = { - status: 502 - }; - const fetchFunction = jest.fn().mockRejectedValue({ response: { - data: error + data: { + status: 502 + } } - }); + }; + const fetchFunction = jest.fn().mockRejectedValue(error); const wrappedFetchFunction = createTryFetchInfoFunction(fetchFunction); // Act: diff --git a/explorer/frontend/api/transactions.js b/explorer/frontend/api/transactions.js index a8ede39f5..8b5acd493 100644 --- a/explorer/frontend/api/transactions.js +++ b/explorer/frontend/api/transactions.js @@ -1,6 +1,6 @@ import config from '@/config'; import { ACCOUNT_STATE_CHANGE_ACTION, COSIGNATORY_MODIFICATION_ACTION, TRANSACTION_DIRECTION, TRANSACTION_TYPE } from '@/constants'; -import { decodeTransactionMessage } from '@/utils/common'; +import { decodeTransactionMessage, truncateDecimals } from '@/utils/common'; import { createAPIURL, createPage, createSearchCriteria, createSearchURL, createTryFetchInfoFunction, makeRequest } from '@/utils/server'; /** @@ -324,21 +324,46 @@ const formatAccountKeyLink = (data, filter) => { const formatMultisigTransaction = (data, filter) => { const rawEmbeddedTransaction = { ...data, - transactionType: data.embeddedTransactions[0].transactionType + transactionType: data.embeddedTransactions[0].transactionType, + fee: data.embeddedTransactions[0].fee }; if (rawEmbeddedTransaction.transactionType === TRANSACTION_TYPE.TRANSFER) rawEmbeddedTransaction.value = [{ message: data.embeddedTransactions[0].message }, data.embeddedTransactions[0].mosaics]; else rawEmbeddedTransaction.value = data.embeddedTransactions; + const formattedTransaction = formatBaseTransaction(data, filter); const formattedEmbeddedTransaction = transactionFromDTO(rawEmbeddedTransaction, filter.address); + // Fees breakdown + const multisigFee = truncateDecimals(formattedTransaction.fee, config.NATIVE_MOSAIC_DIVISIBILITY); + const embeddedTransactionsFee = truncateDecimals(formattedEmbeddedTransaction.fee, config.NATIVE_MOSAIC_DIVISIBILITY); + const signaturesFee = truncateDecimals( + data.embeddedTransactions[0].signatures.reduce((total, signature) => total + signature.fee, 0), + config.NATIVE_MOSAIC_DIVISIBILITY + ); + const feesBreakdownData = { + multisigFee, + embeddedTransactionsFee, + signaturesFee, + totalFee: truncateDecimals( + (signaturesFee + multisigFee + embeddedTransactionsFee).toPrecision(config.NATIVE_MOSAIC_DIVISIBILITY), + config.NATIVE_MOSAIC_DIVISIBILITY + ) + }; + const feesBreakdown = Object.entries(feesBreakdownData).map(([key, value]) => ({ + type: key, + amount: value + })); + return { - ...formatBaseTransaction(data, filter), + ...formattedTransaction, signatures: data.embeddedTransactions[0].signatures, signer: data.embeddedTransactions[0].initiator, amount: formattedEmbeddedTransaction.amount, value: formattedEmbeddedTransaction.value, - body: formattedEmbeddedTransaction.body + body: formattedEmbeddedTransaction.body, + fee: feesBreakdownData.totalFee, + feesBreakdown }; }; diff --git a/explorer/frontend/components/Table.jsx b/explorer/frontend/components/Table.jsx index f597e3a49..6c87b975b 100644 --- a/explorer/frontend/components/Table.jsx +++ b/explorer/frontend/components/Table.jsx @@ -14,19 +14,23 @@ const Table = ({ isLoading, isError, isLastPage, - isLastColumnAligned + isLastColumnAligned, + isHeaderHidden, + isColumnsStacked }) => { const { t } = useTranslation('common'); const isMobile = useMediaQuery('(max-width: 767.8px)'); const isMobileTableVisible = isMobile && !!renderItemMobile; const isDesktopTableVisible = !isMobile || !isMobileTableVisible; const desktopTableStyle = !renderItemMobile ? styles.dataMobile : ''; + const headerRowStyle = `${styles.header} ${isColumnsStacked ? styles.header_stacked : ''}`; const headerCellStyle = `${styles.headerCell} ${isLastColumnAligned && styles.headerCell_aligned}`; + const dataRowStyle = `${styles.dataRow} ${isColumnsStacked ? styles.dataRow_stacked : ''}`; const dataCellStyle = isLastColumnAligned ? styles.dataCell_aligned : ''; const isEmptyTableMessageShown = !isLoading && ((!!data && !data.length) || (!!sections && !sections.length)); const renderRow = (row, index) => ( -