Skip to content

Stop daemon broadcast events from rejecting pending wallet_ui requests - #3012

Merged
Starttoaster merged 1 commit into
Chia-Network:mainfrom
jlobue10:fix/daemon-socket-bigint-parse
Aug 19, 2026
Merged

Stop daemon broadcast events from rejecting pending wallet_ui requests#3012
Starttoaster merged 1 commit into
Chia-Network:mainfrom
jlobue10:fix/daemon-socket-bigint-parse

Conversation

@jlobue10

@jlobue10 jlobue10 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Accepting an offer in the Offers tab can fail with an error dialog like:

Error: Cannot convert 1.7656183690123726 to a BigInt

The offer is never sent to the wallet (no spend is pushed). On farms with slower plot lookups this happens on nearly every accept attempt.

Root cause

packages/gui/src/electron/api/sendCommand.ts registers its daemon socket as service wallet_ui, so the daemon forwards every broadcast event to it (farming_info, get_fee_estimate, get_connections, …) in addition to RPC responses.

Its handleMessage parsed every incoming frame with JSONBig({ useNativeBigInt: true }) before checking request_id. json-bigint's parser passes any number literal longer than 15 characters to BigInt() — even when it contains a decimal point ([json-bigint lib/parse.js, the string.length > 15 branch]). A harvester farming_info lookup time such as 1.7656183690123726 therefore throws SyntaxError: Cannot convert 1.7656183690123726 to a BigInt, and the catch rejected whichever request happened to be pending.

The user-visible failure chain: Offers-tab accept → take_offer intercepted by the main-process confirmation layer (onSend in main.tsx) → parseCommandDisplaygetOfferSummarysendCommand('get_offer_summary') → an unrelated broadcast with a long-precision float lands during the round trip → the pending request is rejected → onSend throws → the bridge synthesizes an error response → the renderer shows the BigInt error and take_offer is never transmitted.

Verified against a live mainnet daemon: a 30-second passive wallet_ui listener observed multiple poison frames (chia_harvester farming_info with time floats of 1.2–1.8 s, chia_full_node get_fee_estimate, chia_farmer get_connections float timestamps), so the race window is hit almost every time on affected setups.

The same flaw exists in connect()'s register_service handler, where a poison frame during the handshake tears down the socket.

Fix

Parse incoming frames with the native-bigint parser first, fall back to the BigNumber-based parser (json-bigint's default, which handles long-precision floats fine) when it throws, and ignore frames that are not valid JSON at all instead of rejecting the pending request. Matched responses keep their existing native-bigint behavior for large integers.

Tests

Four new regression tests in sendCommand.test.ts (all four fail against the previous implementation):

  • ignores a farming_info-style broadcast with a >15-char float while a command is pending
  • resolves a matched response that itself contains long-precision floats
  • ignores frames that are not valid JSON while a command is pending
  • ignores poison broadcasts during register_service

Existing tests, including "parses unsafe integer response values as native bigints", still pass (10/10).

🤖 Generated with Claude Code

https://claude.ai/code/session_016jfMfuGTvCmMyL7EM92dmj


Note

Medium Risk
Changes core Electron daemon IPC parsing for all wallet commands; behavior is intentional but any mismatch in request_id handling or fallback parsing could affect RPC reliability.

Overview
Fixes intermittent offer accept failures (Cannot convert … to a BigInt) when unrelated daemon broadcast frames arrive while a wallet_ui command is in flight.

Incoming WebSocket frames are parsed via a new parseIncomingMessage: try native-bigint json-bigint first, fall back to the default BigNumber parser when long-precision floats trip BigInt(), and drop non-JSON frames instead of rejecting the pending RPC. The same logic applies during register_service.

Four regression tests cover poison broadcasts, matched responses with long floats, invalid JSON, and registration-time broadcasts.

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

The main-process sendCommand socket registers as service wallet_ui, so
the daemon forwards every broadcast event to it (farming_info,
get_fee_estimate, get_connections, ...). Its message handler parsed
each frame with json-bigint's useNativeBigInt parser before checking
request_id, and that parser passes any number literal longer than 15
characters to BigInt() even when it contains a decimal point. A
harvester farming_info lookup time such as 1.7656183690123726 therefore
threw "Cannot convert 1.7656183690123726 to a BigInt", and the catch
block rejected whichever request happened to be pending.

Because get_offer_summary runs inside the take_offer confirmation flow,
any farm with slow-enough plot lookups hits this race on nearly every
offer accept: the user sees the BigInt error dialog and the offer
command is never sent to the wallet.

Parse incoming frames with the native-bigint parser first, fall back to
the BigNumber parser for frames carrying long-precision floats, and
ignore frames that are not valid JSON instead of rejecting the pending
request. Matched responses keep their existing native-bigint behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jfMfuGTvCmMyL7EM92dmj
@jlobue10
jlobue10 requested a review from a team as a code owner August 2, 2026 15:23
@emlowe

emlowe commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

close and reopen to get new CI run with updated packages

@emlowe emlowe closed this Aug 19, 2026
@emlowe emlowe reopened this Aug 19, 2026
@Starttoaster
Starttoaster merged commit b89bea1 into Chia-Network:main Aug 19, 2026
16 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants