@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.
| 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) | void | Throw unless value looks like SP….contract::asset (or a wildcard). |
| assetId(value) | AssetIdentifier | Narrow a runtime string to an AssetIdentifier, validating it. |
| assertContractId(field, value) | void | Throw unless value is a contract id SP….name (or a wildcard). |
| assertPrincipalish(field, value) | void | Throw unless value is a principal or a wildcard pattern. |
| hasWildcard(value) | boolean | Tells whether a value contains a * wildcard. |
| isPrincipal(value) | value is Principal | true 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.
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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.
Parameters
hover a row to find it in the codeOptions
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).
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeRequired
valuerequiredstring |
Throw unless value is a contract id SP….name (or a wildcard).
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeRequired
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.
Parameters
hover a row to find it in the codeRequired
valuerequiredstring |
Event types and specs
Every filter member and the spec each one takes.
import from @secondlayer/stacks/filters
Constants
CHAIN_EVENT_FILTER_TYPESprint_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["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", …VM_EVENT_TYPES["nested_contract_call", "var_set", "map_set", "map_insert", "map_delete"]VM_NODE_TO_STORED_TYPE/new_block.vm_events[].type → stored/Index/Streams name. { contract_call_event: "nested_contract_call"; var_set_event: "var_set"; map_se…AbiBufferbuffAbiContractAbiFunctionAbiFungibleTokennameAbiListTypelistAbiMapname, key, valueAbiNonFungibleTokenname, typeAbiOptionalTypeoptionalAbiResponseTyperesponseAbiStringAsciistring-asciiAbiStringUtf8string-utf8AbiTraitDefinitionname, functionsAbiTraitFunctionname, access, args, outputsAbiTupleTypetupleAbiTypeAbiVariablename, type, accessAssetIdentifier<contract>::<asset-name>.ChainEventFilterChainEventFilterSpecStxTransferSpec | StxMintSpec | StxBurnSpec | StxLockSpec | FtTransferSpec | FtMintSpec | FtBurnSpec | NftTra…ChainTriggerOfbigint amounts stringified (uint128 exceeds JS safe integers) and the type-only abi/prints decorations dropped.ChainTriggerShapeContractCallsParamsShapeindex.contractCalls.*.ContractCallSpectype, contractId, functionName, caller, abi, trait, …ContractDeploySpectype, deployer, contractNameFieldstype.FtBurnSpectype, assetIdentifier, sender, minAmount, traitFtMintSpectype, assetIdentifier, recipient, minAmount, traitFtTransferSpectype, assetIdentifier, sender, recipient, minAmount, traitFunctionAccess"public" | "read-only" | "private"FunctionArgname, typeIndexEventsParamsShapeindex.events.* (spread into list/walk/consume).MapDeleteSpectype, contractId, map, trait, factoryMapInsertSpectype, contractId, map, trait, factoryMapSetSpectype, contractId, map, trait, factoryNestedContractCallSpectype, contractId, functionName, caller, sender, trait, …NftBurnSpectype, assetIdentifier, sender, traitNftMintSpectype, assetIdentifier, recipient, traitNftTransferSpectype, assetIdentifier, sender, recipient, traitPrincipalPrintEventSpectype, contractId, topic, where, prints, trait, …PrintFieldTypePrintField in @secondlayer/subgraphs.PrintScalarTypeColumnType).SbtcDepositSpectype, sender, minAmount, maxAmount, bitcoinTxid, requestIdSbtcWithdrawalAcceptSpectype, requestId, sweepTxidSbtcWithdrawalCreateSpectype, sender, minAmount, maxAmount, requestIdSbtcWithdrawalRejectSpectype, requestIdSbtcWithdrawalSweptConfirmedSpectype, requestId, sweepTxidSpecForStreamsParamsShapestreams.events.* (Streams 1.0).StreamsVmParamsShapeclock is the "vm" literal so SDK overload 1 matches.StxBurnSpectype, sender, minAmountStxLockSpectype, lockedAddress, minAmountStxMintSpectype, recipient, minAmountStxTransferSpectype, sender, recipient, minAmount, maxAmountSubgraphMemberTypeSubgraphSourceSpectoSubgraphSource() output / fromSubgraphSource() input).TraitFunctionAccess"public" | "read-only"VariableAccess"constant" | "variable"VarSetSpectype, contractId, varName, trait, factory