fix: [Mobile] Perps KEYRING_LOCKED error in HyperLiquidWalletService#30077
Conversation
Constraint: HyperLiquid SDK preserves the original KEYRING_LOCKED error in cause while provider catches saw the wrapper message. Rejected: Check only ensureError(error).message | misses AbstractWalletError-wrapped signing failures. Confidence: high Scope-risk: narrow Directive: Keep perps signing setup catches using isKeyringLockedError so wrapped wallet failures stay retryable and out of generic Sentry paths. Tested: yarn lint && NODE_OPTIONS='--max-old-space-size=8192' yarn lint:tsc && yarn format:check Tested: yarn jest app/controllers/perps/utils/errorUtils.test.ts app/controllers/perps/providers/HyperLiquidProvider.test.ts --no-coverage Tested: yarn coverage:analyze --files app/controllers/perps/utils/errorUtils.ts app/controllers/perps/providers/HyperLiquidProvider.ts Tested: bash scripts/perps/agentic/validate-recipe.sh .task/fix/tat-3176-0512-222920/artifacts/ --skip-manual Not-tested: Android device reproduction; fix is shared TypeScript and was validated with unit/state checks.
Constraint: Self-review found wrapped builder-fee KEYRING_LOCKED coverage inside a skipped describe. Rejected: Keep private-method test under skipped cache describe | Jest would not execute the regression coverage. Confidence: high Scope-risk: narrow Directive: Keep wrapped keyring-lock provider coverage on executed public paths. Tested: yarn jest app/controllers/perps/providers/HyperLiquidProvider.test.ts --no-coverage Tested: yarn lint && NODE_OPTIONS='--max-old-space-size=8192' yarn lint:tsc && yarn format:check Tested: bash scripts/perps/agentic/validate-recipe.sh .task/fix/tat-3176-0512-222920/artifacts/ --skip-manual Not-tested: GitHub PR publication; branch remains local for gateway publishing.
Document why the keyring-locked catches inspect HyperLiquid SDK cause chains, so future edits do not reintroduce failure-cache or Sentry handling for retryable locked-keyring setup. Constraint: HyperLiquid wraps wallet signing failures while preserving KEYRING_LOCKED in Error.cause Rejected: replacing this with a preflight-only gate | races and SDK wrapping still require catch-time classification Confidence: high Scope-risk: narrow Directive: Keep cause-chain classification on signing setup catches unless signing errors are normalized below the SDK boundary Tested: git diff --check -- app/controllers/perps/providers/HyperLiquidProvider.ts .task/fix/tat-3176-0512-222920/artifacts/pr-description.md Not-tested: Jest not rerun; comment-only code change
Clarify the Perps error utility module scope after adding a perps-specific keyring classification helper. Constraint: Self-review requested the smallest possible documentation fix in the flagged file Rejected: moving isKeyringLockedError elsewhere | broader refactor is unnecessary for a header mismatch Confidence: high Scope-risk: narrow Directive: Keep the module header aligned with both generic helpers and perps-specific classifiers Tested: yarn jest app/controllers/perps/utils/errorUtils.test.ts --no-coverage; yarn lint && NODE_OPTIONS='--max-old-space-size=8192' yarn lint:tsc && yarn format:check; bash scripts/perps/agentic/validate-recipe.sh .task/fix/tat-3176-0512-222920/artifacts/ --skip-manual Not-tested: No manual device testing; comment-only fix
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Worker reportTAT-3176 ReportSummaryFixed wrapped Root cause
Reproduction commitMarker commit: Metro excerpt: Changes
Test plan
Feature: Wrapped KEYRING_LOCKED handling
Scenario: wrapped keyring lock is retried later
Given HyperLiquid setup receives an SDK error with cause.message KEYRING_LOCKED
When the provider classifies the setup error
Then the retry-later branch is used
And the generic Sentry failure branch is not usedEvidence
TicketTAT-3176: https://consensyssoftware.atlassian.net/browse/TAT-3176 Self-Review Fixes
Workflow Diagram (Mermaid)flowchart TD Recipe workflow diagramflowchart TD
ac1["ac1-assert-wrapped-keyring-locked"]
done["done"]
ac1 --> done
|
Retrigger CI after unrelated iOS confirmations smoke failures on PR #30077; branch-local lint, typecheck, format, and recipe checks pass with no code changes needed. Constraint: CI-FIX.md requires commit and push after triage; failed jobs are outside the Perps controller diff Rejected: code change in confirmations smoke flow | failures are unrelated to TAT-3176 changed files and branch-relevant checks passed Confidence: medium Scope-risk: narrow Directive: Re-evaluate if the same iOS smoke shards fail again after rerun Tested: yarn lint && NODE_OPTIONS='--max-old-space-size=8192' yarn lint:tsc && yarn format:check; bash scripts/perps/agentic/validate-recipe.sh .task/fix/tat-3176-0512-222920/artifacts/ --skip-manual Not-tested: iOS E2E smoke not rerun locally
Worker report
|
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Tag rationale:
No changes to UI components, navigation, shared infrastructure, or other controllers. Risk is medium because the fix touches core trading flow error handling in the perps provider. Performance Test Selection: |
|



Description
Fixes Perps
KEYRING_LOCKEDhandling when HyperLiquid wraps wallet signing failures. The provider now walks theError.causechain so wrapped keyring-lock errors use the retry-later path instead of being reported as generic setup failures.Follow-up considered: preflight-gating Perps signing setup until the keyring is unlocked/available. That may avoid entering SDK signing paths that cannot succeed, but it changes initialization timing and retry behavior. This PR keeps the existing retry-later flow and fixes the concrete error-boundary bug: HyperLiquid SDK wraps
KEYRING_LOCKEDas the errorcause, so provider catches must inspect the cause chain. We will monitor Sentry after release; if locked signing events remain meaningful, the next step is a keyring-availability gate before signing-dependent setup.Changelog
CHANGELOG entry: Fixed a Perps setup error that could report locked-keyring retries as failures
Related issues
Fixes: TAT-3176
Manual testing steps
Screenshots/Recordings
No visual evidence selected for publication.
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Validation Recipe
recipe.json
{ "pr": "", "title": "TAT-3176 wrapped KEYRING_LOCKED classifier", "jira": "TAT-3176", "acceptance_criteria": [ "Wrapped KEYRING_LOCKED errors whose cause.message is KEYRING_LOCKED are classified as keyring-locked retry-later errors instead of falling through to generic logger.error/Sentry, failed AccountSetup analytics, or failure caches." ], "validate": { "workflow": { "entry": "ac1-assert-wrapped-keyring-locked", "nodes": { "ac1-assert-wrapped-keyring-locked": { "action": "eval_sync", "expression": "(function(){var mods=globalThis.__r.getModules();var moduleId=null;mods.forEach(function(v,k){if(v&&v.verboseName==='app/controllers/perps/utils/errorUtils.ts'){moduleId=k;}});var errorUtils=globalThis.__r(moduleId);var cause=new Error('KEYRING_LOCKED');var wrapped=new Error('Failed to sign typed data with viem wallet');wrapped.cause=cause;return JSON.stringify({moduleFound:moduleId!==null,classified:errorUtils.isKeyringLockedError(wrapped)});})()", "assert": { "operator": "eq", "field": "classified", "value": true }, "next": "done" }, "done": { "action": "end", "status": "pass" } } } } }Recipe Workflow
workflow.mmd
Note
Medium Risk
Changes error classification for keyring-locked signing failures, affecting retry/caching and whether failures get logged/reported; mistakes here could cause repeated prompts or suppressed retries in trading setup.
Overview
Prevents HyperLiquid SDK-wrapped signing failures from being treated as generic setup errors by introducing
isKeyringLockedError()(walks theError.causechain) and using it in HyperLiquid unified account enablement, builder-fee approval, and referral setup.Adds test coverage ensuring wrapped
KEYRING_LOCKEDerrors do not populate failure caches (TradingReadinessCache/PerpsSigningCache) or trigger error logging, while still releasing in-flight locks and allowing the order/setup flow to proceed.Reviewed by Cursor Bugbot for commit 4fdd74f. Bugbot is set up for automated code reviews on this repo. Configure here.