Skip to content

Instantly share code, notes, and snippets.

@kelsos
Created February 28, 2026 18:31
Show Gist options
  • Select an option

  • Save kelsos/7b5bcfd970d76199fa2ea7f027dc01cc to your computer and use it in GitHub Desktop.

Select an option

Save kelsos/7b5bcfd970d76199fa2ea7f027dc01cc to your computer and use it in GitHub Desktop.
Pinia Settings Domain Composables — Detailed Implementation Plan

Settings Domain Composables — Implementation Plan

Context

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.


PR 1: useCurrencyInfo + migrate ~21 files (highest impact)

Create composable

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 useAmountDisplaySettings for files that only need currency info

Create test

File: frontend/app/src/composables/settings/use-currency-info.spec.ts

Optionally refactor useAmountDisplaySettings to use useCurrencyInfo internally

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.

Migrate files

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 (needs floatingPrecision alongside many other store refs)

PR 2: useDateSettings + migrate ~6 files

Create composable

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.

Create test

File: frontend/app/src/composables/settings/use-date-settings.spec.ts

Migrate files

# 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)


PR 3: usePrivacySettings + migrate ~4 files

Create composable

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().

Create test

File: frontend/app/src/composables/settings/use-privacy-settings.spec.ts

Migrate files

# 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.


PR 4: Expand useModules() adoption — migrate ~5 files

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).

Migrate files

# 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.


Verification (all PRs)

From frontend/:

pnpm run lint:fix
pnpm run typecheck
pnpm run test:unit

Each 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.

Key files reference

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment