Skip to content

fix(desktop): wallet balance follows actual recharge currency - #7790

Open
clearnature wants to merge 3 commits into
esengine:main-v2from
clearnature:fix-wallet-currency-follow-balance
Open

fix(desktop): wallet balance follows actual recharge currency#7790
clearnature wants to merge 3 commits into
esengine:main-v2from
clearnature:fix-wallet-currency-follow-balance

Conversation

@clearnature

Copy link
Copy Markdown
Contributor

Summary

Wallet balance display followed the UI language guess (zh→CNY, en→USD),
which is wrong for overseas Chinese users who recharge USD but use a zh
interface. Also, picking CNY/USD in Settings did not refresh the
status-bar balance readout.

Changes

  1. Balance.PrimaryCurrency() (internal/billing/balance.go)
    Returns the largest reported balance's currency. DeepSeek returns one
    Info per currency; the largest balance is the one the user actually
    recharged, so display should follow it rather than a language guess.

  2. BalanceForTab (desktop/app.go)
    When desktop currency is auto (no explicit choice), display follows
    PrimaryCurrency() instead of the UI-language guess. An explicit
    CNY/USD choice in Settings still wins.

  3. applyDeepSeekOfficialDefaultPricingWithOverride
    (internal/config/pricing.go)
    Match provider-wide price against p.ModelList() so
    deepseek-responses (models list + provider-wide price fallback, empty
    p.Model) also gets converted to the selected CNY/USD table. Before
    this, a USD default stayed in dollars even with [desktop] currency = CNY.

  4. useController.ts (desktop frontend)
    Refresh the wallet readout on reasonix:model-catalog-changed, which
    SettingsPanel dispatches after applying currency/model changes. Before
    this, picking CNY/USD in Settings did not update the status bar.

Verification

  • go test ./internal/billing/ ./internal/config/ - all pass
  • New: TestPrimaryCurrencyFollowsLargestBalance,
    TestApplyDeepSeekOfficialPricingOverridesProviderWidePrice
  • Frontend tsc --noEmit - clean

Cache-impact: low - config/billing/desktop display only; no provider wire
or system-prompt changes.
Cache-guard: go test ./internal/billing/ ./internal/config/ -count=1

Documentation-impact: none - internal display logic, no user-facing docs.

System-prompt-review: none - no system-prompt or boot surface changes.

Problem: balance display followed the UI language guess (zh→CNY, en→USD),
which is wrong for overseas Chinese users who recharge USD but use a zh UI.
Also, picking CNY/USD in Settings did not refresh the status-bar balance.

Fix:
- Balance.PrimaryCurrency(): return the largest reported balance's currency
  (DeepSeek returns one Info per currency; the largest is what the user
  actually recharged).
- BalanceForTab: when desktop currency is auto, display follows
  PrimaryCurrency instead of the language guess. Explicit currency still wins.
- applyDeepSeekOfficialDefaultPricingWithOverride: match provider-wide
  'price' against p.ModelList() so deepseek-responses (models list + price
  fallback, empty p.Model) also gets converted to the selected CNY/USD table.
- useController: refresh the wallet readout on model-catalog-changed, which
  SettingsPanel dispatches after applying currency/model changes.

Tests: TestPrimaryCurrencyFollowsLargestBalance,
TestApplyDeepSeekOfficialPricingOverridesProviderWidePrice.
Copilot AI lite review requested due to automatic review settings August 6, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes desktop wallet balance and pricing-currency behavior so the displayed wallet currency follows the user’s actual recharge currency (when desktop currency is set to auto), and so changing CNY/USD in Settings refreshes the status-bar wallet readout and correctly converts DeepSeek official default pricing even when a provider uses a model list with a provider-wide price fallback.

Changes:

  • Add Balance.PrimaryCurrency() to select the currency associated with the largest reported balance entry.
  • Update desktop balance display logic to prefer the actual recharge currency when desktop currency is auto, and refresh the balance readout when Settings applies model/currency changes.
  • Fix DeepSeek official pricing override logic to also apply to provider-wide price fallbacks when using a models list; add regression tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/config/pricing.go Adjust DeepSeek official pricing override to handle provider-wide price when models list is used.
internal/config/backfill_test.go Add regression test ensuring provider-wide DeepSeek pricing gets overridden to selected currency table.
internal/billing/balance.go Add PrimaryCurrency() to infer display currency from the largest reported balance.
internal/billing/balance_test.go Add test coverage for PrimaryCurrency() selection behavior.
desktop/app.go Prefer actual recharge currency for balance display when desktop currency is auto.
desktop/frontend/src/lib/useController.ts Refresh wallet balance readout when Settings dispatches the model-catalog-changed event.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/config/pricing.go Outdated
Comment thread desktop/app.go Outdated
@github-actions github-actions Bot added desktop Wails desktop app (desktop/**) config Configuration & setup (internal/config) labels Aug 7, 2026
…ide, single config load for balance

Copilot review esengine#7790 findings:
1. Provider-wide price override only checked models[0]; a multi-model entry
   whose first model is not a recognized official pricing model kept the wrong
   currency table. Now scans the whole resolved model list and overrides when
   ANY model matches the known official defaults.
2. BalanceForTab loaded the desktop user config twice (balanceDisplayCurrency
   + DesktopCurrency check) — extra disk/stat + TOML parse on every balance
   refresh, and the override depended on a second load succeeding. Load once
   and pass the config+err into balanceDisplayCurrency.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (1)

desktop/app.go:6758

  • err is reused for the config-load call after it already held the balance-fetch error earlier in this function. Reassigning the same err name for an unrelated operation is easy to misread and makes future edits riskier (e.g., accidentally checking the wrong error). Use a distinct name like cfgErr and pass that through.
	cfg, _, err := a.loadDesktopUserConfigForView()
	currency := a.balanceDisplayCurrency(cfg, err)
	if actual := b.PrimaryCurrency(); actual != "" {
		if err == nil && cfg != nil && cfg.DesktopCurrency() == "" {
			currency = actual

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

Labels

config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants