Skip to content

frontend: move web config access into config context/provider#3916

Open
smokyisthatyou wants to merge 24 commits into
BitBoxSwiss:masterfrom
smokyisthatyou:config-context-provider
Open

frontend: move web config access into config context/provider#3916
smokyisthatyou wants to merge 24 commits into
BitBoxSwiss:masterfrom
smokyisthatyou:config-context-provider

Conversation

@smokyisthatyou
Copy link
Copy Markdown
Contributor

Add ConfigContext + ConfigProvider in frontends/web and refactor React components/hooks to consume getConfig/setConfig through useConfig() instead of importing utils/config directly. Keep non-React config consumers on the shared utils/config implementation path, and update related hook dependency arrays.

Before asking for reviews, here is a check list of the most common things you might need to consider:

  • updating the Changelog
  • writing unit tests
  • checking if your changes affect other coins or tokens in unintended ways
  • testing on multiple environments (Qt, Android, ...)
  • having an AI review your changes

cc @thisconnect

@thisconnect
Copy link
Copy Markdown
Collaborator

nice, please make one more change/commit. Currently each component still does a get request when using getConfig.

Instead it could call getConfig once on startup and keep the "config" object in the context. getConfig could then either read out the local "config" object, or context could expose "config" object along with setConfig. I am not sure what is better.

With this all components that depend on "config" object can read from the context without doing an additional api call.

We want the source of truth still to be the backend, so in the context it should update the "config" object after setConfig and fetch from the api.

Also the api function in utils should be moved into frontends/web/src/api/config.ts

@thisconnect thisconnect requested a review from shonsirsha March 10, 2026 05:44
@shonsirsha
Copy link
Copy Markdown
Collaborator

concept ACK

@thisconnect thisconnect requested review from thisconnect and removed request for shonsirsha March 10, 2026 12:39
Comment thread frontends/web/src/hooks/bitsurance.ts
Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/api/config.ts
Comment thread frontends/web/src/components/banners/offline-error.tsx Outdated
Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/contexts/RatesProvider.tsx Outdated
Comment thread frontends/web/src/components/status/status.tsx Outdated
Comment thread frontends/web/src/contexts/DarkmodeProvider.tsx
Comment thread frontends/web/src/contexts/DarkmodeProvider.tsx Outdated

if (cancelledAccounts?.includes(code)) {
alertUser(t('account.insuranceExpired'));
// remove the pending notification from the frontend settings.
Copy link
Copy Markdown
Collaborator

@thisconnect thisconnect Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the comment

@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch from 30401e1 to ea60d60 Compare March 12, 2026 16:16
@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch from ea60d60 to 4da6264 Compare March 30, 2026 14:48
@smokyisthatyou smokyisthatyou marked this pull request as ready for review March 30, 2026 15:49
@smokyisthatyou
Copy link
Copy Markdown
Contributor Author

@thisconnect moving this from draft, rebased

Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/api/config.ts
Comment thread frontends/web/src/components/status/status.tsx Outdated
@smokyisthatyou
Copy link
Copy Markdown
Contributor Author

@thisconnect ptal whenever you have time 🙏

Copy link
Copy Markdown
Collaborator

@thisconnect thisconnect left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you I think we should merge this first step soon, as it reduces api calls to the config endpoint and is the base for further updates: like fully typing TConfig

Comment thread frontends/web/src/utils/config.ts Outdated
Comment thread frontends/web/src/utils/config.ts Outdated
Comment thread frontends/web/src/components/banners/offline-error.tsx Outdated
Comment thread frontends/web/src/components/status/status.tsx Outdated
Comment thread frontends/web/src/contexts/AppProvider.tsx Outdated
Comment thread frontends/web/src/contexts/AppProvider.tsx Outdated
Comment thread frontends/web/src/contexts/ConfigContext.tsx Outdated
@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch from e991fa0 to 8fb8728 Compare March 31, 2026 13:29
@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch 7 times, most recently from ed28dd9 to 925a212 Compare April 10, 2026 10:44
@smokyisthatyou
Copy link
Copy Markdown
Contributor Author

@jadzeidan while working on this pr i think i introduced an old behaviour of the app that was opening the guide on first run. i implemented the code thinking it was the current expected flow, but @thisconnect pointed out this was actually deprecated in v4.40.

personally i’m not a huge fan of the auto-opening guide for aesthetic reasons, though I can see the utility.
do you think we should reintroduce this or keep it as is?

@jadzeidan
Copy link
Copy Markdown
Contributor

thanks @smokyisthatyou for finding this 😄

I agree that guide shouldn't open automatically, so let's keep the "new" behaviour.

@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch 2 times, most recently from d730016 to cacf20f Compare April 13, 2026 13:20
@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch from cacf20f to bd2bd6c Compare May 11, 2026 14:17
@smokyisthatyou smokyisthatyou requested a review from a team as a code owner May 11, 2026 14:17
@smokyisthatyou
Copy link
Copy Markdown
Contributor Author

@thisconnect rebased

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors the application's configuration management from a utility-based pattern to a React context-based system. A new typed API module (frontends/web/src/api/config.ts) defines configuration structures for backend (coin settings, proxy, language) and frontend (feature toggles, UI preferences). A ConfigProvider component fetches configuration on mount and distributes it through React context via a useConfig() hook, replacing direct imports of getConfig() and setConfig() throughout the codebase. The utility layer bridges old and new approaches, while provider-level components and all consumer components are migrated to the reactive context pattern for centralized, type-safe configuration state management.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch 2 times, most recently from 491ab75 to 0feada1 Compare May 15, 2026 15:08
smokyisthatyou and others added 9 commits May 19, 2026 16:29
- Introduce ConfigProvider and ConfigContext and wrap app with
  provider
- Fetch config once when the app loads and expose config + setConfig
  via useConfig
- Refactor config consumers to read from context instead of calling
  getConfig per component
Stop auto-opening the guide when no frontend config is present.
This prevents the guide overlay from blocking interactions on fresh starts.
- Add TFrontendConfig with known frontend settings flags and keep index signature
- Update consumers to use typed config.frontend keys and drop casts/guards
- Add TBackendConfig and related types to api/config and use them in TConfig
- Introduce TConfigUpdate so setConfig can accept partial backend/frontend updates
- Update utils/config and ConfigProvider/Context to use TConfigUpdate merge + pendingConfig
- Drop remaining backend casts in offline-error, electrum-servers, and RatesProvider
Type known frontend/backend config keys in api/config, remove duplicate
advanced-settings types and unsafe casts, tighten TConfigUpdate and
normalization, and add mockConfig for unit tests.
this avoids calling getConfig/setConfig directly and redundant config
fetches
Drop the onChangeConfig callback chain; children already update config via useConfig().
- Simplify darkmode unset spread in DarkmodeProvider
- Remove redundant userLanguage cast in i18n detector after truthiness
guard.
- Align feetargets expertFee access with context nullability (direct
frontend read in effect, optional config in render).
- Simplify remember-wallet dialog config check to optional chaining.
@smokyisthatyou smokyisthatyou force-pushed the config-context-provider branch from 0feada1 to 1e34610 Compare May 19, 2026 14:30
Copy link
Copy Markdown
Collaborator

@thisconnect thisconnect left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

partially reviewed

Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/api/config.ts
Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/contexts/ConfigProvider.tsx
Comment thread frontends/web/src/api/config.ts
Comment thread frontends/web/src/components/banners/offline-error.tsx Outdated
Comment thread frontends/web/src/components/new-badge/new-badge.tsx Outdated
Comment thread frontends/web/src/contexts/AppProvider.tsx Outdated
Copy link
Copy Markdown
Collaborator

@thisconnect thisconnect left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice almost there

swap.tsx was recently merged, please also useConfig there instead of useLoad(getConfig)

Comment thread frontends/web/src/api/config.ts
Comment thread frontends/web/src/api/config.ts Outdated
Comment thread frontends/web/src/components/new-badge/new-badge.tsx Outdated
Comment thread frontends/web/src/utils/config.ts Outdated
};
let pendingConfig: TConfigUpdate = {};

export const emptyBackendConfig = (): TConfig['backend'] => ({} as TConfig['backend']);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We trust the backend returns what is defined in api files.

Comment thread frontends/web/src/utils/config.ts
Comment thread frontends/web/src/utils/config.ts Outdated
Comment thread frontends/web/src/test/mock-config.ts Outdated
};

export const EnableAuthSetting = ({ backendConfig, onChangeConfig }: TProps) => {
export const EnableAuthSetting = ({ backendConfig }: TProps) => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use config?.backend from useConfig(); a few lines below and drop passing config with backendConfig prop.

const dismissGuideIfPresent = async (driver) => {
await driver.execute(() => {
const overlays = document.querySelectorAll('div');
for (const el of overlays) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use data-testid on the dialog component's overlay so you dont have to traverse the DOM here.

The react testing library style would more be to find web accessible elements by role atc. https://testing-library.com/docs/queries/about/#priority
but refactoring the diaog/overlay seems a bit out of scope of this PR so best to just add data-testid in this dialog.

},
});
} else {
// darkmode is different from OS, save to config
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the comment

if (config.frontend.selectedExchangeRegion) {
// pre-select config region
setSelectedRegion(config.frontend.selectedExchangeRegion);
setSelectedRegion(String(config.frontend.selectedExchangeRegion));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
setSelectedRegion(String(config.frontend.selectedExchangeRegion));
setSelectedRegion(config.frontend.selectedExchangeRegion);

}
};
useEffect(() => {
updateRatesConfig();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateRatesConfig function is only used here, also the function returns a promise but that is not needed here. I think it is fine to just move the 5 lines logic of the function into the effect here.

<EnableAuthSetting />
<EnableTorProxySetting proxyConfig={config?.backend.proxy} />
<RestartInTestnetSetting />
<CustomGapLimitSettings />
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to get rid of the remaining props where config is passed (frontendConfig and proxyConfig)

const nextConfig = Object.assign(currentConfig, {
backend: Object.assign({}, currentConfig.backend, pendingConfig.backend, object.backend),
frontend: Object.assign({}, currentConfig.frontend, pendingConfig.frontend, object.frontend)
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont understand why there is different behavior for merging frontend and backend. Or if you found a bug and this fixes something.

As this PR is already vvery big I'd prefer to keep the merging with Object.assign and you drop the new commit that add mergeBackend/mergeFrontend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants