Skip to content

fix(wallet): unblock Hive Engine token transfers and harden HE reads#3254

Merged
feruzm merged 3 commits into
developmentfrom
fix/he-token-transfer-precision
Jun 13, 2026
Merged

fix(wallet): unblock Hive Engine token transfers and harden HE reads#3254
feruzm merged 3 commits into
developmentfrom
fix/he-token-transfer-precision

Conversation

@feruzm

@feruzm feruzm commented Jun 13, 2026

Copy link
Copy Markdown
Member

Problem

Hive Engine (HE) token transfers — e.g. ARCHON — could not be sent: the NEXT button stayed disabled for every HE token, with a valid recipient, amount, and memo. Some users also saw the wallet intermittently fail to load.

Root cause: the transfer screen gates NEXT on the token's precision being known, but precision was read from the HE balances table, which has no precision field — it lives on the tokens table. So tokenPrecision was always undefined and the gate never passed. (Even when it didn't block, an unknown precision let an over-precise quantity reach the sidechain, where it is silently rejected.)

Separately, all HE reads go through a single proxy with no request timeout or retry, so a transient blip surfaced as an empty wallet or a stuck transfer — while the same operation works on hive-engine.com (which fails over across nodes).

Fix

Transfer (precision):

  • Source Engine precision from the tokens table (fetchTokens) instead of the balances row; fetch balances + token info in parallel. Precision 0 (integer tokens) is preserved, not defaulted away.
  • Thread token precision through the HiveAuth op-builder path (buildTransferOpsArraygetEngineActionOpArraygetEngineActionJSON) so the broadcast quantity is truncated to the token's real precision on all auth types (key / HiveSigner / HiveAuth), not the 8-decimal fallback.

Reliability (wallet load):

  • Add a request timeout + bounded retry-with-backoff to the HE proxy reads.
  • Surface wallet-load failures with a Retry affordance instead of a blank list, and cap the portfolio query's retry backoff so it can't sit on the skeleton.

Tests

  • New unit tests covering engine precision threading (over-precise truncation, integer/precision-0 tokens, 8-decimal fallback when precision is unknown).
  • yarn lint clean; transactionOpsBuilder / number / wallet suites green (110 tests).

Notes

  • Pure-JS change — no native rebuild required.
  • Follow-up (not in this PR): poll the HE sidechain tx status after broadcast so a rejected transfer stops reporting "Successful".

Summary by CodeRabbit

  • New Features

    • Wallet now shows a refresh-failure banner with a "try again" button when data fails to load.
  • Improvements

    • Network requests use per-request timeouts and sequential retries with a capped retry delay to surface errors faster.
    • Token transfers now preserve and honor explicit token precision (including zero) for more accurate amounts; whole-number engine-token sends are allowed while precision is loading.
  • Tests

    • Added tests covering engine token precision handling.

Hive Engine token transfers (e.g. ARCHON) could not proceed — the NEXT
button stayed disabled for every HE token. Token precision was read from the
Engine balances table, which has no precision field (it lives on the tokens
table), so tokenPrecision was always undefined and the transfer's precision
gate never passed.

- Source Engine precision from the tokens table (fetchTokens) instead of the
  balances row; fetch both in parallel. Preserve precision 0 (integer tokens).
- Thread token precision through the HiveAuth op-builder path
  (buildTransferOpsArray -> getEngineActionOpArray -> getEngineActionJSON) so
  the broadcast quantity is truncated to the token's real precision on every
  auth type, not the 8-decimal fallback (over-precise quantities are rejected
  by the Engine sidechain).
- Add a request timeout + bounded retry-with-backoff to the HE proxy reads,
  which previously had neither, so a transient proxy blip no longer surfaces as
  an empty wallet or a stuck transfer.
- Surface wallet-load failures with a Retry instead of a blank list, and cap
  the portfolio query retry backoff.
- Cover the engine precision threading with unit tests.
@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes two bugs in the Hive Engine token flow: the NEXT button was permanently disabled because token precision was read from the balances table (which has no precision field) instead of the tokens table; and the single Ecency proxy had no timeout or retry, so transient network errors silently produced empty wallets or stuck transfers.

  • Precision fix: transferContainer now fetches balances and token metadata in parallel via Promise.allSettled, sourcing enginePrecision from the tokens table; precision is threaded through buildTransferOpsArraygetEngineActionOpArraygetEngineActionJSON on all auth paths (key/HiveAuth); the NEXT-button gate is relaxed to allow whole-number amounts even when precision is still loading.
  • Reliability: postEngineContract wraps every HE read with a 15 s per-request timeout and up to 2 sequential retries with exponential backoff; the portfolio query's retry delay is capped at 4 s so the wallet error state surfaces quickly.
  • Error UI: a Retry banner rendered above the FlatList (not as ListEmptyComponent) correctly surfaces failures on both first-load and subsequent refreshes of an already-populated wallet.

Confidence Score: 5/5

Safe to merge — the precision source fix is targeted and correct, the retry/timeout wrapper is conservative, and the NEXT-button relaxation is guarded by both a positive-amount check and an integer test.

All three changed paths (key/HiveSigner/HiveAuth) format the broadcast quantity correctly; the integer-amount bypass on the NEXT button cannot produce an over-precise quantity; the Promise.allSettled pattern tolerates one-leg failures without discarding valid data; and the new unit tests cover the precision-threading contract.

No files require special attention; the one styling nit (Retry button blending into the error banner) does not affect functionality.

Important Files Changed

Filename Overview
src/containers/transferContainer.ts Fixes the root cause: fetches token precision from the tokens table (not balances) using parallel Promise.allSettled; partial failure in either leg is handled gracefully without discarding the other result.
src/providers/hive-engine/hiveEngine.ts Replaces per-call fire-and-forget with a shared postEngineContract helper that adds per-request timeout (15s) and sequential retry-with-backoff; removes three functions now handled by the SDK; transport errors now reject instead of resolving to an empty array.
src/providers/hive-engine/hiveEngineActions.ts Threads the optional precision parameter through getEngineActionJSON and getEngineActionOpArray; now truncates via formatTokenQuantity(parseToken(amount), precision) so precision-0 integer tokens are handled correctly.
src/providers/queries/walletQueries/walletQueries.ts Adds retryDelay cap (max 4s) to useAssetsQuery so the portfolio query surfaces its error/retry state quickly instead of climbing toward React Query's default ~30s exponential backoff.
src/screens/transfer/screen/transferScreen.tsx Relaxes the NEXT-button gate so whole-number amounts bypass the precision requirement; HiveAuth path now passes tokenPrecision to buildTransferOpsArray; HiveSigner path omits tokenPrecision on getEngineActionJSON calls but is safe because hsEngineAmount is pre-truncated.
src/screens/wallet/screen/walletScreen.tsx Adds an error banner rendered above the FlatList; correctly gates on walletQuery.isError && !walletQuery.isFetching so it works for both first-load failures and refresh failures on an already-populated list.
src/screens/wallet/screen/walletScreenStyles.ts Adds errorBanner and errorText styles; the banner reuses headerActionButton for the Retry button, which shares backgroundColor with the banner container — the button shape blends into the background.
src/utils/transactionOpsBuilder.ts Adds precision to TansferData interface and threads it through buildTransferOpsArray → getEngineActionOpArray; amount normalization now calls formatTokenQuantity(amount, precision) for ENGINE tokens.
src/utils/transactionOpsBuilder.test.ts Adds three targeted tests covering over-precise truncation, precision-0 (integer) tokens, and the 8-decimal fallback path; leverages the existing mock shape correctly.

Sequence Diagram

sequenceDiagram
    participant UI as TransferScreen
    participant TC as TransferContainer
    participant HE as hiveEngine (postEngineContract)
    participant OB as transactionOpsBuilder
    participant HA as hiveEngineActions

    UI->>TC: mount (ENGINE token)
    par Parallel fetch
        TC->>HE: fetchTokenBalances(username)
        HE-->>TC: TokenBalance[] (no precision field)
    and
        TC->>HE: fetchTokens([fundType])
        Note over HE: timeout 15s, retry x2
        HE-->>TC: Token[] (precision: number)
    end
    TC->>TC: "enginePrecision = tokens.find(fundType)?.precision"
    TC-->>UI: tokenPrecision (from tokens table)

    UI->>UI: nextBtnDisabled check
    Note over UI: Allow if precision known OR amount is whole number

    UI->>OB: "buildTransferOpsArray({..., precision})"
    OB->>OB: formatTokenQuantity(amount, precision)
    OB->>HA: getEngineActionOpArray(..., precision)
    HA->>HA: getEngineActionJSON(..., precision)
    HA->>HA: "quantity = formatTokenQuantity(parseToken(amount), precision)"
    HA-->>UI: custom_json op with truncated quantity
Loading

Fix All in Claude Code

Reviews (3): Last reviewed commit: "fix(wallet): coerce amount for integer g..." | Re-trigger Greptile

Comment thread src/screens/wallet/screen/walletScreen.tsx
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50e20801-3a6e-4570-b4a4-e8a2e51e2d90

📥 Commits

Reviewing files that changed from the base of the PR and between 3f24933 and 452774b.

📒 Files selected for processing (2)
  • src/screens/transfer/screen/transferScreen.tsx
  • src/screens/wallet/screen/walletScreen.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/screens/transfer/screen/transferScreen.tsx

📝 Walkthrough

Walkthrough

Derive ENGINE token precision from token definitions and pass it through transfer builders; add a Hive-Engine POST wrapper with timeout and sequential retries; cap asset-query retry delay; surface wallet query errors with a retry banner above the wallet list.

Changes

Engine Token Precision Propagation & Engine Request Retry

Layer / File(s) Summary
Engine Request Retry and Timeout Wrapper
src/providers/hive-engine/hiveEngine.ts
Add postEngineContract with per-request timeout and sequential exponential-backoff retry; update fetchTokenBalances and fetchTokens to use it and avoid silently returning empty arrays on transport errors.
Token Precision Data Fetching in Container
src/containers/transferContainer.ts
Import fetchTokens; fetch engine token balances and token definitions in parallel with Promise.allSettled, derive tokenPrecision from the matched token definition's precision (preserving 0), and set tokenPrecision.
Engine Action Building with Precision Parameter
src/providers/hive-engine/hiveEngineActions.ts, src/utils/transactionOpsBuilder.ts
getEngineActionJSON and getEngineActionOpArray accept optional precision; TansferData adds precision?; buildTransferOpsArray formats ENGINE quantities with provided precision and forwards it into engine op construction.
Transfer Screen Precision Integration
src/screens/transfer/screen/transferScreen.tsx
Pass tokenPrecision into buildTransferOpsArray for Hive-auth operations; allow integer ENGINE amounts when precision is missing but require precision for fractional amounts.
Engine Precision Unit Tests
src/utils/transactionOpsBuilder.test.ts
Add tests validating precision truncation (including precision: 0) and an 8-decimal fallback when precision is undefined; assert precision propagation in the engine op tuple.

Wallet Empty State and Retry Delay

Layer / File(s) Summary
Wallet Query Retry Delay Cap
src/providers/queries/walletQueries/walletQueries.ts
Add retryDelay to useAssetsQuery to cap exponential backoff at 4000ms.
Wallet Error and Empty State Rendering
src/screens/wallet/screen/walletScreen.tsx, src/screens/wallet/screen/walletScreenStyles.ts
Render an error banner with localized message and a retry TouchableOpacity above the FlatList when the wallet query errors and is not fetching; add errorBanner and errorText styles.

Sequence Diagram(s)

sequenceDiagram
  participant TransferScreen
  participant TransferContainer
  participant postEngineContract
  participant HiveEngineAPI
  TransferScreen->>TransferContainer: request token balances/precision for symbol
  TransferContainer->>postEngineContract: fetchTokenBalances / fetchTokens
  postEngineContract->>HiveEngineAPI: POST /contract (with timeout & retries)
  HiveEngineAPI-->>postEngineContract: response or error
  postEngineContract-->>TransferContainer: token balances / token definitions or throw
  TransferContainer->>TransferScreen: tokenPrecision (including 0) and balances
  TransferScreen->>buildTransferOpsArray: include precision in op payload
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ecency/ecency-mobile#3224: Threads Hive-Engine token precision through TransferContainer/transferScreen into operation builders with adjusted ENGINE quantity formatting to match the provided precision.
  • ecency/ecency-mobile#3188: Modifies ENGINE transfer operation construction around getEngineActionOpArray/buildTransferOpsArray for multi-recipient ENGINE transfers.

Poem

🐰 I fetched each token, counted every dot,
Precision carried through each tiny spot.
Retries patrolled the noisy network trail,
Wallet now asks gently when things fail.
A rabbit's soft cheer for a safer send and plot.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(wallet): unblock Hive Engine token transfers and harden HE reads' accurately captures the two primary objectives: unblocking HE token transfers (by threading precision through the transfer flow) and hardening HE reads (by adding timeout/retry/error handling). The title reflects the main changes in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/he-token-transfer-precision

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed due to a network error.


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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/screens/transfer/screen/transferScreen.tsx (1)

754-768: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

This gate reintroduces the disabled-NEXT failure mode for unknown Engine precision.

The new builder path already handles precision === undefined by falling back to 8-decimal formatting, but this condition blocks the screen from ever reaching that path. If the token-definition lookup misses or degrades, the button stays disabled again instead of using the fallback you just added and tested. If the intent is only to block while precision is actively loading, this needs a dedicated loading flag rather than tokenPrecision !== undefined.

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/providers/hive-engine/hiveEngine.ts`:
- Around line 43-63: The metrics call still uses raw ecencyApi.post against
PATH_ENGINE_CONTRACTS (in fetchMetics()/fetchHiveEngineTokenBalances) and
therefore lacks the timeout/backoff behavior; replace that direct post with the
existing retry wrapper postEngineContract<T>() (or call it from
fetchMetics/fetchHiveEngineTokenBalances) so the metrics leg benefits from the
same timeout and exponential backoff, ensuring you remove the raw
ecencyApi.post(PATH_ENGINE_CONTRACTS, ...) usage and adapt the call/site to
await postEngineContract with the appropriate payload and type.
- Around line 79-83: The code is swallowing engine errors by normalizing result
to [] and catching all errors; in functions like fetchTokenBalances (and the
related fetchTokens block around lines 100-104) remove the result ?? []
normalization and remove the blanket .catch that returns [] so that
postEngineContract<TokenBalance[]>(data) is returned directly (or rethrow any
caught error) and failures propagate to callers instead of resolving as empty
arrays; ensure fetchTokens and fetchTokenBalances signatures still return the
promise from postEngineContract so callers can handle/retry on rejection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e0b15a39-1463-4a30-b9a3-b2bbbd53e473

📥 Commits

Reviewing files that changed from the base of the PR and between e7a5217 and d32fdbd.

📒 Files selected for processing (9)
  • src/containers/transferContainer.ts
  • src/providers/hive-engine/hiveEngine.ts
  • src/providers/hive-engine/hiveEngineActions.ts
  • src/providers/queries/walletQueries/walletQueries.ts
  • src/screens/transfer/screen/transferScreen.tsx
  • src/screens/wallet/screen/walletScreen.tsx
  • src/screens/wallet/screen/walletScreenStyles.ts
  • src/utils/transactionOpsBuilder.test.ts
  • src/utils/transactionOpsBuilder.ts

Comment thread src/providers/hive-engine/hiveEngine.ts
Comment thread src/providers/hive-engine/hiveEngine.ts Outdated
Comment on lines 79 to 83
return postEngineContract<TokenBalance[]>(data)
.then((result) => result ?? [])
.catch(() => {
return [];
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Stop converting Engine read failures into empty successes.

The result ?? [] normalization plus the blanket catches still make fetchTokenBalances() / fetchTokens() resolve successfully on proxy failures. That means query consumers never enter an error state: src/screens/assetsSelect/screen/assetsSelect.tsx uses fetchTokenBalances() directly as its query function, so an outage still looks like an empty wallet, and fetchTokens() resolving [] leaves transfer precision unset instead of surfacing a retriable failure.

Also applies to: 100-104

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/hive-engine/hiveEngine.ts` around lines 79 - 83, The code is
swallowing engine errors by normalizing result to [] and catching all errors; in
functions like fetchTokenBalances (and the related fetchTokens block around
lines 100-104) remove the result ?? [] normalization and remove the blanket
.catch that returns [] so that postEngineContract<TokenBalance[]>(data) is
returned directly (or rethrow any caught error) and failures propagate to
callers instead of resolving as empty arrays; ensure fetchTokens and
fetchTokenBalances signatures still return the promise from postEngineContract
so callers can handle/retry on rejection.

- transferScreen: allow whole-number Engine transfers through when token
  precision is unknown (precision-safe), so a degraded token-metadata lookup no
  longer dead-buttons NEXT; fractional amounts still wait for precision.
- hiveEngine: stop swallowing engine read failures into [] — fetchTokenBalances/
  fetchTokens now reject on a real transport failure (after retries) and resolve
  [] only for a genuine empty result, so the wallet query and assetsSelect can
  retry/surface errors instead of showing an outage as an empty wallet.
- transferContainer: fetch balances and token metadata with allSettled so one
  leg failing no longer discards the other.
- walletScreen: show the load-failure Retry as a banner above the list so a
  failed refresh of an already-loaded (stale) wallet is also surfaced, not just
  the first-load empty case.
- hiveEngine: remove dead fetchHiveEngineTokenBalances/fetchMetics/
  fetchUnclaimedRewards (no callers) and now-unused imports.
@feruzm

feruzm commented Jun 13, 2026

Copy link
Copy Markdown
Member Author

Addressed the review feedback in 3f24933:

  • NEXT gate blocking on unknown precision (CodeRabbit): the precision gate now only applies to fractional Engine amounts. A whole-number amount is precision-safe at any precision, so it's allowed through even if the token-metadata lookup degrades — the common case no longer dead-buttons NEXT, while fractional amounts still wait for precision so an over-precise quantity can't reach the sidechain.
  • Engine reads swallowing failures into [] (CodeRabbit): fetchTokenBalances/fetchTokens now reject on a real transport failure (after the retries) and resolve [] only for a genuine empty result, so the wallet query and assetsSelect can retry/surface the error instead of treating an outage as an empty wallet. The transfer balance fetch uses Promise.allSettled so one leg failing doesn't discard the other.
  • Dead fetchHiveEngineTokenBalances/fetchMetics (CodeRabbit): removed — they had no callers (so they weren't actually aborting any wallet load), along with their now-unused imports.
  • Error UI hidden when stale data is cached (Greptile): the load-failure Retry is now a banner above the list rather than ListEmptyComponent, so a failed refresh of an already-loaded wallet is surfaced too, not just the first-load empty case.

Lint/types clean; engine precision threading unit tests still green.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/screens/transfer/screen/transferScreen.tsx`:
- Around line 759-764: The check using Number.isInteger(amount) is ineffective
because amount is a string; update the integer gate used with
isEngineToken/tokenPrecision to test the numeric value instead (e.g. replace
Number.isInteger(amount) with Number.isInteger(Number(amount)) &&
!Number.isNaN(Number(amount)) or an equivalent string-integer test like
/^\s*\d+(\.0+)?\s*$/) so that whole-number strings like "1" allow
unknown-precision Engine transfers to proceed.

In `@src/screens/wallet/screen/walletScreen.tsx`:
- Around line 257-259: The retry button is using a non-existent locale id
'alert.try_again'; update the intl call to use the existing key by replacing
intl.formatMessage({ id: 'alert.try_again' }) with intl.formatMessage({ id:
'try_again' }) in the Wallet screen where the retry Text (styled by
styles.headerActionButtonText) is rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 43c9082d-e163-4f6e-8d77-d4f56cb8b974

📥 Commits

Reviewing files that changed from the base of the PR and between d32fdbd and 3f24933.

📒 Files selected for processing (5)
  • src/containers/transferContainer.ts
  • src/providers/hive-engine/hiveEngine.ts
  • src/screens/transfer/screen/transferScreen.tsx
  • src/screens/wallet/screen/walletScreen.tsx
  • src/screens/wallet/screen/walletScreenStyles.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/containers/transferContainer.ts

Comment thread src/screens/transfer/screen/transferScreen.tsx Outdated
Comment on lines +257 to +259
<Text style={styles.headerActionButtonText}>
{intl.formatMessage({ id: 'alert.try_again' })}
</Text>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use an existing locale id for the retry button label.

On Line 258, intl.formatMessage({ id: 'alert.try_again' }) does not match the provided
locale structure (which includes alert.wallet_refresh_failed and a separate try_again key).
This can render fallback text instead of the translated label.

Suggested fix
-            {intl.formatMessage({ id: 'alert.try_again' })}
+            {intl.formatMessage({ id: 'try_again' })}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Text style={styles.headerActionButtonText}>
{intl.formatMessage({ id: 'alert.try_again' })}
</Text>
<Text style={styles.headerActionButtonText}>
{intl.formatMessage({ id: 'try_again' })}
</Text>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/screens/wallet/screen/walletScreen.tsx` around lines 257 - 259, The retry
button is using a non-existent locale id 'alert.try_again'; update the intl call
to use the existing key by replacing intl.formatMessage({ id: 'alert.try_again'
}) with intl.formatMessage({ id: 'try_again' }) in the Wallet screen where the
retry Text (styled by styles.headerActionButtonText) is rendered.

- transferScreen: amount is string state, so Number.isInteger(amount) was
  always false and the whole-number degraded-mode escape never activated
  (engine integer transfers stayed blocked when precision was unknown). Coerce
  with Number(amount).
- walletScreen: alert.try_again does not exist (try_again lives under another
  namespace); use the existing alert.something_wrong_reload so the retry label
  renders translated instead of a raw id.
@feruzm

feruzm commented Jun 13, 2026

Copy link
Copy Markdown
Member Author

Both follow-up findings were real — fixed in 452774b:

  • Number.isInteger(amount) always false (CodeRabbit + Greptile): amount is string state, so the whole-number degraded-mode escape never activated — engine integer transfers stayed blocked when precision was unknown, defeating the intended fallback. Now Number.isInteger(Number(amount)). (The existing amount > 0 clause still blocks empty/"0", so coercing ""0 is harmless.)
  • alert.try_again doesn't exist (CodeRabbit): try_again lives under ai_assist, not alert, so the label would render a raw id. Switched to the existing alert.something_wrong_reload. (Note: the IntlProvider loads only the active locale with no en-US fallback, so a new en-US-only key wasn't an option — reused an existing key present in all 39 locales.)

One deliberate deviation: I kept result ?? [] on fetchTokenBalances/fetchTokens. A 200 response with no result is a genuine empty wallet (new accounts) and must stay []; only transport failures now reject (the blanket .catch is gone). Dropping ?? [] would make callers iterate over undefined.

@feruzm feruzm merged commit 4533ce1 into development Jun 13, 2026
10 of 12 checks passed
@feruzm feruzm deleted the fix/he-token-transfer-precision branch June 13, 2026 07:45
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