@secondlayer/stacks 2.22.0 → 3.0.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.
- package/dist/shared/stacks-86ngngnk.cjs +271 -0
- package/dist/shared/stacks-86ngngnk.cjs.map +12 -0
- package/dist/shared/stacks-qc25xx02.js +259 -0
- package/dist/shared/stacks-qc25xx02.js.map +12 -0
- package/dist/src/accounts/index.js +1 -2
- package/dist/src/accounts/index.js.map +2 -2
- package/dist/src/actions/index.js +1 -2
- package/dist/src/actions/index.js.map +1 -1
- package/dist/src/bitcoin/index.js +1 -2
- package/dist/src/bitcoin/index.js.map +2 -2
- package/dist/src/bns/index.js +1 -2
- package/dist/src/bns/index.js.map +2 -2
- package/dist/src/chains/index.js +1 -2
- package/dist/src/chains/index.js.map +1 -1
- package/dist/src/clarity/index.js +1 -2
- package/dist/src/clarity/index.js.map +1 -1
- package/dist/src/filters/index.cjs +1 -261
- package/dist/src/filters/index.cjs.map +3 -6
- package/dist/src/filters/index.d.cts +52 -27
- package/dist/src/filters/index.d.ts +52 -27
- package/dist/src/filters/index.js +15 -249
- package/dist/src/filters/index.js.map +3 -6
- package/dist/src/index.cjs +2 -75
- package/dist/src/index.cjs.map +3 -8
- package/dist/src/index.d.cts +401 -164
- package/dist/src/index.d.ts +401 -164
- package/dist/src/index.js +5 -78
- package/dist/src/index.js.map +3 -8
- package/dist/src/postconditions/index.js +1 -2
- package/dist/src/postconditions/index.js.map +1 -1
- package/dist/src/pox/index.cjs +71 -14
- package/dist/src/pox/index.cjs.map +4 -4
- package/dist/src/pox/index.d.cts +437 -1
- package/dist/src/pox/index.d.ts +437 -1
- package/dist/src/pox/index.js +71 -15
- package/dist/src/pox/index.js.map +4 -4
- package/dist/src/pox5/index.cjs +70 -33
- package/dist/src/pox5/index.cjs.map +3 -3
- package/dist/src/pox5/index.d.cts +899 -1
- package/dist/src/pox5/index.d.ts +899 -1
- package/dist/src/pox5/index.js +70 -34
- package/dist/src/pox5/index.js.map +3 -3
- package/dist/src/sbtc/index.js +1 -2
- package/dist/src/sbtc/index.js.map +2 -2
- package/dist/src/stackingdao/index.js +1 -2
- package/dist/src/stackingdao/index.js.map +2 -2
- package/dist/src/subscriptions/index.js +1 -2
- package/dist/src/subscriptions/index.js.map +1 -1
- package/dist/src/transactions/index.js +1 -2
- package/dist/src/transactions/index.js.map +1 -1
- package/dist/src/utils/index.js +1 -2
- package/dist/src/utils/index.js.map +2 -2
- package/dist/src/x402/index.js +1 -2
- package/dist/src/x402/index.js.map +2 -2
- package/package.json +3 -5
- package/dist/shared/stacks-cfazrteq.js +0 -20
- package/dist/shared/stacks-cfazrteq.js.map +0 -9
|
@@ -1,263 +1,3 @@
|
|
|
1
|
-
// src/filters/index.ts
|
|
2
|
-
var exports_filters = {};
|
|
3
|
-
__export(exports_filters, {
|
|
4
|
-
on: () => on,
|
|
5
|
-
makeChainEventFilter: () => makeChainEventFilter,
|
|
6
|
-
isPrincipal: () => isPrincipal,
|
|
7
|
-
hasWildcard: () => hasWildcard,
|
|
8
|
-
fromSubgraphSource: () => fromSubgraphSource,
|
|
9
|
-
assertPrincipalish: () => assertPrincipalish,
|
|
10
|
-
assertContractId: () => assertContractId,
|
|
11
|
-
assertAssetIdentifier: () => assertAssetIdentifier,
|
|
12
|
-
DECODED_EVENT_TYPES: () => DECODED_EVENT_TYPES,
|
|
13
|
-
CHAIN_EVENT_FILTER_TYPES: () => CHAIN_EVENT_FILTER_TYPES
|
|
14
|
-
});
|
|
15
|
-
module.exports = __toCommonJS(exports_filters);
|
|
16
1
|
|
|
17
|
-
|
|
18
|
-
var DECODED_EVENT_TYPES = [
|
|
19
|
-
"stx_transfer",
|
|
20
|
-
"stx_mint",
|
|
21
|
-
"stx_burn",
|
|
22
|
-
"stx_lock",
|
|
23
|
-
"ft_transfer",
|
|
24
|
-
"ft_mint",
|
|
25
|
-
"ft_burn",
|
|
26
|
-
"nft_transfer",
|
|
27
|
-
"nft_mint",
|
|
28
|
-
"nft_burn",
|
|
29
|
-
"print"
|
|
30
|
-
];
|
|
31
|
-
var CHAIN_EVENT_FILTER_TYPES = [
|
|
32
|
-
"stx_transfer",
|
|
33
|
-
"stx_mint",
|
|
34
|
-
"stx_burn",
|
|
35
|
-
"stx_lock",
|
|
36
|
-
"ft_transfer",
|
|
37
|
-
"ft_mint",
|
|
38
|
-
"ft_burn",
|
|
39
|
-
"nft_transfer",
|
|
40
|
-
"nft_mint",
|
|
41
|
-
"nft_burn",
|
|
42
|
-
"contract_call",
|
|
43
|
-
"contract_deploy",
|
|
44
|
-
"print_event",
|
|
45
|
-
"sbtc_deposit",
|
|
46
|
-
"sbtc_withdrawal_create",
|
|
47
|
-
"sbtc_withdrawal_accept",
|
|
48
|
-
"sbtc_withdrawal_reject",
|
|
49
|
-
"sbtc_withdrawal_swept_confirmed"
|
|
50
|
-
];
|
|
51
|
-
// src/filters/validate.ts
|
|
52
|
-
function isPrincipal(value) {
|
|
53
|
-
const parts = value.split(".");
|
|
54
|
-
if (parts.length > 2)
|
|
55
|
-
return false;
|
|
56
|
-
const [addr, contractName] = parts;
|
|
57
|
-
if (!addr || !isValidAddress(addr))
|
|
58
|
-
return false;
|
|
59
|
-
if (parts.length === 2 && !contractName)
|
|
60
|
-
return false;
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
function hasWildcard(value) {
|
|
64
|
-
return value.includes("*");
|
|
65
|
-
}
|
|
66
|
-
function assertPrincipalish(field, value) {
|
|
67
|
-
if (hasWildcard(value))
|
|
68
|
-
return;
|
|
69
|
-
if (!isPrincipal(value)) {
|
|
70
|
-
throw new Error(`${field} "${value}" is not a valid Stacks principal (SP…/ST…, optionally .contract-name).`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function assertAssetIdentifier(field, value) {
|
|
74
|
-
if (hasWildcard(value))
|
|
75
|
-
return;
|
|
76
|
-
const [contractId, assetName, ...rest] = value.split("::");
|
|
77
|
-
if (!contractId || !assetName || rest.length > 0 || !contractId.includes(".") || !isPrincipal(contractId)) {
|
|
78
|
-
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.`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function assertContractId(field, value) {
|
|
82
|
-
if (hasWildcard(value))
|
|
83
|
-
return;
|
|
84
|
-
if (value.includes("::")) {
|
|
85
|
-
throw new Error(`${field} "${value}" is an asset identifier, not a contract id — use assetIdentifier for that.`);
|
|
86
|
-
}
|
|
87
|
-
if (!value.includes(".") || !isPrincipal(value)) {
|
|
88
|
-
throw new Error(`${field} "${value}" is not a valid contract id (SP….contract-name).`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// src/filters/factories.ts
|
|
93
|
-
var PRINCIPAL_FIELDS = new Set([
|
|
94
|
-
"sender",
|
|
95
|
-
"recipient",
|
|
96
|
-
"caller",
|
|
97
|
-
"deployer",
|
|
98
|
-
"lockedAddress"
|
|
99
|
-
]);
|
|
100
|
-
var AMOUNT_FIELDS = new Set(["minAmount", "maxAmount"]);
|
|
101
|
-
var DECORATIVE_FIELDS = new Set(["abi", "prints"]);
|
|
102
|
-
function specEntries(spec) {
|
|
103
|
-
return Object.entries(spec).filter(([key, value]) => key !== "type" && value !== undefined);
|
|
104
|
-
}
|
|
105
|
-
function validateSpec(spec) {
|
|
106
|
-
for (const [key, value] of specEntries(spec)) {
|
|
107
|
-
if (PRINCIPAL_FIELDS.has(key)) {
|
|
108
|
-
assertPrincipalish(key, value);
|
|
109
|
-
} else if (key === "assetIdentifier") {
|
|
110
|
-
assertAssetIdentifier(key, value);
|
|
111
|
-
} else if (key === "contractId") {
|
|
112
|
-
for (const id of Array.isArray(value) ? value : [value]) {
|
|
113
|
-
assertContractId(key, id);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function unsupported(surface, field, hint) {
|
|
119
|
-
throw new Error(`${field} cannot be expressed on ${surface} — ${hint}. Drop the field from the filter or use the surface that supports it.`);
|
|
120
|
-
}
|
|
121
|
-
function assertNoWildcards(surface, spec) {
|
|
122
|
-
for (const [key, value] of specEntries(spec)) {
|
|
123
|
-
if (typeof value === "string" && hasWildcard(value)) {
|
|
124
|
-
unsupported(surface, `${key} wildcard "${value}"`, "wildcard patterns are Subscriptions-only");
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
function toChainTrigger(spec) {
|
|
129
|
-
const out = {};
|
|
130
|
-
for (const [key, value] of specEntries(spec)) {
|
|
131
|
-
if (DECORATIVE_FIELDS.has(key))
|
|
132
|
-
continue;
|
|
133
|
-
if (Array.isArray(value)) {
|
|
134
|
-
unsupported("Subscriptions", `${key} set`, "a chain trigger targets ONE contract — create one subscription per contract, or use Index/Subgraphs which accept the set");
|
|
135
|
-
}
|
|
136
|
-
out[key] = typeof value === "bigint" ? value.toString() : value;
|
|
137
|
-
}
|
|
138
|
-
return { type: spec.type, ...out };
|
|
139
|
-
}
|
|
140
|
-
function toIndexParams(spec, extra = {}) {
|
|
141
|
-
assertNoWildcards("Index events", spec);
|
|
142
|
-
const out = {
|
|
143
|
-
eventType: spec.type === "print_event" ? "print" : spec.type
|
|
144
|
-
};
|
|
145
|
-
for (const [key, value] of specEntries(spec)) {
|
|
146
|
-
if (DECORATIVE_FIELDS.has(key))
|
|
147
|
-
continue;
|
|
148
|
-
if (AMOUNT_FIELDS.has(key)) {
|
|
149
|
-
unsupported("Index events", key, "amount predicates are Subscriptions/Subgraphs-only; filter client-side on the decoded rows");
|
|
150
|
-
}
|
|
151
|
-
if (key === "topic") {
|
|
152
|
-
unsupported("Index events", "topic", "per-topic reads are Subgraphs/Subscriptions-only (or read the contract's print feed and switch on topic)");
|
|
153
|
-
}
|
|
154
|
-
if (key === "lockedAddress") {
|
|
155
|
-
unsupported("Index events", "lockedAddress", "stx_lock address filtering is Subscriptions/Subgraphs-only");
|
|
156
|
-
}
|
|
157
|
-
if (key === "caller") {
|
|
158
|
-
unsupported("Index events", "caller", "contract-call fields live on index.contractCalls");
|
|
159
|
-
}
|
|
160
|
-
out[key] = value;
|
|
161
|
-
}
|
|
162
|
-
return { ...out, ...extra };
|
|
163
|
-
}
|
|
164
|
-
function toStreamsParams(spec, extra = {}) {
|
|
165
|
-
assertNoWildcards("Streams", spec);
|
|
166
|
-
const out = {
|
|
167
|
-
types: [spec.type === "print_event" ? "print" : spec.type]
|
|
168
|
-
};
|
|
169
|
-
for (const [key, value] of specEntries(spec)) {
|
|
170
|
-
if (DECORATIVE_FIELDS.has(key))
|
|
171
|
-
continue;
|
|
172
|
-
if (AMOUNT_FIELDS.has(key)) {
|
|
173
|
-
unsupported("Streams", key, "amount predicates are Subscriptions/Subgraphs-only");
|
|
174
|
-
}
|
|
175
|
-
if (key === "trait") {
|
|
176
|
-
unsupported("Streams", "trait", "Streams has no trait resolution — Index and Subgraphs do");
|
|
177
|
-
}
|
|
178
|
-
if (key === "topic") {
|
|
179
|
-
unsupported("Streams", "topic", "per-topic filtering is Subgraphs/Subscriptions-only");
|
|
180
|
-
}
|
|
181
|
-
if (key === "lockedAddress") {
|
|
182
|
-
unsupported("Streams", "lockedAddress", "stx_lock address filtering is Subscriptions/Subgraphs-only");
|
|
183
|
-
}
|
|
184
|
-
out[key] = value;
|
|
185
|
-
}
|
|
186
|
-
return { ...out, ...extra };
|
|
187
|
-
}
|
|
188
|
-
function toContractCallsParams(spec, extra = {}) {
|
|
189
|
-
assertNoWildcards("Index contract-calls", spec);
|
|
190
|
-
const out = {};
|
|
191
|
-
for (const [key, value] of specEntries(spec)) {
|
|
192
|
-
if (DECORATIVE_FIELDS.has(key))
|
|
193
|
-
continue;
|
|
194
|
-
if (key === "caller") {
|
|
195
|
-
unsupported("Index contract-calls", "caller", "caller filtering is Subscriptions/Subgraphs-only (the endpoint filters by tx sender)");
|
|
196
|
-
}
|
|
197
|
-
out[key] = value;
|
|
198
|
-
}
|
|
199
|
-
return { ...out, ...extra };
|
|
200
|
-
}
|
|
201
|
-
function toSubgraphSource(spec) {
|
|
202
|
-
return Object.fromEntries([
|
|
203
|
-
["type", spec.type],
|
|
204
|
-
...specEntries(spec)
|
|
205
|
-
]);
|
|
206
|
-
}
|
|
207
|
-
var DECODED_MEMBERS = new Set([
|
|
208
|
-
"stx_transfer",
|
|
209
|
-
"stx_mint",
|
|
210
|
-
"stx_burn",
|
|
211
|
-
"stx_lock",
|
|
212
|
-
"ft_transfer",
|
|
213
|
-
"ft_mint",
|
|
214
|
-
"ft_burn",
|
|
215
|
-
"nft_transfer",
|
|
216
|
-
"nft_mint",
|
|
217
|
-
"nft_burn",
|
|
218
|
-
"print_event"
|
|
219
|
-
]);
|
|
220
|
-
function makeChainEventFilter(type, fields) {
|
|
221
|
-
const spec = { type, ...fields };
|
|
222
|
-
validateSpec(spec);
|
|
223
|
-
const filter = { ...spec };
|
|
224
|
-
filter.toChainTrigger = () => toChainTrigger(spec);
|
|
225
|
-
if (DECODED_MEMBERS.has(type)) {
|
|
226
|
-
filter.toIndexParams = (extra) => toIndexParams(spec, extra);
|
|
227
|
-
filter.toStreamsParams = (extra) => toStreamsParams(spec, extra);
|
|
228
|
-
}
|
|
229
|
-
if (type === "contract_call") {
|
|
230
|
-
filter.toContractCallsParams = (extra) => toContractCallsParams(spec, extra);
|
|
231
|
-
}
|
|
232
|
-
if (!type.startsWith("sbtc_")) {
|
|
233
|
-
filter.toSubgraphSource = () => toSubgraphSource(spec);
|
|
234
|
-
}
|
|
235
|
-
return filter;
|
|
236
|
-
}
|
|
237
|
-
function fromSubgraphSource(source) {
|
|
238
|
-
const { type, ...fields } = source;
|
|
239
|
-
return makeChainEventFilter(type, fields);
|
|
240
|
-
}
|
|
241
|
-
var on = {
|
|
242
|
-
stxTransfer: (fields = {}) => makeChainEventFilter("stx_transfer", fields),
|
|
243
|
-
stxMint: (fields = {}) => makeChainEventFilter("stx_mint", fields),
|
|
244
|
-
stxBurn: (fields = {}) => makeChainEventFilter("stx_burn", fields),
|
|
245
|
-
stxLock: (fields = {}) => makeChainEventFilter("stx_lock", fields),
|
|
246
|
-
ftTransfer: (fields = {}) => makeChainEventFilter("ft_transfer", fields),
|
|
247
|
-
ftMint: (fields = {}) => makeChainEventFilter("ft_mint", fields),
|
|
248
|
-
ftBurn: (fields = {}) => makeChainEventFilter("ft_burn", fields),
|
|
249
|
-
nftTransfer: (fields = {}) => makeChainEventFilter("nft_transfer", fields),
|
|
250
|
-
nftMint: (fields = {}) => makeChainEventFilter("nft_mint", fields),
|
|
251
|
-
nftBurn: (fields = {}) => makeChainEventFilter("nft_burn", fields),
|
|
252
|
-
contractCall: (fields = {}) => makeChainEventFilter("contract_call", fields),
|
|
253
|
-
contractDeploy: (fields = {}) => makeChainEventFilter("contract_deploy", fields),
|
|
254
|
-
print: (fields = {}) => makeChainEventFilter("print_event", fields),
|
|
255
|
-
sbtcDeposit: (fields = {}) => makeChainEventFilter("sbtc_deposit", fields),
|
|
256
|
-
sbtcWithdrawalCreate: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_create", fields),
|
|
257
|
-
sbtcWithdrawalAccept: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_accept", fields),
|
|
258
|
-
sbtcWithdrawalReject: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_reject", fields),
|
|
259
|
-
sbtcWithdrawalSweptConfirmed: (fields = {}) => makeChainEventFilter("sbtc_withdrawal_swept_confirmed", fields)
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
//# debugId=4F3F23D41E73CECF64756E2164756E21
|
|
2
|
+
//# debugId=DDDF1E5FDE06A0EC64756E2164756E21
|
|
263
3
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [
|
|
3
|
+
"sources": [],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// The decoded event-type vocabulary — canonical home. Index (decoded layer)\n// and Streams (canonical firehose) expose the SAME set. This lives in\n// @secondlayer/stacks because it is the leaf of the dependency graph\n// (shared → stacks), so no package can drift a private copy upward:\n// @secondlayer/shared re-exports it for back-compat.\nexport const DECODED_EVENT_TYPES = [\n\t\"stx_transfer\",\n\t\"stx_mint\",\n\t\"stx_burn\",\n\t\"stx_lock\",\n\t\"ft_transfer\",\n\t\"ft_mint\",\n\t\"ft_burn\",\n\t\"nft_transfer\",\n\t\"nft_mint\",\n\t\"nft_burn\",\n\t\"print\",\n] as const;\n\nexport type DecodedEventType = (typeof DECODED_EVENT_TYPES)[number];\n\n/** Every chain-event filter member across all four surfaces: the 10 decoded\n * token/STX types, the three contract-shaped types (spelled as subgraphs and\n * triggers spell them — Index/Streams project `print_event` → `print`), and\n * the five sBTC lifecycle types (Subscriptions-only). */\nexport const CHAIN_EVENT_FILTER_TYPES = [\n\t\"stx_transfer\",\n\t\"stx_mint\",\n\t\"stx_burn\",\n\t\"stx_lock\",\n\t\"ft_transfer\",\n\t\"ft_mint\",\n\t\"ft_burn\",\n\t\"nft_transfer\",\n\t\"nft_mint\",\n\t\"nft_burn\",\n\t\"contract_call\",\n\t\"contract_deploy\",\n\t\"print_event\",\n\t\"sbtc_deposit\",\n\t\"sbtc_withdrawal_create\",\n\t\"sbtc_withdrawal_accept\",\n\t\"sbtc_withdrawal_reject\",\n\t\"sbtc_withdrawal_swept_confirmed\",\n] as const;\n\nexport type ChainEventFilterType = (typeof CHAIN_EVENT_FILTER_TYPES)[number];\n",
|
|
6
|
-
"import { isValidAddress } from \"../utils/address.ts\";\n\n/** A validated Stacks principal (standard or contract). Branded so downstream\n * code can require \"already validated\" without re-checking. */\nexport type Principal = string & { readonly __principal: unique symbol };\n\n/** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */\nexport function isPrincipal(value: string): value is Principal {\n\tconst parts = value.split(\".\");\n\tif (parts.length > 2) return false;\n\tconst [addr, contractName] = parts;\n\tif (!addr || !isValidAddress(addr)) return false;\n\tif (parts.length === 2 && !contractName) return false;\n\treturn true;\n}\n\n/** Subscriptions match `*` wildcards in principal/identifier patterns; every\n * other surface treats the value literally. */\nexport function hasWildcard(value: string): boolean {\n\treturn value.includes(\"*\");\n}\n\n/** Throw unless `value` is a principal or a wildcard pattern. The factories\n * call this so a swapped argument (asset id where a sender belongs, typo'd\n * address) fails at construction — not as a silent zero-row query. */\nexport function assertPrincipalish(field: string, value: string): void {\n\tif (hasWildcard(value)) return;\n\tif (!isPrincipal(value)) {\n\t\tthrow new Error(\n\t\t\t`${field} \"${value}\" is not a valid Stacks principal (SP…/ST…, optionally .contract-name).`,\n\t\t);\n\t}\n}\n\n/** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */\nexport function assertAssetIdentifier(field: string, value: string): void {\n\tif (hasWildcard(value)) return;\n\tconst [contractId, assetName, ...rest] = value.split(\"::\");\n\tif (\n\t\t!contractId ||\n\t\t!assetName ||\n\t\trest.length > 0 ||\n\t\t!contractId.includes(\".\") ||\n\t\t!isPrincipal(contractId)\n\t) {\n\t\tthrow new Error(\n\t\t\t`${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.`,\n\t\t);\n\t}\n}\n\n/** Throw unless `value` is a contract id `SP….name` (or a wildcard). */\nexport function assertContractId(field: string, value: string): void {\n\tif (hasWildcard(value)) return;\n\tif (value.includes(\"::\")) {\n\t\tthrow new Error(\n\t\t\t`${field} \"${value}\" is an asset identifier, not a contract id — use assetIdentifier for that.`,\n\t\t);\n\t}\n\tif (!value.includes(\".\") || !isPrincipal(value)) {\n\t\tthrow new Error(\n\t\t\t`${field} \"${value}\" is not a valid contract id (SP….contract-name).`,\n\t\t);\n\t}\n}\n",
|
|
7
|
-
"import type { AbiContract } from \"../clarity/abi/contract.ts\";\nimport type { ChainEventFilterType } from \"./event-types.ts\";\nimport type { SubgraphMemberType, SubgraphSourceSpec } from \"./types.ts\";\nimport type {\n\tChainEventFilter,\n\tChainEventFilterSpec,\n\tChainTriggerShape,\n\tContractCallsParamsShape,\n\tIndexEventsParamsShape,\n\tPrintFieldType,\n\tSpecFor,\n\tStreamsParamsShape,\n} from \"./types.ts\";\nimport {\n\tassertAssetIdentifier,\n\tassertContractId,\n\tassertPrincipalish,\n\thasWildcard,\n} from \"./validate.ts\";\n\n// ── Field metadata driving validation and projections ────────────────────\n\nconst PRINCIPAL_FIELDS = new Set([\n\t\"sender\",\n\t\"recipient\",\n\t\"caller\",\n\t\"deployer\",\n\t\"lockedAddress\",\n]);\nconst AMOUNT_FIELDS = new Set([\"minAmount\", \"maxAmount\"]);\n/** Fields with no filtering semantics — safe to drop in a projection. */\nconst DECORATIVE_FIELDS = new Set([\"abi\", \"prints\"]);\n\nfunction specEntries(spec: ChainEventFilterSpec): Array<[string, unknown]> {\n\treturn Object.entries(spec).filter(\n\t\t([key, value]) => key !== \"type\" && value !== undefined,\n\t);\n}\n\nfunction validateSpec(spec: ChainEventFilterSpec): void {\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (PRINCIPAL_FIELDS.has(key)) {\n\t\t\tassertPrincipalish(key, value as string);\n\t\t} else if (key === \"assetIdentifier\") {\n\t\t\tassertAssetIdentifier(key, value as string);\n\t\t} else if (key === \"contractId\") {\n\t\t\t// A contract SET validates member-wise — one bad id in a router+pools\n\t\t\t// list must fail as loudly as a bad single id.\n\t\t\tfor (const id of Array.isArray(value) ? value : [value]) {\n\t\t\t\tassertContractId(key, id as string);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Throw for a field the target surface cannot express — dropping it would\n * silently widen the match, which is the exact bug this module exists to\n * kill. Names the surface that CAN express it. */\nfunction unsupported(surface: string, field: string, hint: string): never {\n\tthrow new Error(\n\t\t`${field} cannot be expressed on ${surface} — ${hint}. Drop the field from the filter or use the surface that supports it.`,\n\t);\n}\n\nfunction assertNoWildcards(surface: string, spec: ChainEventFilterSpec): void {\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (typeof value === \"string\" && hasWildcard(value)) {\n\t\t\tunsupported(\n\t\t\t\tsurface,\n\t\t\t\t`${key} wildcard \"${value}\"`,\n\t\t\t\t\"wildcard patterns are Subscriptions-only\",\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ── Projections ──────────────────────────────────────────────────────────\n\nfunction toChainTrigger(spec: ChainEventFilterSpec): ChainTriggerShape {\n\tconst out: Record<string, string | number> = {};\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (DECORATIVE_FIELDS.has(key)) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\t// One trigger, one contract: silently taking the first would watch\n\t\t\t// a fraction of what the filter says. Create one subscription per\n\t\t\t// contract instead.\n\t\t\tunsupported(\n\t\t\t\t\"Subscriptions\",\n\t\t\t\t`${key} set`,\n\t\t\t\t\"a chain trigger targets ONE contract — create one subscription per contract, or use Index/Subgraphs which accept the set\",\n\t\t\t);\n\t\t}\n\t\t// The one sanctioned bigint→string boundary.\n\t\tout[key] =\n\t\t\ttypeof value === \"bigint\" ? value.toString() : (value as string | number);\n\t}\n\treturn { type: spec.type, ...out };\n}\n\nfunction toIndexParams(\n\tspec: ChainEventFilterSpec,\n\textra: Record<string, unknown> = {},\n): IndexEventsParamsShape {\n\tassertNoWildcards(\"Index events\", spec);\n\tconst out: Record<string, unknown> = {\n\t\teventType: spec.type === \"print_event\" ? \"print\" : spec.type,\n\t};\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (DECORATIVE_FIELDS.has(key)) continue;\n\t\tif (AMOUNT_FIELDS.has(key)) {\n\t\t\tunsupported(\n\t\t\t\t\"Index events\",\n\t\t\t\tkey,\n\t\t\t\t\"amount predicates are Subscriptions/Subgraphs-only; filter client-side on the decoded rows\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"topic\") {\n\t\t\tunsupported(\n\t\t\t\t\"Index events\",\n\t\t\t\t\"topic\",\n\t\t\t\t\"per-topic reads are Subgraphs/Subscriptions-only (or read the contract's print feed and switch on topic)\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"lockedAddress\") {\n\t\t\tunsupported(\n\t\t\t\t\"Index events\",\n\t\t\t\t\"lockedAddress\",\n\t\t\t\t\"stx_lock address filtering is Subscriptions/Subgraphs-only\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"caller\") {\n\t\t\tunsupported(\n\t\t\t\t\"Index events\",\n\t\t\t\t\"caller\",\n\t\t\t\t\"contract-call fields live on index.contractCalls\",\n\t\t\t);\n\t\t}\n\t\tout[key] = value;\n\t}\n\treturn { ...out, ...extra } as IndexEventsParamsShape;\n}\n\nfunction toStreamsParams(\n\tspec: ChainEventFilterSpec,\n\textra: Record<string, unknown> = {},\n): StreamsParamsShape {\n\tassertNoWildcards(\"Streams\", spec);\n\tconst out: Record<string, unknown> = {\n\t\ttypes: [spec.type === \"print_event\" ? \"print\" : spec.type],\n\t};\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (DECORATIVE_FIELDS.has(key)) continue;\n\t\tif (AMOUNT_FIELDS.has(key)) {\n\t\t\tunsupported(\n\t\t\t\t\"Streams\",\n\t\t\t\tkey,\n\t\t\t\t\"amount predicates are Subscriptions/Subgraphs-only\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"trait\") {\n\t\t\tunsupported(\n\t\t\t\t\"Streams\",\n\t\t\t\t\"trait\",\n\t\t\t\t\"Streams has no trait resolution — Index and Subgraphs do\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"topic\") {\n\t\t\tunsupported(\n\t\t\t\t\"Streams\",\n\t\t\t\t\"topic\",\n\t\t\t\t\"per-topic filtering is Subgraphs/Subscriptions-only\",\n\t\t\t);\n\t\t}\n\t\tif (key === \"lockedAddress\") {\n\t\t\tunsupported(\n\t\t\t\t\"Streams\",\n\t\t\t\t\"lockedAddress\",\n\t\t\t\t\"stx_lock address filtering is Subscriptions/Subgraphs-only\",\n\t\t\t);\n\t\t}\n\t\tout[key] = value;\n\t}\n\treturn { ...out, ...extra } as StreamsParamsShape;\n}\n\nfunction toContractCallsParams(\n\tspec: ChainEventFilterSpec,\n\textra: Record<string, unknown> = {},\n): ContractCallsParamsShape {\n\tassertNoWildcards(\"Index contract-calls\", spec);\n\tconst out: Record<string, unknown> = {};\n\tfor (const [key, value] of specEntries(spec)) {\n\t\tif (DECORATIVE_FIELDS.has(key)) continue;\n\t\tif (key === \"caller\") {\n\t\t\tunsupported(\n\t\t\t\t\"Index contract-calls\",\n\t\t\t\t\"caller\",\n\t\t\t\t\"caller filtering is Subscriptions/Subgraphs-only (the endpoint filters by tx sender)\",\n\t\t\t);\n\t\t}\n\t\tout[key] = value;\n\t}\n\treturn { ...out, ...extra } as ContractCallsParamsShape;\n}\n\nfunction toSubgraphSource(spec: ChainEventFilterSpec): ChainEventFilterSpec {\n\t// The spec IS the subgraph source shape (camelCase, bigint amounts,\n\t// literal prints/abi preserved). Strip the projection methods by copying\n\t// data fields only.\n\treturn Object.fromEntries([\n\t\t[\"type\", spec.type],\n\t\t...specEntries(spec),\n\t]) as unknown as ChainEventFilterSpec;\n}\n\n// ── Factory ──────────────────────────────────────────────────────────────\n\nconst DECODED_MEMBERS = new Set<ChainEventFilterType>([\n\t\"stx_transfer\",\n\t\"stx_mint\",\n\t\"stx_burn\",\n\t\"stx_lock\",\n\t\"ft_transfer\",\n\t\"ft_mint\",\n\t\"ft_burn\",\n\t\"nft_transfer\",\n\t\"nft_mint\",\n\t\"nft_burn\",\n\t\"print_event\",\n]);\n\n/** Build a canonical filter: validated spec + the projections its member\n * supports (methods are attached per member at runtime, matching the\n * type-level gating exactly). `const F` preserves field literals — a\n * `prints`/`abi` declaration keeps its exact type through\n * `toSubgraphSource()`, which is what feeds `defineSubgraph` narrowing. */\nexport function makeChainEventFilter<\n\tT extends ChainEventFilterType,\n\tconst F extends Omit<SpecFor<T>, \"type\">,\n>(type: T, fields: F): ChainEventFilter<T, { type: T } & F> {\n\tconst spec = { type, ...fields } as unknown as SpecFor<T>;\n\tvalidateSpec(spec);\n\n\tconst filter = { ...spec } as unknown as Record<string, unknown>;\n\tfilter.toChainTrigger = () => toChainTrigger(spec);\n\tif (DECODED_MEMBERS.has(type)) {\n\t\tfilter.toIndexParams = (extra?: Record<string, unknown>) =>\n\t\t\ttoIndexParams(spec, extra);\n\t\tfilter.toStreamsParams = (extra?: Record<string, unknown>) =>\n\t\t\ttoStreamsParams(spec, extra);\n\t}\n\tif (type === \"contract_call\") {\n\t\tfilter.toContractCallsParams = (extra?: Record<string, unknown>) =>\n\t\t\ttoContractCallsParams(spec, extra);\n\t}\n\tif (!type.startsWith(\"sbtc_\")) {\n\t\tfilter.toSubgraphSource = () => toSubgraphSource(spec);\n\t}\n\treturn filter as unknown as ChainEventFilter<T, { type: T } & F>;\n}\n\n/**\n * Rehydrate a canonical filter from a subgraph-source-shaped object (the\n * inverse of `toSubgraphSource`). Powers migration and the round-trip\n * property gate: `toSubgraphSource(fromSubgraphSource(f))` must deep-equal\n * `f` for every production subgraph source.\n */\nexport function fromSubgraphSource(\n\tsource: SubgraphSourceSpec,\n): ChainEventFilter<SubgraphMemberType> {\n\tconst { type, ...fields } = source;\n\treturn makeChainEventFilter(\n\t\ttype,\n\t\tfields as Omit<SpecFor<typeof type>, \"type\">,\n\t) as unknown as ChainEventFilter<SubgraphMemberType>;\n}\n\ntype Fields<T extends ChainEventFilterType> = Omit<SpecFor<T>, \"type\">;\n\n/** The `on.*` namespace, annotated explicitly — bunup's dts emitter needs an\n * annotation on exported values (an inferred object of generic factories\n * collapses to `{}` in the emitted declarations). */\nexport interface OnNamespace {\n\tstxTransfer(\n\t\tfields?: Fields<\"stx_transfer\">,\n\t): ChainEventFilter<\"stx_transfer\">;\n\tstxMint(fields?: Fields<\"stx_mint\">): ChainEventFilter<\"stx_mint\">;\n\tstxBurn(fields?: Fields<\"stx_burn\">): ChainEventFilter<\"stx_burn\">;\n\tstxLock(fields?: Fields<\"stx_lock\">): ChainEventFilter<\"stx_lock\">;\n\tftTransfer(fields?: Fields<\"ft_transfer\">): ChainEventFilter<\"ft_transfer\">;\n\tftMint(fields?: Fields<\"ft_mint\">): ChainEventFilter<\"ft_mint\">;\n\tftBurn(fields?: Fields<\"ft_burn\">): ChainEventFilter<\"ft_burn\">;\n\tnftTransfer(\n\t\tfields?: Fields<\"nft_transfer\">,\n\t): ChainEventFilter<\"nft_transfer\">;\n\tnftMint(fields?: Fields<\"nft_mint\">): ChainEventFilter<\"nft_mint\">;\n\tnftBurn(fields?: Fields<\"nft_burn\">): ChainEventFilter<\"nft_burn\">;\n\t/** `abi` literals are preserved (`const A`) so `toSubgraphSource()` keeps\n\t * typing `event.input` inside `defineSubgraph`. */\n\tcontractCall<const A extends AbiContract | undefined = undefined>(\n\t\tfields?: Omit<SpecFor<\"contract_call\">, \"type\" | \"abi\"> & { abi?: A },\n\t): ChainEventFilter<\n\t\t\"contract_call\",\n\t\t{ type: \"contract_call\" } & Omit<\n\t\t\tSpecFor<\"contract_call\">,\n\t\t\t\"type\" | \"abi\"\n\t\t> & {\n\t\t\t\tabi?: A;\n\t\t\t}\n\t>;\n\tcontractDeploy(\n\t\tfields?: Fields<\"contract_deploy\">,\n\t): ChainEventFilter<\"contract_deploy\">;\n\t/** Canonical member is `print_event` (as Subgraphs and Subscriptions spell\n\t * it); `toIndexParams`/`toStreamsParams` project to `print`. `prints`\n\t * literals are preserved (`const P`) for per-topic `event.data` narrowing. */\n\tprint<\n\t\tconst P extends\n\t\t\t| Record<string, Record<string, PrintFieldType>>\n\t\t\t| undefined = undefined,\n\t>(\n\t\tfields?: Omit<SpecFor<\"print_event\">, \"type\" | \"prints\"> & { prints?: P },\n\t): ChainEventFilter<\n\t\t\"print_event\",\n\t\t{ type: \"print_event\" } & Omit<\n\t\t\tSpecFor<\"print_event\">,\n\t\t\t\"type\" | \"prints\"\n\t\t> & {\n\t\t\t\tprints?: P;\n\t\t\t}\n\t>;\n\tsbtcDeposit(\n\t\tfields?: Fields<\"sbtc_deposit\">,\n\t): ChainEventFilter<\"sbtc_deposit\">;\n\tsbtcWithdrawalCreate(\n\t\tfields?: Fields<\"sbtc_withdrawal_create\">,\n\t): ChainEventFilter<\"sbtc_withdrawal_create\">;\n\tsbtcWithdrawalAccept(\n\t\tfields?: Fields<\"sbtc_withdrawal_accept\">,\n\t): ChainEventFilter<\"sbtc_withdrawal_accept\">;\n\tsbtcWithdrawalReject(\n\t\tfields?: Fields<\"sbtc_withdrawal_reject\">,\n\t): ChainEventFilter<\"sbtc_withdrawal_reject\">;\n\tsbtcWithdrawalSweptConfirmed(\n\t\tfields?: Fields<\"sbtc_withdrawal_swept_confirmed\">,\n\t): ChainEventFilter<\"sbtc_withdrawal_swept_confirmed\">;\n}\n\n/**\n * `on.*` — one filter vocabulary for every surface.\n *\n * ```ts\n * import { on } from \"@secondlayer/stacks/filters\";\n *\n * const usdc = on.ftTransfer({ assetIdentifier: USDC, minAmount: 1_000_000n });\n *\n * sl.index.events.list(usdc.toIndexParams({ limit: 100 })); // pull\n * sl.streams.events.consume({ ...usdc.toStreamsParams(), onBatch });\n * sl.subscriptions.create({ name, url, triggers: [usdc.toChainTrigger()] });\n * defineSubgraph({ sources: { usdc: usdc.toSubgraphSource() }, schema, handlers });\n * ```\n *\n * A surface a member can't reach is a missing method (compile error), and a\n * field a surface can't express throws at projection time — never a silent\n * zero-row or over-wide match.\n */\nexport const on: OnNamespace = {\n\tstxTransfer: (fields: Fields<\"stx_transfer\"> = {}) =>\n\t\tmakeChainEventFilter(\"stx_transfer\", fields),\n\tstxMint: (fields: Fields<\"stx_mint\"> = {}) =>\n\t\tmakeChainEventFilter(\"stx_mint\", fields),\n\tstxBurn: (fields: Fields<\"stx_burn\"> = {}) =>\n\t\tmakeChainEventFilter(\"stx_burn\", fields),\n\tstxLock: (fields: Fields<\"stx_lock\"> = {}) =>\n\t\tmakeChainEventFilter(\"stx_lock\", fields),\n\tftTransfer: (fields: Fields<\"ft_transfer\"> = {}) =>\n\t\tmakeChainEventFilter(\"ft_transfer\", fields),\n\tftMint: (fields: Fields<\"ft_mint\"> = {}) =>\n\t\tmakeChainEventFilter(\"ft_mint\", fields),\n\tftBurn: (fields: Fields<\"ft_burn\"> = {}) =>\n\t\tmakeChainEventFilter(\"ft_burn\", fields),\n\tnftTransfer: (fields: Fields<\"nft_transfer\"> = {}) =>\n\t\tmakeChainEventFilter(\"nft_transfer\", fields),\n\tnftMint: (fields: Fields<\"nft_mint\"> = {}) =>\n\t\tmakeChainEventFilter(\"nft_mint\", fields),\n\tnftBurn: (fields: Fields<\"nft_burn\"> = {}) =>\n\t\tmakeChainEventFilter(\"nft_burn\", fields),\n\tcontractCall: <const A extends AbiContract | undefined = undefined>(\n\t\tfields: Omit<SpecFor<\"contract_call\">, \"type\" | \"abi\"> & { abi?: A } = {},\n\t) => makeChainEventFilter(\"contract_call\", fields),\n\tcontractDeploy: (fields: Fields<\"contract_deploy\"> = {}) =>\n\t\tmakeChainEventFilter(\"contract_deploy\", fields),\n\t/** Canonical member is `print_event` (as Subgraphs and Subscriptions spell\n\t * it); `toIndexParams`/`toStreamsParams` project to `print`. */\n\tprint: <\n\t\tconst P extends\n\t\t\t| Record<string, Record<string, PrintFieldType>>\n\t\t\t| undefined = undefined,\n\t>(\n\t\tfields: Omit<SpecFor<\"print_event\">, \"type\" | \"prints\"> & {\n\t\t\tprints?: P;\n\t\t} = {},\n\t) => makeChainEventFilter(\"print_event\", fields),\n\tsbtcDeposit: (fields: Fields<\"sbtc_deposit\"> = {}) =>\n\t\tmakeChainEventFilter(\"sbtc_deposit\", fields),\n\tsbtcWithdrawalCreate: (fields: Fields<\"sbtc_withdrawal_create\"> = {}) =>\n\t\tmakeChainEventFilter(\"sbtc_withdrawal_create\", fields),\n\tsbtcWithdrawalAccept: (fields: Fields<\"sbtc_withdrawal_accept\"> = {}) =>\n\t\tmakeChainEventFilter(\"sbtc_withdrawal_accept\", fields),\n\tsbtcWithdrawalReject: (fields: Fields<\"sbtc_withdrawal_reject\"> = {}) =>\n\t\tmakeChainEventFilter(\"sbtc_withdrawal_reject\", fields),\n\tsbtcWithdrawalSweptConfirmed: (\n\t\tfields: Fields<\"sbtc_withdrawal_swept_confirmed\"> = {},\n\t) => makeChainEventFilter(\"sbtc_withdrawal_swept_confirmed\", fields),\n};\n"
|
|
8
5
|
],
|
|
9
|
-
"mappings": "
|
|
10
|
-
"debugId": "
|
|
6
|
+
"mappings": "",
|
|
7
|
+
"debugId": "DDDF1E5FDE06A0EC64756E2164756E21",
|
|
11
8
|
"names": []
|
|
12
9
|
}
|
|
@@ -102,6 +102,49 @@ interface AbiContract {
|
|
|
102
102
|
implemented_traits?: ReadonlyArray<string>;
|
|
103
103
|
defined_traits?: ReadonlyArray<AbiTraitDefinition>;
|
|
104
104
|
}
|
|
105
|
+
/** A validated Stacks principal (standard or contract). Branded so downstream
|
|
106
|
+
* code can require "already validated" without re-checking. */
|
|
107
|
+
type Principal = string & {
|
|
108
|
+
readonly __principal: unique symbol
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* `<contract>::<asset-name>` — the shape a fungible/non-fungible asset filter
|
|
112
|
+
* takes, expressed so the compiler can check it.
|
|
113
|
+
*
|
|
114
|
+
* The most common mistake in this API is passing a CONTRACT ID
|
|
115
|
+
* (`SP….sbtc-token`) where an asset identifier (`SP….sbtc-token::sbtc-token`)
|
|
116
|
+
* belongs, and the failure mode is a query that quietly returns zero rows. The
|
|
117
|
+
* two differ structurally by `::`, so a template-literal type catches it at the
|
|
118
|
+
* call site — no brand, no cast, literals just work.
|
|
119
|
+
*
|
|
120
|
+
* A value that is only known at runtime (config, env) is not narrow enough on
|
|
121
|
+
* purpose; run it through {@link assetId} once, which validates and narrows.
|
|
122
|
+
*
|
|
123
|
+
* Wildcard patterns (Subscriptions-only) are admitted by the second arm — they
|
|
124
|
+
* are legitimately not full identifiers (`SPB.*`), and the runtime validator
|
|
125
|
+
* short-circuits on them for the same reason.
|
|
126
|
+
*/
|
|
127
|
+
type AssetIdentifier = `${string}::${string}` | `${string}*${string}`;
|
|
128
|
+
/**
|
|
129
|
+
* Narrow a runtime string to an {@link AssetIdentifier}, validating it.
|
|
130
|
+
*
|
|
131
|
+
* The escape hatch for config-driven values: `assetId(process.env.ASSET!)`
|
|
132
|
+
* throws on a contract id instead of letting it through to a zero-row query.
|
|
133
|
+
*/
|
|
134
|
+
declare function assetId(value: string): AssetIdentifier;
|
|
135
|
+
/** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
|
|
136
|
+
declare function isPrincipal(value: string): value is Principal;
|
|
137
|
+
/** Subscriptions match `*` wildcards in principal/identifier patterns; every
|
|
138
|
+
* other surface treats the value literally. */
|
|
139
|
+
declare function hasWildcard(value: string): boolean;
|
|
140
|
+
/** Throw unless `value` is a principal or a wildcard pattern. The factories
|
|
141
|
+
* call this so a swapped argument (asset id where a sender belongs, typo'd
|
|
142
|
+
* address) fails at construction — not as a silent zero-row query. */
|
|
143
|
+
declare function assertPrincipalish(field: string, value: string): void;
|
|
144
|
+
/** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
|
|
145
|
+
declare function assertAssetIdentifier(field: string, value: string): void;
|
|
146
|
+
/** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
|
|
147
|
+
declare function assertContractId(field: string, value: string): void;
|
|
105
148
|
/** Scalar print field types (structural mirror of the subgraphs `ColumnType`). */
|
|
106
149
|
type PrintScalarType = "uint" | "int" | "text" | "principal" | "boolean" | "timestamp" | "jsonb";
|
|
107
150
|
/**
|
|
@@ -150,37 +193,37 @@ type TraitScope = {
|
|
|
150
193
|
};
|
|
151
194
|
interface FtTransferSpec extends TraitScope {
|
|
152
195
|
type: "ft_transfer";
|
|
153
|
-
assetIdentifier?:
|
|
196
|
+
assetIdentifier?: AssetIdentifier;
|
|
154
197
|
sender?: string;
|
|
155
198
|
recipient?: string;
|
|
156
199
|
minAmount?: bigint;
|
|
157
200
|
}
|
|
158
201
|
interface FtMintSpec extends TraitScope {
|
|
159
202
|
type: "ft_mint";
|
|
160
|
-
assetIdentifier?:
|
|
203
|
+
assetIdentifier?: AssetIdentifier;
|
|
161
204
|
recipient?: string;
|
|
162
205
|
minAmount?: bigint;
|
|
163
206
|
}
|
|
164
207
|
interface FtBurnSpec extends TraitScope {
|
|
165
208
|
type: "ft_burn";
|
|
166
|
-
assetIdentifier?:
|
|
209
|
+
assetIdentifier?: AssetIdentifier;
|
|
167
210
|
sender?: string;
|
|
168
211
|
minAmount?: bigint;
|
|
169
212
|
}
|
|
170
213
|
interface NftTransferSpec extends TraitScope {
|
|
171
214
|
type: "nft_transfer";
|
|
172
|
-
assetIdentifier?:
|
|
215
|
+
assetIdentifier?: AssetIdentifier;
|
|
173
216
|
sender?: string;
|
|
174
217
|
recipient?: string;
|
|
175
218
|
}
|
|
176
219
|
interface NftMintSpec extends TraitScope {
|
|
177
220
|
type: "nft_mint";
|
|
178
|
-
assetIdentifier?:
|
|
221
|
+
assetIdentifier?: AssetIdentifier;
|
|
179
222
|
recipient?: string;
|
|
180
223
|
}
|
|
181
224
|
interface NftBurnSpec extends TraitScope {
|
|
182
225
|
type: "nft_burn";
|
|
183
|
-
assetIdentifier?:
|
|
226
|
+
assetIdentifier?: AssetIdentifier;
|
|
184
227
|
sender?: string;
|
|
185
228
|
}
|
|
186
229
|
interface ContractCallSpec extends TraitScope {
|
|
@@ -263,7 +306,7 @@ type ChainTriggerShape = ChainTriggerOf<ChainEventFilterSpec>;
|
|
|
263
306
|
type IndexEventsParamsShape = {
|
|
264
307
|
eventType: DecodedEventType
|
|
265
308
|
contractId?: string
|
|
266
|
-
assetIdentifier?:
|
|
309
|
+
assetIdentifier?: AssetIdentifier
|
|
267
310
|
sender?: string
|
|
268
311
|
recipient?: string
|
|
269
312
|
trait?: string
|
|
@@ -281,7 +324,7 @@ type StreamsParamsShape = {
|
|
|
281
324
|
contractId?: string
|
|
282
325
|
sender?: string
|
|
283
326
|
recipient?: string
|
|
284
|
-
assetIdentifier?:
|
|
327
|
+
assetIdentifier?: AssetIdentifier
|
|
285
328
|
};
|
|
286
329
|
type DecodedMember = "stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print_event";
|
|
287
330
|
type ProjectionsFor<
|
|
@@ -397,22 +440,4 @@ interface OnNamespace {
|
|
|
397
440
|
* zero-row or over-wide match.
|
|
398
441
|
*/
|
|
399
442
|
declare const on: OnNamespace;
|
|
400
|
-
|
|
401
|
-
* code can require "already validated" without re-checking. */
|
|
402
|
-
type Principal = string & {
|
|
403
|
-
readonly __principal: unique symbol
|
|
404
|
-
};
|
|
405
|
-
/** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
|
|
406
|
-
declare function isPrincipal(value: string): value is Principal;
|
|
407
|
-
/** Subscriptions match `*` wildcards in principal/identifier patterns; every
|
|
408
|
-
* other surface treats the value literally. */
|
|
409
|
-
declare function hasWildcard(value: string): boolean;
|
|
410
|
-
/** Throw unless `value` is a principal or a wildcard pattern. The factories
|
|
411
|
-
* call this so a swapped argument (asset id where a sender belongs, typo'd
|
|
412
|
-
* address) fails at construction — not as a silent zero-row query. */
|
|
413
|
-
declare function assertPrincipalish(field: string, value: string): void;
|
|
414
|
-
/** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
|
|
415
|
-
declare function assertAssetIdentifier(field: string, value: string): void;
|
|
416
|
-
/** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
|
|
417
|
-
declare function assertContractId(field: string, value: string): void;
|
|
418
|
-
export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assertPrincipalish, assertContractId, assertAssetIdentifier, SubgraphSourceSpec, SubgraphMemberType, StxTransferSpec, StxMintSpec, StxLockSpec, StxBurnSpec, StreamsParamsShape, SpecFor, SbtcWithdrawalSweptConfirmedSpec, SbtcWithdrawalRejectSpec, SbtcWithdrawalCreateSpec, SbtcWithdrawalAcceptSpec, SbtcDepositSpec, PrintScalarType, 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 };
|
|
443
|
+
export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assetId, assertPrincipalish, assertContractId, assertAssetIdentifier, SubgraphSourceSpec, SubgraphMemberType, StxTransferSpec, StxMintSpec, StxLockSpec, StxBurnSpec, StreamsParamsShape, SpecFor, SbtcWithdrawalSweptConfirmedSpec, SbtcWithdrawalRejectSpec, SbtcWithdrawalCreateSpec, SbtcWithdrawalAcceptSpec, SbtcDepositSpec, PrintScalarType, 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, AssetIdentifier };
|
|
@@ -102,6 +102,49 @@ interface AbiContract {
|
|
|
102
102
|
implemented_traits?: ReadonlyArray<string>;
|
|
103
103
|
defined_traits?: ReadonlyArray<AbiTraitDefinition>;
|
|
104
104
|
}
|
|
105
|
+
/** A validated Stacks principal (standard or contract). Branded so downstream
|
|
106
|
+
* code can require "already validated" without re-checking. */
|
|
107
|
+
type Principal = string & {
|
|
108
|
+
readonly __principal: unique symbol
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* `<contract>::<asset-name>` — the shape a fungible/non-fungible asset filter
|
|
112
|
+
* takes, expressed so the compiler can check it.
|
|
113
|
+
*
|
|
114
|
+
* The most common mistake in this API is passing a CONTRACT ID
|
|
115
|
+
* (`SP….sbtc-token`) where an asset identifier (`SP….sbtc-token::sbtc-token`)
|
|
116
|
+
* belongs, and the failure mode is a query that quietly returns zero rows. The
|
|
117
|
+
* two differ structurally by `::`, so a template-literal type catches it at the
|
|
118
|
+
* call site — no brand, no cast, literals just work.
|
|
119
|
+
*
|
|
120
|
+
* A value that is only known at runtime (config, env) is not narrow enough on
|
|
121
|
+
* purpose; run it through {@link assetId} once, which validates and narrows.
|
|
122
|
+
*
|
|
123
|
+
* Wildcard patterns (Subscriptions-only) are admitted by the second arm — they
|
|
124
|
+
* are legitimately not full identifiers (`SPB.*`), and the runtime validator
|
|
125
|
+
* short-circuits on them for the same reason.
|
|
126
|
+
*/
|
|
127
|
+
type AssetIdentifier = `${string}::${string}` | `${string}*${string}`;
|
|
128
|
+
/**
|
|
129
|
+
* Narrow a runtime string to an {@link AssetIdentifier}, validating it.
|
|
130
|
+
*
|
|
131
|
+
* The escape hatch for config-driven values: `assetId(process.env.ASSET!)`
|
|
132
|
+
* throws on a contract id instead of letting it through to a zero-row query.
|
|
133
|
+
*/
|
|
134
|
+
declare function assetId(value: string): AssetIdentifier;
|
|
135
|
+
/** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
|
|
136
|
+
declare function isPrincipal(value: string): value is Principal;
|
|
137
|
+
/** Subscriptions match `*` wildcards in principal/identifier patterns; every
|
|
138
|
+
* other surface treats the value literally. */
|
|
139
|
+
declare function hasWildcard(value: string): boolean;
|
|
140
|
+
/** Throw unless `value` is a principal or a wildcard pattern. The factories
|
|
141
|
+
* call this so a swapped argument (asset id where a sender belongs, typo'd
|
|
142
|
+
* address) fails at construction — not as a silent zero-row query. */
|
|
143
|
+
declare function assertPrincipalish(field: string, value: string): void;
|
|
144
|
+
/** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
|
|
145
|
+
declare function assertAssetIdentifier(field: string, value: string): void;
|
|
146
|
+
/** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
|
|
147
|
+
declare function assertContractId(field: string, value: string): void;
|
|
105
148
|
/** Scalar print field types (structural mirror of the subgraphs `ColumnType`). */
|
|
106
149
|
type PrintScalarType = "uint" | "int" | "text" | "principal" | "boolean" | "timestamp" | "jsonb";
|
|
107
150
|
/**
|
|
@@ -150,37 +193,37 @@ type TraitScope = {
|
|
|
150
193
|
};
|
|
151
194
|
interface FtTransferSpec extends TraitScope {
|
|
152
195
|
type: "ft_transfer";
|
|
153
|
-
assetIdentifier?:
|
|
196
|
+
assetIdentifier?: AssetIdentifier;
|
|
154
197
|
sender?: string;
|
|
155
198
|
recipient?: string;
|
|
156
199
|
minAmount?: bigint;
|
|
157
200
|
}
|
|
158
201
|
interface FtMintSpec extends TraitScope {
|
|
159
202
|
type: "ft_mint";
|
|
160
|
-
assetIdentifier?:
|
|
203
|
+
assetIdentifier?: AssetIdentifier;
|
|
161
204
|
recipient?: string;
|
|
162
205
|
minAmount?: bigint;
|
|
163
206
|
}
|
|
164
207
|
interface FtBurnSpec extends TraitScope {
|
|
165
208
|
type: "ft_burn";
|
|
166
|
-
assetIdentifier?:
|
|
209
|
+
assetIdentifier?: AssetIdentifier;
|
|
167
210
|
sender?: string;
|
|
168
211
|
minAmount?: bigint;
|
|
169
212
|
}
|
|
170
213
|
interface NftTransferSpec extends TraitScope {
|
|
171
214
|
type: "nft_transfer";
|
|
172
|
-
assetIdentifier?:
|
|
215
|
+
assetIdentifier?: AssetIdentifier;
|
|
173
216
|
sender?: string;
|
|
174
217
|
recipient?: string;
|
|
175
218
|
}
|
|
176
219
|
interface NftMintSpec extends TraitScope {
|
|
177
220
|
type: "nft_mint";
|
|
178
|
-
assetIdentifier?:
|
|
221
|
+
assetIdentifier?: AssetIdentifier;
|
|
179
222
|
recipient?: string;
|
|
180
223
|
}
|
|
181
224
|
interface NftBurnSpec extends TraitScope {
|
|
182
225
|
type: "nft_burn";
|
|
183
|
-
assetIdentifier?:
|
|
226
|
+
assetIdentifier?: AssetIdentifier;
|
|
184
227
|
sender?: string;
|
|
185
228
|
}
|
|
186
229
|
interface ContractCallSpec extends TraitScope {
|
|
@@ -263,7 +306,7 @@ type ChainTriggerShape = ChainTriggerOf<ChainEventFilterSpec>;
|
|
|
263
306
|
type IndexEventsParamsShape = {
|
|
264
307
|
eventType: DecodedEventType
|
|
265
308
|
contractId?: string
|
|
266
|
-
assetIdentifier?:
|
|
309
|
+
assetIdentifier?: AssetIdentifier
|
|
267
310
|
sender?: string
|
|
268
311
|
recipient?: string
|
|
269
312
|
trait?: string
|
|
@@ -281,7 +324,7 @@ type StreamsParamsShape = {
|
|
|
281
324
|
contractId?: string
|
|
282
325
|
sender?: string
|
|
283
326
|
recipient?: string
|
|
284
|
-
assetIdentifier?:
|
|
327
|
+
assetIdentifier?: AssetIdentifier
|
|
285
328
|
};
|
|
286
329
|
type DecodedMember = "stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print_event";
|
|
287
330
|
type ProjectionsFor<
|
|
@@ -397,22 +440,4 @@ interface OnNamespace {
|
|
|
397
440
|
* zero-row or over-wide match.
|
|
398
441
|
*/
|
|
399
442
|
declare const on: OnNamespace;
|
|
400
|
-
|
|
401
|
-
* code can require "already validated" without re-checking. */
|
|
402
|
-
type Principal = string & {
|
|
403
|
-
readonly __principal: unique symbol
|
|
404
|
-
};
|
|
405
|
-
/** `true` for a standard (`SP…`/`ST…`) or contract (`SP….name`) principal. */
|
|
406
|
-
declare function isPrincipal(value: string): value is Principal;
|
|
407
|
-
/** Subscriptions match `*` wildcards in principal/identifier patterns; every
|
|
408
|
-
* other surface treats the value literally. */
|
|
409
|
-
declare function hasWildcard(value: string): boolean;
|
|
410
|
-
/** Throw unless `value` is a principal or a wildcard pattern. The factories
|
|
411
|
-
* call this so a swapped argument (asset id where a sender belongs, typo'd
|
|
412
|
-
* address) fails at construction — not as a silent zero-row query. */
|
|
413
|
-
declare function assertPrincipalish(field: string, value: string): void;
|
|
414
|
-
/** Throw unless `value` looks like `SP….contract::asset` (or a wildcard). */
|
|
415
|
-
declare function assertAssetIdentifier(field: string, value: string): void;
|
|
416
|
-
/** Throw unless `value` is a contract id `SP….name` (or a wildcard). */
|
|
417
|
-
declare function assertContractId(field: string, value: string): void;
|
|
418
|
-
export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assertPrincipalish, assertContractId, assertAssetIdentifier, SubgraphSourceSpec, SubgraphMemberType, StxTransferSpec, StxMintSpec, StxLockSpec, StxBurnSpec, StreamsParamsShape, SpecFor, SbtcWithdrawalSweptConfirmedSpec, SbtcWithdrawalRejectSpec, SbtcWithdrawalCreateSpec, SbtcWithdrawalAcceptSpec, SbtcDepositSpec, PrintScalarType, 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 };
|
|
443
|
+
export { on, makeChainEventFilter, isPrincipal, hasWildcard, fromSubgraphSource, assetId, assertPrincipalish, assertContractId, assertAssetIdentifier, SubgraphSourceSpec, SubgraphMemberType, StxTransferSpec, StxMintSpec, StxLockSpec, StxBurnSpec, StreamsParamsShape, SpecFor, SbtcWithdrawalSweptConfirmedSpec, SbtcWithdrawalRejectSpec, SbtcWithdrawalCreateSpec, SbtcWithdrawalAcceptSpec, SbtcDepositSpec, PrintScalarType, 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, AssetIdentifier };
|