fix(frontend): humanize post-sign fee guard errors for users (#371) #884

Merged
PlasticDigits merged 2 commits from fix/371-insufficient-gas-user-copy into main 2026-06-12 11:39:40 +00:00
PlasticDigits commented 2026-06-12 11:09:31 +00:00 (Migrated from gitlab.com)

Summary

Fixes #371: when the post-sign fee/gas guard blocks a transaction (e.g. Keplr returns a very low gas limit), the UI no longer shows developer diagnostics (GitLab issue refs, uluna/gas values, npm ci CLI hints, Station-specific steps).

  • Adds EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE retail copy in extensionSignedFeeGuard.ts
  • tryHumanizeTerraTxMessage maps guard failures to that message (was passthrough)
  • broadcastTerraExecuteContracts no longer bypasses humanization for guard errors; full diagnostics remain in console.error
  • Docs/skills updated (docs/frontend.md, AGENTS_FRONTEND_USER_ERRORS.md, AGENTS_TERRACLASSIC_GAS.md)

Acceptance checklist

Criterion Verification Result
UI shows short plain-language fee mismatch message, not developer copy bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:unit -- src/utils/__tests__/humanizeTerraTxError.test.ts src/utils/__tests__/humanizeUserFacingError.test.ts PASS
No GitLab issue numbers in user-facing string Same tests + terraBroadcast.test.ts guard case PASS
No raw uluna/gas values in user-facing string humanizeTerraTxError.test.ts extension signed fee undershoot case PASS
No shell CLI instructions in user-facing string Same PASS
No Station-specific troubleshooting in user-facing string Same PASS
Broadcast path humanizes guard errors src/services/terraclassic/__tests__/terraBroadcast.test.ts PASS
Guard diagnostics still available for developers terraBroadcast.ts logs raw error via console.error before handleBroadcastError PASS
Manual repro on Swap + Keplr low gas (LocalTerra) Requires LocalTerra + Keplr manual QA SKIP

Third-party verification

  1. Check out branch fix/371-insufficient-gas-user-copy
  2. Run unit tests:
    bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:unit -- \
      src/utils/__tests__/humanizeTerraTxError.test.ts \
      src/utils/__tests__/humanizeUserFacingError.test.ts \
      src/services/terraclassic/__tests__/terraBroadcast.test.ts
    
  3. Optional manual: make setup-cloud-localterra && make dev, connect Keplr, set very low gas in Keplr advanced settings, submit swap — alert should read: "Transaction fee mismatch. Please reconnect your wallet and try again. If the problem persists, contact support." (no #127, uluna, or npm ci).

Blockers

  • Manual LocalTerra + Keplr repro not run in this session (unit/integration coverage PASS).

Related: #371 (issue stays open until merge).


Note

Low Risk
Copy and error-handling funnel only; post-sign guard logic and logging are unchanged.

Overview
Post-sign fee/gas guard failures no longer reach the UI as developer diagnostics (GitLab refs, raw uluna/gas, npm ci, Station steps). A shared retail string EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE is added, and tryHumanizeTerraTxMessage maps guard errors to that copy instead of passing the raw message through.

broadcastTerraExecuteContracts drops the special-case that skipped humanization for guard errors; failures still log the full error via console.error before handleBroadcastError runs. Unit tests and docs/skills (docs/frontend.md, AGENTS_FRONTEND_USER_ERRORS.md, AGENTS_TERRACLASSIC_GAS.md) document the split between logs and UI.

Reviewed by Cursor Bugbot for commit b066bdb330. Bugbot is set up for automated code reviews on this repo. Configure here.

## Summary Fixes [#371](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/371): when the post-sign fee/gas guard blocks a transaction (e.g. Keplr returns a very low gas limit), the UI no longer shows developer diagnostics (GitLab issue refs, `uluna`/gas values, `npm ci` CLI hints, Station-specific steps). - Adds **`EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE`** retail copy in `extensionSignedFeeGuard.ts` - **`tryHumanizeTerraTxMessage`** maps guard failures to that message (was passthrough) - **`broadcastTerraExecuteContracts`** no longer bypasses humanization for guard errors; full diagnostics remain in `console.error` - Docs/skills updated (`docs/frontend.md`, `AGENTS_FRONTEND_USER_ERRORS.md`, `AGENTS_TERRACLASSIC_GAS.md`) ## Acceptance checklist | Criterion | Verification | Result | |-----------|--------------|--------| | UI shows short plain-language fee mismatch message, not developer copy | `bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:unit -- src/utils/__tests__/humanizeTerraTxError.test.ts src/utils/__tests__/humanizeUserFacingError.test.ts` | PASS | | No GitLab issue numbers in user-facing string | Same tests + `terraBroadcast.test.ts` guard case | PASS | | No raw uluna/gas values in user-facing string | `humanizeTerraTxError.test.ts` extension signed fee undershoot case | PASS | | No shell CLI instructions in user-facing string | Same | PASS | | No Station-specific troubleshooting in user-facing string | Same | PASS | | Broadcast path humanizes guard errors | `src/services/terraclassic/__tests__/terraBroadcast.test.ts` | PASS | | Guard diagnostics still available for developers | `terraBroadcast.ts` logs raw error via `console.error` before `handleBroadcastError` | PASS | | Manual repro on Swap + Keplr low gas (LocalTerra) | Requires LocalTerra + Keplr manual QA | SKIP | ## Third-party verification 1. Check out branch `fix/371-insufficient-gas-user-copy` 2. Run unit tests: ```bash bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:unit -- \ src/utils/__tests__/humanizeTerraTxError.test.ts \ src/utils/__tests__/humanizeUserFacingError.test.ts \ src/services/terraclassic/__tests__/terraBroadcast.test.ts ``` 3. Optional manual: `make setup-cloud-localterra && make dev`, connect Keplr, set very low gas in Keplr advanced settings, submit swap — alert should read: *"Transaction fee mismatch. Please reconnect your wallet and try again. If the problem persists, contact support."* (no `#127`, `uluna`, or `npm ci`). ## Blockers - Manual LocalTerra + Keplr repro not run in this session (unit/integration coverage PASS). Related: #371 (issue stays open until merge). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Copy and error-handling funnel only; post-sign guard logic and logging are unchanged. > > **Overview** > Post-sign **fee/gas guard** failures no longer reach the UI as developer diagnostics (GitLab refs, raw `uluna`/gas, `npm ci`, Station steps). A shared retail string **`EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE`** is added, and **`tryHumanizeTerraTxMessage`** maps guard errors to that copy instead of passing the raw message through. > > **`broadcastTerraExecuteContracts`** drops the special-case that skipped humanization for guard errors; failures still log the full error via **`console.error`** before **`handleBroadcastError`** runs. Unit tests and docs/skills (**`docs/frontend.md`**, **`AGENTS_FRONTEND_USER_ERRORS.md`**, **`AGENTS_TERRACLASSIC_GAS.md`**) document the split between logs and UI. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b066bdb3307d7fdd10a7052752d6bda447d30c2a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
ghost1 commented 2026-06-12 11:09:39 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-12 11:09:47 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-12 11:11:14 +00:00 (Migrated from gitlab.com)

Security review — MR !884

Commit reviewed: b63edb011c77d3727672826b8b7ce8aaa2fb8f1b

Scope: Error-humanization path for post-sign fee/gas guard failures (extensionSignedFeeGuard.ts, humanizeTerraTxError.ts, terraBroadcast.ts) plus tests and agent/docs updates.

Method: Traced attacker-controlled inputs (wallet extension throws, LCD rawLog, indexer transport strings) through handleBroadcastError → tryHumanizeTerraTxMessage → humanizeUserFacingError → TxResultAlert (React text node, no dangerouslySetInnerHTML). Verified fee-guard enforcement remains in the cosmes patch / extensionSignedFeeGuard.ts (unchanged); this MR only alters UI copy routing.

Outcome: FINDINGS: 0 medium+

Notes:

  • Change replaces developer diagnostics (issue refs, uluna/gas values, CLI hints) with static retail copy — reduces information disclosure to end users; full throws still logged via console.error in terraBroadcast.ts.
  • Prefix match on EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX is preceded by higher-priority classifiers (Unauthorized, blacklist, paused, etc.); no authz or guard-bypass regression identified.
  • No new dependencies, secrets, SSRF/XSS/injection sinks, or permission-boundary changes in the diff.

Inline threads: none (no medium+ findings).

Security review: no medium+ findings on this diff.

## Security review — MR !884 **Commit reviewed:** `b63edb011c77d3727672826b8b7ce8aaa2fb8f1b` **Scope:** Error-humanization path for post-sign fee/gas guard failures (`extensionSignedFeeGuard.ts`, `humanizeTerraTxError.ts`, `terraBroadcast.ts`) plus tests and agent/docs updates. **Method:** Traced attacker-controlled inputs (wallet extension throws, LCD `rawLog`, indexer transport strings) through `handleBroadcastError` → `tryHumanizeTerraTxMessage` → `humanizeUserFacingError` → `TxResultAlert` (React text node, no `dangerouslySetInnerHTML`). Verified fee-guard enforcement remains in the cosmes patch / `extensionSignedFeeGuard.ts` (unchanged); this MR only alters UI copy routing. **Outcome:** `FINDINGS: 0` medium+ **Notes:** - Change replaces developer diagnostics (issue refs, `uluna`/gas values, CLI hints) with static retail copy — reduces information disclosure to end users; full throws still logged via `console.error` in `terraBroadcast.ts`. - Prefix match on `EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX` is preceded by higher-priority classifiers (`Unauthorized`, blacklist, paused, etc.); no authz or guard-bypass regression identified. - No new dependencies, secrets, SSRF/XSS/injection sinks, or permission-boundary changes in the diff. **Inline threads:** none (no medium+ findings). Security review: no medium+ findings on this diff.
PlasticDigits commented 2026-06-12 11:17:36 +00:00 (Migrated from gitlab.com)

added 55 commits

  • b63edb01...0cf04e53 - 54 commits from branch main
  • b066bdb3 - Merge branch 'main' into fix/371-insufficient-gas-user-copy

Compare with previous version

added 55 commits <ul><li>b63edb01...0cf04e53 - 54 commits from branch <code>main</code></li><li>b066bdb3 - Merge branch &#39;main&#39; into fix/371-insufficient-gas-user-copy</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/166/diffs?diff_id=1848891937&start_sha=b63edb011c77d3727672826b8b7ce8aaa2fb8f1b)
PlasticDigits commented 2026-06-12 11:17:43 +00:00 (Migrated from gitlab.com)

Resolved merge conflicts with main:

  • terraBroadcast.ts: kept main's broadcast-recovery imports (pollTxUntilRecoveryDeadline, split sign/broadcast helpers) while preserving #371 behavior — fee-guard errors still flow through handleBroadcastError / tryHumanizeTerraTxMessage (removed the old EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX bypass from main).
  • AGENTS_TERRACLASSIC_GAS.md: combined main's cosmes patch SHA-256 guard (#367) with #371's retail user-message note for extensionSignedFeeGuard.ts.

Unit tests for humanization + terraBroadcast pass locally (47 tests).

Resolved merge conflicts with `main`: - **`terraBroadcast.ts`**: kept main's broadcast-recovery imports (`pollTxUntilRecoveryDeadline`, split sign/broadcast helpers) while preserving #371 behavior — fee-guard errors still flow through `handleBroadcastError` / `tryHumanizeTerraTxMessage` (removed the old `EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX` bypass from main). - **`AGENTS_TERRACLASSIC_GAS.md`**: combined main's cosmes patch SHA-256 guard (#367) with #371's retail user-message note for `extensionSignedFeeGuard.ts`. Unit tests for humanization + `terraBroadcast` pass locally (47 tests).
ghost1 commented 2026-06-12 11:17:49 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-12 11:19:46 +00:00 (Migrated from gitlab.com)

Security review — MR !884

Commit reviewed: b066bdb3307d7fdd10a7052752d6bda447d30c2a

Scope: Error-humanization path for post-sign fee/gas guard failures (extensionSignedFeeGuard.ts, humanizeTerraTxError.ts, terraBroadcast.ts) plus unit tests and agent/docs updates. Merge from main preserved broadcast-recovery plumbing; this diff only removes the fee-guard humanization bypass and routes guard throws to static retail copy.

Method: Traced attacker-controlled inputs (malicious/compromised wallet extension throws, LCD rawLog, indexer transport strings) through handleBroadcastError → tryHumanizeTerraTxMessage → humanizeUserFacingError / toastErrorMessage → TxResultAlert (React text node; no dangerouslySetInnerHTML). Confirmed post-sign fee/gas enforcement remains in the cosmes patch / extensionSignedFeeGuard.ts (guard logic unchanged). Verified prefix classification is preceded by higher-priority on-chain classifiers (Unauthorized, blacklist, paused, spread, etc.).

Outcome: FINDINGS: 0 medium+

Notes:

  • Change reduces user-facing information disclosure (issue refs, raw uluna/gas, CLI hints) while retaining full diagnostics in console.error — security-positive for retail users.
  • inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX) only swaps display copy; it does not weaken signing, broadcast, or recovery controls. A crafted LCD/rawLog containing the fixed prefix could mis-label an unrelated failure as “fee mismatch” (UX only; no fund-loss path).
  • No new dependencies, secrets, SSRF/XSS/injection sinks, authz bypasses, or permission-boundary changes in the MR diff.

Inline threads: none (no medium+ findings).

Security review: no medium+ findings on this diff.

## Security review — MR !884 **Commit reviewed:** `b066bdb3307d7fdd10a7052752d6bda447d30c2a` **Scope:** Error-humanization path for post-sign fee/gas guard failures (`extensionSignedFeeGuard.ts`, `humanizeTerraTxError.ts`, `terraBroadcast.ts`) plus unit tests and agent/docs updates. Merge from `main` preserved broadcast-recovery plumbing; this diff only removes the fee-guard humanization bypass and routes guard throws to static retail copy. **Method:** Traced attacker-controlled inputs (malicious/compromised wallet extension throws, LCD `rawLog`, indexer transport strings) through `handleBroadcastError` → `tryHumanizeTerraTxMessage` → `humanizeUserFacingError` / `toastErrorMessage` → `TxResultAlert` (React text node; no `dangerouslySetInnerHTML`). Confirmed post-sign fee/gas enforcement remains in the cosmes patch / `extensionSignedFeeGuard.ts` (guard logic unchanged). Verified prefix classification is preceded by higher-priority on-chain classifiers (`Unauthorized`, blacklist, paused, spread, etc.). **Outcome:** `FINDINGS: 0` medium+ **Notes:** - Change reduces user-facing information disclosure (issue refs, raw `uluna`/gas, CLI hints) while retaining full diagnostics in `console.error` — security-positive for retail users. - `inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX)` only swaps display copy; it does not weaken signing, broadcast, or recovery controls. A crafted LCD/`rawLog` containing the fixed prefix could mis-label an unrelated failure as “fee mismatch” (UX only; no fund-loss path). - No new dependencies, secrets, SSRF/XSS/injection sinks, authz bypasses, or permission-boundary changes in the MR diff. **Inline threads:** none (no medium+ findings). Security review: no medium+ findings on this diff.
PlasticDigits commented 2026-06-12 11:39:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 809d2b9842

mentioned in commit 809d2b984246290b600cae2a9805425aae413434
PlasticDigits (Migrated from gitlab.com) merged commit 809d2b9842 into main 2026-06-12 11:39:40 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic!884
No description provided.