@secondlayer/stacks 2.19.2 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,389 @@
1
+ declare const DECODED_EVENT_TYPES: readonly ["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", "ft_burn", "nft_transfer", "nft_mint", "nft_burn", "print"];
2
+ type DecodedEventType = (typeof DECODED_EVENT_TYPES)[number];
3
+ /** Every chain-event filter member across all four surfaces: the 10 decoded
4
+ * token/STX types, the three contract-shaped types (spelled as subgraphs and
5
+ * triggers spell them — Index/Streams project `print_event` → `print`), and
6
+ * the five sBTC lifecycle types (Subscriptions-only). */
7
+ declare const CHAIN_EVENT_FILTER_TYPES: readonly ["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", "sbtc_deposit", "sbtc_withdrawal_create", "sbtc_withdrawal_accept", "sbtc_withdrawal_reject", "sbtc_withdrawal_swept_confirmed"];
8
+ type ChainEventFilterType = (typeof CHAIN_EVENT_FILTER_TYPES)[number];
9
+ type AbiUInt128 = "uint128";
10
+ type AbiInt128 = "int128";
11
+ type AbiBool = "bool";
12
+ type AbiPrincipal = "principal";
13
+ type AbiTraitReference = "trait_reference";
14
+ type AbiNone = "none";
15
+ type AbiStringAscii<L extends number = number> = {
16
+ "string-ascii": {
17
+ length: L
18
+ }
19
+ };
20
+ type AbiStringUtf8<L extends number = number> = {
21
+ "string-utf8": {
22
+ length: L
23
+ }
24
+ };
25
+ type AbiBuffer<L extends number = number> = {
26
+ buff: {
27
+ length: L
28
+ }
29
+ };
30
+ type AbiPrimitiveType = AbiUInt128 | AbiInt128 | AbiBool | AbiPrincipal | AbiTraitReference | AbiNone | AbiStringAscii | AbiStringUtf8 | AbiBuffer;
31
+ interface AbiListType {
32
+ list: {
33
+ type: AbiType
34
+ length: number
35
+ };
36
+ }
37
+ interface AbiTupleType {
38
+ tuple: ReadonlyArray<{
39
+ name: string
40
+ type: AbiType
41
+ }>;
42
+ }
43
+ interface AbiOptionalType {
44
+ optional: AbiType;
45
+ }
46
+ interface AbiResponseType {
47
+ response: {
48
+ ok: AbiType
49
+ error: AbiType
50
+ };
51
+ }
52
+ /** Discriminated union of all Clarity value types (primitives, buffers, lists, tuples, optionals, responses). */
53
+ type AbiType = AbiPrimitiveType | AbiListType | AbiTupleType | AbiOptionalType | AbiResponseType;
54
+ type FunctionAccess = "public" | "read-only" | "private";
55
+ interface FunctionArg {
56
+ name: string;
57
+ type: AbiType;
58
+ }
59
+ /** A single Clarity function definition with name, access level, arguments, and return type. */
60
+ interface AbiFunction {
61
+ name: string;
62
+ access: FunctionAccess;
63
+ args: ReadonlyArray<FunctionArg>;
64
+ outputs: AbiType;
65
+ }
66
+ type VariableAccess = "constant" | "variable";
67
+ interface AbiVariable {
68
+ name: string;
69
+ type: AbiType;
70
+ access: VariableAccess;
71
+ }
72
+ interface AbiMap {
73
+ name: string;
74
+ key: AbiType;
75
+ value: AbiType;
76
+ }
77
+ interface AbiFungibleToken {
78
+ name: string;
79
+ }
80
+ interface AbiNonFungibleToken {
81
+ name: string;
82
+ type: AbiType;
83
+ }
84
+ type TraitFunctionAccess = Exclude<FunctionAccess, "private">;
85
+ interface AbiTraitFunction {
86
+ name: string;
87
+ access: TraitFunctionAccess;
88
+ args: ReadonlyArray<FunctionArg>;
89
+ outputs: AbiType;
90
+ }
91
+ interface AbiTraitDefinition {
92
+ name: string;
93
+ functions: ReadonlyArray<AbiTraitFunction>;
94
+ }
95
+ /** Full Clarity contract ABI including functions, maps, variables, and token definitions. */
96
+ interface AbiContract {
97
+ functions: ReadonlyArray<AbiFunction>;
98
+ maps?: ReadonlyArray<AbiMap>;
99
+ variables?: ReadonlyArray<AbiVariable>;
100
+ fungible_tokens?: ReadonlyArray<AbiFungibleToken>;
101
+ non_fungible_tokens?: ReadonlyArray<AbiNonFungibleToken>;
102
+ implemented_traits?: ReadonlyArray<string>;
103
+ defined_traits?: ReadonlyArray<AbiTraitDefinition>;
104
+ }
105
+ /** Print field-schema vocabulary (structural mirror of the subgraphs
106
+ * `ColumnType`; kept literal so `toSubgraphSource()` preserves narrowing). */
107
+ type PrintFieldType = "uint" | "int" | "text" | "principal" | "boolean" | "timestamp" | "jsonb";
108
+ interface StxTransferSpec {
109
+ type: "stx_transfer";
110
+ sender?: string;
111
+ recipient?: string;
112
+ minAmount?: bigint;
113
+ maxAmount?: bigint;
114
+ }
115
+ interface StxMintSpec {
116
+ type: "stx_mint";
117
+ recipient?: string;
118
+ minAmount?: bigint;
119
+ }
120
+ interface StxBurnSpec {
121
+ type: "stx_burn";
122
+ sender?: string;
123
+ minAmount?: bigint;
124
+ }
125
+ interface StxLockSpec {
126
+ type: "stx_lock";
127
+ lockedAddress?: string;
128
+ minAmount?: bigint;
129
+ }
130
+ /** Scope to contracts conforming to a trait/standard (e.g. "sip-010") instead
131
+ * of a fixed contract. Index + Subgraphs + Subscriptions; Streams has no
132
+ * trait resolution — `toStreamsParams()` throws if set. */
133
+ type TraitScope = {
134
+ trait?: string
135
+ };
136
+ interface FtTransferSpec extends TraitScope {
137
+ type: "ft_transfer";
138
+ assetIdentifier?: string;
139
+ sender?: string;
140
+ recipient?: string;
141
+ minAmount?: bigint;
142
+ }
143
+ interface FtMintSpec extends TraitScope {
144
+ type: "ft_mint";
145
+ assetIdentifier?: string;
146
+ recipient?: string;
147
+ minAmount?: bigint;
148
+ }
149
+ interface FtBurnSpec extends TraitScope {
150
+ type: "ft_burn";
151
+ assetIdentifier?: string;
152
+ sender?: string;
153
+ minAmount?: bigint;
154
+ }
155
+ interface NftTransferSpec extends TraitScope {
156
+ type: "nft_transfer";
157
+ assetIdentifier?: string;
158
+ sender?: string;
159
+ recipient?: string;
160
+ }
161
+ interface NftMintSpec extends TraitScope {
162
+ type: "nft_mint";
163
+ assetIdentifier?: string;
164
+ recipient?: string;
165
+ }
166
+ interface NftBurnSpec extends TraitScope {
167
+ type: "nft_burn";
168
+ assetIdentifier?: string;
169
+ sender?: string;
170
+ }
171
+ interface ContractCallSpec extends TraitScope {
172
+ type: "contract_call";
173
+ contractId?: string;
174
+ functionName?: string;
175
+ caller?: string;
176
+ /** Contract ABI (`as const`) — preserved literally so `toSubgraphSource()`
177
+ * keeps typing `event.input` in `defineSubgraph`. */
178
+ abi?: AbiContract;
179
+ }
180
+ interface ContractDeploySpec {
181
+ type: "contract_deploy";
182
+ deployer?: string;
183
+ contractName?: string;
184
+ }
185
+ interface PrintEventSpec extends TraitScope {
186
+ type: "print_event";
187
+ contractId?: string;
188
+ topic?: string;
189
+ /** Per-topic field schema — preserved literally so `toSubgraphSource()`
190
+ * keeps the discriminated-union narrowing of `event.data`. */
191
+ prints?: Record<string, Record<string, PrintFieldType>>;
192
+ }
193
+ interface SbtcDepositSpec {
194
+ type: "sbtc_deposit";
195
+ sender?: string;
196
+ minAmount?: bigint;
197
+ maxAmount?: bigint;
198
+ bitcoinTxid?: string;
199
+ requestId?: number;
200
+ }
201
+ interface SbtcWithdrawalCreateSpec {
202
+ type: "sbtc_withdrawal_create";
203
+ sender?: string;
204
+ minAmount?: bigint;
205
+ maxAmount?: bigint;
206
+ requestId?: number;
207
+ }
208
+ interface SbtcWithdrawalAcceptSpec {
209
+ type: "sbtc_withdrawal_accept";
210
+ requestId?: number;
211
+ sweepTxid?: string;
212
+ }
213
+ interface SbtcWithdrawalRejectSpec {
214
+ type: "sbtc_withdrawal_reject";
215
+ requestId?: number;
216
+ }
217
+ interface SbtcWithdrawalSweptConfirmedSpec {
218
+ type: "sbtc_withdrawal_swept_confirmed";
219
+ requestId?: number;
220
+ sweepTxid?: string;
221
+ }
222
+ type ChainEventFilterSpec = StxTransferSpec | StxMintSpec | StxBurnSpec | StxLockSpec | FtTransferSpec | FtMintSpec | FtBurnSpec | NftTransferSpec | NftMintSpec | NftBurnSpec | ContractCallSpec | ContractDeploySpec | PrintEventSpec | SbtcDepositSpec | SbtcWithdrawalCreateSpec | SbtcWithdrawalAcceptSpec | SbtcWithdrawalRejectSpec | SbtcWithdrawalSweptConfirmedSpec;
223
+ type SpecFor<T extends ChainEventFilterType> = Extract<ChainEventFilterSpec, {
224
+ type: T
225
+ }>;
226
+ /** Wire shape of a chain trigger (Subscriptions), derived per member from
227
+ * the spec: same fields, with `bigint` amounts stringified (uint128 exceeds
228
+ * JS safe integers) and the type-only `abi`/`prints` decorations dropped.
229
+ * Structurally assignable to the SDK's `ChainTrigger` union. */
230
+ type ChainTriggerOf<S> = { [K in keyof Omit<S, "abi" | "prints">] : S[K] extends bigint | undefined ? Exclude<S[K], bigint> | string : S[K] };
231
+ /** Loose trigger shape (any member). */
232
+ type ChainTriggerShape = ChainTriggerOf<ChainEventFilterSpec>;
233
+ /** Params fragment for `index.events.*` (spread into list/walk/consume). */
234
+ type IndexEventsParamsShape = {
235
+ eventType: DecodedEventType
236
+ contractId?: string
237
+ assetIdentifier?: string
238
+ sender?: string
239
+ recipient?: string
240
+ trait?: string
241
+ };
242
+ /** Params fragment for `index.contractCalls.*`. */
243
+ type ContractCallsParamsShape = {
244
+ contractId?: string
245
+ functionName?: string
246
+ sender?: string
247
+ trait?: string
248
+ };
249
+ /** Params fragment for `streams.events.*`. */
250
+ type StreamsParamsShape = {
251
+ types: readonly DecodedEventType[]
252
+ contractId?: string
253
+ sender?: string
254
+ recipient?: string
255
+ assetIdentifier?: string
256
+ };
257
+ type DecodedMember = "stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print_event";
258
+ type ProjectionsFor<
259
+ T extends ChainEventFilterType,
260
+ S
261
+ > = {
262
+ /** Wire trigger for `subscriptions.create({ triggers: [...] })`. BigInt
263
+ * amounts become strings here — the one sanctioned boundary. */
264
+ toChainTrigger(): ChainTriggerOf<S>
265
+ } & (T extends DecodedMember ? {
266
+ /** Params for `index.events.list/walk/consume` (merge your own
267
+ * `limit`/`fromHeight`/`txContext` etc. on top). */
268
+ toIndexParams<Extra extends Record<string, unknown>>(extra?: Extra): IndexEventsParamsShape & Extra
269
+ /** Params for `streams.events.list/consume/stream`. Throws if the
270
+ * filter uses `trait` (Streams has no trait resolution) or a
271
+ * min/max amount (Streams filters have no amount predicates). */
272
+ toStreamsParams<Extra extends Record<string, unknown>>(extra?: Extra): StreamsParamsShape & Extra
273
+ } : {}) & (T extends "contract_call" ? {
274
+ /** Params for `index.contractCalls.list/walk/consume`. */
275
+ toContractCallsParams<Extra extends Record<string, unknown>>(extra?: Extra): ContractCallsParamsShape & Extra
276
+ } : {}) & (T extends Exclude<ChainEventFilterType, `sbtc_${string}`> ? {
277
+ /** The `sources` entry for `defineSubgraph` — literal `prints`/`abi`
278
+ * types are preserved, so handler narrowing survives. */
279
+ toSubgraphSource(): S
280
+ } : {});
281
+ /**
282
+ * A canonical chain-event filter: the spec fields plus the projections its
283
+ * member supports. Write the filter once; project it to a query
284
+ * (`toIndexParams`), a stream (`toStreamsParams`), a webhook trigger
285
+ * (`toChainTrigger`), or a subgraph source (`toSubgraphSource`).
286
+ */
287
+ type ChainEventFilter<
288
+ T extends ChainEventFilterType = ChainEventFilterType,
289
+ S extends {
290
+ type: T
291
+ } = SpecFor<T>
292
+ > = S & ProjectionsFor<T, S>;
293
+ /** Build a canonical filter: validated spec + the projections its member
294
+ * supports (methods are attached per member at runtime, matching the
295
+ * type-level gating exactly). `const F` preserves field literals — a
296
+ * `prints`/`abi` declaration keeps its exact type through
297
+ * `toSubgraphSource()`, which is what feeds `defineSubgraph` narrowing. */
298
+ declare function makeChainEventFilter<
299
+ T extends ChainEventFilterType,
300
+ const F extends Omit<SpecFor<T>, "type">
301
+ >(type: T, fields: F): ChainEventFilter<T, {
302
+ type: T
303
+ } & F>;
304
+ /**
305
+ * Rehydrate a canonical filter from a subgraph-source-shaped object (the
306
+ * inverse of `toSubgraphSource`). Powers migration and the round-trip
307
+ * property gate: `toSubgraphSource(fromSubgraphSource(f))` must deep-equal
308
+ * `f` for every production subgraph source.
309
+ */
310
+ declare function fromSubgraphSource(source: ChainEventFilterSpec): ChainEventFilter;
311
+ type Fields<T extends ChainEventFilterType> = Omit<SpecFor<T>, "type">;
312
+ /** The `on.*` namespace, annotated explicitly — bunup's dts emitter needs an
313
+ * annotation on exported values (an inferred object of generic factories
314
+ * collapses to `{}` in the emitted declarations). */
315
+ interface OnNamespace {
316
+ stxTransfer(fields?: Fields<"stx_transfer">): ChainEventFilter<"stx_transfer">;
317
+ stxMint(fields?: Fields<"stx_mint">): ChainEventFilter<"stx_mint">;
318
+ stxBurn(fields?: Fields<"stx_burn">): ChainEventFilter<"stx_burn">;
319
+ stxLock(fields?: Fields<"stx_lock">): ChainEventFilter<"stx_lock">;
320
+ ftTransfer(fields?: Fields<"ft_transfer">): ChainEventFilter<"ft_transfer">;
321
+ ftMint(fields?: Fields<"ft_mint">): ChainEventFilter<"ft_mint">;
322
+ ftBurn(fields?: Fields<"ft_burn">): ChainEventFilter<"ft_burn">;
323
+ nftTransfer(fields?: Fields<"nft_transfer">): ChainEventFilter<"nft_transfer">;
324
+ nftMint(fields?: Fields<"nft_mint">): ChainEventFilter<"nft_mint">;
325
+ nftBurn(fields?: Fields<"nft_burn">): ChainEventFilter<"nft_burn">;
326
+ /** `abi` literals are preserved (`const A`) so `toSubgraphSource()` keeps
327
+ * typing `event.input` inside `defineSubgraph`. */
328
+ contractCall<const A extends AbiContract | undefined = undefined>(fields?: Omit<SpecFor<"contract_call">, "type" | "abi"> & {
329
+ abi?: A
330
+ }): ChainEventFilter<"contract_call", {
331
+ type: "contract_call"
332
+ } & Omit<SpecFor<"contract_call">, "type" | "abi"> & {
333
+ abi?: A
334
+ }>;
335
+ contractDeploy(fields?: Fields<"contract_deploy">): ChainEventFilter<"contract_deploy">;
336
+ /** Canonical member is `print_event` (as Subgraphs and Subscriptions spell
337
+ * it); `toIndexParams`/`toStreamsParams` project to `print`. `prints`
338
+ * literals are preserved (`const P`) for per-topic `event.data` narrowing. */
339
+ print<const P extends Record<string, Record<string, PrintFieldType>> | undefined = undefined>(fields?: Omit<SpecFor<"print_event">, "type" | "prints"> & {
340
+ prints?: P
341
+ }): ChainEventFilter<"print_event", {
342
+ type: "print_event"
343
+ } & Omit<SpecFor<"print_event">, "type" | "prints"> & {
344
+ prints?: P
345
+ }>;
346
+ sbtcDeposit(fields?: Fields<"sbtc_deposit">): ChainEventFilter<"sbtc_deposit">;
347
+ sbtcWithdrawalCreate(fields?: Fields<"sbtc_withdrawal_create">): ChainEventFilter<"sbtc_withdrawal_create">;
348
+ sbtcWithdrawalAccept(fields?: Fields<"sbtc_withdrawal_accept">): ChainEventFilter<"sbtc_withdrawal_accept">;
349
+ sbtcWithdrawalReject(fields?: Fields<"sbtc_withdrawal_reject">): ChainEventFilter<"sbtc_withdrawal_reject">;
350
+ sbtcWithdrawalSweptConfirmed(fields?: Fields<"sbtc_withdrawal_swept_confirmed">): ChainEventFilter<"sbtc_withdrawal_swept_confirmed">;
351
+ }
352
+ /**
353
+ * `on.*` — one filter vocabulary for every surface.
354
+ *
355
+ * ```ts
356
+ * import { on } from "@secondlayer/stacks/filters";
357
+ *
358
+ * const usdc = on.ftTransfer({ assetIdentifier: USDC, minAmount: 1_000_000n });
359
+ *
360
+ * sl.index.events.list(usdc.toIndexParams({ limit: 100 })); // pull
361
+ * sl.streams.events.consume({ ...usdc.toStreamsParams(), onBatch });
362
+ * sl.subscriptions.create({ name, url, triggers: [usdc.toChainTrigger()] });
363
+ * defineSubgraph({ sources: { usdc: usdc.toSubgraphSource() }, schema, handlers });
364
+ * ```
365
+ *
366
+ * A surface a member can't reach is a missing method (compile error), and a
367
+ * field a surface can't express throws at projection time — never a silent
368
+ * zero-row or over-wide match.
369
+ */
370
+ declare const on: OnNamespace;
371
+ /** A validated Stacks principal (standard or contract). Branded so downstream
372
+ * code can require "already validated" without re-checking. */
373
+ type Principal = string & {
374
+ readonly __principal: unique symbol
375
+ };
376
+ /** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
377
+ declare function isPrincipal(value: string): value is Principal;
378
+ /** Subscriptions match `*` wildcards in principal/identifier patterns; every
379
+ * other surface treats the value literally. */
380
+ declare function hasWildcard(value: string): boolean;
381
+ /** Throw unless `value` is a principal or a wildcard pattern. The factories
382
+ * call this so a swapped argument (asset id where a sender belongs, typo'd
383
+ * address) fails at construction — not as a silent zero-row query. */
384
+ declare function assertPrincipalish(field: string, value: string): void;
385
+ /** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
386
+ declare function assertAssetIdentifier(field: string, value: string): void;
387
+ /** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
388
+ declare function assertContractId(field: string, value: string): void;
389
+ export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assertPrincipalish, assertContractId, assertAssetIdentifier, StxTransferSpec, StxMintSpec, StxLockSpec, StxBurnSpec, StreamsParamsShape, SpecFor, SbtcWithdrawalSweptConfirmedSpec, SbtcWithdrawalRejectSpec, SbtcWithdrawalCreateSpec, SbtcWithdrawalAcceptSpec, SbtcDepositSpec, PrintFieldType, PrintEventSpec, Principal, NftTransferSpec, NftMintSpec, NftBurnSpec, IndexEventsParamsShape, FtTransferSpec, FtMintSpec, FtBurnSpec, DecodedEventType, DECODED_EVENT_TYPES, ContractDeploySpec, ContractCallsParamsShape, ContractCallSpec, ChainTriggerShape, ChainTriggerOf, ChainEventFilterType, ChainEventFilterSpec, ChainEventFilter, CHAIN_EVENT_FILTER_TYPES };
@@ -0,0 +1,260 @@
1
+ import {
2
+ isValidAddress
3
+ } from "../../shared/stacks-azp00pve.js";
4
+ import"../../shared/stacks-qs5fzts5.js";
5
+ import"../../shared/stacks-cfazrteq.js";
6
+
7
+ // src/filters/event-types.ts
8
+ var DECODED_EVENT_TYPES = [
9
+ "stx_transfer",
10
+ "stx_mint",
11
+ "stx_burn",
12
+ "stx_lock",
13
+ "ft_transfer",
14
+ "ft_mint",
15
+ "ft_burn",
16
+ "nft_transfer",
17
+ "nft_mint",
18
+ "nft_burn",
19
+ "print"
20
+ ];
21
+ var CHAIN_EVENT_FILTER_TYPES = [
22
+ "stx_transfer",
23
+ "stx_mint",
24
+ "stx_burn",
25
+ "stx_lock",
26
+ "ft_transfer",
27
+ "ft_mint",
28
+ "ft_burn",
29
+ "nft_transfer",
30
+ "nft_mint",
31
+ "nft_burn",
32
+ "contract_call",
33
+ "contract_deploy",
34
+ "print_event",
35
+ "sbtc_deposit",
36
+ "sbtc_withdrawal_create",
37
+ "sbtc_withdrawal_accept",
38
+ "sbtc_withdrawal_reject",
39
+ "sbtc_withdrawal_swept_confirmed"
40
+ ];
41
+ // src/filters/validate.ts
42
+ function isPrincipal(value) {
43
+ const parts = value.split(".");
44
+ if (parts.length > 2)
45
+ return false;
46
+ const [addr, contractName] = parts;
47
+ if (!addr || !isValidAddress(addr))
48
+ return false;
49
+ if (parts.length === 2 && !contractName)
50
+ return false;
51
+ return true;
52
+ }
53
+ function hasWildcard(value) {
54
+ return value.includes("*");
55
+ }
56
+ function assertPrincipalish(field, value) {
57
+ if (hasWildcard(value))
58
+ return;
59
+ if (!isPrincipal(value)) {
60
+ throw new Error(`${field} "${value}" is not a valid Stacks principal (SP…/ST…, optionally .contract-name).`);
61
+ }
62
+ }
63
+ function assertAssetIdentifier(field, value) {
64
+ if (hasWildcard(value))
65
+ return;
66
+ const [contractId, assetName, ...rest] = value.split("::");
67
+ if (!contractId || !assetName || rest.length > 0 || !contractId.includes(".") || !isPrincipal(contractId)) {
68
+ throw new Error(`${field} "${value}" is not a valid asset identifier (SP….contract-name::asset-name). Passing a bare contract id here matches zero rows — use contractId for that.`);
69
+ }
70
+ }
71
+ function assertContractId(field, value) {
72
+ if (hasWildcard(value))
73
+ return;
74
+ if (value.includes("::")) {
75
+ throw new Error(`${field} "${value}" is an asset identifier, not a contract id — use assetIdentifier for that.`);
76
+ }
77
+ if (!value.includes(".") || !isPrincipal(value)) {
78
+ throw new Error(`${field} "${value}" is not a valid contract id (SP….contract-name).`);
79
+ }
80
+ }
81
+
82
+ // src/filters/factories.ts
83
+ var PRINCIPAL_FIELDS = new Set([
84
+ "sender",
85
+ "recipient",
86
+ "caller",
87
+ "deployer",
88
+ "lockedAddress"
89
+ ]);
90
+ var AMOUNT_FIELDS = new Set(["minAmount", "maxAmount"]);
91
+ var DECORATIVE_FIELDS = new Set(["abi", "prints"]);
92
+ function specEntries(spec) {
93
+ return Object.entries(spec).filter(([key, value]) => key !== "type" && value !== undefined);
94
+ }
95
+ function validateSpec(spec) {
96
+ for (const [key, value] of specEntries(spec)) {
97
+ if (PRINCIPAL_FIELDS.has(key)) {
98
+ assertPrincipalish(key, value);
99
+ } else if (key === "assetIdentifier") {
100
+ assertAssetIdentifier(key, value);
101
+ } else if (key === "contractId") {
102
+ assertContractId(key, value);
103
+ }
104
+ }
105
+ }
106
+ function unsupported(surface, field, hint) {
107
+ throw new Error(`${field} cannot be expressed on ${surface} — ${hint}. Drop the field from the filter or use the surface that supports it.`);
108
+ }
109
+ function assertNoWildcards(surface, spec) {
110
+ for (const [key, value] of specEntries(spec)) {
111
+ if (typeof value === "string" && hasWildcard(value)) {
112
+ unsupported(surface, `${key} wildcard "${value}"`, "wildcard patterns are Subscriptions-only");
113
+ }
114
+ }
115
+ }
116
+ function toChainTrigger(spec) {
117
+ const out = {};
118
+ for (const [key, value] of specEntries(spec)) {
119
+ if (DECORATIVE_FIELDS.has(key))
120
+ continue;
121
+ out[key] = typeof value === "bigint" ? value.toString() : value;
122
+ }
123
+ return { type: spec.type, ...out };
124
+ }
125
+ function toIndexParams(spec, extra = {}) {
126
+ assertNoWildcards("Index events", spec);
127
+ const out = {
128
+ eventType: spec.type === "print_event" ? "print" : spec.type
129
+ };
130
+ for (const [key, value] of specEntries(spec)) {
131
+ if (DECORATIVE_FIELDS.has(key))
132
+ continue;
133
+ if (AMOUNT_FIELDS.has(key)) {
134
+ unsupported("Index events", key, "amount predicates are Subscriptions/Subgraphs-only; filter client-side on the decoded rows");
135
+ }
136
+ if (key === "topic") {
137
+ unsupported("Index events", "topic", "per-topic reads are Subgraphs/Subscriptions-only (or read the contract's print feed and switch on topic)");
138
+ }
139
+ if (key === "lockedAddress") {
140
+ unsupported("Index events", "lockedAddress", "stx_lock address filtering is Subscriptions/Subgraphs-only");
141
+ }
142
+ if (key === "caller") {
143
+ unsupported("Index events", "caller", "contract-call fields live on index.contractCalls");
144
+ }
145
+ out[key] = value;
146
+ }
147
+ return { ...out, ...extra };
148
+ }
149
+ function toStreamsParams(spec, extra = {}) {
150
+ assertNoWildcards("Streams", spec);
151
+ const out = {
152
+ types: [spec.type === "print_event" ? "print" : spec.type]
153
+ };
154
+ for (const [key, value] of specEntries(spec)) {
155
+ if (DECORATIVE_FIELDS.has(key))
156
+ continue;
157
+ if (AMOUNT_FIELDS.has(key)) {
158
+ unsupported("Streams", key, "amount predicates are Subscriptions/Subgraphs-only");
159
+ }
160
+ if (key === "trait") {
161
+ unsupported("Streams", "trait", "Streams has no trait resolution — Index and Subgraphs do");
162
+ }
163
+ if (key === "topic") {
164
+ unsupported("Streams", "topic", "per-topic filtering is Subgraphs/Subscriptions-only");
165
+ }
166
+ if (key === "lockedAddress") {
167
+ unsupported("Streams", "lockedAddress", "stx_lock address filtering is Subscriptions/Subgraphs-only");
168
+ }
169
+ out[key] = value;
170
+ }
171
+ return { ...out, ...extra };
172
+ }
173
+ function toContractCallsParams(spec, extra = {}) {
174
+ assertNoWildcards("Index contract-calls", spec);
175
+ const out = {};
176
+ for (const [key, value] of specEntries(spec)) {
177
+ if (DECORATIVE_FIELDS.has(key))
178
+ continue;
179
+ if (key === "caller") {
180
+ unsupported("Index contract-calls", "caller", "caller filtering is Subscriptions/Subgraphs-only (the endpoint filters by tx sender)");
181
+ }
182
+ out[key] = value;
183
+ }
184
+ return { ...out, ...extra };
185
+ }
186
+ function toSubgraphSource(spec) {
187
+ return Object.fromEntries([
188
+ ["type", spec.type],
189
+ ...specEntries(spec)
190
+ ]);
191
+ }
192
+ var DECODED_MEMBERS = new Set([
193
+ "stx_transfer",
194
+ "stx_mint",
195
+ "stx_burn",
196
+ "stx_lock",
197
+ "ft_transfer",
198
+ "ft_mint",
199
+ "ft_burn",
200
+ "nft_transfer",
201
+ "nft_mint",
202
+ "nft_burn",
203
+ "print_event"
204
+ ]);
205
+ function makeChainEventFilter(type, fields) {
206
+ const spec = { type, ...fields };
207
+ validateSpec(spec);
208
+ const filter = { ...spec };
209
+ filter.toChainTrigger = () => toChainTrigger(spec);
210
+ if (DECODED_MEMBERS.has(type)) {
211
+ filter.toIndexParams = (extra) => toIndexParams(spec, extra);
212
+ filter.toStreamsParams = (extra) => toStreamsParams(spec, extra);
213
+ }
214
+ if (type === "contract_call") {
215
+ filter.toContractCallsParams = (extra) => toContractCallsParams(spec, extra);
216
+ }
217
+ if (!type.startsWith("sbtc_")) {
218
+ filter.toSubgraphSource = () => toSubgraphSource(spec);
219
+ }
220
+ return filter;
221
+ }
222
+ function fromSubgraphSource(source) {
223
+ const { type, ...fields } = source;
224
+ return makeChainEventFilter(type, fields);
225
+ }
226
+ var on = {
227
+ stxTransfer: (fields = {}) => makeChainEventFilter("stx_transfer", fields),
228
+ stxMint: (fields = {}) => makeChainEventFilter("stx_mint", fields),
229
+ stxBurn: (fields = {}) => makeChainEventFilter("stx_burn", fields),
230
+ stxLock: (fields = {}) => makeChainEventFilter("stx_lock", fields),
231
+ ftTransfer: (fields = {}) => makeChainEventFilter("ft_transfer", fields),
232
+ ftMint: (fields = {}) => makeChainEventFilter("ft_mint", fields),
233
+ ftBurn: (fields = {}) => makeChainEventFilter("ft_burn", fields),
234
+ nftTransfer: (fields = {}) => makeChainEventFilter("nft_transfer", fields),
235
+ nftMint: (fields = {}) => makeChainEventFilter("nft_mint", fields),
236
+ nftBurn: (fields = {}) => makeChainEventFilter("nft_burn", fields),
237
+ contractCall: (fields = {}) => makeChainEventFilter("contract_call", fields),
238
+ contractDeploy: (fields = {}) => makeChainEventFilter("contract_deploy", fields),
239
+ print: (fields = {}) => makeChainEventFilter("print_event", fields),
240
+ sbtcDeposit: (fields = {}) => makeChainEventFilter("sbtc_deposit", fields),
241
+ sbtcWithdrawalCreate: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_create", fields),
242
+ sbtcWithdrawalAccept: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_accept", fields),
243
+ sbtcWithdrawalReject: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_reject", fields),
244
+ sbtcWithdrawalSweptConfirmed: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_swept_confirmed", fields)
245
+ };
246
+ export {
247
+ on,
248
+ makeChainEventFilter,
249
+ isPrincipal,
250
+ hasWildcard,
251
+ fromSubgraphSource,
252
+ assertPrincipalish,
253
+ assertContractId,
254
+ assertAssetIdentifier,
255
+ DECODED_EVENT_TYPES,
256
+ CHAIN_EVENT_FILTER_TYPES
257
+ };
258
+
259
+ //# debugId=D4FDF12B084C2C7164756E2164756E21
260
+ //# sourceMappingURL=index.js.map