The rotki frontend has 4 settings stores consumed by ~210 files (~39% of the codebase). currencySymbol alone is imported in 42 files. Components must know which store holds which setting, creating tight coupling and boilerplate. The goal is to create domain composables (following the existing useAmountDisplaySettings pattern) so most components never import a settings store directly.
File: frontend/app/src/composables/settings/use-currency-info.ts
import type { ComputedRef } from 'vue';
import type { Currency, SupportedCurrency } from '@/types/currencies';
import { useGeneralSettingsStore } from '@/store/settings/general';
export interface CurrencyInfo {
currency: ComputedRef<Currency>;
currencySymbol: ComputedRef<SupportedCurrency>;
floatingPrecision: ComputedRef<number>;
}
export function useCurrencyInfo(): CurrencyInfo {
const { currency, currencySymbol, floatingPrecision } = storeToRefs(useGeneralSettingsStore());
return { currency, currencySymbol, floatingPrecision };
}- No
createSharedComposable(Pinia stores are already singletons) - Lightweight alternative to
useAmountDisplaySettingsfor files that only need currency info
File: frontend/app/src/composables/settings/use-currency-info.spec.ts
File: frontend/app/src/modules/amount-display/composables/use-amount-display-settings.ts
Replace:
const { currency, currencySymbol, floatingPrecision } = storeToRefs(generalSettingsStore);With:
const { currency, currencySymbol, floatingPrecision } = useCurrencyInfo();No public API change — just DRY.
Each migration replaces storeToRefs(useGeneralSettingsStore()) with useCurrencyInfo():
Simple replacements (remove useGeneralSettingsStore import entirely):
| # | File | Property used |
|---|---|---|
| 1 | composables/dashboard/use-dashboard-stores.ts |
currencySymbol |
| 2 | modules/amount-display/composables/use-oracle-info.ts |
currencySymbol |
| 3 | composables/staking/eth/use-eth-validator-data.ts |
currencySymbol |
| 4 | components/assets/use-asset-locations-data.ts |
currencySymbol |
| 5 | store/prices/historic.ts |
currencySymbol |
| 6 | components/exchanges/BinanceSavingDetail.vue |
currencySymbol |
| 7 | components/dashboard/edit-snapshot/EditBalancesSnapshotAssetPriceForm.vue |
currencySymbol |
| 8 | components/dashboard/edit-snapshot/EditLocationDataSnapshotForm.vue |
currencySymbol |
| 9 | components/dashboard/edit-snapshot/EditLocationDataSnapshotTable.vue |
currencySymbol |
| 10 | components/dashboard/edit-snapshot/EditSnapshotTotal.vue |
currencySymbol |
| 11 | components/dashboard/edit-snapshot/EditBalancesSnapshotTable.vue |
currencySymbol |
| 12 | components/AssetBalances.vue |
currencySymbol |
| 13 | components/helper/hint/ValueAccuracyHint.vue |
currencySymbol |
| 14 | components/assets/AssetValueRow.vue |
currencySymbol |
| 15 | components/settings/HideSmallBalances.vue |
currencySymbol |
| 16 | components/EvmNativeTokenBreakdown.vue |
currencySymbol |
| 17 | modules/prices/use-price-task-manager.ts |
currencySymbol |
| 18 | modules/accounts/table/composables/use-account-table-config.ts |
currencySymbol |
| 19 | components/CurrencyDropdown.vue |
currency |
Partial replacements (file still needs useFrontendSettingsStore for other properties):
| # | File | Currency prop | Other props kept from stores |
|---|---|---|---|
| 20 | composables/dashboard/use-dashboard-table-config.ts |
currencySymbol | dashboardTablesVisibleColumns (frontend) |
| 21 | modules/balances/non-fungible/composables/use-nft-data.ts |
currencySymbol | dashboardTablesVisibleColumns (frontend) |
Not migrating (need write access or are boundary code):
- Settings page components using
updateSetting() premium/premium-apis.ts(library integration)composables/use-currency-update.ts(needs both store + price stores)store/statistics/index.ts(needsfloatingPrecisionalongside many other store refs)
File: frontend/app/src/composables/settings/use-date-settings.ts
import type { ComputedRef } from 'vue';
import { useFrontendSettingsStore } from '@/store/settings/frontend';
import { useGeneralSettingsStore } from '@/store/settings/general';
export interface DateSettings {
dateDisplayFormat: ComputedRef<string>;
displayDateInLocaltime: ComputedRef<boolean>;
dateInputFormat: ComputedRef<string>;
}
export function useDateSettings(): DateSettings {
const { dateDisplayFormat, displayDateInLocaltime } = storeToRefs(useGeneralSettingsStore());
const { dateInputFormat } = storeToRefs(useFrontendSettingsStore());
return { dateDisplayFormat, dateInputFormat, displayDateInLocaltime };
}Key value: consumers no longer need to know date display format is in the general store while date input format is in the frontend store.
File: frontend/app/src/composables/settings/use-date-settings.spec.ts
| # | File | Properties used |
|---|---|---|
| 1 | components/display/DateDisplay.vue |
dateDisplayFormat (from general) |
| 2 | pages/reports/use-reports-page-actions.ts |
dateDisplayFormat (from general) |
| 3 | composables/history/events/tx/index.ts |
dateDisplayFormat (from general) |
| 4 | composables/filters/events.ts |
dateInputFormat (from frontend) |
| 5 | components/staking/kraken/KrakenDateFilter.vue |
dateInputFormat (from frontend) |
| 6 | modules/staking/eth/components/EthValidatorCombinedFilter.vue |
dateInputFormat (from frontend) |
Not migrating: components/settings/general/DateInputFormatSetting.vue (settings page, needs updateSetting)
File: frontend/app/src/composables/settings/use-privacy-settings.ts
import type { ComputedRef } from 'vue';
import type { PrivacyMode } from '@/types/session';
import { useFrontendSettingsStore } from '@/store/settings/frontend';
export interface PrivacySettings {
shouldShowAmount: ComputedRef<boolean>;
shouldShowPercentage: ComputedRef<boolean>;
privacyMode: ComputedRef<PrivacyMode>;
}
export function usePrivacySettings(): PrivacySettings {
const { privacyMode, shouldShowAmount, shouldShowPercentage } = storeToRefs(useFrontendSettingsStore());
return { privacyMode, shouldShowAmount, shouldShowPercentage };
}Read-only visibility flags. For mode toggling use usePrivacyMode(), for scramble utilities use useScramble().
File: frontend/app/src/composables/settings/use-privacy-settings.spec.ts
| # | File | Property used |
|---|---|---|
| 1 | components/display/PercentageDisplay.vue |
shouldShowPercentage |
| 2 | components/accounts/IconTokenDisplay.vue |
shouldShowAmount |
| 3 | modules/balances/protocols/components/ChainBalanceTooltipIcon.vue |
shouldShowAmount |
| 4 | modules/balances/protocols/ProtocolTooltipIcon.vue |
shouldShowAmount |
Not migrating: useScramble, useAmountDisplaySettings, premium-apis.ts, statistics/index.ts — these are lower-level composables/stores that legitimately need direct access.
The composable already exists at composables/session/modules.ts with isModuleEnabled(module) and isAnyModuleEnabled(modules) helpers. Several files still manually do activeModules.includes(Module.X).
| # | File | Current pattern | New pattern |
|---|---|---|---|
| 1 | modules/balances/services/use-loopring-balance-service.ts |
get(activeModules).includes(Module.LOOPRING) |
get(isModuleEnabled(Module.LOOPRING)) |
| 2 | modules/balances/nft/use-nft-balances.ts |
activeModules.includes(Module.NFTS) |
isModuleEnabled(Module.NFTS) |
| 3 | modules/dashboard/liquidity-pools/use-pool-balances.ts |
activeModules ref passed to fetchDataAsync |
useModules().activeModules (same ComputedRef type) |
| 4 | components/settings/api-keys/external/LoopringApiKey.vue |
useArrayIncludes(activeModules, Module.LOOPRING) |
isModuleEnabled(Module.LOOPRING) |
| 5 | components/accounts/ModuleActivator.vue |
get(activeModules).includes(identifier) |
isModuleEnabled(identifier) |
Not migrating: components/defi/ActiveModules.vue, components/defi/wizard/ModuleSelector.vue — these need write access to update modules.
From frontend/:
pnpm run lint:fix
pnpm run typecheck
pnpm run test:unitEach migration is mechanically simple (replace storeToRefs(useXxxStore()) with the composable call). Since composables return the identical ref objects from the same singleton stores, there is zero behavioral change.
| Purpose | Path |
|---|---|
| Gold-standard pattern | modules/amount-display/composables/use-amount-display-settings.ts |
| General settings store | store/settings/general.ts |
| Frontend settings store | store/settings/frontend.ts |
| Existing modules composable | composables/session/modules.ts |
| Existing privacy composable | composables/privacy.ts |
| Existing scramble composable | composables/scramble.ts |
| Currency types | types/currencies.ts |
| Privacy mode types | types/session.ts |