Reference / SDK reference

SDK reference

Every export of @secondlayer/sdk, extracted from its TypeScript source.

Start with the guide

This is the index. SDK explains the client, consumers, proofs, and signature verification in the order you'd actually use them.

@secondlayer/sdk@6.49.2 · 314 exports · extracted with openpkg

Client

ActiveSubgraphOperationinterfacesource
ContextAccountinterfacesource
ContextApiKeyinterfacesource

Compact API-key view for {@link ContextSnapshot} — never the plaintext.

ContextProjectinterfacesource

Compact project view for {@link ContextSnapshot}.

ContextSnapshotinterfacesource

A point-in-time orientation snapshot for an agent: who you are, the live tips, and what you own.

resolveApiKeyfunctionsource
resolveApiKey(apiKey?: string): null | string

Resolve the credential a client should use.

SecondLayerclasssource
SecondLayer(options?: object): unknown
SecondLayerOptionsinterfacesource

Index

BlockEnvelopetypesource
BlocksEnvelopetypesource
BlocksListParamstypesource
BlocksWalkParamstypesource
CanonicalEnvelopetypesource
CanonicalListParamstypesource
CanonicalWalkParamstypesource
consumeIndexFeedfunctionsource
consumeIndexFeed(opts: object): object

Checkpointed pull loop over a cursor-paginated Index feed — the Index port of `consumeStreamsEvents`, sharing its contract: at-least-once delivery, client-owned checkpoints (`onBatch` may return th…

ContractCallsConsumeParamstypesource
ContractCallsEnvelopetypesource
ContractCallsListParamstypesource
ContractCallsWalkParamstypesource
EventsConsumeParamstypesource
EventsEnvelopetypesource
EventsListParamstypesource
EventsWalkParamstypesource
FtTransfertypesource
FtTransfersEnvelopetypesource
FtTransfersListParamstypesource
FtTransfersResourceinterfacesource
FtTransfersResource(params: object): object

`index.ftTransfers` — callable shorthand for `.list()`, with `.list`/`.walk` still available: `await sl.index.ftTransfers({ contractId })`.

FtTransfersWalkParamstypesource
Indexclasssource
Index(options?: object): unknown
IndexAlwaysFieldstypesource

Fields every read returns regardless of `fields` — the consume contract (`cursor`, `block_height`) plus the union discriminant.

IndexBlocktypesource

A block resource.

IndexCanonicalBlocktypesource

One canonical block in the sync map.

IndexConsumeOptionstypesource

Consumer options shared by `index.events.consume` and `index.contractCalls.consume`.

IndexContractCalltypesource
IndexDiscoverytypesource

The `GET /v1/index` discovery doc — live endpoint + filter vocabulary.

IndexEventtypesource

Decoded chain event, discriminated by `event_type`.

IndexEventFieldstypesource

An event row narrowed to a `fields` selection (plus what always ships).

IndexEventOftypesource

The single decoded-event member matching one `event_type` literal.

IndexEventsResourceinterfacesource
IndexEventsResource(params: object): object

`index.events` — callable shorthand for `.list()`; `eventType` is required.

IndexEventTypetypesource
IndexEventTypeFilterstypesource

Per-event-type filter vocabulary in the {@link IndexDiscovery} doc.

IndexFeedEnvelopetypesource

Minimum envelope shape of a consumable Index feed page.

IndexFeedFetchertypesource

One page fetch.

IndexFeedItemtypesource

Minimum shape a consumed Index row must expose.

IndexFtBurntypesource
IndexFtMinttypesource
IndexFtTransfertypesource
IndexMempoolTransactiontypesource

A pending (unconfirmed) transaction.

IndexNftBurntypesource
IndexNftMinttypesource
IndexNftTransfertypesource
IndexPostConditiontypesource
IndexPox5Eventtypesource

A raw decoded PoX-5 print event.

IndexPox5EventTopictypesource

The decoded `pox-5` boot-contract print topics (SIP-045 Bitcoin Staking) — one source of truth in `@secondlayer/stacks/pox5` (already a dependency; the old "SDK owns its own dependency surface" rat…

IndexPoxCycletypesource

Aggregate stats for one PoX reward cycle — distinct from `index.stacking` (decoded per-call PoX-4 actions); this is the reward-cycle rollup.

IndexPoxFunctionCounttypesource

Per-function action count within a reward cycle.

IndexPrinttypesource
IndexReorgtypesource

A chain reorg overlapping a returned page's height range.

IndexSbtcDeposittypesource

A completed sBTC peg-in, keyed by `bitcoin_txid` (deposits carry no `request_id`).

IndexSbtcDepositDetailtypesource

A deposit fetched by Bitcoin txid — always terminal, hence `status`.

IndexSbtcEventtypesource

A raw decoded sBTC protocol-state event — the full `sbtc_events` row, one per event across all topics.

IndexSbtcSummarytypesource

The peg "scoreboard" — a single all-time canonical aggregate.

IndexSbtcWithdrawaltypesource

A peg-out collapsed to one row per `request_id`, with lifecycle `status` derived from the latest accept/reject.

IndexSbtcWithdrawalDetailtypesource

A single peg-out's full assembled lifecycle, fetched by `request_id`.

IndexSbtcWithdrawalPhasetypesource

One phase of a withdrawal's lifecycle (the on-Stacks event that drove it).

IndexStackingActiontypesource

A decoded PoX-4 stacking action (one per stacking contract call).

IndexStxBurntypesource
IndexStxLocktypesource
IndexStxMinttypesource
IndexStxTransfertypesource
IndexTiptypesource
IndexTransactiontypesource

Full transaction document: columnar fields plus `raw_tx`-decoded enrichment.

IndexUsagetypesource
MempoolEnvelopetypesource
MempoolListParamstypesource
MempoolTransactionEnvelopetypesource
MempoolWalkParamstypesource
NftTransfertypesource
NftTransfersEnvelopetypesource
NftTransfersListParamstypesource
NftTransfersResourceinterfacesource
NftTransfersResource(params: object): object

`index.nftTransfers` — callable shorthand for `.list()` (see {@link FtTransfersResource}).

NftTransfersWalkParamstypesource
Pox5EventsEnvelopetypesource
Pox5EventsListParamstypesource
Pox5EventsWalkParamstypesource
Pox5Resourceinterfacesource

`index.pox5` — decoded PoX-5 print events, the staking primitive from the epoch 4.0 hard fork onward (PoX-4's `index.stacking` stream ends there).

PoxCycleEnvelopetypesource
PoxCyclesEnvelopetypesource
PoxCyclesListParamstypesource
PoxCyclesWalkParamstypesource
PoxResourceinterfacesource

`index.pox` — PoX reward-cycle aggregates.

PrintSchemaResponsetypesource

Empirical per-topic print payload schema for a contract, inferred from sampled on-chain events.

SbtcDepositEnvelopetypesource
SbtcDepositsConsumeParamstypesource
SbtcDepositsEnvelopetypesource
SbtcDepositsListParamstypesource
SbtcDepositsWalkParamstypesource
SbtcEventsConsumeParamstypesource
SbtcEventsEnvelopetypesource
SbtcEventsListParamstypesource
SbtcEventsWalkParamstypesource
SbtcResourceinterfacesource

`index.sbtc` — the decoded sBTC peg surface (deposits, withdrawals, raw events, scoreboard).

SbtcSummaryEnvelopetypesource
SbtcWithdrawalEnvelopetypesource
SbtcWithdrawalsEnvelopetypesource
SbtcWithdrawalsListParamstypesource
SbtcWithdrawalStatustypesource
SbtcWithdrawalsWalkParamstypesource
StackingEnvelopetypesource
StackingListParamstypesource
StackingWalkParamstypesource
TransactionEnvelopetypesource
TransactionsEnvelopetypesource
TransactionsListParamstypesource
TransactionsWalkParamstypesource

Subgraphs

getSubgraphfunctionsource
getSubgraph(def: object, options?: Subgraphs | SecondLayer | object): InferSubgraphClient

Returns a typed client for a subgraph defined with `defineSubgraph()`.

SubgraphAgentSchemainterfacesource
SubgraphOperationStatusinterfacesource

Status of a tracked reindex/backfill operation (poll until terminal).

Subgraphsclasssource
Subgraphs(options?: object): unknown
SubgraphSpecFormattypesource
SubgraphSpecOptionsinterfacesource

Streams

ConsumerBatchContexttypesource

What the loop knows at the end of a page, handed to `onBatch`.

createStreamsClientfunctionsource
createStreamsClient(options: CreateStreamsClientOptions): StreamsClient
Cursorvariablesource

Helpers for Streams cursors.

decodefunctionsource
decode(event: StreamsEvent): IndexEvent

Decode a raw Streams event into the SAME flat, `event_type`-discriminated row shape Index serves — so Streams consumption reads identically to Index consumption, with one call instead of eleven gua…

DecodedEventColumnstypesource

Superset of the columns the decoded_events table holds.

DecodedEventRowtypesource
DecodedFtBurntypesource
DecodedFtBurnPayloadtypesource
DecodedFtMinttypesource
DecodedFtMintPayloadtypesource
DecodedFtTransfertypesource
DecodedFtTransferPayloadtypesource
DecodedNftBurntypesource
DecodedNftBurnPayloadtypesource
DecodedNftMinttypesource
DecodedNftMintPayloadtypesource
DecodedNftTransfertypesource
DecodedNftTransferPayloadtypesource
DecodedPrinttypesource
DecodedPrintPayloadtypesource
DecodedPrintValuetypesource

Decoded form of a Clarity `print` event: - `topic`: the print topic, when the contract emits a `{ topic, ...

DecodedStxBurntypesource
DecodedStxBurnPayloadtypesource
DecodedStxLocktypesource
DecodedStxLockPayloadtypesource
DecodedStxMinttypesource
DecodedStxMintPayloadtypesource
DecodedStxTransfertypesource
DecodedStxTransferPayloadtypesource
decodeFtBurnfunctionsource
decodeFtBurn(event: StreamsEvent): DecodedFtBurn
decodeFtMintfunctionsource
decodeFtMint(event: StreamsEvent): DecodedFtMint
decodeFtTransferfunctionsource
decodeFtTransfer(event: StreamsEvent): DecodedFtTransfer
decodeNftBurnfunctionsource
decodeNftBurn(event: StreamsEvent): DecodedNftBurn
decodeNftMintfunctionsource
decodeNftMint(event: StreamsEvent): DecodedNftMint
decodeNftTransferfunctionsource
decodeNftTransfer(event: StreamsEvent): DecodedNftTransfer
decodePrintfunctionsource
decodePrint(event: StreamsEvent): DecodedPrint
decodeStxBurnfunctionsource
decodeStxBurn(event: StreamsEvent): DecodedStxBurn
decodeStxLockfunctionsource
decodeStxLock(event: StreamsEvent): DecodedStxLock
decodeStxMintfunctionsource
decodeStxMint(event: StreamsEvent): DecodedStxMint
decodeStxTransferfunctionsource
decodeStxTransfer(event: StreamsEvent): DecodedStxTransfer
FetchLiketypesource
FtTransferEventtypesource
FtTransferPayloadtypesource
isFtBurnfunctionsource
isFtBurn(event: StreamsEvent): boolean
isFtMintfunctionsource
isFtMint(event: StreamsEvent): boolean
isFtTransferfunctionsource
isFtTransfer(event: StreamsEvent): boolean
isNftBurnfunctionsource
isNftBurn(event: StreamsEvent): boolean
isNftMintfunctionsource
isNftMint(event: StreamsEvent): boolean
isNftTransferfunctionsource
isNftTransfer(event: StreamsEvent): boolean
isPrintfunctionsource
isPrint(event: StreamsEvent): boolean
isStxBurnfunctionsource
isStxBurn(event: StreamsEvent): boolean
isStxLockfunctionsource
isStxLock(event: StreamsEvent): boolean
isStxMintfunctionsource
isStxMint(event: StreamsEvent): boolean
isStxTransferfunctionsource
isStxTransfer(event: StreamsEvent): boolean
NftTransferEventtypesource
NftTransferPayloadtypesource
StreamsBatchtypesource

One yielded page from {@link StreamsClient.consume} — the `GET /v1/streams/events` envelope verbatim, with `next_cursor` renamed to `cursor` (the checkpoint to persist and resume from).

StreamsBatchContexttypesource
StreamsCanonicalBlocktypesource
StreamsClienttypesource
StreamsConsumeParamstypesource
StreamsDumpFiletypesource

One bulk parquet file in the dumps manifest.

StreamsDumpstypesource
StreamsDumpsManifesttypesource
StreamsEventtypesource

A raw Streams event.

StreamsEventPayloadtypesource

Union of every Streams payload shape, discriminated by `event_type` on the parent `StreamsEvent`.

StreamsEventsConsumeParamstypesource
StreamsEventsConsumeResulttypesource
StreamsEventsEnvelopetypesource
StreamsEventsListEnvelopetypesource
StreamsEventsListParamstypesource
StreamsEventsStreamParamstypesource
StreamsEventsSubscribeParamstypesource
StreamsEventTypetypesource
StreamsReorgtypesource
StreamsReorgContexttypesource

The checkpoint for a reorg rollback.

StreamsReorgsListEnvelopetypesource
StreamsReorgsListParamstypesource
StreamsServerErrorclasssource
StreamsServerError(message: string, status: number, body?: object): unknown

Thrown on a 5xx from the Streams API.

StreamsSignatureErrorclasssource
StreamsSignatureError(message?: string): unknown

Thrown when response signature verification is enabled and fails.

StreamsTiptypesource
StreamsUsagetypesource

Subscriptions and webhooks

ChainApplyDeliveryOftypesource

One delivery body, generic over its trigger literal + matched-event shape.

ChainApplyEnvelopeinterfacesource

Delivered when a matched chain event lands in a canonical block (`event_type: "chain.<trigger>.apply"`).

ChainApplyEnvelopeOfinterfacesource

One `apply` envelope, generic over its trigger literal + matched-event shape.

ChainEventEnvelopeinterfacesource

Wrapper around an event-level trigger's matched event.

ChainFtBurnDatainterfacesource

`event.data` for an `ft_burn` delivery.

ChainFtMintDatainterfacesource

`event.data` for an `ft_mint` delivery.

ChainFtTransferDatainterfacesource

`event.data` for an `ft_transfer` delivery.

ChainNftBurnDatainterfacesource

`event.data` for an `nft_burn` delivery.

ChainNftMintDatainterfacesource

`event.data` for an `nft_mint` delivery.

ChainNftTransferDatainterfacesource

`event.data` for an `nft_transfer` delivery.

ChainPrintEventDatainterfacesource

`event.data` for a `print_event` delivery.

ChainReorgOrphanedEntryinterfacesource

One orphaned delivery recalled by a reorg rollback.

ChainReorgRollbackDeliveryinterfacesource

Delivered once per affected subscription on a reorg (`type: "chain.reorg.rollback"`).

ChainReorgRollbackEnvelopeinterfacesource

Delivered once per affected subscription on a reorg (`event_type: "chain.reorg.rollback"`).

ChainStxBurnDatainterfacesource

`event.data` for a `stx_burn` delivery.

ChainStxLockDatainterfacesource

`event.data` for a `stx_lock` delivery.

ChainStxMintDatainterfacesource

`event.data` for a `stx_mint` delivery.

ChainStxTransferDatainterfacesource

`event.data` for a `stx_transfer` delivery.

ChainTestDeliveryinterfacesource

The `POST /subscriptions/:id/test` ping (`type: "chain.test.apply"`) — not a real chain event.

ChainTriggertypesource

JSON mirror of the subgraph runtime's `SubgraphFilter` union.

ChainTriggerTypetypesource
ChainTxLevelEventinterfacesource

A tx-level trigger's matched event (`contract_call` / `contract_deploy`) — flat, no nested `data` key.

ChainWebhookDeliverytypesource

The full wire body of a chain-subscription webhook delivery, as sent to a `format: "standard-webhooks"` subscription (the default) — `{ type, timestamp, data }`.

ChainWebhookEnvelopetypesource

Any chain-subscription webhook body.

CreateSubscriptionRequestinterfacesource
CreateSubscriptionResponseinterfacesource
DeadRowinterfacesource
decodeChainWebhookfunctionsource
decodeChainWebhook(rawBody: string): ChainWebhookDelivery

Decode + narrow a chain-subscription webhook delivery body into a typed {@link ChainWebhookDelivery}.

DeliveryRowinterfacesource
ReplayResultinterfacesource
RotateSecretResponseinterfacesource
SbtcDepositEventinterfacesource

Payload for `sbtc_deposit` (topic: completed-deposit).

SbtcWithdrawalEventinterfacesource

Payload for `sbtc_withdrawal_create`, `sbtc_withdrawal_accept`, `sbtc_withdrawal_reject` — the on-Stacks lifecycle events.

SbtcWithdrawalSweptConfirmedEventinterfacesource

Payload for `sbtc_withdrawal_swept_confirmed` — fired once when a peg-out's committed BTC sweep crosses the confirmation threshold on Bitcoin.

StandardWebhooksHeadersinterfacesource

Standard Webhooks signing helpers — https://standardwebhooks.com

SubscriptionDetailinterfacesource
SubscriptionFormattypesource
SubscriptionKindtypesource

Polymorphic subscription mode (mirrors db/types `SubscriptionKind`).

SubscriptionRuntimetypesource
Subscriptionsclasssource
Subscriptions(options?: object): unknown
SubscriptionStatustypesource
SubscriptionSummaryinterfacesource
triggervariablesource

Ergonomic chain-trigger constructors for `subscriptions.create({ triggers })`.

UpdateSubscriptionRequestinterfacesource
verifySecondlayerSignaturefunctionsource
verifySecondlayerSignature(rawBody: string, headers: WebhookHeaderInput, publicKeyPem: string): boolean

Verify the universal Secondlayer authenticity signature that every delivery carries, regardless of body format (`raw`, `cloudevents`, `standard-webhooks`, …).

verifyStandardWebhooksHeadersfunctionsource
verifyStandardWebhooksHeaders(body: string, headers: StandardWebhooksHeaders | object, secret: string, opts?: VerifyOptions): boolean
verifyWebhookSignaturefunctionsource
verifyWebhookSignature(rawBody: string, headers: WebhookHeaderInput, secret: string, toleranceSeconds?: number): boolean

Verify a Secondlayer webhook delivery signature.

WebhookHeaderInputtypesource

Account

ApiKeysclasssource
ApiKeys(options?: object): unknown
ApiKeySummaryinterfacesource

A key as seen by {@link ApiKeys.list} — metadata only, never the plaintext.

CreateApiKeyParamsinterfacesource
CreateApiKeyResponseinterfacesource
CreateProjectParamsinterfacesource
Projectinterfacesource

Typed client for project management (`/api/projects/*`).

ProjectInvitationinterfacesource
Projectsclasssource
Projects(options?: object): unknown
ProjectTeaminterfacesource
ProjectTeamMemberinterfacesource
ScopedKeyProducttypesource

Scope of a minted read key.

UpdateProjectParamsinterfacesource

Clarity

decodeClarityValuefunctionsource
decodeClarityValue(hex: string): object

Decode a hex-encoded Clarity value to JSON-safe JS (uints as strings, buffers as `0x…` hex, tuples as objects).

toJsonSafefunctionsource
toJsonSafe(value: object): object

Make a cvToValue result JSON-serializable: Clarity (u)ints decode to bigint, which JSON.stringify can't handle — convert recursively to strings.

Contracts

ContractConformancetypesource

Whether a trait match must be declared in source, inferred from ABI, or either.

Contractsclasssource
Contracts(options?: object): unknown
ContractsEnvelopeinterfacesource
ContractsListParamsinterfacesource
ContractSummaryinterfacesource

Errors

ApiErrorclasssource
ApiError(status: number, message: string, body?: object, code?: string, options?: SecondLayerErrorOptions): unknown

Error thrown by {@link SecondLayer} when an API request fails.

AuthErrorclasssource
AuthError(message?: string): unknown

Thrown on a 401 — by both the platform clients and Streams.

ByoBreakingChangeDetailsinterfacesource

Structured payload carried on a refused BYO breaking-change deploy.

ByoBreakingChangeErrorclasssource
ByoBreakingChangeError(message: string, details: ByoBreakingChangeDetails): unknown

Thrown when a BYO subgraph deploy is refused for a breaking schema change.

parseRetryAfterfunctionsource
parseRetryAfter(value?: null | string): null | number

Parse a `Retry-After` header: delta-seconds or an HTTP-date.

RateLimitErrorclasssource
RateLimitError(message?: string, retryAfter?: string): unknown

Thrown on a 429 — by both the platform clients and Streams.

SecondLayerErrorclasssource
SecondLayerError(shortMessage: string, options?: SecondLayerErrorOptions): unknown

Root of the SDK error family.

SecondLayerErrorOptionsinterfacesource

Options accepted by every error in the family.

ValidationErrorclasssource
ValidationError(message: string, status: number, body?: object): unknown

Thrown on a 4xx the caller can fix (bad cursor, bad params).

VersionConflictErrorclasssource
VersionConflictError(currentVersion: string, expectedVersion: string, message?: string): unknown

Thrown on optimistic-concurrency conflict when a deploy supplies an `expectedVersion` that no longer matches the server's stored version.

Proofs

fetchRewardSetfunctionsource
fetchRewardSet(opts: object): object

Resolve a reward set directly from a stacks-node (`/v3/stacker_set/{cycle}`), so a caller can verify the consensus layer against a node IT trusts rather than the reward set Secondlayer embedded in …

RewardSetinterfacesource
TransactionProofinterfacesource

Trustless transaction-inclusion proof verification.

TransactionProofVerifyResultinterfacesource
verifyTransactionProoffunctionsource
verifyTransactionProof(proof: TransactionProof, opts?: object): TransactionProofVerifyResult

Verify a transaction-inclusion proof.

x402

buildSignedX402Paymentfunctionsource
buildSignedX402Payment(opts: BuildSignedX402PaymentOptions): object

Build a signed, base64 `PAYMENT-SIGNATURE` header for one `accepts[]` entry.

BuildSignedX402PaymentOptionstypesource
createX402Clientfunctionsource
createX402Client(opts: X402ClientOptions): X402Client

A small client over {@link withX402}: `.get/.post` against `baseUrl`, returning parsed JSON plus the settlement receipt.

DEFAULT_PREFER_ASSETSvariablesource

Bitcoin-native first — sBTC is the compelling micropay asset; USDCx the dollar peg; STX the fallback.

payAndRetryfunctionsource
payAndRetry(doFetch: X402FetchFn, opts: PayAndRetryOptions): object

Low-level: run a request via a caller-controlled fetch; if it 402s, pay and retry once.

PayAndRetryOptionstypesource
readX402Challengefunctionsource
readX402Challenge(res: Response): object

Read the x402 challenge from a 402 response — prefer the wire header, fall back to the JSON body.

readX402Receiptfunctionsource
readX402Receipt(res: Response): null | X402Receipt

Read the settlement receipt from a paid 200 response.

resolveAccountNoncefunctionsource
resolveAccountNonce(address: string, nodeUrl?: string): object

Fetch the payer account's next nonce from a Stacks node (`/v2/accounts`).

selectOfferfunctionsource
selectOffer(challenge: X402Challenge, opts?: SelectOfferOptions): object

Choose an `accepts[]` entry by preference order, skipping any that exceed the per-asset spend cap.

SelectOfferOptionstypesource
withX402functionsource
withX402(baseFetch: object, opts: WithX402Options): X402Fetch

Wrap a `fetch` so requests transparently pay on 402: select an offer (by `preferAssets` + `maxAmountPerCall`), resolve the nonce, sign origin-only, and retry once with `PAYMENT-SIGNATURE`.

WithX402Optionstypesource
X402Accepttypesource

Client for the x402 pay-per-request rail.

X402Challengetypesource
X402Clienttypesource
X402ClientOptionstypesource
X402Fetchtypesource
X402Receipttypesource

Decoded `PAYMENT-RESPONSE` settlement receipt.

X402Resulttypesource
X402SpendGuardErrorclasssource
X402SpendGuardError(message: string): unknown

Thrown when no offered asset is within the caller's spend guard / preferences.

Other

consumerHealthfunctionsource
consumerHealth(options?: object): ConsumerHealth

Liveness for a consume loop.

ConsumerHealthinterfacesource

The two pieces every "deploy a consumer" guide leaves out, packaged: a liveness endpoint and a graceful-shutdown signal.

ConsumerSinkinterfacesource

A consumer sink: the destination adapter a consume loop writes through.

SbtcEventTopictypesource
shutdownSignalfunctionsource
shutdownSignal(options?: object): AbortSignal

An `AbortSignal` wired to SIGTERM/SIGINT (redeploys arrive as SIGTERM).

SinkTxtypesource

The transaction type a sink hands to `onBatch` (`ctx.tx`).

WithSinkTxtypesource

`ctx` gains `tx` exactly when a sink is attached; without one the shape is unchanged (an intersection with `unknown` is an identity, so contextual typing of `onBatch` callbacks never degrades to a …