diff --git a/web/cashtab/src/hooks/useWallet.js b/web/cashtab/src/hooks/useWallet.js --- a/web/cashtab/src/hooks/useWallet.js +++ b/web/cashtab/src/hooks/useWallet.js @@ -16,6 +16,7 @@ getHashArrayFromWallet, parseChronikTx, checkWalletForTokenInfo, + isActiveWebsocket, } from 'utils/cashMethods'; import { isValidCashtabSettings, isValidContactList } from 'utils/validation'; import localforage from 'localforage'; @@ -1216,7 +1217,9 @@ // Parse for incoming XEC transactions // hasUpdated is set to true in the useAsyncTimeout function, and re-sets to false during activateWallet + // Do not show this notification if websocket connection is live; in this case the websocket will handle it if ( + !isActiveWebsocket(chronikWebsocket) && previousBalances && balances && 'totalBalance' in previousBalances && @@ -1235,7 +1238,9 @@ } // Parse for incoming eToken transactions + // Do not show this notification if websocket connection is live; in this case the websocket will handle it if ( + !isActiveWebsocket(chronikWebsocket) && tokens && tokens[0] && tokens[0].balance && diff --git a/web/cashtab/src/utils/__mocks__/chronikWs.js b/web/cashtab/src/utils/__mocks__/chronikWs.js --- a/web/cashtab/src/utils/__mocks__/chronikWs.js +++ b/web/cashtab/src/utils/__mocks__/chronikWs.js @@ -207,3 +207,56 @@ timeFirstSeen: '1652823534', network: 'XEC', }; + +export const activeWebsocketAlpha = { + autoReconnect: true, + _manuallyClosed: false, + _subs: [ + { + scriptType: 'p2pkh', + scriptPayload: '1fb76a7db96fc774cbad00e8a72890602b4be304', + }, + { + scriptType: 'p2pkh', + scriptPayload: 'a9f494266e4b3c823712f27dedcb83e30b2fe59f', + }, + { + scriptType: 'p2pkh', + scriptPayload: '95e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d', + }, + ], + _wsUrl: 'wss://chronik.be.cash/xec/ws', + _ws: { readyState: 1 }, + _connected: {}, +}; + +export const disconnectedWebsocketAlpha = { + autoReconnect: true, + _manuallyClosed: false, + _subs: [ + { + scriptType: 'p2pkh', + scriptPayload: '1fb76a7db96fc774cbad00e8a72890602b4be304', + }, + { + scriptType: 'p2pkh', + scriptPayload: 'a9f494266e4b3c823712f27dedcb83e30b2fe59f', + }, + { + scriptType: 'p2pkh', + scriptPayload: '95e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d', + }, + ], + _wsUrl: 'wss://chronik.be.cash/xec/ws', + _ws: { readyState: 3 }, + _connected: {}, +}; + +export const unsubscribedWebsocket = { + autoReconnect: true, + _manuallyClosed: false, + _subs: [], + _wsUrl: 'wss://chronik.be.cash/xec/ws', + _ws: { readyState: 1 }, + _connected: {}, +}; diff --git a/web/cashtab/src/utils/__tests__/cashMethods.test.js b/web/cashtab/src/utils/__tests__/cashMethods.test.js --- a/web/cashtab/src/utils/__tests__/cashMethods.test.js +++ b/web/cashtab/src/utils/__tests__/cashMethods.test.js @@ -27,6 +27,7 @@ getHashArrayFromWallet, parseChronikTx, checkWalletForTokenInfo, + isActiveWebsocket, } from 'utils/cashMethods'; import { currency } from 'components/Common/Ticker'; import { @@ -167,6 +168,9 @@ lambdaOutgoingXecTx, lambdaIncomingEtokenTx, lambdaOutgoingEtokenTx, + activeWebsocketAlpha, + disconnectedWebsocketAlpha, + unsubscribedWebsocket, } from '../__mocks__/chronikWs'; describe('Correctly executes cash utility functions', () => { @@ -975,4 +979,16 @@ ), ).toBe(false); }); + it(`isActiveWebsocket returns true for an active chronik websocket connection`, () => { + expect(isActiveWebsocket(activeWebsocketAlpha)).toBe(true); + }); + it(`isActiveWebsocket returns false for a disconnected chronik websocket connection`, () => { + expect(isActiveWebsocket(disconnectedWebsocketAlpha)).toBe(false); + }); + it(`isActiveWebsocket returns false for a null chronik websocket connection`, () => { + expect(isActiveWebsocket(null)).toBe(false); + }); + it(`isActiveWebsocket returns false for an active websocket connection with no subscriptions`, () => { + expect(isActiveWebsocket(unsubscribedWebsocket)).toBe(false); + }); }); diff --git a/web/cashtab/src/utils/cashMethods.js b/web/cashtab/src/utils/cashMethods.js --- a/web/cashtab/src/utils/cashMethods.js +++ b/web/cashtab/src/utils/cashMethods.js @@ -1112,3 +1112,17 @@ return false; }; + +export const isActiveWebsocket = ws => { + // Return true if websocket is connected and subscribed + // Otherwise return false + return ( + ws !== null && + ws && + '_ws' in ws && + 'readyState' in ws._ws && + ws._ws.readyState === 1 && + '_subs' in ws && + ws._subs.length > 0 + ); +};