fix(build-web3): correct streams-reference against the live API
Every JavaScript filter example in this reference threw or silently returned
nothing, and the documented `dataset` values are rejected by the API. Agents read
this file to generate filter code, so each defect became broken generated code.
Verified with POST /streams/test_filter (read-only, creates nothing) on Ethereum
blocks 21000000 / 21000280 and Solana slot 300000000.
## Defects
1. dataset enum — `log`, `transaction`, `receipt` are rejected with HTTP 400; the
API accepts `logs`, `transactions`, `receipts`. The table listed 5 of 19 valid
values; now complete, sourced from the OpenAPI enum.
2. stream.data shape — it is an array whose nesting depends on the dataset, and
was treated as a single object throughout. All 12 runnable examples failed:
Block / Receipt Streams Cannot read properties of undefined ('length')
Transaction / Utilities Cannot convert undefined to a BigInt
Logs / NFT Transfer Cannot read properties of undefined ('0')
DEX / Monitor Contract Cannot read properties of undefined ('toLowerCase')
Function Signature processedData is not defined
Whale, Solana x2 silent null — no error, no data
For `logs` the middle dimension is TRANSACTIONS, not blocks: the real shape is
data[block][tx][log]. On block 21000000 a block's entry holds 181 groups, one
per transaction, each group's logs sharing one transactionHash.
3. Batch safety — the outer dimension is the batch. `stream.data.length` equals
`dataset_batch_size` (default 1), so indexing `stream.data[0]` silently
processes only the first block. Every example now iterates. This is not
hypothetical: 9 of 20 streams on our own account run batch sizes of 5 or 50.
4. auth header — Management API examples used `Authorization: Bearer`; the API's
only securityScheme is `x-api-key`. The webhook destination's own Bearer
header is unrelated and left alone.
5. Create Stream body — was camelCase `filterFunction` with a nested
`destination` object. The API takes snake_case `filter_function`
(base64-encoded), a `destination` string enum, and separate
`destination_attributes`. Added the required-field list.
6. metadata field names — documented as `streamId`; the API returns `stream_id`,
and every metadata key is snake_case.
7. DEX swap example — filtered `Swap` events by router address, but the emitter
is always the pool. Block 21000000 has 22 Swap events and zero from a router,
so it could never match at any nesting depth. Now filters by event signature.
8. Solana examples — `programs_with_logs` items have no `programId`; it lives at
`programInvocations[].programId`. Balance deltas come from
`instruction.accounts[].pre/postBalance`, not `meta.pre/postBalances`.
## Additions
- A `**Test:**` line on every example naming the network, block, and the result
it produces, so a reader can confirm their setup before adapting the code.
Track Whale Transactions is pinned to 21000280 (a 2143 ETH transfer) because
1000+ ETH transfers are absent from most blocks.
- Payload Shape section documenting nesting per dataset and the batch dimension.
- Test a Filter section covering POST /streams/test_filter, including that
`block` must be a string and that a thrown filter still returns HTTP 201 with
the error nested in `result.error`.
## Verified after the change
Block Streams block @ 21000000 ok
Transaction Streams transactions @ 21000000 ok
Logs Streams logs @ 21000000 ok
Receipt Streams receipts @ 21000000 ok
Function Signature logs @ 21000000 ok
Available Utilities transactions @ 21000000 ok
Complex Filter Example logs @ 21000000 ok
Monitor Specific Contract logs @ 21000000 ok
Track Whale Transactions transactions @ 21000280 ok
NFT Transfer Tracking logs @ 21000000 ok
Monitor Program Logs programs_with_logs @ 300000000 ok
Track SOL Transfers programs_with_logs @ 300000000 ok
Key-Value Store Integration is the only example not executed; it needs a
pre-populated KV list.
0 commit comments