@secondlayer/subgraphs 6.4.0 → 6.5.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.
- package/README.md +1 -0
- package/dist/index.d.ts +121 -121
- package/dist/index.js +262 -27
- package/dist/index.js.map +9 -8
- package/dist/runtime/emitter.js +1 -1
- package/dist/runtime/emitter.js.map +2 -2
- package/dist/runtime/replay.d.ts +32 -13
- package/dist/runtime/replay.js +723 -22
- package/dist/runtime/replay.js.map +8 -5
- package/dist/schema/index.d.ts +39 -39
- package/dist/schema/index.js +27 -14
- package/dist/schema/index.js.map +5 -5
- package/dist/testing/index.d.ts +105 -105
- package/dist/testing/index.js +406 -95
- package/dist/testing/index.js.map +7 -6
- package/dist/types.d.ts +31 -31
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +27 -27
- package/dist/validate.js +1 -1
- package/dist/validate.js.map +2 -2
- package/dist/verification.d.ts +41 -26
- package/dist/verification.js +23 -13
- package/dist/verification.js.map +4 -4
- package/dist/verify/index.d.ts +475 -0
- package/dist/verify/index.js +3341 -0
- package/dist/verify/index.js.map +27 -0
- package/package.json +9 -3
package/dist/types.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { AssetIdentifier } from "@secondlayer/stacks/filters";
|
|
|
16
16
|
*/
|
|
17
17
|
type ChainReadCacheMode = "per-block" | "contract-constant";
|
|
18
18
|
type ChainReadOptions = {
|
|
19
|
-
cache?: ChainReadCacheMode
|
|
19
|
+
cache?: ChainReadCacheMode;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
22
|
* `ChainReadClient` with the ABI generic erased. Structurally cheap, so the
|
|
@@ -25,7 +25,7 @@ type ChainReadOptions = {
|
|
|
25
25
|
*/
|
|
26
26
|
interface ErasedChainReadClient {
|
|
27
27
|
contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
|
|
28
|
-
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown
|
|
28
|
+
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>;
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
/** Supported column types for subgraph schemas */
|
|
@@ -86,7 +86,7 @@ interface StxLockFilter {
|
|
|
86
86
|
* as-of each processed block. Lets a source index "all SIP-010 tokens" etc.
|
|
87
87
|
*/
|
|
88
88
|
type TraitScope = {
|
|
89
|
-
trait?: string
|
|
89
|
+
trait?: string;
|
|
90
90
|
};
|
|
91
91
|
/**
|
|
92
92
|
* Scope a source to a DYNAMIC address set discovered from another source's
|
|
@@ -126,10 +126,10 @@ type TraitScope = {
|
|
|
126
126
|
interface FactoryScope {
|
|
127
127
|
factory?: {
|
|
128
128
|
/** Source name whose events reveal the addresses. */
|
|
129
|
-
from: string
|
|
129
|
+
from: string;
|
|
130
130
|
/** Dotted path to the address on that source's payload
|
|
131
131
|
* (e.g. `"data.pool"`, `"contractId"`, `"data.token.id"`). */
|
|
132
|
-
field: string
|
|
132
|
+
field: string;
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
135
|
/** FT event filters */
|
|
@@ -202,12 +202,12 @@ interface ContractCallEvent {
|
|
|
202
202
|
resultHex: string | null;
|
|
203
203
|
/** Transaction metadata. */
|
|
204
204
|
tx: {
|
|
205
|
-
txId: string
|
|
206
|
-
sender: string
|
|
207
|
-
type: string
|
|
208
|
-
status: string
|
|
209
|
-
contractId: string | null
|
|
210
|
-
functionName: string | null
|
|
205
|
+
txId: string;
|
|
206
|
+
sender: string;
|
|
207
|
+
type: string;
|
|
208
|
+
status: string;
|
|
209
|
+
contractId: string | null;
|
|
210
|
+
functionName: string | null;
|
|
211
211
|
};
|
|
212
212
|
}
|
|
213
213
|
/** Contract event filters */
|
|
@@ -276,12 +276,12 @@ interface MapWriteFilter extends TraitScope, FactoryScope {
|
|
|
276
276
|
* - `{ list: F }` — a list of `F`.
|
|
277
277
|
*/
|
|
278
278
|
type PrintField = ColumnType | {
|
|
279
|
-
type: PrintField
|
|
280
|
-
optional: true
|
|
279
|
+
type: PrintField;
|
|
280
|
+
optional: true;
|
|
281
281
|
} | {
|
|
282
|
-
tuple: Record<string, PrintField
|
|
282
|
+
tuple: Record<string, PrintField>;
|
|
283
283
|
} | {
|
|
284
|
-
list: PrintField
|
|
284
|
+
list: PrintField;
|
|
285
285
|
};
|
|
286
286
|
/**
|
|
287
287
|
* Per-topic field schema for a print_event source. When declared, the handler's
|
|
@@ -293,34 +293,34 @@ type PrintField = ColumnType | {
|
|
|
293
293
|
*/
|
|
294
294
|
type PrintEventPrints = Record<string, Record<string, PrintField>>;
|
|
295
295
|
type PrintEventFields = FactoryScope & {
|
|
296
|
-
type: "print_event"
|
|
297
|
-
topic?: string
|
|
296
|
+
type: "print_event";
|
|
297
|
+
topic?: string;
|
|
298
298
|
};
|
|
299
299
|
/**
|
|
300
300
|
* Pinned to one or more contract ids with no trait — `prints` is required so
|
|
301
301
|
* `event.data` is typed and empty-table handlers cannot typecheck.
|
|
302
302
|
*/
|
|
303
303
|
type PinnedPrintEventFilter = PrintEventFields & {
|
|
304
|
-
contractId: string | readonly string[]
|
|
305
|
-
trait?: undefined
|
|
306
|
-
prints: PrintEventPrints
|
|
304
|
+
contractId: string | readonly string[];
|
|
305
|
+
trait?: undefined;
|
|
306
|
+
prints: PrintEventPrints;
|
|
307
307
|
};
|
|
308
308
|
/**
|
|
309
309
|
* Trait-scoped print source (optionally narrowed by contractId). No single
|
|
310
310
|
* schema — `prints` stays optional.
|
|
311
311
|
*/
|
|
312
312
|
type TraitPrintEventFilter = PrintEventFields & {
|
|
313
|
-
contractId?: string | readonly string[]
|
|
314
|
-
trait: string
|
|
315
|
-
prints?: PrintEventPrints
|
|
313
|
+
contractId?: string | readonly string[];
|
|
314
|
+
trait: string;
|
|
315
|
+
prints?: PrintEventPrints;
|
|
316
316
|
};
|
|
317
317
|
/**
|
|
318
318
|
* Unpinned / factory-only print source (no contractId). `prints` optional.
|
|
319
319
|
*/
|
|
320
320
|
type UnpinnedPrintEventFilter = PrintEventFields & {
|
|
321
|
-
contractId?: undefined
|
|
322
|
-
trait?: string
|
|
323
|
-
prints?: PrintEventPrints
|
|
321
|
+
contractId?: undefined;
|
|
322
|
+
trait?: string;
|
|
323
|
+
prints?: PrintEventPrints;
|
|
324
324
|
};
|
|
325
325
|
/**
|
|
326
326
|
* Print-event filter. Pinned sources (contractId set, no trait) require
|
|
@@ -343,12 +343,12 @@ type RowValue = string | number | bigint | boolean | null | undefined | Record<s
|
|
|
343
343
|
/** Context passed to subgraph handlers during event processing */
|
|
344
344
|
interface SubgraphContext {
|
|
345
345
|
block: {
|
|
346
|
-
height: number
|
|
347
|
-
hash: string
|
|
348
|
-
timestamp: number
|
|
349
|
-
burnBlockHeight: number
|
|
346
|
+
height: number;
|
|
347
|
+
hash: string;
|
|
348
|
+
timestamp: number;
|
|
349
|
+
burnBlockHeight: number;
|
|
350
350
|
/** Nakamoto StacksBlockId, when the block row carries one. */
|
|
351
|
-
indexBlockHash?: string | null
|
|
351
|
+
indexBlockHash?: string | null;
|
|
352
352
|
};
|
|
353
353
|
tx: TxMeta;
|
|
354
354
|
/**
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
package/dist/validate.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { AssetIdentifier } from "@secondlayer/stacks/filters";
|
|
|
17
17
|
*/
|
|
18
18
|
type ChainReadCacheMode = "per-block" | "contract-constant";
|
|
19
19
|
type ChainReadOptions = {
|
|
20
|
-
cache?: ChainReadCacheMode
|
|
20
|
+
cache?: ChainReadCacheMode;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
23
|
* `ChainReadClient` with the ABI generic erased. Structurally cheap, so the
|
|
@@ -26,7 +26,7 @@ type ChainReadOptions = {
|
|
|
26
26
|
*/
|
|
27
27
|
interface ErasedChainReadClient {
|
|
28
28
|
contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
|
|
29
|
-
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown
|
|
29
|
+
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>;
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
/** Supported column types for subgraph schemas */
|
|
@@ -87,7 +87,7 @@ interface StxLockFilter {
|
|
|
87
87
|
* as-of each processed block. Lets a source index "all SIP-010 tokens" etc.
|
|
88
88
|
*/
|
|
89
89
|
type TraitScope = {
|
|
90
|
-
trait?: string
|
|
90
|
+
trait?: string;
|
|
91
91
|
};
|
|
92
92
|
/**
|
|
93
93
|
* Scope a source to a DYNAMIC address set discovered from another source's
|
|
@@ -127,10 +127,10 @@ type TraitScope = {
|
|
|
127
127
|
interface FactoryScope {
|
|
128
128
|
factory?: {
|
|
129
129
|
/** Source name whose events reveal the addresses. */
|
|
130
|
-
from: string
|
|
130
|
+
from: string;
|
|
131
131
|
/** Dotted path to the address on that source's payload
|
|
132
132
|
* (e.g. `"data.pool"`, `"contractId"`, `"data.token.id"`). */
|
|
133
|
-
field: string
|
|
133
|
+
field: string;
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
/** FT event filters */
|
|
@@ -236,12 +236,12 @@ interface MapWriteFilter extends TraitScope, FactoryScope {
|
|
|
236
236
|
* - `{ list: F }` — a list of `F`.
|
|
237
237
|
*/
|
|
238
238
|
type PrintField = ColumnType | {
|
|
239
|
-
type: PrintField
|
|
240
|
-
optional: true
|
|
239
|
+
type: PrintField;
|
|
240
|
+
optional: true;
|
|
241
241
|
} | {
|
|
242
|
-
tuple: Record<string, PrintField
|
|
242
|
+
tuple: Record<string, PrintField>;
|
|
243
243
|
} | {
|
|
244
|
-
list: PrintField
|
|
244
|
+
list: PrintField;
|
|
245
245
|
};
|
|
246
246
|
/**
|
|
247
247
|
* Per-topic field schema for a print_event source. When declared, the handler's
|
|
@@ -253,34 +253,34 @@ type PrintField = ColumnType | {
|
|
|
253
253
|
*/
|
|
254
254
|
type PrintEventPrints = Record<string, Record<string, PrintField>>;
|
|
255
255
|
type PrintEventFields = FactoryScope & {
|
|
256
|
-
type: "print_event"
|
|
257
|
-
topic?: string
|
|
256
|
+
type: "print_event";
|
|
257
|
+
topic?: string;
|
|
258
258
|
};
|
|
259
259
|
/**
|
|
260
260
|
* Pinned to one or more contract ids with no trait — `prints` is required so
|
|
261
261
|
* `event.data` is typed and empty-table handlers cannot typecheck.
|
|
262
262
|
*/
|
|
263
263
|
type PinnedPrintEventFilter = PrintEventFields & {
|
|
264
|
-
contractId: string | readonly string[]
|
|
265
|
-
trait?: undefined
|
|
266
|
-
prints: PrintEventPrints
|
|
264
|
+
contractId: string | readonly string[];
|
|
265
|
+
trait?: undefined;
|
|
266
|
+
prints: PrintEventPrints;
|
|
267
267
|
};
|
|
268
268
|
/**
|
|
269
269
|
* Trait-scoped print source (optionally narrowed by contractId). No single
|
|
270
270
|
* schema — `prints` stays optional.
|
|
271
271
|
*/
|
|
272
272
|
type TraitPrintEventFilter = PrintEventFields & {
|
|
273
|
-
contractId?: string | readonly string[]
|
|
274
|
-
trait: string
|
|
275
|
-
prints?: PrintEventPrints
|
|
273
|
+
contractId?: string | readonly string[];
|
|
274
|
+
trait: string;
|
|
275
|
+
prints?: PrintEventPrints;
|
|
276
276
|
};
|
|
277
277
|
/**
|
|
278
278
|
* Unpinned / factory-only print source (no contractId). `prints` optional.
|
|
279
279
|
*/
|
|
280
280
|
type UnpinnedPrintEventFilter = PrintEventFields & {
|
|
281
|
-
contractId?: undefined
|
|
282
|
-
trait?: string
|
|
283
|
-
prints?: PrintEventPrints
|
|
281
|
+
contractId?: undefined;
|
|
282
|
+
trait?: string;
|
|
283
|
+
prints?: PrintEventPrints;
|
|
284
284
|
};
|
|
285
285
|
/**
|
|
286
286
|
* Print-event filter. Pinned sources (contractId set, no trait) require
|
|
@@ -301,12 +301,12 @@ interface TxMeta {
|
|
|
301
301
|
/** Context passed to subgraph handlers during event processing */
|
|
302
302
|
interface SubgraphContext {
|
|
303
303
|
block: {
|
|
304
|
-
height: number
|
|
305
|
-
hash: string
|
|
306
|
-
timestamp: number
|
|
307
|
-
burnBlockHeight: number
|
|
304
|
+
height: number;
|
|
305
|
+
hash: string;
|
|
306
|
+
timestamp: number;
|
|
307
|
+
burnBlockHeight: number;
|
|
308
308
|
/** Nakamoto StacksBlockId, when the block row carries one. */
|
|
309
|
-
indexBlockHash?: string | null
|
|
309
|
+
indexBlockHash?: string | null;
|
|
310
310
|
};
|
|
311
311
|
tx: TxMeta;
|
|
312
312
|
/**
|
|
@@ -405,7 +405,7 @@ declare function validateSubgraphDefinition(def: unknown): SubgraphDefinition;
|
|
|
405
405
|
* means adding a field to a filter can never leave the documentation behind.
|
|
406
406
|
*/
|
|
407
407
|
declare function filterFieldsByType(): Array<{
|
|
408
|
-
type: string
|
|
409
|
-
fields: string[]
|
|
408
|
+
type: string;
|
|
409
|
+
fields: string[];
|
|
410
410
|
}>;
|
|
411
411
|
export { AbiContractSchema, ColumnTypeSchema, PrintFieldSchema, SqlIdentifierSchema, SubgraphColumnSchema, SubgraphDefinitionSchema, SubgraphFilterSchema, SubgraphNameSchema, SubgraphSchemaSchema, SubgraphTableSchema, VALID_FILTER_TYPES, filterFieldsByType, validateSubgraphDefinition };
|
package/dist/validate.js
CHANGED
package/dist/validate.js.map
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["
|
|
3
|
+
"sources": ["src/validate.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { z } from \"zod\";\nimport type {\n\tColumnType,\n\tSubgraphColumn,\n\tSubgraphDefinition,\n\tSubgraphFilter,\n\tSubgraphSchema,\n\tSubgraphTable,\n} from \"./types.ts\";\n\nexport const SubgraphNameSchema: z.ZodType<string> = z\n\t.string()\n\t.min(1)\n\t.max(63)\n\t.regex(\n\t\t/^[a-z][a-z0-9-]*$/,\n\t\t\"Must start with lowercase letter, contain only lowercase alphanumeric and hyphens\",\n\t);\n\n/**\n * A safe SQL identifier (table or column name). Mirrors the runtime guard in\n * runtime/context.ts (validateColumnName) so the schema validator can never\n * accept a name the runtime would reject — and closes the deploy-time DDL\n * injection path in schema/generator.ts, which interpolates these names raw.\n */\nexport const SqlIdentifierSchema: z.ZodType<string> = z\n\t.string()\n\t.min(1)\n\t.max(63) // Postgres truncates identifiers > 63 bytes; reject rather than collide.\n\t.regex(\n\t\t/^[a-z_][a-z0-9_]*$/i,\n\t\t\"Must be a valid SQL identifier: start with a letter or underscore, then letters/digits/underscores only\",\n\t);\n\nexport const ColumnTypeSchema: z.ZodType<ColumnType> = z.enum([\n\t\"text\",\n\t\"uint\",\n\t\"int\",\n\t\"principal\",\n\t\"boolean\",\n\t\"timestamp\",\n\t\"jsonb\",\n]);\n\n/**\n * One declared print field: a bare column type, or a composite (optional,\n * nested tuple, list). Recursive — real print payloads nest, and a vocabulary\n * that could only say `\"jsonb\"` is what let a flat-field declaration pass\n * while every event decoded to null.\n */\nexport const PrintFieldSchema: z.ZodType<unknown> = z.lazy(() =>\n\tz.union([\n\t\tColumnTypeSchema,\n\t\tz.object({ type: PrintFieldSchema, optional: z.literal(true) }),\n\t\tz.object({ tuple: z.record(z.string(), PrintFieldSchema) }),\n\t\tz.object({ list: PrintFieldSchema }),\n\t]),\n);\n\n/**\n * A Clarity ABI type: a primitive name, or one of the composite shapes.\n * Recursive, so nested tuples/lists/optionals are checked all the way down.\n */\nconst AbiTypeSchema: z.ZodType<unknown> = z.lazy(() =>\n\tz.union([\n\t\tz.string(),\n\t\tz.object({ buff: z.object({ length: z.number() }) }),\n\t\tz.object({ \"string-ascii\": z.object({ length: z.number() }) }),\n\t\tz.object({ \"string-utf8\": z.object({ length: z.number() }) }),\n\t\tz.object({ optional: AbiTypeSchema }),\n\t\tz.object({\n\t\t\tlist: z.object({ type: AbiTypeSchema, length: z.number() }),\n\t\t}),\n\t\tz.object({\n\t\t\ttuple: z.array(z.object({ name: z.string(), type: AbiTypeSchema })),\n\t\t}),\n\t\tz.object({\n\t\t\tresponse: z.object({ ok: AbiTypeSchema, error: AbiTypeSchema }),\n\t\t}),\n\t]),\n);\n\n/**\n * The canonical `AbiContract` shape, validated at deploy time.\n *\n * This used to be `z.record(z.string(), z.any())`, which accepted a raw\n * Hiro/Clarinet ABI (`read_only` access, `buffer` types, outputs wrapped as\n * `{ type: … }`) and let it through — the deploy succeeded and `event.input`\n * then mis-decoded at RUNTIME, per event, forever. Reject it here instead,\n * and name the fix: run it through `normalizeAbi` from\n * `@secondlayer/stacks/clarity`.\n */\nexport const AbiContractSchema: z.ZodType<unknown> = z.object({\n\tfunctions: z.array(\n\t\tz.object({\n\t\t\tname: z.string(),\n\t\t\taccess: z.enum([\"public\", \"read-only\", \"private\"], {\n\t\t\t\tmessage:\n\t\t\t\t\t\"ABI access must be public | read-only | private — a raw Hiro/Clarinet ABI uses `read_only`. Normalize it first: normalizeAbi() from @secondlayer/stacks/clarity.\",\n\t\t\t}),\n\t\t\targs: z.array(z.object({ name: z.string(), type: AbiTypeSchema })),\n\t\t\t// Canonical shape is a bare AbiType; raw ABIs wrap it as `{ type: … }`.\n\t\t\toutputs: AbiTypeSchema,\n\t\t}),\n\t),\n\tmaps: z.array(z.unknown()).optional(),\n\tvariables: z.array(z.unknown()).optional(),\n\tfungible_tokens: z.array(z.unknown()).optional(),\n\tnon_fungible_tokens: z.array(z.unknown()).optional(),\n\timplemented_traits: z.array(z.unknown()).optional(),\n\tdefined_traits: z.array(z.unknown()).optional(),\n});\n\nexport const SubgraphColumnSchema: z.ZodType<SubgraphColumn> = z.object({\n\ttype: ColumnTypeSchema,\n\tnullable: z.boolean().optional(),\n\tindexed: z.boolean().optional(),\n\tsearch: z.boolean().optional(),\n\tdefault: z.union([z.string(), z.number(), z.boolean()]).optional(),\n}) as z.ZodType<SubgraphColumn>;\n\nexport const SubgraphTableSchema: z.ZodType<SubgraphTable> = z.object({\n\tcolumns: z\n\t\t.record(SqlIdentifierSchema, SubgraphColumnSchema)\n\t\t.refine(\n\t\t\t(c) => Object.keys(c).length > 0,\n\t\t\t\"Table must have at least one column\",\n\t\t),\n\tindexes: z.array(z.array(SqlIdentifierSchema)).optional(),\n\tuniqueKeys: z.array(z.array(SqlIdentifierSchema)).optional(),\n}) as z.ZodType<SubgraphTable>;\n\nexport const SubgraphSchemaSchema: z.ZodType<Record<string, SubgraphTable>> = z\n\t.record(SqlIdentifierSchema, SubgraphTableSchema)\n\t.refine(\n\t\t(s) => Object.keys(s).length > 0,\n\t\t\"Schema must have at least one table\",\n\t) as z.ZodType<Record<string, SubgraphTable>>;\n\nexport const VALID_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\"nested_contract_call\",\n\t\"var_set\",\n\t\"map_set\",\n\t\"map_insert\",\n\t\"map_delete\",\n] as const;\n\n/** A contract id, or a set of them (max 20, matching the Index API cap). */\nconst contractIdField = z.union([\n\tz.string(),\n\tz.array(z.string()).min(1).max(20),\n]);\n\n/** Fields shared by the trait-scopable filters. */\nconst traitScope = { trait: z.string().optional() };\n/** Dynamic address set discovered from another source's events. */\nconst factoryScope = {\n\tfactory: z\n\t\t.object({ from: z.string().min(1), field: z.string().min(1) })\n\t\t.strict()\n\t\t.optional(),\n};\nconst amountRange = {\n\tminAmount: z.bigint().optional(),\n\tmaxAmount: z.bigint().optional(),\n};\n\n/**\n * A REAL discriminated union — one member per source type, each `.strict()`\n * with only the fields that type actually supports.\n *\n * It used to be one flat object with every field optional, so\n * `{ type: \"contract_deploy\", assetIdentifier: \"SP…\", minAmount: 1n }`\n * validated clean at deploy and then matched nothing, forever. The runtime\n * union already knew better; only the validator didn't.\n */\nconst SubgraphFilterUnion = z.discriminatedUnion(\"type\", [\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_transfer\"),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...amountRange,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_mint\"),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_burn\"),\n\t\t\tsender: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_lock\"),\n\t\t\tlockedAddress: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_transfer\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_mint\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_burn\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_transfer\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_mint\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_burn\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"contract_call\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tfunctionName: z.string().optional(),\n\t\t\tcaller: z.string().optional(),\n\t\t\tabi: AbiContractSchema.optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"contract_deploy\"),\n\t\t\tdeployer: z.string().optional(),\n\t\t\tcontractName: z.string().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"print_event\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\ttopic: z.string().optional(),\n\t\t\tprints: z\n\t\t\t\t.record(z.string(), z.record(z.string(), PrintFieldSchema))\n\t\t\t\t.optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nested_contract_call\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tfunctionName: z.string().optional(),\n\t\t\tcaller: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"var_set\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tvarName: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_set\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_insert\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_delete\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n]);\n\n/**\n * `trait` and `contractId` compose rather than conflict: the matcher ANDs\n * them, so the pair means \"contracts conforming to this trait, narrowed to\n * these ids\". (The Index READ API refuses the combination because its query\n * planner picks one index path — that's an API constraint, not a semantic\n * one, and subgraph sources are not bound by it.)\n */\nexport const SubgraphFilterSchema: z.ZodType<SubgraphFilter> =\n\tSubgraphFilterUnion as unknown as z.ZodType<SubgraphFilter>;\n\n/** Pinned contractId: a non-empty string or a non-empty array of ids. */\nfunction hasPinnedContractId(\n\tcontractId: string | readonly string[] | undefined,\n): boolean {\n\tif (typeof contractId === \"string\") return contractId.length > 0;\n\tif (Array.isArray(contractId)) return contractId.length > 0;\n\treturn false;\n}\n\n/**\n * Deploy gates beyond the per-filter union: pinned print_event needs a\n * non-empty `prints` map, contract_call+functionName needs `abi`, and every\n * source needs a handler of the same name.\n */\nfunction refineDeployGates(\n\tdef: {\n\t\tsources: Record<string, SubgraphFilter>;\n\t\thandlers: Record<string, unknown>;\n\t\tschema: SubgraphSchema;\n\t},\n\tctx: z.RefinementCtx,\n): void {\n\tfor (const [name, filter] of Object.entries(def.sources)) {\n\t\tif (filter.type === \"print_event\") {\n\t\t\t// Trait / unpinned (no contractId) may omit prints — no single schema.\n\t\t\tconst pinned = hasPinnedContractId(filter.contractId) && !filter.trait;\n\t\t\tif (pinned) {\n\t\t\t\tconst prints = filter.prints;\n\t\t\t\tif (\n\t\t\t\t\tprints === undefined ||\n\t\t\t\t\ttypeof prints !== \"object\" ||\n\t\t\t\t\tObject.keys(prints).length === 0\n\t\t\t\t) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tpath: [\"sources\", name, \"prints\"],\n\t\t\t\t\t\tmessage: `print_event source \"${name}\" has no prints map — field names would be untyped and empty tables would typecheck. Declare prints from index_print_schema / create --from-contract.`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (filter.type === \"contract_call\" && filter.functionName !== undefined) {\n\t\t\tif (filter.abi === undefined) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\tpath: [\"sources\", name, \"abi\"],\n\t\t\t\t\tmessage: `contract_call source \"${name}\" has functionName but no abi. \\`secondlayer subgraphs deploy\\` fills it in from the deployed contract; otherwise pass abi (normalizeAbi() from @secondlayer/stacks/clarity).`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const name of Object.keys(def.sources)) {\n\t\tif (def.handlers[name] == null) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [\"handlers\", name],\n\t\t\t\tmessage: `source \"${name}\" has no handler. Add handlers.${name}, or its events are skipped and the table stays empty.`,\n\t\t\t});\n\t\t}\n\t}\n}\n\nexport const SubgraphDefinitionSchema: z.ZodType<SubgraphDefinition> = z\n\t.object({\n\t\tname: SubgraphNameSchema,\n\t\tdescription: z.string().optional(),\n\t\tstartBlock: z.number().int().nonnegative().optional(),\n\t\t// 'concurrent' = tip-first deploy: go live at tip immediately, fill\n\t\t// history via a background backfill. Only safe for order-tolerant\n\t\t// handlers (commutative or insert-only writes).\n\t\tbackfillMode: z.enum([\"blocking\", \"concurrent\"]).optional(),\n\t\tsources: z\n\t\t\t.record(z.string(), SubgraphFilterSchema)\n\t\t\t.refine(\n\t\t\t\t(s) => Object.keys(s).length > 0,\n\t\t\t\t\"Must have at least one source\",\n\t\t\t),\n\t\tschema: SubgraphSchemaSchema,\n\t\thandlers: z.record(z.string(), z.any()),\n\t})\n\t.superRefine((def, ctx) => {\n\t\trefineDeployGates(\n\t\t\tdef as {\n\t\t\t\tsources: Record<string, SubgraphFilter>;\n\t\t\t\thandlers: Record<string, unknown>;\n\t\t\t\tschema: SubgraphSchema;\n\t\t\t},\n\t\t\tctx,\n\t\t);\n\t}) as unknown as z.ZodType<SubgraphDefinition>;\n\n/**\n * Validates a subgraph definition, returning the parsed result or throwing on failure.\n */\nexport function validateSubgraphDefinition(def: unknown): SubgraphDefinition {\n\treturn SubgraphDefinitionSchema.parse(def);\n}\n\n/**\n * Per-source-type field vocabulary, DERIVED from\n * {@link SubgraphFilterSchema}. Agent-facing surfaces (the MCP filters\n * reference) used to hand-maintain a parallel copy of this list; deriving it\n * means adding a field to a filter can never leave the documentation behind.\n */\nexport function filterFieldsByType(): Array<{\n\ttype: string;\n\tfields: string[];\n}> {\n\t// Read the UNION directly (SubgraphFilterSchema wraps it in superRefine).\n\t// biome-ignore lint/suspicious/noExplicitAny: reading zod's internal option shapes\n\tconst options = (SubgraphFilterUnion as any)?._def?.options ?? [];\n\tconst out: Array<{ type: string; fields: string[] }> = [];\n\tfor (const option of options) {\n\t\t// `.superRefine()` wraps the union, so unwrap one level when present.\n\t\tconst shape = option?.shape ?? option?._def?.shape;\n\t\tif (!shape) continue;\n\t\tconst literal =\n\t\t\tshape.type?._def?.values?.[0] ?? shape.type?._def?.value ?? undefined;\n\t\tif (typeof literal !== \"string\") continue;\n\t\tout.push({\n\t\t\ttype: literal,\n\t\t\tfields: Object.keys(shape).filter((k) => k !== \"type\"),\n\t\t});\n\t}\n\treturn out;\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "3596CDEC5E862E6064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/verification.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { AssetIdentifier } from "@secondlayer/stacks/filters";
|
|
|
17
17
|
*/
|
|
18
18
|
type ChainReadCacheMode = "per-block" | "contract-constant";
|
|
19
19
|
type ChainReadOptions = {
|
|
20
|
-
cache?: ChainReadCacheMode
|
|
20
|
+
cache?: ChainReadCacheMode;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
23
|
* `ChainReadClient` with the ABI generic erased. Structurally cheap, so the
|
|
@@ -26,7 +26,7 @@ type ChainReadOptions = {
|
|
|
26
26
|
*/
|
|
27
27
|
interface ErasedChainReadClient {
|
|
28
28
|
contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
|
|
29
|
-
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown
|
|
29
|
+
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>;
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
/** Supported column types for subgraph schemas */
|
|
@@ -87,7 +87,7 @@ interface StxLockFilter {
|
|
|
87
87
|
* as-of each processed block. Lets a source index "all SIP-010 tokens" etc.
|
|
88
88
|
*/
|
|
89
89
|
type TraitScope = {
|
|
90
|
-
trait?: string
|
|
90
|
+
trait?: string;
|
|
91
91
|
};
|
|
92
92
|
/**
|
|
93
93
|
* Scope a source to a DYNAMIC address set discovered from another source's
|
|
@@ -127,10 +127,10 @@ type TraitScope = {
|
|
|
127
127
|
interface FactoryScope {
|
|
128
128
|
factory?: {
|
|
129
129
|
/** Source name whose events reveal the addresses. */
|
|
130
|
-
from: string
|
|
130
|
+
from: string;
|
|
131
131
|
/** Dotted path to the address on that source's payload
|
|
132
132
|
* (e.g. `"data.pool"`, `"contractId"`, `"data.token.id"`). */
|
|
133
|
-
field: string
|
|
133
|
+
field: string;
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
/** FT event filters */
|
|
@@ -236,12 +236,12 @@ interface MapWriteFilter extends TraitScope, FactoryScope {
|
|
|
236
236
|
* - `{ list: F }` — a list of `F`.
|
|
237
237
|
*/
|
|
238
238
|
type PrintField = ColumnType | {
|
|
239
|
-
type: PrintField
|
|
240
|
-
optional: true
|
|
239
|
+
type: PrintField;
|
|
240
|
+
optional: true;
|
|
241
241
|
} | {
|
|
242
|
-
tuple: Record<string, PrintField
|
|
242
|
+
tuple: Record<string, PrintField>;
|
|
243
243
|
} | {
|
|
244
|
-
list: PrintField
|
|
244
|
+
list: PrintField;
|
|
245
245
|
};
|
|
246
246
|
/**
|
|
247
247
|
* Per-topic field schema for a print_event source. When declared, the handler's
|
|
@@ -253,34 +253,34 @@ type PrintField = ColumnType | {
|
|
|
253
253
|
*/
|
|
254
254
|
type PrintEventPrints = Record<string, Record<string, PrintField>>;
|
|
255
255
|
type PrintEventFields = FactoryScope & {
|
|
256
|
-
type: "print_event"
|
|
257
|
-
topic?: string
|
|
256
|
+
type: "print_event";
|
|
257
|
+
topic?: string;
|
|
258
258
|
};
|
|
259
259
|
/**
|
|
260
260
|
* Pinned to one or more contract ids with no trait — `prints` is required so
|
|
261
261
|
* `event.data` is typed and empty-table handlers cannot typecheck.
|
|
262
262
|
*/
|
|
263
263
|
type PinnedPrintEventFilter = PrintEventFields & {
|
|
264
|
-
contractId: string | readonly string[]
|
|
265
|
-
trait?: undefined
|
|
266
|
-
prints: PrintEventPrints
|
|
264
|
+
contractId: string | readonly string[];
|
|
265
|
+
trait?: undefined;
|
|
266
|
+
prints: PrintEventPrints;
|
|
267
267
|
};
|
|
268
268
|
/**
|
|
269
269
|
* Trait-scoped print source (optionally narrowed by contractId). No single
|
|
270
270
|
* schema — `prints` stays optional.
|
|
271
271
|
*/
|
|
272
272
|
type TraitPrintEventFilter = PrintEventFields & {
|
|
273
|
-
contractId?: string | readonly string[]
|
|
274
|
-
trait: string
|
|
275
|
-
prints?: PrintEventPrints
|
|
273
|
+
contractId?: string | readonly string[];
|
|
274
|
+
trait: string;
|
|
275
|
+
prints?: PrintEventPrints;
|
|
276
276
|
};
|
|
277
277
|
/**
|
|
278
278
|
* Unpinned / factory-only print source (no contractId). `prints` optional.
|
|
279
279
|
*/
|
|
280
280
|
type UnpinnedPrintEventFilter = PrintEventFields & {
|
|
281
|
-
contractId?: undefined
|
|
282
|
-
trait?: string
|
|
283
|
-
prints?: PrintEventPrints
|
|
281
|
+
contractId?: undefined;
|
|
282
|
+
trait?: string;
|
|
283
|
+
prints?: PrintEventPrints;
|
|
284
284
|
};
|
|
285
285
|
/**
|
|
286
286
|
* Print-event filter. Pinned sources (contractId set, no trait) require
|
|
@@ -301,12 +301,12 @@ interface TxMeta {
|
|
|
301
301
|
/** Context passed to subgraph handlers during event processing */
|
|
302
302
|
interface SubgraphContext {
|
|
303
303
|
block: {
|
|
304
|
-
height: number
|
|
305
|
-
hash: string
|
|
306
|
-
timestamp: number
|
|
307
|
-
burnBlockHeight: number
|
|
304
|
+
height: number;
|
|
305
|
+
hash: string;
|
|
306
|
+
timestamp: number;
|
|
307
|
+
burnBlockHeight: number;
|
|
308
308
|
/** Nakamoto StacksBlockId, when the block row carries one. */
|
|
309
|
-
indexBlockHash?: string | null
|
|
309
|
+
indexBlockHash?: string | null;
|
|
310
310
|
};
|
|
311
311
|
tx: TxMeta;
|
|
312
312
|
/**
|
|
@@ -417,10 +417,25 @@ interface PinInput {
|
|
|
417
417
|
/** Defaults to {@link SUBGRAPHS_RUNTIME}. */
|
|
418
418
|
runtime?: string;
|
|
419
419
|
}
|
|
420
|
+
/** What a pin commits to, as stored in `pin_preimage`. */
|
|
421
|
+
interface PinFields {
|
|
422
|
+
/** sha256 of the bundled handler, hex. */
|
|
423
|
+
handlerHash: string;
|
|
424
|
+
network: string;
|
|
425
|
+
runtime: string;
|
|
426
|
+
schemaHash: string;
|
|
427
|
+
startBlock: number | null;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* The canonical JSON a pin is the sha256 of: fixed key order, primitives
|
|
431
|
+
* only. Stored beside the pin so anyone can recompute it from the served
|
|
432
|
+
* handler code.
|
|
433
|
+
*/
|
|
434
|
+
declare function pinPreimage(input: PinInput): string;
|
|
420
435
|
/**
|
|
421
436
|
* Content hash over everything that shapes a subgraph's rows. Unlike
|
|
422
437
|
* `schema_hash`, it changes with the handler, `startBlock` and runtime, so
|
|
423
438
|
* two deploys with the same pin produce the same rows from the same chain.
|
|
424
439
|
*/
|
|
425
440
|
declare function computePin(input: PinInput): string;
|
|
426
|
-
export { ALLOWED_GLOBALS, ALLOWED_MATH, FORBIDDEN_GLOBALS, HandlerFinding, LOCALE_METHODS, PinInput, SUBGRAPHS_RUNTIME, SubgraphVerification, computePin, deriveVerification, formatFinding, isDeterminismViolation };
|
|
441
|
+
export { ALLOWED_GLOBALS, ALLOWED_MATH, FORBIDDEN_GLOBALS, HandlerFinding, LOCALE_METHODS, PinFields, PinInput, SUBGRAPHS_RUNTIME, SubgraphVerification, computePin, deriveVerification, formatFinding, isDeterminismViolation, pinPreimage };
|
package/dist/verification.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@secondlayer/subgraphs",
|
|
6
|
-
version: "6.
|
|
6
|
+
version: "6.5.0",
|
|
7
7
|
description: "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
|
|
8
8
|
license: "MIT",
|
|
9
9
|
repository: {
|
|
@@ -47,6 +47,10 @@ var package_default = {
|
|
|
47
47
|
"./testing": {
|
|
48
48
|
types: "./dist/testing/index.d.ts",
|
|
49
49
|
import: "./dist/testing/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./verify": {
|
|
52
|
+
types: "./dist/verify/index.d.ts",
|
|
53
|
+
import: "./dist/verify/index.js"
|
|
50
54
|
}
|
|
51
55
|
},
|
|
52
56
|
files: ["dist"],
|
|
@@ -58,14 +62,16 @@ var package_default = {
|
|
|
58
62
|
prepublishOnly: "bun run build"
|
|
59
63
|
},
|
|
60
64
|
dependencies: {
|
|
61
|
-
"@secondlayer/shared": "^11.
|
|
62
|
-
"@secondlayer/stacks": "^6.
|
|
65
|
+
"@secondlayer/shared": "^11.23.0",
|
|
66
|
+
"@secondlayer/stacks": "^6.2.0",
|
|
67
|
+
"@secondlayer/verify": "^0.3.0",
|
|
63
68
|
esbuild: "^0.28.2",
|
|
64
69
|
kysely: "0.28.17",
|
|
65
70
|
zod: "^4.3.6"
|
|
66
71
|
},
|
|
67
72
|
devDependencies: {
|
|
68
73
|
"@types/bun": "latest",
|
|
74
|
+
bunup: "0.16.32",
|
|
69
75
|
typescript: "^5"
|
|
70
76
|
},
|
|
71
77
|
publishConfig: {
|
|
@@ -195,7 +201,6 @@ function formatFinding(f) {
|
|
|
195
201
|
var STATE_SOURCE_TYPES = new Set([
|
|
196
202
|
"var_set",
|
|
197
203
|
"map_set",
|
|
198
|
-
"map_insert",
|
|
199
204
|
"map_delete"
|
|
200
205
|
]);
|
|
201
206
|
var LEVEL_RANK = { state: 0, events: 1, none: 2 };
|
|
@@ -212,6 +217,9 @@ function deriveVerification(def, findings = []) {
|
|
|
212
217
|
if (filter.trait) {
|
|
213
218
|
raise("none");
|
|
214
219
|
reasons.push(`source "${name}": trait scope needs a proven contract registry`);
|
|
220
|
+
} else if (filter.type === "map_insert") {
|
|
221
|
+
raise("events");
|
|
222
|
+
reasons.push(`map_insert source "${name}": map_insert vs map_set needs event proofs`);
|
|
215
223
|
} else if (!STATE_SOURCE_TYPES.has(filter.type)) {
|
|
216
224
|
raise("events");
|
|
217
225
|
reasons.push(`${filter.type} source "${name}" needs event proofs`);
|
|
@@ -229,14 +237,12 @@ function deriveVerification(def, findings = []) {
|
|
|
229
237
|
if (findings.length > MAX_LISTED_FINDINGS) {
|
|
230
238
|
reasons.push(`…and ${findings.length - MAX_LISTED_FINDINGS} more handler findings`);
|
|
231
239
|
}
|
|
232
|
-
const writesMapInsert = Object.values(def.sources ?? {}).some((s) => s.type === "map_insert");
|
|
233
240
|
return {
|
|
234
241
|
level,
|
|
235
242
|
reasons,
|
|
236
243
|
unproven: reasons.length === 0 ? [
|
|
237
244
|
"tx attribution of writes: event.tx, _tx_id (needs event proofs)",
|
|
238
|
-
"intermediate writes within a block (needs event proofs)"
|
|
239
|
-
...writesMapInsert ? ["map_insert vs map_set (needs event proofs)"] : []
|
|
245
|
+
"intermediate writes within a block (needs event proofs)"
|
|
240
246
|
] : []
|
|
241
247
|
};
|
|
242
248
|
}
|
|
@@ -246,15 +252,18 @@ function isDeterminismViolation(v) {
|
|
|
246
252
|
function sha256(input) {
|
|
247
253
|
return createHash("sha256").update(input).digest("hex");
|
|
248
254
|
}
|
|
249
|
-
function
|
|
250
|
-
const
|
|
255
|
+
function pinPreimage(input) {
|
|
256
|
+
const fields = {
|
|
251
257
|
handlerHash: sha256(input.handlerCode),
|
|
252
258
|
network: input.network,
|
|
253
259
|
runtime: input.runtime ?? SUBGRAPHS_RUNTIME,
|
|
254
260
|
schemaHash: input.schemaHash,
|
|
255
261
|
startBlock: input.startBlock ?? null
|
|
256
|
-
}
|
|
257
|
-
return
|
|
262
|
+
};
|
|
263
|
+
return JSON.stringify(fields);
|
|
264
|
+
}
|
|
265
|
+
function computePin(input) {
|
|
266
|
+
return sha256(pinPreimage(input));
|
|
258
267
|
}
|
|
259
268
|
export {
|
|
260
269
|
ALLOWED_GLOBALS,
|
|
@@ -265,8 +274,9 @@ export {
|
|
|
265
274
|
computePin,
|
|
266
275
|
deriveVerification,
|
|
267
276
|
formatFinding,
|
|
268
|
-
isDeterminismViolation
|
|
277
|
+
isDeterminismViolation,
|
|
278
|
+
pinPreimage
|
|
269
279
|
};
|
|
270
280
|
|
|
271
|
-
//# debugId=
|
|
281
|
+
//# debugId=FE2C72378A236A9764756E2164756E21
|
|
272
282
|
//# sourceMappingURL=verification.js.map
|