<!-- source: https://secondlayer.tools/docs/filters-reference -->

# `@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](/docs/sdk) has the walkthrough.

## Build a filter

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

Import from `@secondlayer/stacks/filters`.

### fromSubgraphSource(source)

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.

```ts
fromSubgraphSource(source: SubgraphSourceSpec): ChainEventFilter<SubgraphMemberType>
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | `SubgraphSourceSpec` | yes |  |

### makeChainEventFilter(type, fields)

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.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | `T` | yes |  |
| `fields` | `F` | yes |  |

### on.stxTransfer(fields)

Matches STX transfers.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"stx_transfer">` | no |  |

### on.stxMint(fields)

Matches STX mints.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"stx_mint">` | no |  |

### on.stxBurn(fields)

Matches STX burns.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"stx_burn">` | no |  |

### on.stxLock(fields)

Matches STX lock events.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"stx_lock">` | no |  |

### on.ftTransfer(fields)

Matches fungible token transfers.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"ft_transfer">` | no |  |

### on.ftMint(fields)

Matches fungible token mints.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"ft_mint">` | no |  |

### on.ftBurn(fields)

Matches fungible token burns.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"ft_burn">` | no |  |

### on.nftTransfer(fields)

Matches NFT transfers.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"nft_transfer">` | no |  |

### on.nftMint(fields)

Matches NFT mints.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"nft_mint">` | no |  |

### on.nftBurn(fields)

Matches NFT burns.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"nft_burn">` | no |  |

### on.contractCall(fields)

Matches contract calls.

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

```ts
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 }>
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `factory` | `{ from: string; field: string }` | no |  |
| `trait` | `string` | no |  |
| `contractId` | `string \| readonly string[]` | no |  |
| `functionName` | `string` | no |  |
| `caller` | `string` | no |  |
| `abi` | `A` | no |  |

### on.contractDeploy(fields)

Matches contract deployments.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"contract_deploy">` | no |  |

### on.print(fields)

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.

```ts
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 }>
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `factory` | `{ from: string; field: string }` | no |  |
| `trait` | `string` | no |  |
| `contractId` | `string \| readonly string[]` | no |  |
| `topic` | `string` | no |  |
| `where` | `Record<string, string \| unknown[]>` | no |  |
| `prints` | `P` | no |  |

### on.nestedCall(fields)

Matches contract calls made from inside another contract.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"nested_contract_call">` | no |  |

### on.varSet(fields)

Matches data variable writes.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"var_set">` | no |  |

### on.mapSet(fields)

Matches `map-set` writes.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"map_set">` | no |  |

### on.mapInsert(fields)

Matches `map-insert` writes.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"map_insert">` | no |  |

### on.mapDelete(fields)

Matches `map-delete` writes.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"map_delete">` | no |  |

### on.sbtcDeposit(fields)

Matches sBTC deposits.

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"sbtc_deposit">` | no |  |

### on.sbtcWithdrawalCreate(fields)

Matches sBTC withdrawal requests.

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"sbtc_withdrawal_create">` | no |  |

### on.sbtcWithdrawalAccept(fields)

Matches accepted sBTC withdrawals.

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"sbtc_withdrawal_accept">` | no |  |

### on.sbtcWithdrawalReject(fields)

Matches rejected sBTC withdrawals.

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"sbtc_withdrawal_reject">` | no |  |

### on.sbtcWithdrawalSweptConfirmed(fields)

Matches sBTC withdrawals whose sweep has confirmed.

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | `Fields<"sbtc_withdrawal_swept_confirmed">` | no |  |

## Identifiers

Validate and narrow principals, contract ids and asset identifiers.

Import from `@secondlayer/stacks/filters`.

### assertAssetIdentifier(field, value)

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `field` | `string` | yes |  |
| `value` | `string` | yes |  |

### assetId(value)

Narrow a runtime string to an [`AssetIdentifier`](/docs/filters-reference#t-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.

```ts
assetId(value: string): AssetIdentifier
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `value` | `string` | yes |  |

### assertContractId(field, value)

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

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `field` | `string` | yes |  |
| `value` | `string` | yes |  |

### assertPrincipalish(field, value)

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.

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `field` | `string` | yes |  |
| `value` | `string` | yes |  |

### hasWildcard(value)

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.

```ts
hasWildcard(value: string): boolean
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `value` | `string` | yes |  |

### isPrincipal(value)

`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.

```ts
isPrincipal(value: string): value is Principal
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `value` | `string` | yes |  |

## Event types and specs

Every filter member and the spec each one takes.

Import from `@secondlayer/stacks/filters`.

### Constants

- `CHAIN_EVENT_FILTER_TYPES`: `["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", "ft_burn", "nft_transfer", "nft_mint", "nft_burn", "contract_call", "contract_deploy", "print_event", "nested_contract_call", "var_set", "map_set", "map_insert", "map_delete", "sbtc_deposit", "sbtc_withdrawal_create", "sbtc_withdrawal_accept", "sbtc_withdrawal_reject", "sbtc_withdrawal_swept_confirmed"]`. 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).
- `DECODED_EVENT_TYPES`: `["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", "ft_burn", "nft_transfer", "nft_mint", "nft_burn", "print"]`. The decoded event types.
- `VM_EVENT_TYPES`: `["nested_contract_call", "var_set", "map_set", "map_insert", "map_delete"]`. Opt-in node vm_events, stored names.
- `VM_NODE_TO_STORED_TYPE`: `{ contract_call_event: "nested_contract_call"; var_set_event: "var_set"; map_set_event: "map_set"; map_insert_event: "map_insert"; map_delete_event: "map_delete" }`. Node `/new_block.vm_events[].type` → stored/Index/Streams name.

## Types

- `AbiBuffer`
  - `buff`: `{ length: L }`
- `AbiContract`: Full Clarity contract ABI including functions, maps, variables, and token definitions.
  - `functions`: `readonly AbiFunction[]`
  - `maps`?: `readonly AbiMap[]`
  - `variables`?: `readonly AbiVariable[]`
  - `fungible_tokens`?: `readonly AbiFungibleToken[]`
  - `non_fungible_tokens`?: `readonly AbiNonFungibleToken[]`
  - `implemented_traits`?: `readonly string[]`
  - `defined_traits`?: `readonly AbiTraitDefinition[]`
- `AbiFunction`: A single Clarity function definition with name, access level, arguments, and return type.
  - `name`: `string`
  - `access`: `FunctionAccess`
  - `args`: `readonly FunctionArg[]`
  - `outputs`: `AbiType`
- `AbiFungibleToken`
  - `name`: `string`
- `AbiListType`
  - `list`: `{ type: AbiType; length: number }`
- `AbiMap`
  - `name`: `string`
  - `key`: `AbiType`
  - `value`: `AbiType`
- `AbiNonFungibleToken`
  - `name`: `string`
  - `type`: `AbiType`
- `AbiOptionalType`
  - `optional`: `AbiType`
- `AbiResponseType`
  - `response`: `{ ok: AbiType; error: AbiType }`
- `AbiStringAscii`
  - `string-ascii`: `{ length: L }`
- `AbiStringUtf8`
  - `string-utf8`: `{ length: L }`
- `AbiTraitDefinition`
  - `name`: `string`
  - `functions`: `readonly AbiTraitFunction[]`
- `AbiTraitFunction`
  - `name`: `string`
  - `access`: `TraitFunctionAccess`
  - `args`: `readonly FunctionArg[]`
  - `outputs`: `AbiType`
- `AbiTupleType`
  - `tuple`: `readonly { name: string; type: AbiType }[]`
- `AbiType`: Discriminated union of all Clarity value types (primitives, buffers, lists, tuples, optionals, responses).
- `AbiVariable`
  - `name`: `string`
  - `type`: `AbiType`
  - `access`: `VariableAccess`
- `AssetIdentifier`: A fungible or non-fungible asset identifier: `<contract>::<asset-name>`.
- `ChainEventFilter`: A chain-event filter: the spec fields plus its member's projections.
  - `toChainTrigger`: `() => ChainTriggerOf<S>`. Wire trigger for `webhooks.create({ triggers: [...] })`. BigInt amounts become strings here — the one sanctioned boundary.
- `ChainEventFilterSpec`: `StxTransferSpec \| StxMintSpec \| StxBurnSpec \| StxLockSpec \| FtTransferSpec \| FtMintSpec \| FtBurnSpec \| NftTransferSpec \| NftMintSpec \| NftBurnSpec \| ContractCallSpec \| ContractDeploySpec \| NestedContractCallSpec \| VarSetSpec \| MapSetSpec \| MapInsertSpec \| MapDeleteSpec \| PrintEventSpec \| SbtcDepositSpec \| SbtcWithdrawalCreateSpec \| SbtcWithdrawalAcceptSpec \| SbtcWithdrawalRejectSpec \| SbtcWithdrawalSweptConfirmedSpec`
- `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.*`.
  - `contractId`?: `string \| readonly string[]`. A spec's contract set passes through verbatim (the API takes up to 20).
  - `functionName`?: `string`
  - `sender`?: `string`. Populated from the spec's `caller` — the endpoint filters by tx sender, which is the caller.
  - `trait`?: `string`
- `ContractCallSpec`
  - `type`: `"contract_call"`
  - `contractId`?: `string \| readonly string[]`. One contract id, or a set of them (max 20). Mirrors the subgraphs filter — a router plus its pools is one source, not N.
  - `functionName`?: `string`
  - `caller`?: `string`
  - `abi`?: `AbiContract`. Contract ABI (`as const`) — preserved literally so `toSubgraphSource()` keeps typing `event.input` in `defineSubgraph`.
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `ContractDeploySpec`
  - `type`: `"contract_deploy"`
  - `deployer`?: `string`
  - `contractName`?: `string`
- `Fields`: The fields a filter factory takes for one event type, without `type`.
- `FtBurnSpec`
  - `type`: `"ft_burn"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `sender`?: `string`
  - `minAmount`?: `bigint`
  - `trait`?: `string`
- `FtMintSpec`
  - `type`: `"ft_mint"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `recipient`?: `string`
  - `minAmount`?: `bigint`
  - `trait`?: `string`
- `FtTransferSpec`
  - `type`: `"ft_transfer"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `sender`?: `string`
  - `recipient`?: `string`
  - `minAmount`?: `bigint`
  - `trait`?: `string`
- `FunctionAccess`: `"public" \| "read-only" \| "private"`
- `FunctionArg`
  - `name`: `string`
  - `type`: `AbiType`
- `IndexEventsParamsShape`: Params fragment for `index.events.*` (spread into list/walk/consume).
  - `eventType`: `"stx_transfer" \| "stx_mint" \| "stx_burn" \| "stx_lock" \| "ft_transfer" \| "ft_mint" \| "ft_burn" \| "nft_transfer" \| "nft_mint" \| "nft_burn" \| "nested_contract_call" \| "var_set" \| "map_set" \| "map_insert" \| "map_delete" \| "print"`
  - `contractId`?: `string \| readonly string[]`. A spec's contract set passes through verbatim (the API takes up to 20).
  - `assetIdentifier`?: `AssetIdentifier`
  - `sender`?: `string`
  - `recipient`?: `string`
  - `functionName`?: `string`
  - `caller`?: `string`
  - `map`?: `string`
  - `varName`?: `string`
  - `trait`?: `string`
- `MapDeleteSpec`
  - `type`: `"map_delete"`
  - `contractId`?: `string \| readonly string[]`
  - `map`?: `string`
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `MapInsertSpec`
  - `type`: `"map_insert"`
  - `contractId`?: `string \| readonly string[]`
  - `map`?: `string`
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `MapSetSpec`
  - `type`: `"map_set"`
  - `contractId`?: `string \| readonly string[]`
  - `map`?: `string`
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `NestedContractCallSpec`
  - `type`: `"nested_contract_call"`
  - `contractId`?: `string \| readonly string[]`
  - `functionName`?: `string`
  - `caller`?: `string`
  - `sender`?: `string`
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `NftBurnSpec`
  - `type`: `"nft_burn"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `sender`?: `string`
  - `trait`?: `string`
- `NftMintSpec`
  - `type`: `"nft_mint"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `recipient`?: `string`
  - `trait`?: `string`
- `NftTransferSpec`
  - `type`: `"nft_transfer"`
  - `assetIdentifier`?: `AssetIdentifier`
  - `sender`?: `string`
  - `recipient`?: `string`
  - `trait`?: `string`
- `Principal`: A validated Stacks principal (standard or contract).
  - `toString`: `() => string`. Returns a string representation of a string.
  - `charAt`: `(pos: number) => string`. Returns the character at the specified index.
  - `charCodeAt`: `(index: number) => number`. Returns the Unicode value of the character at the specified location.
  - `concat`: `(strings?: string[]) => string`. Returns a string that contains the concatenation of two or more strings.
  - `indexOf`: `(searchString: string, position?: number) => number`. Returns the position of the first occurrence of a substring.
  - `lastIndexOf`: `(searchString: string, position?: number) => number`. Returns the last occurrence of a substring in the string.
  - `localeCompare`: `{ (that: string): number; (that: string, locales?: string \| string[], options?: Intl.CollatorOptions): number; (that: string, locales?: Intl.LocalesArgument, options?: Intl.CollatorOptions): number; }`. Determines whether two strings are equivalent in the current locale. Determines whether two strings are equivalent in the current or specified locale.
  - `match`: `{ (regexp: string \| RegExp): RegExpMatchArray \| null; (matcher: { [Symbol.match](string: string): RegExpMatchArray \| null; }): RegExpMatchArray \| null; }`. Matches a string with a regular expression, and returns an array containing the results of that search. Matches a string or an object that supports being matched against, and returns an array containing the results of that search, or null if no matches are found.
  - `replace`: `{ (searchValue: string \| RegExp, replaceValue: string): string; (searchValue: string \| RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string; (searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string; }`. Replaces text in a string, using a regular expression or search string. Passes a string and `replaceValue` to the `[Symbol.replace]` method on `searchValue`. This method is expected to implement its own replacement algorithm. Replaces text in a string, using an object that supports replacement within a string.
  - `search`: `{ (regexp: string \| RegExp): number; (searcher: { [Symbol.search](string: string): number; }): number; }`. Finds the first substring match in a regular expression search.
  - `slice`: `(start?: number, end?: number) => string`. Returns a section of a string.
  - `split`: `{ (separator: string \| RegExp, limit?: number): string[]; (splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[]; }`. Split a string into substrings using the specified separator and return them as an array.
  - `substring`: `(start: number, end?: number) => string`. Returns the substring at the specified location within a String object.
  - `toLowerCase`: `() => string`. Converts all the alphabetic characters in a string to lowercase.
  - `toLocaleLowerCase`: `{ (locales?: string \| string[]): string; (locales?: Intl.LocalesArgument): string; }`. Converts all alphabetic characters to lowercase, taking into account the host environment's current locale.
  - `toUpperCase`: `() => string`. Converts all the alphabetic characters in a string to uppercase.
  - `toLocaleUpperCase`: `{ (locales?: string \| string[]): string; (locales?: Intl.LocalesArgument): string; }`. Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale.
  - `trim`: `() => string`. Removes the leading and trailing white space and line terminator characters from a string.
  - `length`: `number`. Returns the length of a String object.
  - `substr`: `(from: number, length?: number) => string`. Gets a substring beginning at the specified location and having the specified length.
  - `valueOf`: `() => string`. Returns the primitive value of the specified object.
  - `codePointAt`: `(pos: number) => number \| undefined`. Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point value of the UTF-16 encoded code point starting at the string element at position pos in the String resulting from converting this object to a String. If there is no element at that position, the result is undefined. If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.
  - `includes`: `(searchString: string, position?: number) => boolean`. Returns true if searchString appears as a substring of the result of converting this object to a String, at one or more positions that are greater than or equal to position; otherwise, returns false.
  - `endsWith`: `(searchString: string, endPosition?: number) => boolean`. Returns true if the sequence of elements of searchString converted to a String is the same as the corresponding elements of this object (converted to a String) starting at endPosition – length(this). Otherwise returns false.
  - `normalize`: `{ (form: "NFC" \| "NFD" \| "NFKC" \| "NFKD"): string; (form?: string): string; }`. Returns the String value result of normalizing the string into the normalization form named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
  - `repeat`: `(count: number) => string`. Returns a String value that is made from count copies appended together. If count is 0, the empty string is returned.
  - `startsWith`: `(searchString: string, position?: number) => boolean`. Returns true if the sequence of elements of searchString converted to a String is the same as the corresponding elements of this object (converted to a String) starting at position. Otherwise returns false.
  - `anchor`: `(name: string) => string`. Returns an `<a>` HTML anchor element and sets the name attribute to the text value
  - `big`: `() => string`. Returns a `<big>` HTML element
  - `blink`: `() => string`. Returns a `<blink>` HTML element
  - `bold`: `() => string`. Returns a `<b>` HTML element
  - `fixed`: `() => string`. Returns a `<tt>` HTML element
  - `fontcolor`: `(color: string) => string`. Returns a `<font>` HTML element and sets the color attribute value
  - `fontsize`: `{ (size: number): string; (size: string): string; }`. Returns a `<font>` HTML element and sets the size attribute value
  - `italics`: `() => string`. Returns an `<i>` HTML element
  - `link`: `(url: string) => string`. Returns an `<a>` HTML element and sets the href attribute value
  - `small`: `() => string`. Returns a `<small>` HTML element
  - `strike`: `() => string`. Returns a `<strike>` HTML element
  - `sub`: `() => string`. Returns a `<sub>` HTML element
  - `sup`: `() => string`. Returns a `<sup>` HTML element
  - `padStart`: `(maxLength: number, fillString?: string) => string`. Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length. The padding is applied from the start (left) of the current string.
  - `padEnd`: `(maxLength: number, fillString?: string) => string`. Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length. The padding is applied from the end (right) of the current string.
  - `trimEnd`: `() => string`. Removes the trailing white space and line terminator characters from a string.
  - `trimStart`: `() => string`. Removes the leading white space and line terminator characters from a string.
  - `trimLeft`: `() => string`. Removes the leading white space and line terminator characters from a string.
  - `trimRight`: `() => string`. Removes the trailing white space and line terminator characters from a string.
  - `matchAll`: `(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>`. Matches a string with a regular expression, and returns an iterable of matches containing the results of that search.
  - `replaceAll`: `{ (searchValue: string \| RegExp, replaceValue: string): string; (searchValue: string \| RegExp, replacer: (substring: string, ...args: any[]) => string): string; }`. Replace all instances of a substring in a string, using a regular expression or search string.
  - `at`: `(index: number) => string \| undefined`. Returns a new String consisting of the single UTF-16 code unit located at the specified index.
  - `isWellFormed`: `() => boolean`. Returns true if all leading surrogates and trailing surrogates appear paired and in order.
  - `toWellFormed`: `() => string`. Returns a string where all lone or out-of-order surrogates have been replaced by the Unicode replacement character (U+FFFD).
  - `__principal`: `unique symbol`
- `PrintEventSpec`
  - `type`: `"print_event"`
  - `contractId`?: `string \| readonly string[]`. One contract id, or a set of them (max 20).
  - `topic`?: `string`
  - `where`?: `Record<string, string \| readonly string[]>`. Equality on top-level keys of the decoded print tuple, spelled as the contract prints them (`signer-manager`). A value matches the field's JSON form: principals `SP…`, uints as decimal strings, bools `"true"`/`"false"`, buffers `0x…`. An array is any-of (max 20); keys AND (max 10). Nested tuples and lists never match.
  - `prints`?: `Record<string, Record<string, PrintFieldType>>`. Per-topic field schema — preserved literally so `toSubgraphSource()` keeps the discriminated-union narrowing of `event.data`.
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`
- `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`: `"sbtc_deposit"`
  - `sender`?: `string`
  - `minAmount`?: `bigint`
  - `maxAmount`?: `bigint`
  - `bitcoinTxid`?: `string`
  - `requestId`?: `number`
- `SbtcWithdrawalAcceptSpec`
  - `type`: `"sbtc_withdrawal_accept"`
  - `requestId`?: `number`
  - `sweepTxid`?: `string`
- `SbtcWithdrawalCreateSpec`
  - `type`: `"sbtc_withdrawal_create"`
  - `sender`?: `string`
  - `minAmount`?: `bigint`
  - `maxAmount`?: `bigint`
  - `requestId`?: `number`
- `SbtcWithdrawalRejectSpec`
  - `type`: `"sbtc_withdrawal_reject"`
  - `requestId`?: `number`
- `SbtcWithdrawalSweptConfirmedSpec`
  - `type`: `"sbtc_withdrawal_swept_confirmed"`
  - `requestId`?: `number`
  - `sweepTxid`?: `string`
- `SpecFor`: The filter spec for one chain event type.
- `StreamsParamsShape`: Params fragment for classic `streams.events.*` (Streams 1.0).
  - `types`: `readonly ("stx_transfer" \| "stx_mint" \| "stx_burn" \| "stx_lock" \| "ft_transfer" \| "ft_mint" \| "ft_burn" \| "nft_transfer" \| "nft_mint" \| "nft_burn" \| "print")[]`
  - `contractId`?: `string \| readonly string[]`
  - `sender`?: `string`
  - `recipient`?: `string`
  - `assetIdentifier`?: `AssetIdentifier`
- `StreamsVmParamsShape`: VM member projection: `clock` is the `"vm"` literal so SDK overload 1 matches.
  - `types`: `[T]`
  - `clock`: `"vm"`
  - `contractId`?: `string \| readonly string[]`
- `StxBurnSpec`
  - `type`: `"stx_burn"`
  - `sender`?: `string`
  - `minAmount`?: `bigint`
- `StxLockSpec`
  - `type`: `"stx_lock"`
  - `lockedAddress`?: `string`
  - `minAmount`?: `bigint`
- `StxMintSpec`
  - `type`: `"stx_mint"`
  - `recipient`?: `string`
  - `minAmount`?: `bigint`
- `StxTransferSpec`
  - `type`: `"stx_transfer"`
  - `sender`?: `string`
  - `recipient`?: `string`
  - `minAmount`?: `bigint`
  - `maxAmount`?: `bigint`
- `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`: `"var_set"`
  - `contractId`?: `string \| readonly string[]`
  - `varName`?: `string`
  - `trait`?: `string`
  - `factory`?: `{ from: string; field: string }`

## Notes for agents

- Import from '@secondlayer/stacks/filters'. 'on.<event>(fields)' returns a filter with 'toIndexParams', 'toStreamsParams', 'toChainTrigger' and 'toSubgraphSource'.
- A field a surface cannot express throws at projection time; it never matches silently wider.
- Every name on this page is a real export read from the package source, so a signature here is the one the installed version ships.

## Setup

Ensure setup once, skipping any step already done:
- Skill: `bunx skills add ryanwaits/secondlayer --skill secondlayer -y`
- CLI: `bun add -g @secondlayer/cli`
- Instance: `secondlayer init` writes `INSTANCE_TOKEN`. Loopback `/v1` reads need no key.
- Hosted/archive: export `SECONDLAYER_API_KEY` (`sk-sl_*`) or buy credits with `secondlayer credits buy` (`balance`, `refill`), then `secondlayer whoami`
