@secondlayer/stacks 2.19.2 → 2.20.1

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,400 @@
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
+ /** The members expressible as subgraph sources (everything but the
227
+ * Subscriptions-only sBTC lifecycle types). Instantiating
228
+ * `ChainEventFilter<SubgraphMemberType>` keeps `toSubgraphSource` present:
229
+ * the conditional in `ProjectionsFor` evaluates over this whole union
230
+ * (non-distributive at an instantiated site), and every member qualifies. */
231
+ type SubgraphMemberType = Exclude<ChainEventFilterType, `sbtc_${string}`>;
232
+ /** A subgraph-source-shaped filter object (the `toSubgraphSource()` output /
233
+ * `fromSubgraphSource()` input). */
234
+ type SubgraphSourceSpec = Extract<ChainEventFilterSpec, {
235
+ type: SubgraphMemberType
236
+ }>;
237
+ /** Wire shape of a chain trigger (Subscriptions), derived per member from
238
+ * the spec: same fields, with `bigint` amounts stringified (uint128 exceeds
239
+ * JS safe integers) and the type-only `abi`/`prints` decorations dropped.
240
+ * Structurally assignable to the SDK's `ChainTrigger` union. */
241
+ type ChainTriggerOf<S> = { [K in keyof Omit<S, "abi" | "prints">] : S[K] extends bigint | undefined ? Exclude<S[K], bigint> | string : S[K] };
242
+ /** Loose trigger shape (any member). */
243
+ type ChainTriggerShape = ChainTriggerOf<ChainEventFilterSpec>;
244
+ /** Params fragment for `index.events.*` (spread into list/walk/consume). */
245
+ type IndexEventsParamsShape = {
246
+ eventType: DecodedEventType
247
+ contractId?: string
248
+ assetIdentifier?: string
249
+ sender?: string
250
+ recipient?: string
251
+ trait?: string
252
+ };
253
+ /** Params fragment for `index.contractCalls.*`. */
254
+ type ContractCallsParamsShape = {
255
+ contractId?: string
256
+ functionName?: string
257
+ sender?: string
258
+ trait?: string
259
+ };
260
+ /** Params fragment for `streams.events.*`. */
261
+ type StreamsParamsShape = {
262
+ types: readonly DecodedEventType[]
263
+ contractId?: string
264
+ sender?: string
265
+ recipient?: string
266
+ assetIdentifier?: string
267
+ };
268
+ type DecodedMember = "stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print_event";
269
+ type ProjectionsFor<
270
+ T extends ChainEventFilterType,
271
+ S
272
+ > = {
273
+ /** Wire trigger for `subscriptions.create({ triggers: [...] })`. BigInt
274
+ * amounts become strings here — the one sanctioned boundary. */
275
+ toChainTrigger(): ChainTriggerOf<S>
276
+ } & (T extends DecodedMember ? {
277
+ /** Params for `index.events.list/walk/consume` (merge your own
278
+ * `limit`/`fromHeight`/`txContext` etc. on top). */
279
+ toIndexParams<Extra extends Record<string, unknown>>(extra?: Extra): IndexEventsParamsShape & Extra
280
+ /** Params for `streams.events.list/consume/stream`. Throws if the
281
+ * filter uses `trait` (Streams has no trait resolution) or a
282
+ * min/max amount (Streams filters have no amount predicates). */
283
+ toStreamsParams<Extra extends Record<string, unknown>>(extra?: Extra): StreamsParamsShape & Extra
284
+ } : {}) & (T extends "contract_call" ? {
285
+ /** Params for `index.contractCalls.list/walk/consume`. */
286
+ toContractCallsParams<Extra extends Record<string, unknown>>(extra?: Extra): ContractCallsParamsShape & Extra
287
+ } : {}) & (T extends Exclude<ChainEventFilterType, `sbtc_${string}`> ? {
288
+ /** The `sources` entry for `defineSubgraph` — literal `prints`/`abi`
289
+ * types are preserved, so handler narrowing survives. */
290
+ toSubgraphSource(): S
291
+ } : {});
292
+ /**
293
+ * A canonical chain-event filter: the spec fields plus the projections its
294
+ * member supports. Write the filter once; project it to a query
295
+ * (`toIndexParams`), a stream (`toStreamsParams`), a webhook trigger
296
+ * (`toChainTrigger`), or a subgraph source (`toSubgraphSource`).
297
+ */
298
+ type ChainEventFilter<
299
+ T extends ChainEventFilterType = ChainEventFilterType,
300
+ S extends {
301
+ type: T
302
+ } = SpecFor<T>
303
+ > = S & ProjectionsFor<T, S>;
304
+ /** Build a canonical filter: validated spec + the projections its member
305
+ * supports (methods are attached per member at runtime, matching the
306
+ * type-level gating exactly). `const F` preserves field literals — a
307
+ * `prints`/`abi` declaration keeps its exact type through
308
+ * `toSubgraphSource()`, which is what feeds `defineSubgraph` narrowing. */
309
+ declare function makeChainEventFilter<
310
+ T extends ChainEventFilterType,
311
+ const F extends Omit<SpecFor<T>, "type">
312
+ >(type: T, fields: F): ChainEventFilter<T, {
313
+ type: T
314
+ } & F>;
315
+ /**
316
+ * Rehydrate a canonical filter from a subgraph-source-shaped object (the
317
+ * inverse of `toSubgraphSource`). Powers migration and the round-trip
318
+ * property gate: `toSubgraphSource(fromSubgraphSource(f))` must deep-equal
319
+ * `f` for every production subgraph source.
320
+ */
321
+ declare function fromSubgraphSource(source: SubgraphSourceSpec): ChainEventFilter<SubgraphMemberType>;
322
+ type Fields<T extends ChainEventFilterType> = Omit<SpecFor<T>, "type">;
323
+ /** The `on.*` namespace, annotated explicitly — bunup's dts emitter needs an
324
+ * annotation on exported values (an inferred object of generic factories
325
+ * collapses to `{}` in the emitted declarations). */
326
+ interface OnNamespace {
327
+ stxTransfer(fields?: Fields<"stx_transfer">): ChainEventFilter<"stx_transfer">;
328
+ stxMint(fields?: Fields<"stx_mint">): ChainEventFilter<"stx_mint">;
329
+ stxBurn(fields?: Fields<"stx_burn">): ChainEventFilter<"stx_burn">;
330
+ stxLock(fields?: Fields<"stx_lock">): ChainEventFilter<"stx_lock">;
331
+ ftTransfer(fields?: Fields<"ft_transfer">): ChainEventFilter<"ft_transfer">;
332
+ ftMint(fields?: Fields<"ft_mint">): ChainEventFilter<"ft_mint">;
333
+ ftBurn(fields?: Fields<"ft_burn">): ChainEventFilter<"ft_burn">;
334
+ nftTransfer(fields?: Fields<"nft_transfer">): ChainEventFilter<"nft_transfer">;
335
+ nftMint(fields?: Fields<"nft_mint">): ChainEventFilter<"nft_mint">;
336
+ nftBurn(fields?: Fields<"nft_burn">): ChainEventFilter<"nft_burn">;
337
+ /** `abi` literals are preserved (`const A`) so `toSubgraphSource()` keeps
338
+ * typing `event.input` inside `defineSubgraph`. */
339
+ contractCall<const A extends AbiContract | undefined = undefined>(fields?: Omit<SpecFor<"contract_call">, "type" | "abi"> & {
340
+ abi?: A
341
+ }): ChainEventFilter<"contract_call", {
342
+ type: "contract_call"
343
+ } & Omit<SpecFor<"contract_call">, "type" | "abi"> & {
344
+ abi?: A
345
+ }>;
346
+ contractDeploy(fields?: Fields<"contract_deploy">): ChainEventFilter<"contract_deploy">;
347
+ /** Canonical member is `print_event` (as Subgraphs and Subscriptions spell
348
+ * it); `toIndexParams`/`toStreamsParams` project to `print`. `prints`
349
+ * literals are preserved (`const P`) for per-topic `event.data` narrowing. */
350
+ print<const P extends Record<string, Record<string, PrintFieldType>> | undefined = undefined>(fields?: Omit<SpecFor<"print_event">, "type" | "prints"> & {
351
+ prints?: P
352
+ }): ChainEventFilter<"print_event", {
353
+ type: "print_event"
354
+ } & Omit<SpecFor<"print_event">, "type" | "prints"> & {
355
+ prints?: P
356
+ }>;
357
+ sbtcDeposit(fields?: Fields<"sbtc_deposit">): ChainEventFilter<"sbtc_deposit">;
358
+ sbtcWithdrawalCreate(fields?: Fields<"sbtc_withdrawal_create">): ChainEventFilter<"sbtc_withdrawal_create">;
359
+ sbtcWithdrawalAccept(fields?: Fields<"sbtc_withdrawal_accept">): ChainEventFilter<"sbtc_withdrawal_accept">;
360
+ sbtcWithdrawalReject(fields?: Fields<"sbtc_withdrawal_reject">): ChainEventFilter<"sbtc_withdrawal_reject">;
361
+ sbtcWithdrawalSweptConfirmed(fields?: Fields<"sbtc_withdrawal_swept_confirmed">): ChainEventFilter<"sbtc_withdrawal_swept_confirmed">;
362
+ }
363
+ /**
364
+ * `on.*` — one filter vocabulary for every surface.
365
+ *
366
+ * ```ts
367
+ * import { on } from "@secondlayer/stacks/filters";
368
+ *
369
+ * const usdc = on.ftTransfer({ assetIdentifier: USDC, minAmount: 1_000_000n });
370
+ *
371
+ * sl.index.events.list(usdc.toIndexParams({ limit: 100 })); // pull
372
+ * sl.streams.events.consume({ ...usdc.toStreamsParams(), onBatch });
373
+ * sl.subscriptions.create({ name, url, triggers: [usdc.toChainTrigger()] });
374
+ * defineSubgraph({ sources: { usdc: usdc.toSubgraphSource() }, schema, handlers });
375
+ * ```
376
+ *
377
+ * A surface a member can't reach is a missing method (compile error), and a
378
+ * field a surface can't express throws at projection time — never a silent
379
+ * zero-row or over-wide match.
380
+ */
381
+ declare const on: OnNamespace;
382
+ /** A validated Stacks principal (standard or contract). Branded so downstream
383
+ * code can require "already validated" without re-checking. */
384
+ type Principal = string & {
385
+ readonly __principal: unique symbol
386
+ };
387
+ /** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
388
+ declare function isPrincipal(value: string): value is Principal;
389
+ /** Subscriptions match `*` wildcards in principal/identifier patterns; every
390
+ * other surface treats the value literally. */
391
+ declare function hasWildcard(value: string): boolean;
392
+ /** Throw unless `value` is a principal or a wildcard pattern. The factories
393
+ * call this so a swapped argument (asset id where a sender belongs, typo'd
394
+ * address) fails at construction — not as a silent zero-row query. */
395
+ declare function assertPrincipalish(field: string, value: string): void;
396
+ /** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
397
+ declare function assertAssetIdentifier(field: string, value: string): void;
398
+ /** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
399
+ declare function assertContractId(field: string, value: string): void;
400
+ export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assertPrincipalish, assertContractId, assertAssetIdentifier, SubgraphSourceSpec, SubgraphMemberType, 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