mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-02-20 00:33:07 +01:00
feat(trading): add provider metadata handling and related tests
feat(tests): add trading test utilities and refactor provider metadata tests
feat(deps): update @testing-library/react version in package.json
(cherry picked from commit 68f5c75281)
This commit is contained in:
committed by
pavelmario
parent
b8ec4efd1e
commit
10156ad456
@@ -13,13 +13,9 @@ type TradingFooterProps = {
|
||||
|
||||
export const TradingFooter = ({ provider }: TradingFooterProps) => {
|
||||
const currentProviderMetadata = useSelector(selectTradingProviderMetadata);
|
||||
const providerMetadata = provider ?? currentProviderMetadata;
|
||||
const { companyName, termsUrl } = provider ?? currentProviderMetadata ?? {};
|
||||
|
||||
const providerName = providerMetadata?.companyName ? (
|
||||
providerMetadata.companyName
|
||||
) : (
|
||||
<Translation id="TR_TERMS_PROVIDER_PLACEHOLDER" />
|
||||
);
|
||||
const providerName = companyName ?? <Translation id="TR_TERMS_PROVIDER_PLACEHOLDER" />;
|
||||
|
||||
return (
|
||||
<Column alignItems="center" margin={{ top: 48 }} gap={12}>
|
||||
@@ -29,11 +25,7 @@ export const TradingFooter = ({ provider }: TradingFooterProps) => {
|
||||
values={{
|
||||
provider: providerName,
|
||||
comp: chunks =>
|
||||
providerMetadata?.termsUrl ? (
|
||||
<Link href={providerMetadata.termsUrl}>{providerName}</Link>
|
||||
) : (
|
||||
chunks
|
||||
),
|
||||
termsUrl ? <Link href={termsUrl}>{providerName}</Link> : chunks,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@suite-common/wallet-types": "workspace:*",
|
||||
"@suite-common/wallet-utils": "workspace:*",
|
||||
"@suite/intl": "workspace:*",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@trezor/address-validator": "workspace:*",
|
||||
"@trezor/connect": "workspace:*",
|
||||
"@trezor/connect-plugin-ethereum": "workspace:*",
|
||||
@@ -36,7 +37,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@suite-common/test-utils": "workspace:*",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/invity-api": "^1.1.12"
|
||||
}
|
||||
}
|
||||
|
||||
176
suite-common/trading/src/__tests__/testUtils.tsx
Normal file
176
suite-common/trading/src/__tests__/testUtils.tsx
Normal file
@@ -0,0 +1,176 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { combineReducers } from '@reduxjs/toolkit';
|
||||
import { RenderHookOptions, renderHook } from '@testing-library/react';
|
||||
import type { BuyProviderInfo, ExchangeProviderInfo, SellProviderInfo } from 'invity-api';
|
||||
|
||||
import { configureMockStore } from '@suite-common/test-utils';
|
||||
|
||||
import type { BuyInfo } from '../reducers/buyReducer';
|
||||
import type { ExchangeInfo } from '../reducers/exchangeReducer';
|
||||
import type { SellInfo } from '../reducers/sellReducer';
|
||||
import { TradingState, initialState, tradingCommonReducer } from '../reducers/tradingCommonReducer';
|
||||
import { regional } from '../regional';
|
||||
|
||||
export type TradingTestState = {
|
||||
wallet: {
|
||||
trading: TradingState;
|
||||
};
|
||||
};
|
||||
|
||||
type RenderHookWithTradingStoreOptions<Props> = RenderHookOptions<Props> & {
|
||||
preloadedState?: Partial<TradingTestState>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a trading test state with proper structure.
|
||||
*
|
||||
* @param overrides - Partial TradingState to merge with initialState
|
||||
* @returns Complete TradingTestState ready for Redux store
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const state = createTradingTestState({
|
||||
* currentProviderMetadata: mockProvider,
|
||||
* buy: { ...initialState.buy, isLoading: true }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export const createTradingTestState = (
|
||||
overrides: Partial<TradingState> = {},
|
||||
): TradingTestState => ({
|
||||
wallet: {
|
||||
trading: {
|
||||
...initialState,
|
||||
...overrides,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a partial BuyInfo state for testing.
|
||||
*
|
||||
* @param providerInfos - Map of provider name to BuyProviderInfo
|
||||
* @returns Partial BuyInfo with minimal required fields
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const buyInfo = createBuyInfoState({
|
||||
* changenow: getProviderMetadataFixture('changenow') as BuyProviderInfo
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export const createBuyInfoState = (
|
||||
providerInfos: Record<string, BuyProviderInfo> = {},
|
||||
): Partial<BuyInfo> => ({
|
||||
buyInfo: {
|
||||
country: regional.UNKNOWN_COUNTRY,
|
||||
providers: [],
|
||||
defaultAmountsOfFiatCurrencies: {} as any,
|
||||
},
|
||||
providerInfos,
|
||||
supportedCryptoCurrencies: [],
|
||||
supportedFiatCurrencies: [],
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a partial ExchangeInfo state for testing.
|
||||
*
|
||||
* @param providerInfos - Map of provider name to ExchangeProviderInfo
|
||||
* @returns Partial ExchangeInfo with minimal required fields
|
||||
*/
|
||||
export const createExchangeInfoState = (
|
||||
providerInfos: Record<string, ExchangeProviderInfo> = {},
|
||||
): Partial<ExchangeInfo> => ({
|
||||
providerInfos,
|
||||
buyCryptoIds: [],
|
||||
sellCryptoIds: [],
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a partial SellInfo state for testing.
|
||||
*
|
||||
* @param providerInfos - Map of provider name to SellProviderInfo
|
||||
* @returns Partial SellInfo with minimal required fields
|
||||
*/
|
||||
export const createSellInfoState = (
|
||||
providerInfos: Record<string, SellProviderInfo> = {},
|
||||
): Partial<SellInfo> => ({
|
||||
country: regional.UNKNOWN_COUNTRY,
|
||||
providerInfos,
|
||||
supportedCryptoCurrencies: [],
|
||||
supportedFiatCurrencies: [],
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders a hook with pre-configured trading Redux store.
|
||||
*
|
||||
* This utility automatically creates a Redux store with the trading reducer
|
||||
* and wraps the hook in a Provider. It returns the standard React Testing Library
|
||||
* hook result plus the store instance for state assertions.
|
||||
*
|
||||
* @template Result - Return type of the hook
|
||||
* @template Props - Props type for the hook (for rerendering)
|
||||
* @param callback - Hook function to test
|
||||
* @param options - Rendering options
|
||||
* @param options.preloadedState - Initial Redux state for the store
|
||||
* @param options.initialProps - Initial props to pass to the hook
|
||||
* @returns Hook result with additional `store` property
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Simple usage
|
||||
* const { result } = renderHookWithTradingStore(
|
||||
* () => useMyHook('buy')
|
||||
* );
|
||||
*
|
||||
* // With preloaded state
|
||||
* const { result, store } = renderHookWithTradingStore(
|
||||
* () => useProviderMetadataChangeEffect('buy', 'changenow', true),
|
||||
* {
|
||||
* preloadedState: createTradingTestState({
|
||||
* buy: {
|
||||
* ...initialState.buy,
|
||||
* buyInfo: createBuyInfoState({
|
||||
* changenow: mockProvider as BuyProviderInfo
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* }
|
||||
* );
|
||||
*
|
||||
* // With props for rerendering
|
||||
* const { result, rerender } = renderHookWithTradingStore<
|
||||
* ReturnType<typeof useMyHook>,
|
||||
* { provider: string }
|
||||
* >(
|
||||
* ({ provider }) => useMyHook(provider),
|
||||
* { initialProps: { provider: 'changenow' } }
|
||||
* );
|
||||
*
|
||||
* rerender({ provider: 'sideshift' });
|
||||
* ```
|
||||
*/
|
||||
export const renderHookWithTradingStore = <Result, Props = unknown>(
|
||||
callback: (props: Props) => Result,
|
||||
{ preloadedState, ...options }: RenderHookWithTradingStoreOptions<Props> = {},
|
||||
) => {
|
||||
const store = configureMockStore({
|
||||
reducer: combineReducers({
|
||||
wallet: combineReducers({
|
||||
trading: tradingCommonReducer,
|
||||
}),
|
||||
}),
|
||||
preloadedState: preloadedState || createTradingTestState(),
|
||||
});
|
||||
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<Provider store={store}>{children}</Provider>
|
||||
);
|
||||
|
||||
return {
|
||||
...renderHook(callback, { wrapper, ...options }),
|
||||
store,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
import {
|
||||
createBuyInfoState,
|
||||
createExchangeInfoState,
|
||||
createSellInfoState,
|
||||
createTradingTestState,
|
||||
renderHookWithTradingStore,
|
||||
} from '../../__tests__/testUtils';
|
||||
import { getProviderMetadataFixture } from '../../reducers/__fixtures__/providerMetadata';
|
||||
import { initialState } from '../../reducers/tradingCommonReducer';
|
||||
import { TradingType } from '../../types';
|
||||
import { useProviderMetadataChangeEffect } from '../useProviderMetadataChangeEffect';
|
||||
|
||||
const mockProviderMetadataChangeNow = getProviderMetadataFixture();
|
||||
const mockProviderMetadataSideShift = getProviderMetadataFixture('sideshift');
|
||||
|
||||
describe('useProviderMetadataChangeEffect', () => {
|
||||
it('should return undefined when no provider metadata is set', () => {
|
||||
const { result } = renderHookWithTradingStore(() =>
|
||||
useProviderMetadataChangeEffect('buy', undefined, true),
|
||||
);
|
||||
|
||||
expect(result.current).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not update provider metadata when areProviderChangesAllowed is false', () => {
|
||||
const { result, rerender } = renderHookWithTradingStore<
|
||||
ReturnType<typeof useProviderMetadataChangeEffect>,
|
||||
{ tradingType: TradingType; quoteName?: string; areProviderChangesAllowed?: boolean }
|
||||
>(
|
||||
({ tradingType, quoteName, areProviderChangesAllowed }) =>
|
||||
useProviderMetadataChangeEffect(tradingType, quoteName, areProviderChangesAllowed),
|
||||
{
|
||||
preloadedState: createTradingTestState({
|
||||
buy: {
|
||||
...initialState.buy,
|
||||
buyInfo: createBuyInfoState({ changenow: mockProviderMetadataChangeNow }),
|
||||
},
|
||||
}),
|
||||
initialProps: {
|
||||
tradingType: 'buy' as TradingType,
|
||||
quoteName: 'changenow',
|
||||
areProviderChangesAllowed: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current).toBeUndefined();
|
||||
rerender({
|
||||
tradingType: 'buy',
|
||||
quoteName: 'changenow',
|
||||
areProviderChangesAllowed: true,
|
||||
});
|
||||
expect(result.current).toEqual(mockProviderMetadataChangeNow);
|
||||
});
|
||||
|
||||
it('should update provider metadata when provider changes and areProviderChangesAllowed is true (buy)', () => {
|
||||
const { result, rerender } = renderHookWithTradingStore<
|
||||
ReturnType<typeof useProviderMetadataChangeEffect>,
|
||||
{ tradingType: TradingType; quoteName?: string; areProviderChangesAllowed?: boolean }
|
||||
>(
|
||||
({ tradingType, quoteName, areProviderChangesAllowed }) =>
|
||||
useProviderMetadataChangeEffect(tradingType, quoteName, areProviderChangesAllowed),
|
||||
{
|
||||
preloadedState: createTradingTestState({
|
||||
buy: {
|
||||
...initialState.buy,
|
||||
buyInfo: createBuyInfoState({
|
||||
changenow: mockProviderMetadataChangeNow,
|
||||
sideshift: mockProviderMetadataSideShift,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
initialProps: {
|
||||
tradingType: 'buy' as TradingType,
|
||||
quoteName: 'changenow',
|
||||
areProviderChangesAllowed: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
expect(result.current).toEqual(mockProviderMetadataChangeNow);
|
||||
rerender({
|
||||
tradingType: 'buy',
|
||||
quoteName: 'sideshift',
|
||||
areProviderChangesAllowed: true,
|
||||
});
|
||||
|
||||
expect(result.current).toEqual(mockProviderMetadataSideShift);
|
||||
});
|
||||
|
||||
it('should update provider metadata for exchange type', () => {
|
||||
const { result } = renderHookWithTradingStore(
|
||||
() => useProviderMetadataChangeEffect('exchange', 'exchangeProvider', true),
|
||||
{
|
||||
preloadedState: createTradingTestState({
|
||||
exchange: {
|
||||
...initialState.exchange,
|
||||
exchangeInfo: createExchangeInfoState({
|
||||
exchangeProvider: mockProviderMetadataChangeNow,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
expect(result.current).toEqual(mockProviderMetadataChangeNow);
|
||||
});
|
||||
|
||||
it('should update provider metadata for sell type', () => {
|
||||
const { result } = renderHookWithTradingStore(
|
||||
() => useProviderMetadataChangeEffect('sell', 'sellProvider', true),
|
||||
{
|
||||
preloadedState: createTradingTestState({
|
||||
sell: {
|
||||
...initialState.sell,
|
||||
sellInfo: createSellInfoState({
|
||||
sellProvider: mockProviderMetadataChangeNow,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
expect(result.current).toEqual(mockProviderMetadataChangeNow);
|
||||
});
|
||||
|
||||
it('should clear provider metadata on unmount', () => {
|
||||
const { unmount, store } = renderHookWithTradingStore(
|
||||
() => useProviderMetadataChangeEffect('buy', 'changenow', true),
|
||||
{
|
||||
preloadedState: createTradingTestState({
|
||||
currentProviderMetadata: mockProviderMetadataChangeNow,
|
||||
buy: {
|
||||
...initialState.buy,
|
||||
buyInfo: createBuyInfoState({
|
||||
changenow: mockProviderMetadataChangeNow,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toEqual(
|
||||
mockProviderMetadataChangeNow,
|
||||
);
|
||||
unmount();
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle undefined quoteName gracefully', () => {
|
||||
const { result } = renderHookWithTradingStore(() =>
|
||||
useProviderMetadataChangeEffect('buy', undefined, true),
|
||||
);
|
||||
|
||||
expect(result.current).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
} from '../selectors/tradingSelectors';
|
||||
import type { TradingType } from '../types';
|
||||
|
||||
export const useProviderMetadataChangeEffect = (tradingType: TradingType, quoteName?: string) => {
|
||||
export const useProviderMetadataChangeEffect = (
|
||||
tradingType: TradingType,
|
||||
quoteName?: string,
|
||||
areProviderChangesAllowed = true,
|
||||
) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const providerMetadata = useSelector((state: TradingRootState) =>
|
||||
@@ -18,18 +22,16 @@ export const useProviderMetadataChangeEffect = (tradingType: TradingType, quoteN
|
||||
const currentProviderMetadata = useSelector(selectTradingProviderMetadata);
|
||||
|
||||
useEffect(() => {
|
||||
if (!quoteName && providerMetadata) {
|
||||
dispatch(tradingActions.setCurrentProviderMetadata(undefined));
|
||||
if (!areProviderChangesAllowed) {
|
||||
return;
|
||||
}
|
||||
}, [dispatch, quoteName, providerMetadata]);
|
||||
|
||||
useEffect(() => {
|
||||
if (providerMetadata === currentProviderMetadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(tradingActions.setCurrentProviderMetadata(providerMetadata));
|
||||
}, [providerMetadata, currentProviderMetadata, dispatch]);
|
||||
}, [providerMetadata, currentProviderMetadata, dispatch, areProviderChangesAllowed]);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { ProviderMetadata } from 'invity-api';
|
||||
|
||||
export const getProviderMetadataFixture = (
|
||||
providerName: string = 'changenow',
|
||||
): ProviderMetadata => ({
|
||||
name: providerName,
|
||||
companyName: providerName,
|
||||
logo: `${providerName}-icon.jpg`,
|
||||
isActive: true,
|
||||
supportUrl: `https://support.${providerName}.io`,
|
||||
statusUrl: `https://${providerName}.io/exchange/txs/{{orderId}}`,
|
||||
termsUrl: `https://${providerName}.io/terms-of-use`,
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { configureMockStore, extraDependenciesCommonMock } from '@suite-common/t
|
||||
import { selectTradingMaxSlippagePercentage } from '../../selectors/settingsSelectors';
|
||||
import { buyThunks } from '../../thunks/buy';
|
||||
import { sellThunks } from '../../thunks/sell';
|
||||
import { getProviderMetadataFixture } from '../__fixtures__/providerMetadata';
|
||||
import { tradingFixtures } from '../__fixtures__/tradingReducer';
|
||||
import { buyInitialState, tradingBuyActions } from '../buyReducer';
|
||||
import { exchangeInitialState, tradingExchangeActions } from '../exchangeReducer';
|
||||
@@ -137,6 +138,45 @@ describe('Testing trading reducer', () => {
|
||||
|
||||
expect(store.getState().wallet.trading.modalAccountKey).toEqual('MY_KEY');
|
||||
});
|
||||
|
||||
it('should set currentProviderMetadata with complete provider data', () => {
|
||||
const providerMetadata = getProviderMetadataFixture('changenow');
|
||||
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toBeUndefined();
|
||||
|
||||
store.dispatch(tradingActions.setCurrentProviderMetadata(providerMetadata));
|
||||
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toEqual(
|
||||
providerMetadata,
|
||||
);
|
||||
});
|
||||
|
||||
it('should update currentProviderMetadata when called multiple times', () => {
|
||||
const firstProvider = getProviderMetadataFixture('changenow');
|
||||
const secondProvider = getProviderMetadataFixture('sideshift');
|
||||
|
||||
store.dispatch(tradingActions.setCurrentProviderMetadata(firstProvider));
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toEqual(
|
||||
firstProvider,
|
||||
);
|
||||
|
||||
store.dispatch(tradingActions.setCurrentProviderMetadata(secondProvider));
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toEqual(
|
||||
secondProvider,
|
||||
);
|
||||
});
|
||||
|
||||
it('should clear currentProviderMetadata when set to undefined', () => {
|
||||
const providerMetadata = getProviderMetadataFixture('changenow');
|
||||
|
||||
store.dispatch(tradingActions.setCurrentProviderMetadata(providerMetadata));
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toEqual(
|
||||
providerMetadata,
|
||||
);
|
||||
|
||||
store.dispatch(tradingActions.setCurrentProviderMetadata(undefined));
|
||||
expect(store.getState().wallet.trading.currentProviderMetadata).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('tradingSettings', () => {
|
||||
|
||||
@@ -56,6 +56,7 @@ import {
|
||||
selectTradingPlatformByCryptoId,
|
||||
selectTradingPrefilledFromAccount,
|
||||
selectTradingProviderByNameAndTradeType,
|
||||
selectTradingProviderMetadata,
|
||||
selectTradingSellAccountKey,
|
||||
selectTradingSellFormStep,
|
||||
selectTradingSellInfo,
|
||||
@@ -1441,4 +1442,28 @@ describe('tradingSelectors', () => {
|
||||
expect(first).toBe(second);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectTradingProviderMetadata', () => {
|
||||
it('should return currentProviderMetadata from state', () => {
|
||||
const providerMetadata = {
|
||||
name: 'TEST_PROVIDER',
|
||||
companyName: 'Test Company',
|
||||
logo: 'https://example.com/logo.png',
|
||||
isActive: true,
|
||||
};
|
||||
state.wallet.trading.currentProviderMetadata = providerMetadata;
|
||||
|
||||
const result = selectTradingProviderMetadata(state);
|
||||
|
||||
expect(result).toEqual(providerMetadata);
|
||||
});
|
||||
|
||||
it('should return undefined when currentProviderMetadata is not set', () => {
|
||||
state.wallet.trading.currentProviderMetadata = undefined;
|
||||
|
||||
const result = selectTradingProviderMetadata(state);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
type TradingRootState,
|
||||
TradingType,
|
||||
selectTradingProviderByNameAndTradeType,
|
||||
selectTradingProviderMetadata,
|
||||
tradingActions,
|
||||
useProviderMetadataChangeEffect as useCommonProviderMetadataChangeEffect,
|
||||
} from '@suite-common/trading';
|
||||
|
||||
export type QuoteProviderFormWatch = (key: 'quote.exchange') => string | undefined;
|
||||
@@ -17,36 +11,8 @@ export const useProviderMetadataChangeEffect = (
|
||||
watch: QuoteProviderFormWatch,
|
||||
tradingType: TradingType,
|
||||
) => {
|
||||
const dispatch = useDispatch();
|
||||
const exchange = watch('quote.exchange');
|
||||
const isFocused = useIsFocused();
|
||||
|
||||
const providerMetadata = useSelector((state: TradingRootState) =>
|
||||
selectTradingProviderByNameAndTradeType(state, exchange, tradingType),
|
||||
);
|
||||
const currentProviderMetadata = useSelector(selectTradingProviderMetadata);
|
||||
|
||||
useEffect(() => {
|
||||
// On navigation to preview screen the form is cleared, but we want to keep this value, therefore
|
||||
// we skip updates to currentProviderMetadata.
|
||||
// The effect will clear the provider metadata as soon as user goes back to form screen.
|
||||
if (!isFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (providerMetadata === currentProviderMetadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(tradingActions.setCurrentProviderMetadata(providerMetadata));
|
||||
}, [providerMetadata, currentProviderMetadata, dispatch, isFocused]);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
dispatch(tradingActions.setCurrentProviderMetadata(undefined));
|
||||
},
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
return currentProviderMetadata;
|
||||
return useCommonProviderMetadataChangeEffect(tradingType, exchange, isFocused);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user