Skip to content

Commit af5055e

Browse files
authored
feat: use synced exchanges only for query (#11627)
1 parent 7a3c0d4 commit af5055e

File tree

7 files changed

+69
-49
lines changed

7 files changed

+69
-49
lines changed

frontend/app/src/components/history/events/tx/RepullingExchangeForm.vue

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ import LocationIcon from '@/components/history/LocationIcon.vue';
88
import DateTimeRangePicker from '@/components/inputs/DateTimeRangePicker.vue';
99
import { useFormStateWatcher } from '@/composables/form';
1010
import { shouldShowDateRangePicker } from '@/composables/history/events/tx/use-repulling-transaction-form';
11+
import { useExchangeData } from '@/modules/balances/exchanges/use-exchange-data';
1112
import { Routes } from '@/router/routes';
12-
import { useGeneralSettingsStore } from '@/store/settings/general';
13-
import { useSessionSettingsStore } from '@/store/settings/session';
1413
import { useRefPropVModel } from '@/utils/model';
1514
import { toMessages } from '@/utils/validation';
1615
@@ -25,17 +24,9 @@ const fromTimestamp = useRefPropVModel(modelValue, 'fromTimestamp');
2524
const toTimestamp = useRefPropVModel(modelValue, 'toTimestamp');
2625
2726
const exchange = ref<Exchange>();
27+
const { syncingExchanges } = useExchangeData();
2828
29-
const { connectedExchanges } = storeToRefs(useSessionSettingsStore());
30-
const { nonSyncingExchanges } = storeToRefs(useGeneralSettingsStore());
31-
32-
const availableExchanges = computed<Exchange[]>(() => get(connectedExchanges).filter(
33-
exchange => !get(nonSyncingExchanges).some(
34-
excluded => excluded.location === exchange.location && excluded.name === exchange.name,
35-
),
36-
));
37-
38-
const hasNoExchanges = computed<boolean>(() => get(availableExchanges).length === 0);
29+
const hasNoExchanges = computed<boolean>(() => get(syncingExchanges).length === 0);
3930
4031
const showDateRangePicker = computed<boolean>(() => shouldShowDateRangePicker(false, get(exchange)));
4132
@@ -115,7 +106,7 @@ defineExpose({
115106
<template v-else>
116107
<RuiAutoComplete
117108
v-model="exchange"
118-
:options="availableExchanges"
109+
:options="syncingExchanges"
119110
:label="t('common.exchange')"
120111
variant="outlined"
121112
auto-select-first

frontend/app/src/composables/history/events/tx/refresh-handlers.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import { useModules } from '@/composables/session/modules';
55
import { useExternalApiKeys } from '@/composables/settings/api-keys/external';
66
import { useMoneriumOAuth } from '@/modules/external-services/monerium/use-monerium-auth';
77
import { useNotificationsStore } from '@/store/notifications';
8-
import { useGeneralSettingsStore } from '@/store/settings/general';
9-
import { useSessionSettingsStore } from '@/store/settings/session';
108
import { useTaskStore } from '@/store/tasks';
119
import { type Exchange, QueryExchangeEventsPayload } from '@/types/exchanges';
1210
import { OnlineHistoryEventsQueryType } from '@/types/history/events/schemas';
@@ -17,7 +15,7 @@ import { awaitParallelExecution } from '@/utils/await-parallel-execution';
1715
import { logger } from '@/utils/logging';
1816

1917
interface UseRefreshHandlersReturn {
20-
queryAllExchangeEvents: (exchanges?: Exchange[]) => Promise<void>;
18+
queryAllExchangeEvents: (exchanges: Exchange[]) => Promise<void>;
2119
queryOnlineEvent: (queryType: OnlineHistoryEventsQueryType) => Promise<void>;
2220
}
2321

@@ -30,7 +28,6 @@ export function useRefreshHandlers(): UseRefreshHandlersReturn {
3028
const isEth2Enabled = isModuleEnabled(Module.ETH2);
3129
const { apiKey } = useExternalApiKeys(t);
3230
const { authenticated: moneriumAuthenticated, refreshStatus } = useMoneriumOAuth();
33-
const { nonSyncingExchanges } = storeToRefs(useGeneralSettingsStore());
3431

3532
const queryOnlineEvent = async (queryType: OnlineHistoryEventsQueryType): Promise<void> => {
3633
const eth2QueryTypes: OnlineHistoryEventsQueryType[] = [
@@ -116,15 +113,8 @@ export function useRefreshHandlers(): UseRefreshHandlersReturn {
116113
}
117114
};
118115

119-
const queryAllExchangeEvents = async (exchanges?: Exchange[]): Promise<void> => {
120-
const { connectedExchanges } = storeToRefs(useSessionSettingsStore());
121-
const selectedExchanges = exchanges ?? get(connectedExchanges);
122-
const excluded = get(nonSyncingExchanges);
123-
const filteredExchanges = selectedExchanges.filter(exchange => !excluded.some(
124-
excludedExchange => excludedExchange.location === exchange.location
125-
&& excludedExchange.name === exchange.name,
126-
));
127-
const groupedExchanges = Object.entries(groupBy(filteredExchanges, exchange => exchange.location));
116+
const queryAllExchangeEvents = async (exchanges: Exchange[]): Promise<void> => {
117+
const groupedExchanges = Object.entries(groupBy(exchanges, exchange => exchange.location));
128118

129119
await awaitParallelExecution(groupedExchanges, ([group]) => group, async ([_group, exchanges]) => {
130120
for (const exchange of exchanges) {

frontend/app/src/composables/history/events/tx/use-refresh-transactions.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ const mockRefreshHandlers = {
7575
queryOnlineEvent: vi.fn().mockResolvedValue(undefined),
7676
};
7777

78-
const mockSessionSettingsStore = {
79-
connectedExchanges: ref<Exchange[]>(mockExchanges),
78+
const mockExchangeData = {
79+
isSameExchange: (a: Exchange, b: Exchange): boolean => a.location === b.location && a.name === b.name,
80+
syncingExchanges: ref<Exchange[]>(mockExchanges),
8081
};
8182

8283
vi.mock('./use-history-transaction-accounts', () => ({
@@ -107,8 +108,8 @@ vi.mock('./refresh-handlers', () => ({
107108
useRefreshHandlers: vi.fn(() => mockRefreshHandlers),
108109
}));
109110

110-
vi.mock('@/store/settings/session', () => ({
111-
useSessionSettingsStore: vi.fn(() => mockSessionSettingsStore),
111+
vi.mock('@/modules/balances/exchanges/use-exchange-data', () => ({
112+
useExchangeData: vi.fn(() => mockExchangeData),
112113
}));
113114

114115
vi.mock('@/store/history/query-status/tx-query-status', () => ({
@@ -233,7 +234,7 @@ describe('useRefreshTransactions', () => {
233234

234235
await refreshTransactions();
235236

236-
expect(mockRefreshHandlers.queryAllExchangeEvents).toHaveBeenCalledWith(undefined);
237+
expect(mockRefreshHandlers.queryAllExchangeEvents).toHaveBeenCalledWith(mockExchanges);
237238
expect(mockEventsQueryStatusStore.initializeQueryStatus).toHaveBeenCalled();
238239
});
239240
});
@@ -492,7 +493,7 @@ describe('useRefreshTransactions', () => {
492493

493494
it('should not call onHistoryStarted when no accounts or exchanges to refresh', async () => {
494495
mockHistoryTransactionAccounts.getAllAccounts.mockReturnValue([]);
495-
set(mockSessionSettingsStore.connectedExchanges, []);
496+
set(mockExchangeData.syncingExchanges, []);
496497

497498
const { refreshTransactions } = useRefreshTransactions();
498499

frontend/app/src/composables/history/events/tx/use-refresh-transactions.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import { useTransactionSync } from '@/composables/history/events/tx/use-transact
88
import { useSupportedChains } from '@/composables/info/chains';
99
import { useSchedulerState } from '@/composables/session/use-scheduler-state';
1010
import { useStatusUpdater } from '@/composables/status';
11+
import { useExchangeData } from '@/modules/balances/exchanges/use-exchange-data';
1112
import { useHistoryStore } from '@/store/history';
1213
import { useEventsQueryStatusStore } from '@/store/history/query-status/events-query-status';
1314
import { useTxQueryStatusStore } from '@/store/history/query-status/tx-query-status';
1415
import { useHistoryRefreshStateStore } from '@/store/history/refresh-state';
15-
import { useSessionSettingsStore } from '@/store/settings/session';
1616
import { OnlineHistoryEventsQueryType } from '@/types/history/events/schemas';
1717
import { Section, Status } from '@/types/status';
1818
import { LimitedParallelizationQueue } from '@/utils/limited-parallelization-queue';
@@ -51,12 +51,18 @@ export function useRefreshTransactions(): UseRefreshTransactionsReturn {
5151
startRefresh,
5252
} = useHistoryRefreshStateStore();
5353

54+
const { syncingExchanges, isSameExchange } = useExchangeData();
55+
5456
const refreshTransactions = async (params: RefreshTransactionsParams = {}): Promise<void> => {
5557
const { chains = [], disableEvmEvents = false, payload = {}, userInitiated = false } = params;
5658
const { accounts, exchanges, queries } = payload;
5759
const fullRefresh = Object.keys(payload).length === 0;
5860

59-
const { connectedExchanges } = storeToRefs(useSessionSettingsStore());
61+
const usedExchanges: Exchange[] = exchanges
62+
? exchanges.filter(exchange => get(syncingExchanges).some(
63+
syncing => isSameExchange(syncing, exchange),
64+
))
65+
: get(syncingExchanges);
6066

6167
// Determine initial accounts to check
6268
const allCurrentAccounts = accounts?.length
@@ -69,8 +75,7 @@ export function useRefreshTransactions(): UseRefreshTransactionsReturn {
6975
const hasNewAccounts = newAccountsList.length > 0;
7076

7177
// Check for new exchanges
72-
const allCurrentExchanges = exchanges || get(connectedExchanges);
73-
const newExchangesList = getNewExchanges(allCurrentExchanges);
78+
const newExchangesList = getNewExchanges(usedExchanges);
7479
const hasNewExchanges = newExchangesList.length > 0;
7580

7681
// Skip refresh only if fetchDisabled returns true AND there are no new accounts or exchanges
@@ -98,7 +103,7 @@ export function useRefreshTransactions(): UseRefreshTransactionsReturn {
98103
if (hasNewAccounts || userInitiated) {
99104
accountsToRefresh = getAllAccounts(chains);
100105
}
101-
exchangesToRefresh = get(connectedExchanges);
106+
exchangesToRefresh = get(syncingExchanges);
102107
}
103108
else if (hasNewAccounts || hasNewExchanges) {
104109
if (hasNewAccounts)
@@ -146,8 +151,8 @@ export function useRefreshTransactions(): UseRefreshTransactionsReturn {
146151

147152
if (fullRefresh || exchanges) {
148153
if (shouldShowSyncProgress)
149-
initializeExchangeEventsQueryStatus(exchanges || get(connectedExchanges));
150-
asyncOperations.push(queryAllExchangeEvents(exchanges));
154+
initializeExchangeEventsQueryStatus(usedExchanges);
155+
asyncOperations.push(queryAllExchangeEvents(usedExchanges));
151156
}
152157

153158
const queriesToExecute: OnlineHistoryEventsQueryType[] | undefined = fullRefresh || disableEvmEvents

frontend/app/src/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3445,6 +3445,7 @@
34453445
},
34463446
"history_refresh_selection": {
34473447
"back_to_chain": "Back to chain selection",
3448+
"non_syncing_hint": "{count} exchange is excluded from syncing | {count} exchanges are excluded from syncing",
34483449
"refresh": "Refresh {total} {type}",
34493450
"refresh_disabled": "Refreshing {service} is disabled because the required API key is not configured",
34503451
"search_address": "Search by address",

frontend/app/src/modules/balances/exchanges/use-exchange-data.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import type { ComputedRef, MaybeRef } from 'vue';
22
import type { AssetProtocolBalances } from '@/types/blockchain/balances';
3-
import type { ExchangeInfo } from '@/types/exchanges';
3+
import type { Exchange, ExchangeInfo } from '@/types/exchanges';
44
import { useBalancesStore } from '@/modules/balances/use-balances-store';
5+
import { useGeneralSettingsStore } from '@/store/settings/general';
6+
import { useSessionSettingsStore } from '@/store/settings/session';
57
import { sortDesc } from '@/utils/bignumbers';
68
import { balanceSum, exchangeAssetSum } from '@/utils/calculation';
79

810
interface UseExchangeDataReturn {
911
useBaseExchangeBalances: (exchange?: MaybeRef<string>) => ComputedRef<AssetProtocolBalances>;
1012
exchanges: ComputedRef<ExchangeInfo[]>;
13+
syncingExchanges: ComputedRef<Exchange[]>;
14+
isSameExchange: (a: Exchange, b: Exchange) => boolean;
1115
}
1216

1317
export function useExchangeData(): UseExchangeDataReturn {
1418
const { exchangeBalances } = storeToRefs(useBalancesStore());
19+
const { connectedExchanges } = storeToRefs(useSessionSettingsStore());
20+
const { nonSyncingExchanges } = storeToRefs(useGeneralSettingsStore());
1521

1622
const exchanges = computed<ExchangeInfo[]>(() => {
1723
const balances = get(exchangeBalances);
@@ -52,8 +58,20 @@ export function useExchangeData(): UseExchangeDataReturn {
5258
return protocolBalances;
5359
});
5460

61+
function isSameExchange(a: Exchange, b: Exchange): boolean {
62+
return a.location === b.location && a.name === b.name;
63+
}
64+
65+
const syncingExchanges = computed<Exchange[]>(() => get(connectedExchanges).filter(
66+
exchange => !get(nonSyncingExchanges).some(
67+
excluded => isSameExchange(excluded, exchange),
68+
),
69+
));
70+
5571
return {
5672
exchanges,
5773
useBaseExchangeBalances,
74+
syncingExchanges,
75+
isSameExchange,
5876
};
5977
}

frontend/app/src/modules/history/refresh/HistoryRefreshExchanges.vue

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<script setup lang="ts">
22
import type { Exchange } from '@/types/exchanges';
3+
import { getTextToken } from '@rotki/common';
34
import { isEqual, sortBy } from 'es-toolkit';
45
import LocationDisplay from '@/components/history/LocationDisplay.vue';
5-
import { useSessionSettingsStore } from '@/store/settings/session';
6+
import { useExchangeData } from '@/modules/balances/exchanges/use-exchange-data';
7+
import { useGeneralSettingsStore } from '@/store/settings/general';
68
79
const modelValue = defineModel<Exchange[]>({ required: true });
810
const search = defineModel<string>('search', { required: true });
@@ -13,12 +15,17 @@ defineProps<{
1315
1416
const emit = defineEmits<{ 'update:all-selected': [allSelected: boolean] }>();
1517
16-
const { connectedExchanges } = storeToRefs(useSessionSettingsStore());
18+
const { t } = useI18n({ useScope: 'global' });
19+
20+
const { syncingExchanges } = useExchangeData();
21+
const { nonSyncingExchanges } = storeToRefs(useGeneralSettingsStore());
22+
23+
const hasNonSyncingExchanges = computed<boolean>(() => get(nonSyncingExchanges).length > 0);
1724
1825
const filteredExchanges = computed<Exchange[]>(() => {
19-
const query = get(search).toLocaleLowerCase();
20-
return get(connectedExchanges).filter(exchange =>
21-
exchange.name.toLocaleLowerCase().includes(query) || exchange.location.toLocaleLowerCase().includes(query),
26+
const query = getTextToken(get(search));
27+
return get(syncingExchanges).filter(exchange =>
28+
getTextToken(exchange.name).includes(query) || getTextToken(exchange.location).includes(query),
2229
);
2330
});
2431
@@ -32,20 +39,20 @@ function toggleSelect(exchange: Exchange): void {
3239
}
3340
}
3441
35-
function toggleSelectAll() {
42+
function toggleSelectAll(): void {
3643
if (get(modelValue).length > 0) {
3744
updateSelection([]);
3845
}
3946
else {
40-
updateSelection(get(connectedExchanges));
47+
updateSelection(get(syncingExchanges));
4148
}
4249
}
4350
44-
function updateSelection(exchanges: Exchange[]) {
51+
function updateSelection(exchanges: Exchange[]): void {
4552
set(modelValue, exchanges);
4653
emit('update:all-selected', isEqual(
4754
sortBy(exchanges, ['location', 'name']),
48-
sortBy(get(connectedExchanges), ['location', 'name']),
55+
sortBy(get(syncingExchanges), ['location', 'name']),
4956
));
5057
}
5158
@@ -83,4 +90,11 @@ defineExpose({
8390

8491
<div class="grow" />
8592
</div>
93+
94+
<div
95+
v-if="hasNonSyncingExchanges"
96+
class="px-4 py-2 text-xs text-rui-text-secondary italic"
97+
>
98+
{{ t('history_refresh_selection.non_syncing_hint', { count: nonSyncingExchanges.length }) }}
99+
</div>
86100
</template>

0 commit comments

Comments
 (0)