Skip to content

feat(midnight-js): adopt graphql-transport-ws+deflate subscription compression#977

Open
sp-io wants to merge 19 commits into
mainfrom
feat/976-graphql-ws-deflate
Open

feat(midnight-js): adopt graphql-transport-ws+deflate subscription compression#977
sp-io wants to merge 19 commits into
mainfrom
feat/976-graphql-ws-deflate

Conversation

@sp-io

@sp-io sp-io commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #976.

  • Adds a thin webSocketImpl wrapper that offers graphql-transport-ws+deflate first in the negotiation, alongside the standard graphql-transport-ws.
  • When the server picks the deflate variant, binary frames are zlib-inflated transparently before reaching graphql-ws using DecompressionStream('deflate') — a single Web Standard code path covering both Node ≥18 and modern browsers (no node:zlib, no new runtime dependencies). Browser baseline is Chrome 80 / Firefox 113 / Safari 16.4+ (March 2023).
  • Text frames (server skips compression below 256 B) pass through unchanged. Delivery order is preserved across mixed frame types via a per-instance promise queue.
  • Falls back transparently when the server only supports graphql-transport-ws. No public API change.
  • Documents the cross-fetch HTTP Accept-Encoding guarantee in transport.ts so the upcoming indexer 4.4.0 HTTP-response compression also takes effect.

Hardening

  • Module-load fail-fastinflate.ts throws at import time with a descriptive message if DecompressionStream is unavailable.
  • Compression-bomb cap (16 MiB) — streamed chunk-size check aborts inflate via reader.cancel() before allocating a giant buffer.
  • Binary payload normalizationtoArrayBuffer() accepts browser ArrayBuffer and Node Buffer / Uint8Array shapes (narrowed against SharedArrayBuffer), so binary frames from the Node ws package are not silently passed through.
  • Inflate-rejection isolation — per-link try/catch inside the delivery queue drops a single malformed/oversized frame without poisoning subsequent frames or surfacing an unhandled rejection.
  • Post-close delivery gate — drops queued inflate results and swallows rejections after close, preventing unhandled rejections during graphql-ws teardown / reconnect cycles.
  • EventListenerObject supportaddEventListener override wraps both function-style and handleEvent-style listeners so object listeners are not bypassed.
  • Subclassing warning — JSDoc on the returned class explicitly forbids re-subclassing DeflateWebSocket because the onmessage accessor relies on a fixed two-level prototype walk.

Out of scope (follow-ups)

  • E2E against indexer 4.4.0 pre-alpha image in testkit-js-e2e — tracked separately, awaiting CI image availability.
  • Opt-out flag — YAGNI; consumers can swap webSocket for their own impl if needed.
  • Older-Safari fallback (pako/fflate) — module-load fail-fast makes the missing capability loud; revisit only if dApp telemetry shows meaningful traffic from <16.4 Safari.

Test plan

  • Tests written first (TDD), verified failing before implementation
  • Unit tests: subprotocol negotiation (4), binary inflate via addEventListener and onmessage paths, text passthrough, mixed-frame ordering, fallback to plain protocol, binaryType = arraybuffer enforcement, Node Buffer normalization, post-close drop, inflate-throws frame-drop without queue poisoning
  • Unit tests: inflate helper — DecompressionStream guard, round-trip RFC 1950, round-trip repetitive payload, malformed-input zlib Z_DATA_ERROR cause, compression-bomb MAX_INFLATED_BYTES guard
  • All existing tests pass (125 / 127, 2 skipped — no regressions)
  • Lint clean (yarn lint), tsc --noEmit clean, package build clean (no node:* imports in browser-targeted production code)
  • Manual smoke against indexer 4.4.0 pre-alpha (4.4.0-pre-alpha.7-...) — follow-up via testkit-js-e2e once the image is available in CI

sp-io and others added 13 commits June 15, 2026 11:54
… inflate helper

Introduces inflate.ts with a single zlib (RFC 1950) decompression path via
the Web Streams DecompressionStream global, covering Node >= 18 and modern
browsers (Chrome 80 / Firefox 113 / Safari 16.4+). Includes a 16 MiB hard
cap on inflated payload size to prevent compression-bomb DoS vectors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…iption frames

Extends DeflateWebSocket with binary frame inflation, mixed-frame ordering via
a promise queue, transparent fallback when server picks plain subprotocol,
Node Buffer/Uint8Array normalization, and close-gate to avoid post-teardown
unhandled rejections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ions and listener-object inputs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…to Apollo transport

Wrap the user-supplied WebSocket with wrapWithDeflate() before passing to
graphql-ws createClient, enabling transparent perMessageDeflate compression
negotiation on the subscription connection.

Updated transport.test.ts assertions: the wrapped WebSocket is a subclass
of the user-supplied implementation, not an exact reference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sumed by deflate-wrap prototype check

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dArrayBuffer backing

Explicitly check that view.buffer is a plain ArrayBuffer before slicing,
rather than relying on TypeScript's union type assignment. This narrows
the type and eliminates the TS2322 warning about SharedArrayBuffer lacking
ArrayBuffer properties.

We never expect SharedArrayBuffer-backed views from WebSocket frames in
production, and slicing into a fresh ArrayBuffer requires plain ArrayBuffer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s and fix mock.calls indexing

- Replace DOM WebSocket type with isomorphic-ws.WebSocket in all test casts (5 occurrences)
- Fix transport.test.ts mock.calls.at(-1) indexing by properly typing the tuple
- Add explicit toBeDefined() check to fail fast if spy wasn't called
- Update beforeEach return type to match wrapWithDeflate signature

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sp-io sp-io requested a review from a team as a code owner June 15, 2026 11:32
@sp-io sp-io changed the title feat(indexer-public-data-provider): adopt graphql-transport-ws+deflate subscription compression feat(midnight-js): adopt graphql-transport-ws+deflate subscription compression Jun 15, 2026
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor
Title Lines Statements Branches Functions
contracts Coverage: 94%
93.72% (508/542) 87.25% (226/259) 94.73% (108/114)
dapp-connector-proof-provider Coverage: 94%
93.72% (508/542) 87.25% (226/259) 94.73% (108/114)
fetch-zk-config-provider Coverage: 100%
100% (25/25) 80% (12/15) 100% (6/6)
http-client-proof-provider Coverage: 81%
81.81% (36/44) 93.33% (14/15) 66.66% (6/9)
indexer-public-data-provider Coverage: 71%
72.3% (282/390) 61.61% (122/198) 58.82% (80/136)
level-private-state-provider Coverage: 93%
93.05% (590/634) 83.05% (250/301) 100% (86/86)
logger-provider Coverage: 100%
100% (15/15) 100% (0/0) 100% (8/8)
midnight-js Coverage: 100%
100% (0/0) 100% (0/0) 100% (0/0)
node-zk-config-provider Coverage: 94%
94.11% (16/17) 80% (4/5) 100% (5/5)
utils Coverage: 99%
97.96% (241/246) 94.63% (141/149) 95.55% (43/45)

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Unit Test Results - MidnightJS

   28 files    120 suites   5m 46s ⏱️
  970 tests   968 ✅ 2 💤 0 ❌
1 954 runs  1 950 ✅ 4 💤 0 ❌

Results for commit da2dd78.

♻️ This comment has been updated with latest results.

sp-io and others added 4 commits June 15, 2026 13:50
…tance to prevent prototype pollution

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…istener path, logger, typing, and asserts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, exports, deterministic test waits)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@MidnightCI

MidnightCI commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

E2E Tests Results

e2e_tests_reports: Run #3999

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
125 120 1 4 0 0 0 23m 51s

Some tests failed!

Name Failure Message
❌ Ledger API - NodeJS Integration Tests > should run ESM module successfully expected 1 to be +0 // Object.is equality

Suites

120 passed, 1 failed, and 4 other

Suite Passed Failed Other Duration
✅ testkit-js/testkit-js-e2e/test/contracts.blocktime.it.test.ts
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should succeed when both device time and node time are less than future time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should fail immediately on device when device time is already past the check time
        ⏭️ Block Time Contract Tests 1 > blockTimeLt tests > should succeed on device but fail on node when submission is delayed
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should succeed when both device time and node time are greater than past time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should fail immediately on device when device time is less than check time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should succeed even with submission delay when checking past time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should succeed when both device time and node time are greater than past time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should fail when device time is not greater than check time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should succeed when both device time and node time are less than or equal to future time
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should fail immediately on device when device time exceeds check time
        ⏭️ Block Time Contract Tests 1 > blockTimeLt tests > should succeed on device but fail on node when submission delay causes time to exceed threshold
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should demonstrate different failure points for Lt check > Immediate past time - fails on device
        ⏭️ Block Time Contract Tests 1 > blockTimeLt tests > should demonstrate different failure points for Lt check > Near future time with delay - succeeds on device, fails on node
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should demonstrate different failure points for Lt check > Far future time - succeeds on both device and node
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should handle maximum time values
        ✅ Block Time Contract Tests 1 > blockTimeLt tests > should handle zero time value
✅ 13 ❌ 0 ⏭️ 3 2m 47s
✅ testkit-js/testkit-js-e2e/test/contracts.blocktime2.it.test.ts
        ✅ Block Time Contract Tests 2 > blockTimeLt tests > should demonstrate different failure points for Lt check > Immediate past time - fails on device
        ⏭️ Block Time Contract Tests 2 > blockTimeLt tests > should demonstrate different failure points for Lt check > Near future time with delay - succeeds on device, fails on node
        ✅ Block Time Contract Tests 2 > blockTimeLt tests > should demonstrate different failure points for Lt check > Far future time - succeeds on both device and node
        ✅ Block Time Contract Tests 2 > blockTimeLt tests > should handle maximum time values
        ✅ Block Time Contract Tests 2 > blockTimeLt tests > should handle zero time value
✅ 4 ❌ 0 ⏭️ 1 1m 11s
✅ testkit-js/testkit-js-e2e/test/contracts.it.test.ts
        ✅ Contracts API > should create unproven call and deploy transactions for contract with private state
        ✅ Contracts API > should deploy contract on the chain [@slow]
        ✅ Contracts API > should return deployed contract if it exists on specific address
        ✅ Contracts API > should return deployed contract if it exists on specific address without initialPrivateState
        ✅ Contracts API > should throw error if contract address has wrong format - length
        ✅ Contracts API > should return deployed contract if it exists on specific address with initialPrivateState and empty local private state store
        ✅ Contracts API > should return deployed contract if it exists on specific address with different initialPrivateState
        ✅ Contracts API > should wait indefinitely until contract exists on specific address [@slow]
        ✅ Contracts API > should throw for incompatible contract types that differ by circuit ids
        ✅ Contracts API > should throw for incompatible contract types with same shape but different verifier keys
        ✅ Contracts API > should return contract interface and execute circuit operations [@slow]
        ✅ Contracts API > should throw error on undefined public state at wrong address
        ✅ Contracts API > should submit a deploy transaction [@slow]
        ✅ Contracts API > should submit transaction that calls circuit in contract [@slow]
        ✅ Contracts API > should throw error if private state is undefined
        ✅ Contracts API > should throw error if public state is undefined
        ✅ Contracts API > should throw error if contract address has wrong format - not hex
        ✅ Contracts API > should return the latest observed state of a deployed contract and is independent of the chain state
        ✅ Contracts API > should wait indefinitely until state change, if stopped returns last contract state [@slow]
✅ 19 ❌ 0 ⏭️ 0 3m 23s
✅ testkit-js/testkit-js-e2e/test/contracts.scopedtx.it.test.ts
        ✅ Scoped Transaction Contract Tests > should submit scoped transaction that calls circuit in contract [@slow]
        ✅ Scoped Transaction Contract Tests > should submit scoped transaction that calls 2 different circuits in contract [@slow]
        ✅ Scoped Transaction Contract Tests > should submit scoped transaction that calls 2 circuits in contract and DOES NOT preserve execution order [@slow]
        ✅ Scoped Transaction Contract Tests > should not submit scoped transaction when one circuit call fails [@slow]
✅ 4 ❌ 0 ⏭️ 0 55.0s
✅ testkit-js/testkit-js-e2e/test/contracts.singlecontract.nostate.it.test.ts
        ✅ Contracts API > should deploy and find contracts with no private state [@slow]
        ✅ Contracts API > should create unproven call and deploy transactions for contract with no private state
        ✅ Contracts API > should submit deploy and call transactions for contracts with no private state [@slow]
✅ 3 ❌ 0 ⏭️ 0 1m 32s
✅ testkit-js/testkit-js-e2e/test/contracts.snarkupgrade.it.test.ts
        ✅ Contracts API Snark Upgrade [dedicated contract] [@slow] > should successfully remove verifier key using submitRemoveVerifierKeyTx
        ✅ Contracts API Snark Upgrade [dedicated contract] [@slow] > should successfully remove verifier key using createContractMaintenanceTxInterface
        ✅ Contracts API Snark Upgrade [dedicated contract] [@slow] > should successfully remove verifier key and disable circuit operation
        ✅ Contracts API Snark Upgrade [dedicated contract] [@slow] > should succeed on verifier key insertion retry after removal
        ✅ Contracts API Snark Upgrade [dedicated contract] [@slow] > should fail when inserting verifier key for wrong circuit after removal
✅ 5 ❌ 0 ⏭️ 0 3m 22s
✅ testkit-js/testkit-js-e2e/test/contracts.snarkupgrade.singlecontract.it.test.ts
        ✅ Contracts API Snark Upgrade [single contract] > submitReplaceAuthorityTx - successful replace authority with new key[@slow]
        ✅ Contracts API Snark Upgrade [single contract] > submitReplaceAuthorityTx - successful replace authority with same key [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > submitReplaceAuthorityTx - should fail on replace contract that is not deployed to contract address
        ✅ Contracts API Snark Upgrade [single contract] > submitReplaceAuthorityTx - should fail when signing key for contract address does not exist
        ✅ Contracts API Snark Upgrade [single contract] > submitInsertVerifierKeyTx - should fail on invalid verifier key
        ✅ Contracts API Snark Upgrade [single contract] > submitInsertVerifierKeyTx - successful insert on not present circuitId [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > submitInsertVerifierKeyTx - should fail on contract not present on contract address
        ✅ Contracts API Snark Upgrade [single contract] > submitInsertVerifierKeyTx - should fail on providers for different contract with different API
        ✅ Contracts API Snark Upgrade [single contract] > submitRemoveVerifierKeyTx - should fail on not present circuitId
        ✅ Contracts API Snark Upgrade [single contract] > submitRemoveVerifierKeyTx - should fail on contract not present on contract address
        ✅ Contracts API Snark Upgrade [single contract] > submitRemoveVerifierKeyTx - should fail on providers for different contract with different API
        ✅ Contracts API Snark Upgrade [single contract] > createContractMaintenanceTxInterface - replaceAuthority - successful replace authority with the new one [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > createContractMaintenanceTxInterface - replaceAuthority - successful replace authority with the same one [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > createContractMaintenanceTxInterface - replaceAuthority - should fail on contract not present on contract address
        ✅ Contracts API Snark Upgrade [single contract] > createContractMaintenanceTxInterface - insertVerifierKey - fail when key is still present
        ✅ Contracts API Snark Upgrade [single contract] > createContractMaintenanceTxInterface - insertVerifierKey - success when no key present [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > createCircuitMaintenanceTxInterfaces - insertVerifierKey - fail when key is already present
        ✅ Contracts API Snark Upgrade [single contract] > createCircuitMaintenanceTxInterfaces - insertVerifierKey - success when no key present [@slow]
        ✅ Contracts API Snark Upgrade [single contract] > createCircuitMaintenanceTxInterfaces - removeVerifierKey - should fail on contract not present on contract address
✅ 19 ❌ 0 ⏭️ 0 3m 35s
✅ testkit-js/testkit-js-e2e/test/contracts.snarkupgrade.smoke.it.test.ts
        ✅ Contracts API Snark Upgrade [@slow][@smoke] > should update verifier keys from one contract to another [@smoke]
        ✅ Contracts API Snark Upgrade [@slow][@smoke] > should fail on operate with previous authority after replacement
✅ 2 ❌ 0 ⏭️ 0 3m 41s
✅ testkit-js/testkit-js-e2e/test/dapp-connector-proving.it.test.ts
        ✅ DApp Connector Proving > should deploy and call contract using dapp-connector-proof-provider with wallet-delegated proving [@slow]
✅ 1 ❌ 0 ⏭️ 0 35.5s
✅ testkit-js/testkit-js-e2e/test/indexer-public-data-provider.observable1.it.test.ts
        ✅ Indexer API > should return the history of states starting from defined blockHash (inclusive:true, expected:1,2) [@slow]
        ✅ Indexer API > should return the history of states starting from defined blockHash (inclusive:false, expected:2) [@slow]
        ✅ Indexer API > should return the history of states starting from defined txId (inclusive:true, expected states:1,2) [@slow]
        ✅ Indexer API > should return the history of states starting from defined txId (inclusive:false, expected states:2) [@slow]
✅ 4 ❌ 0 ⏭️ 0 3m 39s
✅ testkit-js/testkit-js-e2e/test/indexer-public-data-provider.observable2.it.test.ts
        ✅ Indexer API > should return the history of states starting from defined blockHeight (inclusive:true, expected states:1,2) [@slow]
        ✅ Indexer API > should return the history of states starting from defined blockHeight (inclusive:false, expected states:2) [@slow]
        ✅ Indexer API > should return the entire history of states of the contract with the given address (config:{ type: 'all' }, expected states:0,1,2) [@slow]
        ✅ Indexer API > should return the history of states of the contract with the given address, starting with the most recent state (config:{ type: 'latest' }, expected states:1,2) [@slow]
✅ 4 ❌ 0 ⏭️ 0 3m 39s
✅ testkit-js/testkit-js-e2e/test/indexer-public-data-provider.singlecontract.it.test.ts
        ✅ Indexer API > queryDeployContractState - should return a contract state equivalent to the initial contract state produced during deployment construction
        ✅ Indexer API > queryContractState - should return the current contract state of a deployed contract
        ✅ Indexer API > queryContractState - should return the current contract state of a deployed contract at defined block height
        ✅ Indexer API > queryContractState - should return the current contract state of a deployed contract at defined block hash
        ✅ Indexer API > queryContractState - should return null on no contract at contract address
        ✅ Indexer API > queryZSwapAndContractState - should return the current ZSwap chain state and contract state of a deployed contract
        ✅ Indexer API > queryZSwapAndContractState - should return null on no contract at contract address
        ✅ Indexer API > watchForDeployTxData - should return the data of the transaction containing the deployment of the contract with the given address
        ✅ Indexer API > watchForTxData - should return the data of the transaction containing the contract call with the given transaction id
        ✅ Indexer API > watchForContractState - should immediately return the current state of a deployed contract
✅ 10 ❌ 0 ⏭️ 0 117ms
✅ testkit-js/testkit-js-e2e/test/level-private-state-provider.it.test.ts
        ✅ Level Private State Provider - Export/Import Integration > should preserve private state after database recreation [@slow]
✅ 1 ❌ 0 ⏭️ 0 58.4s
❌ testkit-js/testkit-js-e2e/test/nodejs.it.test.ts
        ❌ Ledger API - NodeJS Integration Tests > should run ESM module successfully
        ✅ Ledger API - NodeJS Integration Tests > should run CJS module with expected exit code
✅ 1 ❌ 1 ⏭️ 0 1m 1s
✅ testkit-js/testkit-js-e2e/test/proof-server.it.test.ts
        ✅ Proof server integration > should create proofs successfully for deploy and call transactions
        ✅ Proof server integration > should create proofs with transactions that has succesfull well-formedness
        ✅ Proof server integration > should execute 5 proveTx calls in parallel without errors
✅ 3 ❌ 0 ⏭️ 0 653ms
✅ testkit-js/testkit-js-e2e/test/shielded.advanced.it.test.ts
        ✅ Shielded tokens - advanced operations > should mint and send immediate shielded tokens
        ✅ Shielded tokens - advanced operations > should mint and burn shielded tokens
✅ 2 ❌ 0 ⏭️ 0 1m 5s
✅ testkit-js/testkit-js-e2e/test/shielded.fallible-segment-routing.it.test.ts
        ✅ Shielded segment routing — regression #876 > user-bound shielded coin lands in the fallible offer when the circuit is fallible
✅ 1 ❌ 0 ⏭️ 0 296ms
✅ testkit-js/testkit-js-e2e/test/shielded.transfer.it.test.ts
        ✅ Shielded tokens > should mint tokens
        ✅ Shielded tokens > should deposit shielded coin via receiveShielded (issue #686)
✅ 2 ❌ 0 ⏭️ 0 1m 17s
✅ testkit-js/testkit-js-e2e/test/unshielded.balance.it.test.ts
        ✅ Unshielded tokens - balance > should get balance of tokens - 0 value
        ✅ Unshielded tokens - balance > should get balance of tokens - minted amount
        ✅ Unshielded tokens - balance > should get balance of tokens - greater than - false
        ✅ Unshielded tokens - balance > should get balance of tokens - greater than - true
        ✅ Unshielded tokens - balance > should get balance of tokens - less than - false
        ✅ Unshielded tokens - balance > should get balance of tokens - less than - true
        ✅ Unshielded tokens - balance > should get balance of tokens - greater than or equal - true (equal)
        ✅ Unshielded tokens - balance > should get balance of tokens - greater than or equal - false
        ✅ Unshielded tokens - balance > should get balance of tokens - less than or equal - true (equal)
        ✅ Unshielded tokens - balance > should get balance of tokens - less than or equal - false
✅ 10 ❌ 0 ⏭️ 0 3m
✅ testkit-js/testkit-js-e2e/test/unshielded.cross-wallet-transfer.it.test.ts
        ✅ Unshielded cross-wallet transfer (issue #720) > should send night tokens to different wallet via right<>(disclose(addr))
        ✅ Unshielded cross-wallet transfer (issue #720) > should send night tokens to different wallet via disclose(recipient) (issue #720)
✅ 2 ❌ 0 ⏭️ 0 36.0s
✅ testkit-js/testkit-js-e2e/test/unshielded.mint-and-send.it.test.ts
        ✅ Unshielded tokens - mint and send variants > should mint tokens to contract address (self)
        ✅ Unshielded tokens - mint and send variants > should mint tokens to user address
        ✅ Unshielded tokens - mint and send variants > should send tokens to self
        ✅ Unshielded tokens - mint and send variants > should send tokens to contract address (self)
✅ 4 ❌ 0 ⏭️ 0 1m 47s
✅ testkit-js/testkit-js-e2e/test/unshielded.transfer.it.test.ts
        ✅ Unshielded tokens > Custom color > should mint different tokens
        ✅ Unshielded tokens > Custom color > should receive tokens - invalid
        ✅ Unshielded tokens > Custom color > should send tokens to wallet
        ✅ Unshielded tokens > Custom color > should receive tokens from wallet
        ✅ Unshielded tokens > Native color > should transfer night from wallet to contract - receiveNightTokens
        ✅ Unshielded tokens > Native color > should transfer night to wallet - sendNightTokensToUser
✅ 6 ❌ 0 ⏭️ 0 2m 6s

Github Test Reporter by CTRF 💚

🔄 This comment has been updated

@sp-io sp-io force-pushed the feat/976-graphql-ws-deflate branch from 5a173bc to 03debab Compare June 15, 2026 14:12
sp-io and others added 2 commits June 16, 2026 10:58
The `.catch` in counter.ts called `logger.error('Counter test failed:',
error)` — pino renders that as the prefix string with no serialization
of the error argument, so CI lost the message, stack, and cause when
the spawned ESM/CJS counter scripts rejected. The flaky
`nodejs.it.test.ts > should run ESM module successfully` was
diagnostically dead from the captured stderr alone.

Routing the error through pino's `err` serializer (`logger.error({ err
}, msg)`) captures `message`, `stack`, and the `cause` chain in the
structured log, so the next CI failure surfaces the actual reason
counter() rejected between wallet sync completion and api.deploy().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

feat: adopt indexer graphql-transport-ws+deflate subscription compression

2 participants