Skip to content

Commit

Permalink
refactor(trading): selectors & minor chores
Browse files Browse the repository at this point in the history
  • Loading branch information
adderpositive committed Feb 18, 2025
1 parent d3af724 commit 9cfe792
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 56 deletions.
3 changes: 3 additions & 0 deletions packages/suite/src/support/extraDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ export const extraDependencies: ExtraDependencies = {
selectRouterApp: (state: AppState) => state.router.app,
selectRoute: (state: AppState) => state.router.route,
selectAddressDisplayType: (state: AppState) => state.suite.settings.addressDisplayType,
selectSelectedAccount: (state: AppState) => state.wallet.selectedAccount,
selectSelectedAccountStatus: (state: AppState) => state.wallet.selectedAccount.status,
selectSuiteSettings,
selectIsWindowVisible,
selectTradingEnvironment: (state: AppState) =>
state.suite.settings.debug.invityServerEnvironment,
},
actions: {
setAccountAddMetadata: metadataActions.setAccountAdd,
Expand Down
4 changes: 4 additions & 0 deletions suite-common/redux-utils/src/extraDependenciesType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,14 @@ export type ExtraDependencies = {
selectMetadata: SuiteCompatibleSelector<any>;
selectDeviceDiscovery: SuiteCompatibleSelector<Discovery | undefined>;
selectAddressDisplayType: SuiteCompatibleSelector<AddressDisplayOptions>;
selectSelectedAccount: SuiteCompatibleSelector<SelectedAccountStatus>;
selectSelectedAccountStatus: SuiteCompatibleSelector<SelectedAccountStatus['status']>;
selectSuiteSettings: SuiteCompatibleSelector<{
defaultWalletLoading: WalletType;
}>;
selectTradingEnvironment: SuiteCompatibleSelector<
'production' | 'staging' | 'dev' | 'localhost' | undefined
>;
};
// You should only use ActionCreatorWithPayload from redux-toolkit!
// That means you will need to convert actual action creators in packages/suite to use createAction from redux-toolkit,
Expand Down
7 changes: 6 additions & 1 deletion suite-common/test-utils/src/extraDependenciesMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createAction } from '@reduxjs/toolkit';
import { ExtraDependencies, createThunk } from '@suite-common/redux-utils';
import { BITCOIN_ONLY_SYMBOLS } from '@suite-common/suite-constants';
import { Route } from '@suite-common/suite-types';
import { AddressDisplayOptions } from '@suite-common/wallet-types';
import { AddressDisplayOptions, SelectedAccountLoaded } from '@suite-common/wallet-types';
import { PROTO } from '@trezor/connect';

import { testMocks } from './mocks';
Expand Down Expand Up @@ -98,11 +98,16 @@ export const extraDependenciesMock: ExtraDependencies = {
'selectAddressDisplayType',
AddressDisplayOptions.CHUNKED,
),
selectSelectedAccount: mockSelector('selectSelectedAccount', {
status: 'loaded',
account: testMocks.getWalletAccount(),
} as SelectedAccountLoaded),
selectSelectedAccountStatus: mockSelector('selectSelectedAccountStatus', 'loaded'),
selectSuiteSettings: mockSelector('selectSuiteSettings', {
defaultWalletLoading: 'standard',
}),
selectIsWindowVisible: mockSelector('selectIsWindowVisible', true),
selectTradingEnvironment: mockSelector('selectTradingEnvironment', 'localhost'),
},
actions: {
setAccountAddMetadata: mockAction('setAccountAddMetadata'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { combineReducers } from '@reduxjs/toolkit';
import { combineReducers, createReducer } from '@reduxjs/toolkit';

import { createReducerWithExtraDeps } from '@suite-common/redux-utils';
import { configureMockStore, extraDependenciesMock } from '@suite-common/test-utils';
import { Account } from '@suite-common/wallet-types';

Expand All @@ -15,7 +14,7 @@ import {
} from '../../reducers/tradingReducer';
import { regional } from '../../regional';
import { buyThunks } from '../../thunks/buy';
import { tradingMiddleware } from '../tradingMiddleware';
import { prepareTradingMiddleware } from '../tradingMiddleware';

jest.mock('../../invityAPI');
invityAPI.setInvityServersEnvironment = () => {};
Expand All @@ -27,15 +26,15 @@ type SelectedAccountStatus = {
account: Account;
};
type SelectedAccountState = SelectedAccountStatus;
const mockedSelectedAccountReducer = createReducerWithExtraDeps<SelectedAccountState>(
const mockedSelectedAccountReducer = createReducer<SelectedAccountState>(
{
status: 'none',
account: accountBtc as Account,
},
() => {},
);

const mockedSuiteReducer = createReducerWithExtraDeps(
const mockedSuiteReducer = createReducer(
{
settings: {
debug: {
Expand All @@ -46,16 +45,24 @@ const mockedSuiteReducer = createReducerWithExtraDeps(
() => {},
);

const tradingMiddleware = prepareTradingMiddleware({
...extraDependenciesMock,
selectors: {
...extraDependenciesMock.selectors,
selectSelectedAccount: () => ({ status: 'loaded', account: accountBtc }) as any,
},
});

const initStore = (localInitialState?: Partial<TradingState>) =>
configureMockStore({
middleware: [tradingMiddleware],
extra: {},
reducer: combineReducers({
wallet: combineReducers({
trading: tradingReducer,
selectedAccount: mockedSelectedAccountReducer(extraDependenciesMock),
selectedAccount: mockedSelectedAccountReducer,
}),
suite: mockedSuiteReducer(extraDependenciesMock),
suite: mockedSuiteReducer,
}),
preloadedState: {
wallet: {
Expand Down
75 changes: 40 additions & 35 deletions suite-common/trading/src/middlewares/tradingMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createMiddleware } from '@suite-common/redux-utils';
import { ExtraDependencies, createMiddlewareWithExtraDeps } from '@suite-common/redux-utils';

import { INVITY_API_RELOAD_DATA_AFTER_MS } from '../constants';
import { invityAPI } from '../invityAPI';
Expand All @@ -9,56 +9,61 @@ import {
selectTradingBuy,
selectTradingInfo,
selectTradingLoadingAndTimestamp,
selectTradingSelectedAccount,
selectTradingSettingEnvironment,
} from '../selectors/tradingSelectors';
import { buyThunks } from '../thunks/buy';

export const getAccountAccordingToSection = (state: TradingRootState) => {
const { account } = selectTradingSelectedAccount(state);
export const getAccountAccordingToSection = (state: TradingRootState, extra: ExtraDependencies) => {
const { account } = extra.selectors.selectSelectedAccount(state);

return account;
};

export const tradingMiddleware = createMiddleware(async (action, { dispatch, next, getState }) => {
const { isLoading, lastLoadedTimestamp } = selectTradingLoadingAndTimestamp(getState());
export const prepareTradingMiddleware = createMiddlewareWithExtraDeps(
async (action, { dispatch, next, getState, extra }) => {
const { isLoading, lastLoadedTimestamp } = selectTradingLoadingAndTimestamp(getState());

if (action.type === tradingActions.loadInvityData.type) {
const account = getAccountAccordingToSection(getState());
const { platforms, coins } = selectTradingInfo(getState());
const { buyInfo } = selectTradingBuy(getState());
if (action.type === tradingActions.loadInvityData.type) {
const account = getAccountAccordingToSection(getState(), extra);
const { platforms, coins } = selectTradingInfo(getState());
const { buyInfo } = selectTradingBuy(getState());

const currentAccountDescriptor = invityAPI.getCurrentAccountDescriptor();
const isDifferentAccount = currentAccountDescriptor !== account?.descriptor;
const areDataOutdated = lastLoadedTimestamp + INVITY_API_RELOAD_DATA_AFTER_MS < Date.now();
const currentAccountDescriptor = invityAPI.getCurrentAccountDescriptor();
const isDifferentAccount = currentAccountDescriptor !== account?.descriptor;
const areDataOutdated =
lastLoadedTimestamp + INVITY_API_RELOAD_DATA_AFTER_MS < Date.now();

if (account && !isLoading && (isDifferentAccount || areDataOutdated)) {
dispatch(tradingActions.setLoading({ isLoading: true }));
if (account && !isLoading && (isDifferentAccount || areDataOutdated)) {
dispatch(tradingActions.setLoading({ isLoading: true }));

const invityServerEnvironment = selectTradingSettingEnvironment(getState());
if (invityServerEnvironment) {
invityAPI.setInvityServersEnvironment(invityServerEnvironment);
}
const invityServerEnvironment =
extra.selectors.selectTradingEnvironment(getState());
if (invityServerEnvironment) {
invityAPI.setInvityServersEnvironment(invityServerEnvironment);
}

invityAPI.createInvityAPIKey(account.descriptor);
invityAPI.createInvityAPIKey(account.descriptor);

if (isDifferentAccount || !platforms || !coins) {
const info = await invityAPI.getInfo();
if (isDifferentAccount || !platforms || !coins) {
const info = await invityAPI.getInfo();

dispatch(tradingActions.saveInfo(info));
}
dispatch(tradingActions.saveInfo(info));
}

if (isDifferentAccount || !buyInfo) {
const buyInfoData = await dispatch(buyThunks.loadInfoThunk()).unwrap();
if (isDifferentAccount || !buyInfo) {
const buyInfoData = await dispatch(buyThunks.loadInfoThunk()).unwrap();

dispatch(tradingBuyActions.saveBuyInfo(buyInfoData));
}
dispatch(tradingBuyActions.saveBuyInfo(buyInfoData));
}

dispatch(
tradingActions.setLoading({ isLoading: false, lastLoadedTimestamp: Date.now() }),
);
dispatch(
tradingActions.setLoading({
isLoading: false,
lastLoadedTimestamp: Date.now(),
}),
);
}
}
}

return next(action);
});
return next(action);
},
);
9 changes: 0 additions & 9 deletions suite-common/trading/src/selectors/tradingSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,6 @@ export const selectTradingBuyQuotesRequest = (state: TradingRootState) =>
export const selectTradingBuySelectedQuote = (state: TradingRootState) =>
state.wallet.trading.buy.selectedQuote;

export const selectTradingSelectedAccount = (state: TradingRootState) =>
state.wallet.selectedAccount;

export const selectTradingSettingEnvironment = (state: TradingRootState) =>
state.suite.settings.debug.invityServerEnvironment;

export const selectTradingSettingAddressDisplayType = (state: TradingRootState) =>
state.suite.settings.addressDisplayType;

export const selectTradingPaymentMethods = (state: TradingRootState) =>
state.wallet.trading.info.paymentMethods;

Expand Down
4 changes: 2 additions & 2 deletions suite-common/trading/src/thunks/buy/loadInfoThunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ export const loadInfoThunk = createThunk<BuyInfo>(

const providerInfos: { [name: string]: BuyProviderInfo } = {};

buyInfo.providers.forEach(e => (providerInfos[e.name] = e));
buyInfo.providers.forEach(provider => (providerInfos[provider.name] = provider));

const supportedFiatCurrencies: string[] = [];
const supportedCryptoCurrencies: CryptoId[] = [];
buyInfo.providers.forEach(provider => {
supportedFiatCurrencies.push(
...provider.tradedFiatCurrencies.map(c => c.toLowerCase()),
...provider.tradedFiatCurrencies.map(currency => currency.toLowerCase()),
);
supportedCryptoCurrencies.push(...provider.tradedCoins);
});
Expand Down
3 changes: 1 addition & 2 deletions suite-common/trading/src/thunks/tradingThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Account, AddressDisplayOptions } from '@suite-common/wallet-types';

import { tradingBuyActions } from '../reducers/buyReducer';
import { tradingActions } from '../reducers/tradingReducer';
import { selectTradingSettingAddressDisplayType } from '../selectors/tradingSelectors';
import { getUnusedAddressFromAccount } from '../utils';

const TRADING_COMMON_PREFIX = '@trading-common/thunk';
Expand Down Expand Up @@ -33,7 +32,7 @@ const verifyAddressThunk = createThunk(

dispatch(tradingActions.setModalAccountKey(account.key));

const addressDisplayType = selectTradingSettingAddressDisplayType(getState());
const addressDisplayType = extra.selectors.selectAddressDisplayType(getState());

const { useEmptyPassphrase, connected, available } = device;

Expand Down

0 comments on commit 9cfe792

Please sign in to comment.