Skip to content

fix(price): reopen the fetch gate, and say which failure happened - #1299

Open
zancas wants to merge 2 commits into
price_fetch_typed_outcomefrom
price_fetch_followup
Open

fix(price): reopen the fetch gate, and say which failure happened#1299
zancas wants to merge 2 commits into
price_fetch_typed_outcomefrom
price_fetch_followup

Conversation

@zancas

@zancas zancas commented Aug 22, 2026

Copy link
Copy Markdown
Member

Stacked on #1298. Review that one first. This branch contains its commit.

This pull request closes the two lesser findings from the price-fetch audit.
They belong to different halves of the code, so they are two commits. A
reviewer can read either one alone.

Commit one, mobile backend: the fetch gate could stay shut forever

5c8cc429, components/Components/priceFetcherStore.ts.

The store raises a loading flag, calls three callbacks the host screen
injects, then lowers the flag. The three are setZecPrice, translate and
addLastSnackbar. Any of them can throw.

A throw skipped the teardown. loading stayed raised, so every later fetch
returned early at the anti-spam gate. scheduleAuto never rearmed the
sixty-second timer. The ring kept spinning against a loop that had stopped,
and the price never refreshed again for the life of the process.

The teardown now runs in a finally block. The gate reopens and the timer
rearms whatever the callbacks do.

Both call sites discarded the rejection through an empty catch, which is what
kept this quiet. They now let it propagate. The store's state no longer depends
on that rejection being caught.

Commit two, UI: the two failures read as one

3db073d3, app/translations/*.json.

English said "Error fetching the price from the Internet." against "Internal
Error fetching the price from the Internet". That is a one-word difference. A
reader could not tell a failed fetch from an unreadable answer, so the
distinction the code preserves never reached anyone.

The pair now names its two cases. One says the price could not be fetched. The
other says the price arrived in a form the app could not read.

Three catalogs also leaked the English word "Error" into their first string.
The Portuguese, Russian and Turkish rewrites drop it. The Turkish second string
carried a trailing space, which goes with it.

The four translations deserve a native reader's eye before merge.

What this does not change

The errorgemini key keeps its name. Gemini is one of several price sources,
so the name is stale, but it is internal and no user sees it. Renaming it would
touch the backend type that lists the catalog keys, which would put a UI concern
into a backend file.

Verification

  • npm run typecheck passes.
  • npx eslint reports nothing on the changed store, and adds no warning where
    the file had none.
  • npx prettier --check passes.
  • Every catalog still parses as JSON.
  • The walletUtils unit suite passes with 24 tests, and the PriceFetcher
    snapshot passes unchanged. No test pins the old copy; the suite asserts the
    error key, not its rendered prose.

🤖 Generated with Claude Code

zancas and others added 2 commits August 21, 2026 21:18
The price store raises a `loading` flag, calls three callbacks the host screen
injects, then lowers the flag. Those callbacks are `setZecPrice`, `translate`
and `addLastSnackbar`, and any of them can throw. A throw skipped the teardown,
so `loading` stayed raised, every later fetch returned early at the anti-spam
gate, and `scheduleAuto` never rearmed the sixty-second timer. The ring kept
spinning against a loop that had stopped, and the price never refreshed again
for the life of the process.

The teardown now runs in a `finally` block, so the gate reopens and the timer
rearms whatever the callbacks do.

Both call sites discarded the rejection through an empty catch, which is what
kept this quiet. They now let it propagate. The store's own state no longer
depends on that rejection being caught, so nothing needs to swallow it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The price fetch can fail two ways, and the snackbar said almost the same
sentence for both. English read "Error fetching the price from the Internet."
against "Internal Error fetching the price from the Internet", a difference of
one word. A reader could not tell a failed fetch from an unreadable answer, so
the distinction the code preserves never reached anyone.

The pair now names its two cases. One says the price could not be fetched. The
other says the price arrived in a form the app could not read.

Three catalogs also leaked the English word "Error" into their first string,
which the Portuguese, Russian and Turkish rewrites drop. The Turkish second
string carried a trailing space, which goes with it.

The four translations deserve a native reader's eye before merge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@zancas
zancas requested a review from juanky201271 August 22, 2026 04:19
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.

1 participant