.md

@secondlayer/stacks/filters

One spelling for a chain event filter. on.ftTransfer(...) builds it once, then projects it to Index params, Streams params, a webhook trigger or a subgraph source. The SDK guide has the walkthrough.

@secondlayer/stacks@6.5.231 functionsfrom source with openpkgSDK guide
Build a filter
fromSubgraphSource(source)ChainEventFilter<SubgraphMemberType>Rebuilds a canonical filter from a subgraph source object.
makeChainEventFilter(type, fields)ChainEventFilter<T, { type: T } & F>Builds a canonical filter from a member type and its fields.
on.stxTransfer(fields)ChainEventFilter<"stx_transfer">Matches STX transfers.
on.stxMint(fields)ChainEventFilter<"stx_mint">Matches STX mints.
on.stxBurn(fields)ChainEventFilter<"stx_burn">Matches STX burns.
on.stxLock(fields)ChainEventFilter<"stx_lock">Matches STX lock events.
on.ftTransfer(fields)ChainEventFilter<"ft_transfer">Matches fungible token transfers.
on.ftMint(fields)ChainEventFilter<"ft_mint">Matches fungible token mints.
on.ftBurn(fields)ChainEventFilter<"ft_burn">Matches fungible token burns.
on.nftTransfer(fields)ChainEventFilter<"nft_transfer">Matches NFT transfers.
on.nftMint(fields)ChainEventFilter<"nft_mint">Matches NFT mints.
on.nftBurn(fields)ChainEventFilter<"nft_burn">Matches NFT burns.
on.contractCall(fields)ChainEventFilter<"contract_call", {…Matches contract calls.
on.contractDeploy(fields)ChainEventFilter<"contract_deploy">Matches contract deployments.
on.print(fields)ChainEventFilter<"print_event", { t…Matches print events.
on.nestedCall(fields)ChainEventFilter<"nested_contract_c…Matches contract calls made from inside another contract.
on.varSet(fields)ChainEventFilter<"var_set">Matches data variable writes.
on.mapSet(fields)ChainEventFilter<"map_set">Matches map-set writes.
on.mapInsert(fields)ChainEventFilter<"map_insert">Matches map-insert writes.
on.mapDelete(fields)ChainEventFilter<"map_delete">Matches map-delete writes.
on.sbtcDeposit(fields)ChainEventFilter<"sbtc_deposit">Matches sBTC deposits.
on.sbtcWithdrawalCreate(fields)ChainEventFilter<"sbtc_withdrawal_c…Matches sBTC withdrawal requests.
on.sbtcWithdrawalAccept(fields)ChainEventFilter<"sbtc_withdrawal_a…Matches accepted sBTC withdrawals.
on.sbtcWithdrawalReject(fields)ChainEventFilter<"sbtc_withdrawal_r…Matches rejected sBTC withdrawals.
on.sbtcWithdrawalSweptConfirmed(fields)ChainEventFilter<"sbtc_withdrawal_s…Matches sBTC withdrawals whose sweep has confirmed.
Identifiers
assertAssetIdentifier(field, value)voidThrow unless value looks like SP….contract::asset (or a wildcard).
assetId(value)AssetIdentifierNarrow a runtime string to an AssetIdentifier, validating it.
assertContractId(field, value)voidThrow unless value is a contract id SP….name (or a wildcard).
assertPrincipalish(field, value)voidThrow unless value is a principal or a wildcard pattern.
hasWildcard(value)booleanTells whether a value contains a * wildcard.
isPrincipal(value)value is Principaltrue for a standard (SP…/ST…) or contract (SP….name) principal.

Build a filter

on.* builds one filter that every surface can project to its own shape.

import from @secondlayer/stacks/filters

Rebuilds a canonical filter from a subgraph source object.

It is the inverse of toSubgraphSource. It powers migration and the round-trip property gate: toSubgraphSource(fromSubgraphSource(f)) must deep-equal f for every production subgraph source.

fromSubgraphSource(source: SubgraphSourceSpec): ChainEventFilter<SubgraphMemberType>

Parameters

hover a row to find it in the code

Required

sourcerequiredSubgraphSourceSpec
Returns ChainEventFilter<SubgraphMemberType>
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Builds a canonical filter from a member type and its fields.

It validates the spec and attaches the projections its member supports. Methods are attached per member at runtime, matching the type-level gating exactly. const F preserves field literals, so a prints or abi declaration keeps its exact type through toSubgraphSource(), which is what feeds defineSubgraph narrowing.

makeChainEventFilter<T extends ChainEventFilterType, const F extends Omit<SpecFor<T>, "type">>(
type: T,
fields: F,
): ChainEventFilter<T, { type: T } & F>

Parameters

hover a row to find it in the code

Required

typerequiredT
fieldsrequiredF
Returns ChainEventFilter<T, { type: T } & F>
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches STX transfers.

on.stxTransfer(fields?: Fields<"stx_transfer">): ChainEventFilter<"stx_transfer">

Parameters

hover a row to find it in the code

Options

fieldsFields<"stx_transfer">
Returns ChainEventFilter<"stx_transfer">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches STX mints.

on.stxMint(fields?: Fields<"stx_mint">): ChainEventFilter<"stx_mint">

Parameters

hover a row to find it in the code

Options

fieldsFields<"stx_mint">
Returns ChainEventFilter<"stx_mint">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches STX burns.

on.stxBurn(fields?: Fields<"stx_burn">): ChainEventFilter<"stx_burn">

Parameters

hover a row to find it in the code

Options

fieldsFields<"stx_burn">
Returns ChainEventFilter<"stx_burn">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches STX lock events.

on.stxLock(fields?: Fields<"stx_lock">): ChainEventFilter<"stx_lock">

Parameters

hover a row to find it in the code

Options

fieldsFields<"stx_lock">
Returns ChainEventFilter<"stx_lock">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches fungible token transfers.

on.ftTransfer(fields?: Fields<"ft_transfer">): ChainEventFilter<"ft_transfer">

Parameters

hover a row to find it in the code

Options

fieldsFields<"ft_transfer">
Returns ChainEventFilter<"ft_transfer">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches fungible token mints.

on.ftMint(fields?: Fields<"ft_mint">): ChainEventFilter<"ft_mint">

Parameters

hover a row to find it in the code

Options

fieldsFields<"ft_mint">
Returns ChainEventFilter<"ft_mint">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches fungible token burns.

on.ftBurn(fields?: Fields<"ft_burn">): ChainEventFilter<"ft_burn">

Parameters

hover a row to find it in the code

Options

fieldsFields<"ft_burn">
Returns ChainEventFilter<"ft_burn">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches NFT transfers.

on.nftTransfer(fields?: Fields<"nft_transfer">): ChainEventFilter<"nft_transfer">

Parameters

hover a row to find it in the code

Options

fieldsFields<"nft_transfer">
Returns ChainEventFilter<"nft_transfer">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches NFT mints.

on.nftMint(fields?: Fields<"nft_mint">): ChainEventFilter<"nft_mint">

Parameters

hover a row to find it in the code

Options

fieldsFields<"nft_mint">
Returns ChainEventFilter<"nft_mint">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches NFT burns.

on.nftBurn(fields?: Fields<"nft_burn">): ChainEventFilter<"nft_burn">

Parameters

hover a row to find it in the code

Options

fieldsFields<"nft_burn">
Returns ChainEventFilter<"nft_burn">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches contract calls.

abi literals are preserved (const A), so toSubgraphSource() keeps typing event.input inside defineSubgraph.

on.contractCall(
fields?: {
factory?: { from: string; field: string };
trait?: string;
contractId?: string | readonly string[];
functionName?: string;
caller?: string;
}
& { abi?: A },
): ChainEventFilter<"contract_call", { type: "contract_call" } & { factory?: { from: string; field: string }; trait?: string; contractId?: string | readonly string[]; functionName?: string; caller?: string } & { abi?: A }>

Parameters

hover a row to find it in the code

Options

factory{ from: string; field: string }
traitstring
contractIdstring | readonly string[]
functionNamestring
callerstring
abiA
Returns ChainEventFilter<"contract_call", { type: "contract_cal…
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches contract deployments.

on.contractDeploy(
fields?: Fields<"contract_deploy">,
): ChainEventFilter<"contract_deploy">

Parameters

hover a row to find it in the code

Options

fieldsFields<"contract_deploy">
Returns ChainEventFilter<"contract_deploy">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches print events.

The canonical member is print_event, as Subgraphs and Webhooks spell it; toIndexParams and toStreamsParams project to print. prints literals are preserved (const P), so event.data narrows per topic.

on.print(
fields?: {
factory?: { from: string; field: string };
trait?: string;
contractId?: string | readonly string[];
topic?: string;
where?: Record<string, string | unknown[]>;
}
& { prints?: P },
): ChainEventFilter<"print_event", { type: "print_event" } & { factory?: { from: string; field: string }; trait?: string; contractId?: string | readonly string[]; topic?: string; where?: Record<string, string | unknown[]> } & { prints?: P }>

Parameters

hover a row to find it in the code

Options

factory{ from: string; field: string }
traitstring
contractIdstring | readonly string[]
topicstring
whereRecord<string, string | unknown[]>
printsP
Returns ChainEventFilter<"print_event", { type: "print_event" }…
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches contract calls made from inside another contract.

on.nestedCall(
fields?: Fields<"nested_contract_call">,
): ChainEventFilter<"nested_contract_call">

Parameters

hover a row to find it in the code

Options

fieldsFields<"nested_contract_call">
Returns ChainEventFilter<"nested_contract_call">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches data variable writes.

on.varSet(fields?: Fields<"var_set">): ChainEventFilter<"var_set">

Parameters

hover a row to find it in the code

Options

fieldsFields<"var_set">
Returns ChainEventFilter<"var_set">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches map-set writes.

on.mapSet(fields?: Fields<"map_set">): ChainEventFilter<"map_set">

Parameters

hover a row to find it in the code

Options

fieldsFields<"map_set">
Returns ChainEventFilter<"map_set">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches map-insert writes.

on.mapInsert(fields?: Fields<"map_insert">): ChainEventFilter<"map_insert">

Parameters

hover a row to find it in the code

Options

fieldsFields<"map_insert">
Returns ChainEventFilter<"map_insert">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches map-delete writes.

on.mapDelete(fields?: Fields<"map_delete">): ChainEventFilter<"map_delete">

Parameters

hover a row to find it in the code

Options

fieldsFields<"map_delete">
Returns ChainEventFilter<"map_delete">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches sBTC deposits.

Webhooks only: it has no Index, Streams or subgraph projection.

on.sbtcDeposit(fields?: Fields<"sbtc_deposit">): ChainEventFilter<"sbtc_deposit">

Parameters

hover a row to find it in the code

Options

fieldsFields<"sbtc_deposit">
Returns ChainEventFilter<"sbtc_deposit">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches sBTC withdrawal requests.

Webhooks only: it has no Index, Streams or subgraph projection.

on.sbtcWithdrawalCreate(
fields?: Fields<"sbtc_withdrawal_create">,
): ChainEventFilter<"sbtc_withdrawal_create">

Parameters

hover a row to find it in the code

Options

fieldsFields<"sbtc_withdrawal_create">
Returns ChainEventFilter<"sbtc_withdrawal_create">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches accepted sBTC withdrawals.

Webhooks only: it has no Index, Streams or subgraph projection.

on.sbtcWithdrawalAccept(
fields?: Fields<"sbtc_withdrawal_accept">,
): ChainEventFilter<"sbtc_withdrawal_accept">

Parameters

hover a row to find it in the code

Options

fieldsFields<"sbtc_withdrawal_accept">
Returns ChainEventFilter<"sbtc_withdrawal_accept">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches rejected sBTC withdrawals.

Webhooks only: it has no Index, Streams or subgraph projection.

on.sbtcWithdrawalReject(
fields?: Fields<"sbtc_withdrawal_reject">,
): ChainEventFilter<"sbtc_withdrawal_reject">

Parameters

hover a row to find it in the code

Options

fieldsFields<"sbtc_withdrawal_reject">
Returns ChainEventFilter<"sbtc_withdrawal_reject">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Matches sBTC withdrawals whose sweep has confirmed.

Webhooks only: it has no Index, Streams or subgraph projection.

on.sbtcWithdrawalSweptConfirmed(
fields?: Fields<"sbtc_withdrawal_swept_confirmed">,
): ChainEventFilter<"sbtc_withdrawal_swept_confirmed">

Parameters

hover a row to find it in the code

Options

fieldsFields<"sbtc_withdrawal_swept_confirmed">
Returns ChainEventFilter<"sbtc_withdrawal_swept_confirmed">
toChainTrigger
Wire trigger for webhooks.create({ triggers: [...] }). BigInt amounts become strings here — the one sanctioned boundary.

Identifiers

Validate and narrow principals, contract ids and asset identifiers.

import from @secondlayer/stacks/filters

Throw unless value looks like SP….contract::asset (or a wildcard).

assertAssetIdentifier(field: string, value: string): void

Parameters

hover a row to find it in the code

Required

fieldrequiredstring
valuerequiredstring

Narrow a runtime string to an AssetIdentifier, validating it.

The escape hatch for config-driven values: assetId(process.env.ASSET!) throws on a contract id instead of letting it through to a zero-row query.

assetId(value: string): AssetIdentifier

Parameters

hover a row to find it in the code

Required

valuerequiredstring

Throw unless value is a contract id SP….name (or a wildcard).

assertContractId(field: string, value: string): void

Parameters

hover a row to find it in the code

Required

fieldrequiredstring
valuerequiredstring

Throw unless value is a principal or a wildcard pattern. The factories call this so a swapped argument (asset id where a sender belongs, typo'd address) fails at construction — not as a silent zero-row query.

assertPrincipalish(field: string, value: string): void

Parameters

hover a row to find it in the code

Required

fieldrequiredstring
valuerequiredstring

Tells whether a value contains a * wildcard.

Webhooks and Subgraph sources match * wildcards in principal and identifier patterns; every other surface treats the value literally.

hasWildcard(value: string): boolean

Parameters

hover a row to find it in the code

Required

valuerequiredstring

true for a standard (SP…/ST…) or contract (SP….name) principal. Shares parsePrincipal with the ABI guards so the two surfaces can't disagree about what a principal is.

isPrincipal(value: string): value is Principal

Parameters

hover a row to find it in the code

Required

valuerequiredstring

Event types and specs

Every filter member and the spec each one takes.

import from @secondlayer/stacks/filters

Constants

CHAIN_EVENT_FILTER_TYPES
Every chain-event filter member across all four surfaces: the 10 decoded token/STX types, the three contract-shaped types (spelled as subgraphs and triggers spell them — Index/Streams project print_event → print), and the five sBTC lifecycle types (Webhooks-only). ["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", …
DECODED_EVENT_TYPES
The decoded event types. ["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", …
VM_EVENT_TYPES
Opt-in node vm_events, stored names. ["nested_contract_call", "var_set", "map_set", "map_insert", "map_delete"]
VM_NODE_TO_STORED_TYPE
Node /new_block.vm_events[].type → stored/Index/Streams name. { contract_call_event: "nested_contract_call"; var_set_event: "var_set"; map_se…
AbiBuffer
buff
AbiContract
Full Clarity contract ABI including functions, maps, variables, and token definitions.
AbiFunction
A single Clarity function definition with name, access level, arguments, and return type.
AbiFungibleToken
name
AbiListType
list
AbiMap
name, key, value
AbiNonFungibleToken
name, type
AbiOptionalType
optional
AbiResponseType
response
AbiStringAscii
string-ascii
AbiStringUtf8
string-utf8
AbiTraitDefinition
name, functions
AbiTraitFunction
name, access, args, outputs
AbiTupleType
tuple
AbiType
Discriminated union of all Clarity value types (primitives, buffers, lists, tuples, optionals, responses).
AbiVariable
name, type, access
AssetIdentifier
A fungible or non-fungible asset identifier: <contract>::<asset-name>.
ChainEventFilter
A chain-event filter: the spec fields plus its member's projections.
ChainEventFilterSpec
StxTransferSpec | StxMintSpec | StxBurnSpec | StxLockSpec | FtTransferSpec | FtMintSpec | FtBurnSpec | NftTra…
ChainTriggerOf
Wire shape of a chain trigger (Webhooks), derived per member from the spec: same fields, with bigint amounts stringified (uint128 exceeds JS safe integers) and the type-only abi/prints decorations dropped.
ChainTriggerShape
Loose trigger shape (any member).
ContractCallsParamsShape
Params fragment for index.contractCalls.*.
ContractCallSpec
type, contractId, functionName, caller, abi, trait, …
ContractDeploySpec
type, deployer, contractName
Fields
The fields a filter factory takes for one event type, without type.
FtBurnSpec
type, assetIdentifier, sender, minAmount, trait
FtMintSpec
type, assetIdentifier, recipient, minAmount, trait
FtTransferSpec
type, assetIdentifier, sender, recipient, minAmount, trait
FunctionAccess
"public" | "read-only" | "private"
FunctionArg
name, type
IndexEventsParamsShape
Params fragment for index.events.* (spread into list/walk/consume).
MapDeleteSpec
type, contractId, map, trait, factory
MapInsertSpec
type, contractId, map, trait, factory
MapSetSpec
type, contractId, map, trait, factory
NestedContractCallSpec
type, contractId, functionName, caller, sender, trait, …
NftBurnSpec
type, assetIdentifier, sender, trait
NftMintSpec
type, assetIdentifier, recipient, trait
NftTransferSpec
type, assetIdentifier, sender, recipient, trait
Principal
A validated Stacks principal (standard or contract).
PrintEventSpec
type, contractId, topic, where, prints, trait, …
PrintFieldType
One declared print field — structural mirror of PrintField in @secondlayer/subgraphs.
PrintScalarType
Scalar print field types (structural mirror of the subgraphs ColumnType).
SbtcDepositSpec
type, sender, minAmount, maxAmount, bitcoinTxid, requestId
SbtcWithdrawalAcceptSpec
type, requestId, sweepTxid
SbtcWithdrawalCreateSpec
type, sender, minAmount, maxAmount, requestId
SbtcWithdrawalRejectSpec
type, requestId
SbtcWithdrawalSweptConfirmedSpec
type, requestId, sweepTxid
SpecFor
The filter spec for one chain event type.
StreamsParamsShape
Params fragment for classic streams.events.* (Streams 1.0).
StreamsVmParamsShape
VM member projection: clock is the "vm" literal so SDK overload 1 matches.
StxBurnSpec
type, sender, minAmount
StxLockSpec
type, lockedAddress, minAmount
StxMintSpec
type, recipient, minAmount
StxTransferSpec
type, sender, recipient, minAmount, maxAmount
SubgraphMemberType
The members you can use as subgraph sources.
SubgraphSourceSpec
A subgraph-source-shaped filter object (the toSubgraphSource() output / fromSubgraphSource() input).
TraitFunctionAccess
"public" | "read-only"
VariableAccess
"constant" | "variable"
VarSetSpec
type, contractId, varName, trait, factory
Edit on GitHub