diff --git a/app/src/modules/storage.js b/app/src/modules/storage.js
index 605dcfc130..5429801f94 100644
--- a/app/src/modules/storage.js
+++ b/app/src/modules/storage.js
@@ -11,6 +11,7 @@ export const setConfig = ({
};
export const readConfig = () => {
- const value = storage.get('config');
+ // Ensure to return empty config if storage does not hold any value
+ const value = storage.get('config') || {};
win.send({ event: 'configRetrieved', value });
};
diff --git a/app/src/modules/storage.test.js b/app/src/modules/storage.test.js
new file mode 100644
index 0000000000..02d569a068
--- /dev/null
+++ b/app/src/modules/storage.test.js
@@ -0,0 +1,25 @@
+import { expect } from 'chai';
+import { spy } from 'sinon';
+import win from './win';
+import { readConfig } from './storage';
+
+jest.mock('electron-store');
+
+describe('Storage', () => {
+ const winSendSpy = spy(win, 'send');
+
+ afterEach(() => {
+ win.eventStack.length = 0;
+ winSendSpy.restore();
+ });
+
+ describe('readConfig', () => {
+ it('should return empty config if storage has no config set', () => {
+ // Act
+ readConfig();
+
+ // Assert
+ expect(winSendSpy).to.have.been.calledWith({ event: 'configRetrieved', value: {} });
+ });
+ });
+});
diff --git a/src/components/screens/multiSignature/result/result.js b/src/components/screens/multiSignature/result/result.js
index c531c095e6..ca963d3242 100644
--- a/src/components/screens/multiSignature/result/result.js
+++ b/src/components/screens/multiSignature/result/result.js
@@ -14,7 +14,8 @@ const Result = ({
const [copied, setCopied] = useState(false);
const onDownload = () => {
- downloadJSON(transaction, `tx-${transactions.signedTransaction.id}`);
+ const transactionId = transaction.id.toString('hex');
+ downloadJSON(transaction, `tx-${transactionId}`);
};
const onCopy = () => {
diff --git a/src/components/shared/transactionResult/index.js b/src/components/shared/transactionResult/index.js
index 196948d48e..2646378c8d 100644
--- a/src/components/shared/transactionResult/index.js
+++ b/src/components/shared/transactionResult/index.js
@@ -1,9 +1,11 @@
/* eslint-disable complexity */
import React from 'react';
+import { useSelector } from 'react-redux';
import { getErrorReportMailto, isEmpty } from '@utils/helpers';
import { transactionToJSON } from '@utils/transaction';
import { TertiaryButton } from '@toolbox/buttons';
import Illustration from '@toolbox/illustration';
+import { selectActiveTokenNetwork } from '@store/selectors';
import styles from './transactionResult.css';
const illustrations = {
@@ -52,36 +54,48 @@ export const getBroadcastStatus = (transactions, isHardwareWalletError) => {
export const TransactionResult = ({
title, message, t, status, children, illustration, className,
-}) => (
-
- {
- typeof illustration === 'string'
- ?
- : React.cloneElement(illustration)
- }
-
{title}
-
{message}
- {children}
- {
- errorTypes.includes(status.code)
- ? (
- <>
-
{t('Does the problem still persist?')}
-
-
- {t('Report the error via email')}
-
-
- >
- )
- : null
- }
-
-);
+}) => {
+ const network = useSelector(selectActiveTokenNetwork);
+
+ return (
+
+ {
+ typeof illustration === 'string'
+ ?
+ : React.cloneElement(illustration)
+ }
+
{title}
+
{message}
+ {children}
+ {
+ errorTypes.includes(status.code)
+ ? (
+ <>
+
{t('Does the problem still persist?')}
+
+
+ {t('Report the error via email')}
+
+
+ >
+ )
+ : null
+ }
+
+ );
+};
export default TransactionResult;
diff --git a/src/store/actions/transactions.js b/src/store/actions/transactions.js
index c2a5d765db..bb319fcbcb 100644
--- a/src/store/actions/transactions.js
+++ b/src/store/actions/transactions.js
@@ -89,7 +89,7 @@ export const resetTransactionResult = () => ({
* Calls transactionAPI.create for create the tx object that will broadcast
* @param {Object} data
* @param {String} data.recipientAddress
- * @param {Number} data.amount - In raw format (satoshis, beddows)
+ * @param {Number} data.amount - In raw format (satoshi, beddows)
* @param {Number} data.fee - In raw format, used for updating the TX List.
* @param {Number} data.dynamicFeePerByte - In raw format, used for creating BTC transaction.
* @param {Number} data.reference - Data field for LSK transactions
@@ -133,7 +133,7 @@ export const transactionCreated = data => async (dispatch, getState) => {
* Calls transactionAPI.broadcast function for put the tx object (signed) into the network
* @param {Object} transaction
* @param {String} transaction.recipientAddress
- * @param {Number} transaction.amount - In raw format (satoshis, beddows)
+ * @param {Number} transaction.amount - In raw format (satoshi, beddows)
* @param {Number} transaction.fee - In raw format, used for updating the TX List.
* @param {Number} transaction.dynamicFeePerByte - In raw format, used for creating BTC transaction.
* @param {Number} transaction.reference - Data field for LSK transactions
diff --git a/src/store/selectors.js b/src/store/selectors.js
index dc06bc9fd2..d7bdc40939 100644
--- a/src/store/selectors.js
+++ b/src/store/selectors.js
@@ -14,6 +14,7 @@ const selectBookmark = (state, address) =>
const selectSettings = state => state.settings;
const selectServiceUrl = state => state.network.networks?.LSK?.serviceUrl;
const selectCurrentBlockHeight = state => state.blocks.latestBlocks[0]?.height || 0;
+const selectActiveTokenNetwork = state => state.network.networks[state.settings.token.active];
export {
selectBookmark,
@@ -30,4 +31,5 @@ export {
selectAccountBalance,
selectServiceUrl,
selectCurrentBlockHeight,
+ selectActiveTokenNetwork,
};
diff --git a/src/utils/api/http.js b/src/utils/api/http.js
index c4223f4321..47fb8cf2ef 100644
--- a/src/utils/api/http.js
+++ b/src/utils/api/http.js
@@ -29,10 +29,12 @@ const http = ({
},
...restOptions,
})
- .then((response) => {
+ .then(async (response) => {
if (!response.ok) {
+ const { message } = await response.json();
const error = Error(response.statusText);
error.code = response.status;
+ error.message = message;
throw error;
}
return response.json();
diff --git a/src/utils/api/http.test.js b/src/utils/api/http.test.js
index 4dbbbcc61a..7beeadc88f 100644
--- a/src/utils/api/http.test.js
+++ b/src/utils/api/http.test.js
@@ -54,12 +54,14 @@ describe('HTTP', () => {
it('should throw error when response.ok is false', async () => {
const statusText = 'Response.ok is false';
+ const message = 'api error';
global.fetch = jest.fn(() => Promise.resolve({
ok: false,
- status: 200,
+ status: 400,
statusText,
+ json: () => Promise.resolve({ message }),
}));
- await expect(http(data)).rejects.toEqual(Error(statusText));
+ await expect(http(data)).rejects.toEqual(Error(message));
});
it('should throw error', async () => {
diff --git a/src/utils/api/network/lsk.js b/src/utils/api/network/lsk.js
index 307f7283b2..c4751895a5 100644
--- a/src/utils/api/network/lsk.js
+++ b/src/utils/api/network/lsk.js
@@ -25,7 +25,7 @@ export const getNetworkStatus = ({
network,
});
-const getServiceUrl = ({ name = networkKeys.mainNet, address = 'http://localhost:4000' }) => {
+const getServiceUrl = ({ name, address = 'http://localhost:4000' }) => {
if ([networkKeys.mainNet, networkKeys.testNet].includes(name)) {
return networks[name].serviceUrl;
}
diff --git a/src/utils/getNetwork.js b/src/utils/getNetwork.js
index 6a279d912f..46a433a4de 100644
--- a/src/utils/getNetwork.js
+++ b/src/utils/getNetwork.js
@@ -8,7 +8,8 @@ export const getNetworksList = () =>
name,
}));
-export const getNetworkName = network => network.name || 'customNode';
+// Return mainnet as back off network name when cache/local storage does not exists
+export const getNetworkName = network => network.name || networkKeys.mainNet;
/**
* Returns human readable error messages
diff --git a/src/utils/getNetwork.test.js b/src/utils/getNetwork.test.js
index d461d2cbec..725351b49f 100644
--- a/src/utils/getNetwork.test.js
+++ b/src/utils/getNetwork.test.js
@@ -16,31 +16,31 @@ describe('Utils: getNetwork', () => {
});
});
- describe.skip('getNetworkName', () => {
- it('should discover mainnet', () => {
+ describe('getNetworkName', () => {
+ it('should return mainnet if network config does not have name set', () => {
+ const network = {};
+ expect(getNetworkName(network)).toEqual('mainnet');
+ });
+
+ it('should return customNode', () => {
const network = {
name: 'customNode',
};
- expect(getNetworkName(network, 'LSK')).toEqual('mainnet');
+ expect(getNetworkName(network)).toEqual(network.name);
});
- it('should discover testnet', () => {
+ it('should return testnet', () => {
const network = {
- name: 'customNode',
+ name: 'testnet',
};
- expect(getNetworkName(network, 'LSK')).toEqual('testnet');
+ expect(getNetworkName(network)).toEqual(network.name);
});
- it('should mark as customNode otherwise', () => {
+ it('should return mainnet', () => {
const network = {
- name: 'customNode',
- networks: {
- LSK: {
- nethash: 'sample_hash',
- },
- },
+ name: 'mainnet',
};
- expect(getNetworkName(network, 'LSK')).toEqual('customNode');
+ expect(getNetworkName(network)).toEqual(network.name);
});
});
diff --git a/src/utils/helpers.js b/src/utils/helpers.js
index 610e7e1071..fca77afc87 100644
--- a/src/utils/helpers.js
+++ b/src/utils/helpers.js
@@ -57,10 +57,20 @@ export const filterObjectPropsWithValue = (object = {}, value) => (
* @param {string} error - error message to put into the email body
* @returns {sting} mailto link with recipient, subject, and body
*/
-export const getErrorReportMailto = (error = 'Unknown error occured') => {
+export const getErrorReportMailto = ({
+ error = 'Unknown error occurred', errorMessage, networkIdentifier, serviceUrl, liskCoreVersion,
+}) => {
const recipient = 'hubdev@lisk.io';
const subject = `User Reported Error - Lisk - ${VERSION}`; // eslint-disable-line no-undef
- const body = encodeURIComponent(`\nImportant metadata for the team, please do not edit: \n\n${error}\n`);
+ const body = encodeURIComponent(`
+ \nImportant metadata for the team, please do not edit:
+ \r
+ Lisk Core Version: ${liskCoreVersion}, NetworkIdentifier: ${networkIdentifier}, ServiceURL: ${serviceUrl}
+ \r
+ Error Message: ${errorMessage}
+ \r
+ Transaction: ${error}
+ `);
return `mailto:${recipient}?&subject=${subject}&body=${body}`;
};