Skip to content

feat(ts-p2p): add typed decoder for the two-layer JSON wire format#251

Open
zcoolz wants to merge 3 commits into
bsv-blockchain:mainfrom
zcoolz:ts-p2p-message-decoder
Open

feat(ts-p2p): add typed decoder for the two-layer JSON wire format#251
zcoolz wants to merge 3 commits into
bsv-blockchain:mainfrom
zcoolz:ts-p2p-message-decoder

Conversation

@zcoolz

@zcoolz zcoolz commented Jun 30, 2026

Copy link
Copy Markdown

What

Adds an optional, typed decoder for the two-layer JSON wire format Teranode broadcasts over GossipSub, plus typed interfaces for each topic payload.

Today TeranodeListener callbacks receive raw Uint8Array, so every consumer has to hand-decode the envelope and inner payload. This adds:

  • src/messages.ts: typed interfaces (MessageEnvelope, BlockMessage, SubtreeMessage, RejectedTxMessage, NodeStatusMessage, FeePolicy) and two helpers, decodeMessage() and tryDecodeMessage(). No new dependencies (base64 is implemented inline, so it runs in any JS runtime).
  • An opt-in decodeMessages?: boolean flag. When set, callbacks receive a typed DecodedMessage { sender, payload } instead of raw bytes; frames that are not valid JSON (e.g. libp2p control frames) are skipped.

Why

The format is two layers: a message-bus envelope { name, data: base64 } wrapping a topic-specific JSON payload. Decoding it correctly, including the PascalCase vs snake_case difference between block/subtree/rejected-tx and node_status, is non-obvious. Shipping the decoder saves every downstream user from reimplementing it.

Compatibility

Fully backward compatible. decodeMessages defaults to false, so existing callbacks keep receiving Uint8Array unchanged.

Verification

Payload interfaces verified field-for-field against the current teranode/services/p2p/message_types.go (including the recently added fee_policy). The added and changed files compile cleanly under the package's tsc config. README and CHANGELOG updated.

Closes #250

Adds optional, typed decoding of the two-layer JSON wire format Teranode broadcasts over GossipSub. New decodeMessage()/tryDecodeMessage() helpers and topic payload interfaces (BlockMessage, SubtreeMessage, RejectedTxMessage, NodeStatusMessage, FeePolicy). Opt in via decodeMessages: true; callbacks then receive a typed DecodedMessage instead of raw bytes. Backward compatible. Payload interfaces verified against teranode/services/p2p/message_types.go.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zcoolz and others added 2 commits June 30, 2026 02:42
Resolves the SonarCloud S8786 super-linear-regex finding on messages.ts. Replaces the trailing-padding regex with a plain trailing-'=' scan: provably linear and behavior-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire up the package's first test harness (ESM ts-jest, mirroring the overlays/topics config) and cover decodeMessage/tryDecodeMessage: PascalCase block and snake_case node_status payloads, nested fee_policy, multi-byte UTF-8, all base64 padding lengths, malformed input, and the null-on-bad-frame paths.

Adds the test/test:coverage scripts plus jest, ts-jest, @jest/globals and @types/jest dev deps, a README testing section and project-structure update, and the ts-p2p importer entries in the lockfile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

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.

ts-p2p: add a typed decoder for the two-layer JSON wire format

2 participants