@secondlayer/subgraphs 0.5.7 → 0.6.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.
@@ -3,14 +3,14 @@
3
3
  "sources": ["../src/types.ts", "../src/runtime/context.ts", "../src/runtime/source-matcher.ts", "../src/runtime/clarity.ts", "../src/runtime/runner.ts", "../src/runtime/block-processor.ts", "../src/schema/utils.ts"],
4
4
  "sourcesContent": [
5
5
  "/** Supported column types for subgraph schemas */\nexport type ColumnType =\n | \"text\"\n | \"uint\"\n | \"int\"\n | \"principal\"\n | \"boolean\"\n | \"timestamp\"\n | \"jsonb\";\n\n/** Column definition in a subgraph table */\nexport interface SubgraphColumn {\n type: ColumnType;\n nullable?: boolean;\n indexed?: boolean;\n search?: boolean;\n default?: string | number | boolean;\n}\n\n/** Table definition within a subgraph schema */\nexport interface SubgraphTable {\n columns: Record<string, SubgraphColumn>;\n /** Composite indexes (each entry is an array of column names) */\n indexes?: string[][];\n /** Unique key constraints (each entry is an array of column names). Required for upsert. */\n uniqueKeys?: string[][];\n}\n\n/** Subgraph schema — maps table names to table definitions */\nexport type SubgraphSchema = Record<string, SubgraphTable>;\n\n/** Source filter for what blockchain data this subgraph processes */\nexport interface SubgraphSource {\n /** Contract principal (e.g., SP000...::contract-name). Supports * wildcards. */\n contract?: string;\n /** Event name/topic to filter on */\n event?: string;\n /** Function name to filter on */\n function?: string;\n /** Transaction type filter (e.g., \"stx_transfer\", \"contract_call\") */\n type?: string;\n /** Minimum amount filter (for stx_transfer sources) */\n minAmount?: bigint;\n}\n\n/** Context passed to subgraph handlers during event processing */\nexport interface SubgraphContext {\n block: { height: number; hash: string; timestamp: number; burnBlockHeight: number };\n tx: { txId: string; sender: string; type: string; status: string };\n insert(table: string, row: Record<string, unknown>): void;\n update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;\n upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;\n delete(table: string, where: Record<string, unknown>): void;\n findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;\n findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;\n}\n\n/** Handler function that processes events and writes to the subgraph */\nexport type SubgraphHandler = (\n event: Record<string, unknown>,\n ctx: SubgraphContext,\n) => Promise<void> | void;\n\n/**\n * Derive the source key used to look up handlers.\n * - { contract: \"SP123.market\", function: \"list\" } → \"SP123.market::list\"\n * - { contract: \"SP123.market\", event: \"sale\" } → \"SP123.market::sale\"\n * - { contract: \"SP123.market\" } → \"SP123.market\"\n * - { type: \"stx_transfer\" } → \"stx_transfer\"\n */\nexport function sourceKey(source: SubgraphSource): string {\n if (source.contract) {\n if (source.function) return `${source.contract}::${source.function}`;\n if (source.event) return `${source.contract}::${source.event}`;\n return source.contract;\n }\n if (source.type) return source.type;\n return \"*\";\n}\n\n/** Complete subgraph definition */\nexport interface SubgraphDefinition {\n /** Unique subgraph name (lowercase, alphanumeric + hyphens) */\n name: string;\n /** Semantic version */\n version?: string;\n /** Human description */\n description?: string;\n /** What blockchain data to process — one or more source filters */\n sources: SubgraphSource[];\n /** Tables in this subgraph */\n schema: SubgraphSchema;\n /** Keyed handler functions — keys match sourceKey() output, \"*\" is catch-all */\n handlers: Record<string, SubgraphHandler>;\n}\n",
6
- "import { sql, type Kysely, type Transaction } from \"kysely\";\nimport type { Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphSchema } from \"../types.ts\";\n\ntype AnyDb = Kysely<Database> | Transaction<Database>;\n\ninterface WriteOp {\n kind: \"insert\" | \"update\" | \"delete\";\n table: string;\n data: Record<string, unknown>;\n /** For update: SET clause */\n set?: Record<string, unknown>;\n}\n\nexport interface BlockMeta {\n height: number;\n hash: string;\n timestamp: number;\n burnBlockHeight: number;\n}\n\nexport interface TxMeta {\n txId: string;\n sender: string;\n type: string;\n status: string;\n}\n\n/** Validate that a column name is safe for SQL identifiers */\nfunction validateColumnName(name: string): void {\n if (!/^[a-z_][a-z0-9_]*$/i.test(name)) {\n throw new Error(`Invalid column name: ${name}`);\n }\n}\n\n/**\n * Runtime context passed to subgraph handlers.\n * Batches writes and flushes them atomically at the end of a block.\n * Reads execute immediately against the DB (pre-flush state).\n */\nexport class SubgraphContext {\n readonly block: BlockMeta;\n private _tx: TxMeta;\n private readonly db: AnyDb;\n private readonly pgSchemaName: string;\n private readonly subgraphSchema: SubgraphSchema;\n private readonly ops: WriteOp[] = [];\n\n constructor(\n db: AnyDb,\n pgSchemaName: string,\n subgraphSchema: SubgraphSchema,\n block: BlockMeta,\n tx: TxMeta,\n ) {\n this.db = db;\n this.pgSchemaName = pgSchemaName;\n this.subgraphSchema = subgraphSchema;\n this.block = block;\n this._tx = tx;\n }\n\n get tx(): TxMeta {\n return this._tx;\n }\n\n /** Update the current transaction context (used by runner between events) */\n setTx(tx: TxMeta): void {\n this._tx = tx;\n }\n\n // --- Write operations (batched) ---\n\n insert(table: string, row: Record<string, unknown>): void {\n this.validateTable(table);\n this.ops.push({ kind: \"insert\", table, data: row });\n }\n\n update(\n table: string,\n where: Record<string, unknown>,\n set: Record<string, unknown>,\n ): void {\n this.validateTable(table);\n this.ops.push({ kind: \"update\", table, data: where, set });\n }\n\n upsert(\n table: string,\n key: Record<string, unknown>,\n row: Record<string, unknown>,\n ): void {\n this.validateTable(table);\n const tableDef = this.subgraphSchema[table]!;\n const keyColumns = Object.keys(key);\n\n // Check if there's a matching uniqueKeys constraint\n const hasUniqueConstraint = tableDef.uniqueKeys?.some(\n (uk) => uk.length === keyColumns.length && uk.every((c) => keyColumns.includes(c)),\n );\n\n if (hasUniqueConstraint) {\n // Use ON CONFLICT for proper upsert\n this.ops.push({ kind: \"insert\", table, data: { ...key, ...row, _upsert_keys: keyColumns } });\n } else {\n // Fallback: log warning, use findOne + conditional insert/update\n logger.warn(\"upsert called without matching uniqueKeys constraint, using fallback\", {\n table,\n keys: keyColumns,\n });\n this.ops.push({ kind: \"insert\", table, data: { ...key, ...row, _upsert_fallback_keys: keyColumns, _upsert_fallback_set: row } });\n }\n }\n\n delete(table: string, where: Record<string, unknown>): void {\n this.validateTable(table);\n this.ops.push({ kind: \"delete\", table, data: where });\n }\n\n // --- Read operations (immediate) ---\n\n async findOne(\n table: string,\n where: Record<string, unknown>,\n ): Promise<Record<string, unknown> | null> {\n this.validateTable(table);\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n const { clause } = buildWhereClause(where);\n const query = `SELECT * FROM ${qualifiedTable} WHERE ${clause} LIMIT 1`;\n const { rows } = await sql.raw(query).execute(this.db);\n const row = (rows as Record<string, unknown>[])[0] ?? null;\n return row ? this.coerceRow(table, row) : null;\n }\n\n async findMany(\n table: string,\n where: Record<string, unknown>,\n ): Promise<Record<string, unknown>[]> {\n this.validateTable(table);\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n const { clause } = buildWhereClause(where);\n const query = `SELECT * FROM ${qualifiedTable} WHERE ${clause}`;\n const { rows } = await sql.raw(query).execute(this.db);\n return (rows as Record<string, unknown>[]).map((r) => this.coerceRow(table, r));\n }\n\n /** Coerce string values from Postgres back to BigInt for uint/int columns */\n private coerceRow(table: string, row: Record<string, unknown>): Record<string, unknown> {\n const tableDef = this.subgraphSchema[table];\n if (!tableDef) return row;\n const result = { ...row };\n for (const [col, def] of Object.entries(tableDef.columns)) {\n if ((def.type === \"uint\" || def.type === \"int\") && typeof result[col] === \"string\") {\n result[col] = BigInt(result[col] as string);\n }\n }\n return result;\n }\n\n // --- Flush ---\n\n /** Number of pending write operations */\n get pendingOps(): number {\n return this.ops.length;\n }\n\n /**\n * Execute all batched writes in a single transaction.\n * Auto-populates _block_height, _tx_id, _created_at on inserts.\n */\n async flush(): Promise<number> {\n if (this.ops.length === 0) return 0;\n\n const opsToFlush = [...this.ops];\n this.ops.length = 0;\n\n const statements = this.buildStatements(opsToFlush);\n\n // If db is already a transaction, execute directly\n if (\"isTransaction\" in this.db) {\n for (const stmt of statements) {\n await sql.raw(stmt).execute(this.db);\n }\n } else {\n await (this.db as Kysely<Database>).transaction().execute(async (tx) => {\n for (const stmt of statements) {\n await sql.raw(stmt).execute(tx);\n }\n });\n }\n\n return opsToFlush.length;\n }\n\n /** Build SQL statements from write ops */\n private buildStatements(ops: WriteOp[]): string[] {\n const statements: string[] = [];\n\n for (const op of ops) {\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${op.table}\"`;\n\n switch (op.kind) {\n case \"insert\": {\n const upsertKeys = op.data._upsert_keys as string[] | undefined;\n const fallbackKeys = op.data._upsert_fallback_keys as string[] | undefined;\n const fallbackSet = op.data._upsert_fallback_set as Record<string, unknown> | undefined;\n const data = { ...op.data };\n delete data._upsert_keys;\n delete data._upsert_fallback_keys;\n delete data._upsert_fallback_set;\n\n // Auto-populate meta columns\n data._block_height = this.block.height;\n data._tx_id = this._tx.txId;\n data._created_at = \"NOW()\";\n\n const cols = Object.keys(data);\n cols.forEach(validateColumnName);\n const vals = cols.map((c) =>\n data[c] === \"NOW()\" ? \"NOW()\" : escapeLiteral(data[c]),\n );\n let stmt = `INSERT INTO ${qualifiedTable} (${cols.map((c) => `\"${c}\"`).join(\", \")}) VALUES (${vals.join(\", \")})`;\n\n if (upsertKeys && upsertKeys.length > 0) {\n const updateCols = cols.filter((c) => !upsertKeys.includes(c) && !c.startsWith(\"_\"));\n if (updateCols.length > 0) {\n const setClauses = updateCols.map((c) => `\"${c}\" = EXCLUDED.\"${c}\"`);\n stmt += ` ON CONFLICT (${upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO UPDATE SET ${setClauses.join(\", \")}`;\n } else {\n stmt += ` ON CONFLICT (${upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO NOTHING`;\n }\n } else if (fallbackKeys && fallbackSet) {\n // Fallback upsert: use ON CONFLICT DO UPDATE but without a declared constraint\n // This will just be a plain INSERT — if it conflicts, PG will raise an error.\n // The caller was already warned. This is the best we can do without a unique constraint.\n }\n\n statements.push(stmt);\n break;\n }\n case \"update\": {\n const setEntries = Object.entries(op.set!);\n setEntries.forEach(([k]) => validateColumnName(k));\n const setClauses = setEntries.map(\n ([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`,\n );\n const { clause } = buildWhereClause(op.data);\n statements.push(\n `UPDATE ${qualifiedTable} SET ${setClauses.join(\", \")} WHERE ${clause}`,\n );\n break;\n }\n case \"delete\": {\n const { clause } = buildWhereClause(op.data);\n statements.push(`DELETE FROM ${qualifiedTable} WHERE ${clause}`);\n break;\n }\n }\n }\n\n return statements;\n }\n\n private validateTable(table: string): void {\n if (!this.subgraphSchema[table]) {\n throw new Error(\n `Table \"${table}\" not found in subgraph schema. Available: [${Object.keys(this.subgraphSchema).join(\", \")}]`,\n );\n }\n }\n}\n\n// --- Helpers ---\n\nfunction escapeLiteral(value: unknown): string {\n if (value === null || value === undefined) return \"NULL\";\n if (typeof value === \"number\" || typeof value === \"bigint\") return String(value);\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n if (typeof value === \"object\") return `'${JSON.stringify(value).replace(/'/g, \"''\")}'::jsonb`;\n // String — escape single quotes\n return `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\nfunction buildWhereClause(where: Record<string, unknown>): {\n clause: string;\n values: unknown[];\n} {\n const entries = Object.entries(where);\n if (entries.length === 0) return { clause: \"TRUE\", values: [] };\n\n entries.forEach(([k]) => validateColumnName(k));\n const parts = entries.map(([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`);\n return { clause: parts.join(\" AND \"), values: [] };\n}\n",
6
+ "import { sql, type Kysely, type Transaction } from \"kysely\";\nimport type { Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphSchema } from \"../types.ts\";\n\ntype AnyDb = Kysely<Database> | Transaction<Database>;\n\ninterface WriteOp {\n kind: \"insert\" | \"update\" | \"delete\";\n table: string;\n data: Record<string, unknown>;\n /** For update: SET clause */\n set?: Record<string, unknown>;\n}\n\nexport interface BlockMeta {\n height: number;\n hash: string;\n timestamp: number;\n burnBlockHeight: number;\n}\n\nexport interface TxMeta {\n txId: string;\n sender: string;\n type: string;\n status: string;\n}\n\n/** Validate that a column name is safe for SQL identifiers */\nfunction validateColumnName(name: string): void {\n if (!/^[a-z_][a-z0-9_]*$/i.test(name)) {\n throw new Error(`Invalid column name: ${name}`);\n }\n}\n\n/**\n * Runtime context passed to subgraph handlers.\n * Batches writes and flushes them atomically at the end of a block.\n * Reads execute immediately against the DB (pre-flush state).\n */\nexport class SubgraphContext {\n readonly block: BlockMeta;\n private _tx: TxMeta;\n private readonly db: AnyDb;\n private readonly pgSchemaName: string;\n private readonly subgraphSchema: SubgraphSchema;\n private readonly ops: WriteOp[] = [];\n\n constructor(\n db: AnyDb,\n pgSchemaName: string,\n subgraphSchema: SubgraphSchema,\n block: BlockMeta,\n tx: TxMeta,\n ) {\n this.db = db;\n this.pgSchemaName = pgSchemaName;\n this.subgraphSchema = subgraphSchema;\n this.block = block;\n this._tx = tx;\n }\n\n get tx(): TxMeta {\n return this._tx;\n }\n\n /** Update the current transaction context (used by runner between events) */\n setTx(tx: TxMeta): void {\n this._tx = tx;\n }\n\n // --- Write operations (batched) ---\n\n insert(table: string, row: Record<string, unknown>): void {\n this.validateTable(table);\n this.ops.push({ kind: \"insert\", table, data: row });\n }\n\n update(\n table: string,\n where: Record<string, unknown>,\n set: Record<string, unknown>,\n ): void {\n this.validateTable(table);\n this.ops.push({ kind: \"update\", table, data: where, set });\n }\n\n upsert(\n table: string,\n key: Record<string, unknown>,\n row: Record<string, unknown>,\n ): void {\n this.validateTable(table);\n const tableDef = this.subgraphSchema[table]!;\n const keyColumns = Object.keys(key);\n\n // Check if there's a matching uniqueKeys constraint\n const hasUniqueConstraint = tableDef.uniqueKeys?.some(\n (uk) => uk.length === keyColumns.length && uk.every((c) => keyColumns.includes(c)),\n );\n\n if (hasUniqueConstraint) {\n // Use ON CONFLICT for proper upsert\n this.ops.push({ kind: \"insert\", table, data: { ...key, ...row, _upsert_keys: keyColumns } });\n } else {\n // Fallback: log warning, use findOne + conditional insert/update\n logger.warn(\"upsert called without matching uniqueKeys constraint, using fallback\", {\n table,\n keys: keyColumns,\n });\n this.ops.push({ kind: \"insert\", table, data: { ...key, ...row, _upsert_fallback_keys: keyColumns, _upsert_fallback_set: row } });\n }\n }\n\n delete(table: string, where: Record<string, unknown>): void {\n this.validateTable(table);\n this.ops.push({ kind: \"delete\", table, data: where });\n }\n\n // --- Read operations (immediate) ---\n\n async findOne(\n table: string,\n where: Record<string, unknown>,\n ): Promise<Record<string, unknown> | null> {\n this.validateTable(table);\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n const { clause } = buildWhereClause(where);\n const query = `SELECT * FROM ${qualifiedTable} WHERE ${clause} LIMIT 1`;\n const { rows } = await sql.raw(query).execute(this.db);\n const row = (rows as Record<string, unknown>[])[0] ?? null;\n return row ? this.coerceRow(table, row) : null;\n }\n\n async findMany(\n table: string,\n where: Record<string, unknown>,\n ): Promise<Record<string, unknown>[]> {\n this.validateTable(table);\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n const { clause } = buildWhereClause(where);\n const query = `SELECT * FROM ${qualifiedTable} WHERE ${clause}`;\n const { rows } = await sql.raw(query).execute(this.db);\n return (rows as Record<string, unknown>[]).map((r) => this.coerceRow(table, r));\n }\n\n /** Coerce string values from Postgres back to BigInt for uint/int columns */\n private coerceRow(table: string, row: Record<string, unknown>): Record<string, unknown> {\n const tableDef = this.subgraphSchema[table];\n if (!tableDef) return row;\n const result = { ...row };\n for (const [col, def] of Object.entries(tableDef.columns)) {\n if ((def.type === \"uint\" || def.type === \"int\") && typeof result[col] === \"string\") {\n result[col] = BigInt(result[col] as string);\n }\n }\n return result;\n }\n\n // --- Flush ---\n\n /** Number of pending write operations */\n get pendingOps(): number {\n return this.ops.length;\n }\n\n /**\n * Execute all batched writes in a single transaction.\n * Auto-populates _block_height, _tx_id, _created_at on inserts.\n */\n async flush(): Promise<number> {\n if (this.ops.length === 0) return 0;\n\n const opsToFlush = [...this.ops];\n this.ops.length = 0;\n\n const statements = this.buildStatements(opsToFlush);\n\n // If db is already a transaction, execute directly\n if (\"isTransaction\" in this.db) {\n for (const stmt of statements) {\n await sql.raw(stmt).execute(this.db);\n }\n } else {\n await (this.db as Kysely<Database>).transaction().execute(async (tx) => {\n for (const stmt of statements) {\n await sql.raw(stmt).execute(tx);\n }\n });\n }\n\n return opsToFlush.length;\n }\n\n /** Prepare a single insert row, returning its data, columns, upsert key for batching. */\n private prepareInsert(op: WriteOp): {\n data: Record<string, unknown>;\n cols: string[];\n vals: string[];\n upsertKeys: string[] | undefined;\n batchKey: string;\n } {\n const upsertKeys = op.data._upsert_keys as string[] | undefined;\n const data = { ...op.data };\n delete data._upsert_keys;\n delete data._upsert_fallback_keys;\n delete data._upsert_fallback_set;\n\n data._block_height = this.block.height;\n data._tx_id = this._tx.txId;\n data._created_at = \"NOW()\";\n\n const cols = Object.keys(data);\n cols.forEach(validateColumnName);\n const vals = cols.map((c) =>\n data[c] === \"NOW()\" ? \"NOW()\" : escapeLiteral(data[c]),\n );\n\n // Batch key: table + sorted columns + upsert key signature (spread to avoid mutating cols)\n const batchKey = `${op.table}:${[...cols].sort().join(\",\")}:${upsertKeys ? [...upsertKeys].sort().join(\",\") : \"\"}`;\n\n return { data, cols, vals, upsertKeys, batchKey };\n }\n\n /** Build SQL statements from write ops, batching compatible INSERTs. */\n private buildStatements(ops: WriteOp[]): string[] {\n const statements: string[] = [];\n\n // Group consecutive inserts by batch key\n type InsertBatch = {\n table: string;\n cols: string[];\n rows: string[][];\n upsertKeys: string[] | undefined;\n };\n\n let currentBatch: InsertBatch | null = null;\n let currentBatchKey = \"\";\n\n const flushInsertBatch = () => {\n if (!currentBatch) return;\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${currentBatch.table}\"`;\n const colList = currentBatch.cols.map((c) => `\"${c}\"`).join(\", \");\n\n // Deduplicate by upsert key — last row wins (Postgres rejects duplicate keys in one INSERT)\n let rows = currentBatch.rows;\n if (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {\n const keyIndices = currentBatch.upsertKeys.map((k) => currentBatch!.cols.indexOf(k));\n const seen = new Map<string, number>();\n for (let i = 0; i < rows.length; i++) {\n const key = keyIndices.map((ki) => rows[i][ki]).join(\"\\0\");\n seen.set(key, i);\n }\n if (seen.size < rows.length) {\n rows = Array.from(seen.values()).map((i) => rows[i]);\n }\n }\n\n const valuesList = rows.map((r) => `(${r.join(\", \")})`).join(\", \");\n let stmt = `INSERT INTO ${qualifiedTable} (${colList}) VALUES ${valuesList}`;\n\n if (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {\n const updateCols = currentBatch.cols.filter(\n (c) => !currentBatch!.upsertKeys!.includes(c) && !c.startsWith(\"_\"),\n );\n if (updateCols.length > 0) {\n const setClauses = updateCols.map((c) => `\"${c}\" = EXCLUDED.\"${c}\"`);\n stmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO UPDATE SET ${setClauses.join(\", \")}`;\n } else {\n stmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO NOTHING`;\n }\n }\n\n statements.push(stmt);\n currentBatch = null;\n currentBatchKey = \"\";\n };\n\n for (const op of ops) {\n const qualifiedTable = `\"${this.pgSchemaName}\".\"${op.table}\"`;\n\n if (op.kind === \"insert\") {\n const { cols, vals, upsertKeys, batchKey } = this.prepareInsert(op);\n\n if (batchKey === currentBatchKey && currentBatch) {\n // Same table + columns + upsert key — append to batch\n currentBatch.rows.push(vals);\n } else {\n // Different batch — flush previous and start new\n flushInsertBatch();\n currentBatch = { table: op.table, cols, rows: [vals], upsertKeys };\n currentBatchKey = batchKey;\n }\n } else {\n // Non-insert — flush any pending insert batch first\n flushInsertBatch();\n\n if (op.kind === \"update\") {\n const setEntries = Object.entries(op.set!);\n setEntries.forEach(([k]) => validateColumnName(k));\n const setClauses = setEntries.map(\n ([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`,\n );\n const { clause } = buildWhereClause(op.data);\n statements.push(\n `UPDATE ${qualifiedTable} SET ${setClauses.join(\", \")} WHERE ${clause}`,\n );\n } else if (op.kind === \"delete\") {\n const { clause } = buildWhereClause(op.data);\n statements.push(`DELETE FROM ${qualifiedTable} WHERE ${clause}`);\n }\n }\n }\n\n // Flush any remaining insert batch\n flushInsertBatch();\n\n return statements;\n }\n\n private validateTable(table: string): void {\n if (!this.subgraphSchema[table]) {\n throw new Error(\n `Table \"${table}\" not found in subgraph schema. Available: [${Object.keys(this.subgraphSchema).join(\", \")}]`,\n );\n }\n }\n}\n\n// --- Helpers ---\n\nfunction escapeLiteral(value: unknown): string {\n if (value === null || value === undefined) return \"NULL\";\n if (typeof value === \"number\" || typeof value === \"bigint\") return String(value);\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n if (typeof value === \"object\") return `'${JSON.stringify(value).replace(/'/g, \"''\")}'::jsonb`;\n // String — escape single quotes\n return `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\nfunction buildWhereClause(where: Record<string, unknown>): {\n clause: string;\n values: unknown[];\n} {\n const entries = Object.entries(where);\n if (entries.length === 0) return { clause: \"TRUE\", values: [] };\n\n entries.forEach(([k]) => validateColumnName(k));\n const parts = entries.map(([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`);\n return { clause: parts.join(\" AND \"), values: [] };\n}\n",
7
7
  "import { type SubgraphSource, sourceKey } from \"../types.ts\";\n\nexport interface MatchedTx {\n tx: { tx_id: string; type: string; sender: string; status: string; contract_id?: string | null; function_name?: string | null };\n events: { id: string; tx_id: string; type: string; event_index: number; data: unknown }[];\n /** Which source produced this match — used for handler dispatch */\n sourceKey: string;\n}\n\n/**\n * Check if a string matches a pattern with `*` wildcard support.\n */\nfunction matchPattern(value: string, pattern: string): boolean {\n if (!pattern.includes(\"*\")) return value === pattern;\n const regex = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\");\n return new RegExp(`^${regex}$`).test(value);\n}\n\ntype TxRecord = { tx_id: string; type: string; sender: string; status: string; contract_id?: string | null; function_name?: string | null };\ntype EventRecord = { id: string; tx_id: string; type: string; event_index: number; data: unknown };\n\n/**\n * Match a single source against transactions and events.\n */\nfunction matchSource(\n source: SubgraphSource,\n transactions: TxRecord[],\n eventsByTx: Map<string, EventRecord[]>,\n): MatchedTx[] {\n const results: MatchedTx[] = [];\n const key = sourceKey(source);\n\n for (const tx of transactions) {\n // Type-based matching (e.g., token_transfer → matches tx.type)\n if (source.type) {\n if (!matchPattern(tx.type, source.type)) continue;\n\n const txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\n // Collect all events for this tx (type-based sources match the whole tx)\n let matchedEvents = txEvents;\n\n // minAmount filter — check events with an amount field\n if (source.minAmount !== undefined) {\n const amountEvents = matchedEvents.filter((e) => {\n const data = e.data as Record<string, unknown> | null;\n const rawAmount = data?.amount as string | number | undefined;\n if (rawAmount === undefined) return false;\n const amount = BigInt(rawAmount);\n return amount >= source.minAmount!;\n });\n if (amountEvents.length === 0) continue;\n matchedEvents = amountEvents;\n }\n\n results.push({ tx, events: matchedEvents, sourceKey: key });\n continue;\n }\n\n // Contract-based matching\n if (source.contract) {\n const txContractMatch = tx.contract_id && matchPattern(tx.contract_id, source.contract);\n\n // Function filter\n if (source.function && tx.function_name) {\n if (!matchPattern(tx.function_name, source.function)) continue;\n } else if (source.function && !tx.function_name) {\n continue;\n }\n\n const txEvents = eventsByTx.get(tx.tx_id) ?? [];\n let matchedEvents = txEvents;\n\n if (!txContractMatch) {\n // Check if any events match the contract\n matchedEvents = txEvents.filter((e) => {\n const data = e.data as Record<string, unknown> | null;\n const contractIdentifier = data?.contract_identifier as string | undefined;\n return contractIdentifier && matchPattern(contractIdentifier, source.contract!);\n });\n if (matchedEvents.length === 0) continue;\n }\n\n // Event type / topic filter\n if (source.event) {\n matchedEvents = matchedEvents.filter((e) => {\n if (matchPattern(e.type, source.event!)) return true;\n const data = e.data as Record<string, unknown> | null;\n const topic = data?.topic as string | undefined;\n return topic ? matchPattern(topic, source.event!) : false;\n });\n }\n\n if (txContractMatch || matchedEvents.length > 0) {\n results.push({ tx, events: matchedEvents, sourceKey: key });\n }\n }\n }\n\n return results;\n}\n\n/**\n * Match all sources against a block's transactions and events.\n * Deduplicates by (txId, sourceKey) — each handler key fires at most once per tx.\n */\nexport function matchSources(\n sources: SubgraphSource[],\n transactions: TxRecord[],\n events: EventRecord[],\n): MatchedTx[] {\n // Index events by txId\n const eventsByTx = new Map<string, EventRecord[]>();\n for (const event of events) {\n const list = eventsByTx.get(event.tx_id) ?? [];\n list.push(event);\n eventsByTx.set(event.tx_id, list);\n }\n\n const seen = new Set<string>();\n const results: MatchedTx[] = [];\n\n for (const source of sources) {\n const matches = matchSource(source, transactions, eventsByTx);\n for (const match of matches) {\n const dedupeKey = `${match.tx.tx_id}:${match.sourceKey}`;\n if (!seen.has(dedupeKey)) {\n seen.add(dedupeKey);\n results.push(match);\n }\n }\n }\n\n return results;\n}\n",
8
8
  "import { cvToJSON, deserializeCV } from \"@secondlayer/stacks/clarity\";\n\n/**\n * Decode a hex-encoded Clarity value to a JS object.\n * Returns original value on failure.\n */\nexport function decodeClarityValue(hex: string): unknown {\n try {\n const cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const cv = deserializeCV(cleanHex);\n return cvToJSON(cv);\n } catch {\n return hex;\n }\n}\n\n/**\n * Recursively decode all hex-encoded Clarity values in an object.\n * Any string starting with \"0x\" and longer than 10 chars is attempted.\n */\nexport function decodeEventData(data: unknown): unknown {\n if (typeof data === \"string\" && data.startsWith(\"0x\") && data.length > 10) {\n return decodeClarityValue(data);\n }\n\n if (Array.isArray(data)) {\n return data.map(decodeEventData);\n }\n\n if (typeof data === \"object\" && data !== null) {\n const decoded: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n decoded[key] = decodeEventData(value);\n }\n return decoded;\n }\n\n return data;\n}\n\n/**\n * Decode function args array (hex-encoded Clarity values).\n */\nexport function decodeFunctionArgs(args: string[]): unknown[] {\n return args.map(decodeClarityValue);\n}\n",
9
9
  "import { logger } from \"@secondlayer/shared/logger\";\nimport { getErrorMessage } from \"@secondlayer/shared\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport type { SubgraphContext } from \"./context.ts\";\nimport type { MatchedTx } from \"./source-matcher.ts\";\nimport { decodeEventData } from \"./clarity.ts\";\n\n/** Max consecutive handler errors before marking subgraph as error */\nconst DEFAULT_ERROR_THRESHOLD = 50;\n\nexport interface RunResult {\n processed: number;\n errors: number;\n}\n\n/**\n * Resolve the handler for a matched tx.\n * Looks up by sourceKey first, then falls back to \"*\" catch-all.\n */\nfunction resolveHandler(handlers: SubgraphDefinition[\"handlers\"], key: string) {\n return handlers[key] ?? handlers[\"*\"] ?? null;\n}\n\n/**\n * Run a subgraph's keyed handlers against all matched transactions/events.\n *\n * Each MatchedTx carries a sourceKey from the matcher. The runner looks up\n * the corresponding handler in subgraph.handlers, falling back to \"*\".\n *\n * Does NOT flush — caller is responsible for flushing ctx after run.\n */\nexport async function runHandlers(\n subgraph: SubgraphDefinition,\n matched: MatchedTx[],\n ctx: SubgraphContext,\n opts?: { errorThreshold?: number },\n): Promise<RunResult> {\n let processed = 0;\n let errors = 0;\n const threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;\n\n for (const { tx, events, sourceKey } of matched) {\n const handler = resolveHandler(subgraph.handlers, sourceKey);\n if (!handler) {\n logger.warn(\"No handler found for source key\", { subgraph: subgraph.name, sourceKey, txId: tx.tx_id });\n continue;\n }\n\n ctx.setTx({\n txId: tx.tx_id,\n sender: tx.sender,\n type: tx.type,\n status: tx.status,\n });\n\n // If no events but tx matched, call handler with tx-level data\n if (events.length === 0) {\n try {\n const txPayload: Record<string, unknown> = {\n tx: {\n txId: tx.tx_id,\n sender: tx.sender,\n type: tx.type,\n status: tx.status,\n contractId: tx.contract_id,\n functionName: tx.function_name,\n },\n };\n await handler(txPayload, ctx);\n processed++;\n } catch (err) {\n errors++;\n logger.error(\"Subgraph handler error\", {\n subgraph: subgraph.name,\n sourceKey,\n txId: tx.tx_id,\n error: getErrorMessage(err),\n });\n }\n continue;\n }\n\n for (const event of events) {\n if (errors >= threshold) {\n logger.error(\"Subgraph error threshold reached, skipping remaining events\", {\n subgraph: subgraph.name,\n errors,\n threshold,\n });\n return { processed, errors };\n }\n\n try {\n const decoded = decodeEventData(event.data) as Record<string, unknown>;\n const eventPayload: Record<string, unknown> = {\n ...decoded,\n _eventId: event.id,\n _eventType: event.type,\n _eventIndex: event.event_index,\n tx: {\n txId: tx.tx_id,\n sender: tx.sender,\n type: tx.type,\n status: tx.status,\n contractId: tx.contract_id,\n functionName: tx.function_name,\n },\n };\n\n await handler(eventPayload, ctx);\n processed++;\n } catch (err) {\n errors++;\n logger.error(\"Subgraph handler error\", {\n subgraph: subgraph.name,\n sourceKey,\n txId: tx.tx_id,\n eventId: event.id,\n eventType: event.type,\n error: getErrorMessage(err),\n });\n }\n }\n }\n\n return { processed, errors };\n}\n",
10
- "import { sql, type Transaction } from \"kysely\";\nimport { getDb, type Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { updateSubgraphStatus, recordSubgraphProcessed } from \"@secondlayer/shared/db/queries/subgraphs\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { pgSchemaName } from \"../schema/utils.ts\";\nimport { SubgraphContext, type BlockMeta, type TxMeta } from \"./context.ts\";\nimport { matchSources } from \"./source-matcher.ts\";\nimport { runHandlers } from \"./runner.ts\";\n\nexport interface ProcessBlockTiming {\n totalMs: number;\n handlerMs: number;\n flushMs: number;\n}\n\nexport interface ProcessBlockResult {\n blockHeight: number;\n matched: number;\n processed: number;\n errors: number;\n skipped: boolean;\n timing?: ProcessBlockTiming;\n}\n\n/**\n * Process a single block through a single subgraph's pipeline.\n *\n * Flow:\n * 1. Load block + txs + events from DB\n * 2. Run source matcher\n * 3. Run handlers with SubgraphContext\n * 4. Flush context (commit writes atomically)\n * 5. Update subgraph.last_processed_block\n */\nexport interface ProcessBlockOptions {\n /** Skip updating last_processed_block in DB (reindex batches this externally). */\n skipProgressUpdate?: boolean;\n}\n\nexport async function processBlock(\n subgraph: SubgraphDefinition,\n subgraphName: string,\n blockHeight: number,\n opts?: ProcessBlockOptions,\n): Promise<ProcessBlockResult> {\n const db = getDb();\n const blockStart = performance.now();\n const result: ProcessBlockResult = {\n blockHeight,\n matched: 0,\n processed: 0,\n errors: 0,\n skipped: false,\n };\n\n // 1. Load block\n const block = await db\n .selectFrom(\"blocks\")\n .selectAll()\n .where(\"height\", \"=\", blockHeight)\n .executeTakeFirst();\n\n if (!block) {\n logger.warn(\"Block not found for subgraph processing\", { subgraph: subgraphName, blockHeight });\n result.skipped = true;\n return result;\n }\n\n if (!block.canonical) {\n logger.debug(\"Skipping non-canonical block\", { subgraph: subgraphName, blockHeight });\n result.skipped = true;\n return result;\n }\n\n // 2. Load txs + events\n const txs = await db\n .selectFrom(\"transactions\")\n .selectAll()\n .where(\"block_height\", \"=\", blockHeight)\n .execute();\n\n const evts = await db\n .selectFrom(\"events\")\n .selectAll()\n .where(\"block_height\", \"=\", blockHeight)\n .execute();\n\n // 3. Match source\n const matched = matchSources(subgraph.sources, txs, evts);\n result.matched = matched.length;\n\n if (matched.length === 0) {\n if (!opts?.skipProgressUpdate) {\n await updateSubgraphStatus(db, subgraphName, \"active\", blockHeight);\n }\n return result;\n }\n\n // 4. Create context and run handlers\n // Use stored schema_name from DB if available, otherwise compute\n const subgraphRecord = await db\n .selectFrom(\"subgraphs\")\n .select(\"schema_name\")\n .where(\"name\", \"=\", subgraphName)\n .executeTakeFirst();\n const schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);\n const blockMeta: BlockMeta = {\n height: block.height,\n hash: block.hash,\n timestamp: block.timestamp,\n burnBlockHeight: block.burn_block_height,\n };\n const initialTx: TxMeta = {\n txId: \"\",\n sender: \"\",\n type: \"\",\n status: \"\",\n };\n\n // Wrap entire block processing in a single transaction\n let handlerMs = 0;\n let flushMs = 0;\n\n await db.transaction().execute(async (tx: Transaction<Database>) => {\n const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx);\n\n const handlerStart = performance.now();\n const runResult = await runHandlers(subgraph, matched, ctx);\n handlerMs = performance.now() - handlerStart;\n\n result.processed = runResult.processed;\n result.errors = runResult.errors;\n\n // 5. Flush writes\n if (ctx.pendingOps > 0) {\n const flushStart = performance.now();\n await ctx.flush();\n flushMs = performance.now() - flushStart;\n }\n\n // 6. Update progress + health metrics (same transaction)\n if (!opts?.skipProgressUpdate) {\n const status = runResult.errors > 0 && runResult.processed === 0 ? \"error\" : \"active\";\n await updateSubgraphStatus(tx, subgraphName, status, blockHeight);\n }\n\n if (!opts?.skipProgressUpdate && (runResult.processed > 0 || runResult.errors > 0)) {\n const lastError = runResult.errors > 0\n ? `${runResult.errors} error(s) at block ${blockHeight}`\n : undefined;\n await recordSubgraphProcessed(tx, subgraphName, runResult.processed, runResult.errors, lastError);\n }\n });\n\n const totalMs = performance.now() - blockStart;\n result.timing = {\n totalMs: Math.round(totalMs),\n handlerMs: Math.round(handlerMs),\n flushMs: Math.round(flushMs),\n };\n\n // 7. Row count warning — sample every 1000 blocks\n if (blockHeight % 1000 === 0) {\n try {\n const tables = Object.keys(subgraph.schema);\n for (const table of tables) {\n const { rows } = await sql.raw(\n `SELECT COUNT(*) as count FROM \"${schemaName}\".\"${table}\"`,\n ).execute(db);\n const count = Number((rows[0] as Record<string, unknown>).count);\n if (count >= 10_000_000) {\n logger.warn(\"Subgraph table exceeds 10M rows\", { subgraph: subgraphName, table, count });\n }\n }\n } catch {\n // Table may not exist yet\n }\n }\n\n return result;\n}\n",
10
+ "import { sql, type Transaction } from \"kysely\";\nimport { getDb, type Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { updateSubgraphStatus, recordSubgraphProcessed } from \"@secondlayer/shared/db/queries/subgraphs\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { pgSchemaName } from \"../schema/utils.ts\";\nimport { SubgraphContext, type BlockMeta, type TxMeta } from \"./context.ts\";\nimport { matchSources } from \"./source-matcher.ts\";\nimport { runHandlers } from \"./runner.ts\";\n\n// Cache schema_name per subgraph to avoid per-block DB lookups\nconst schemaNameCache = new Map<string, string>();\n\nexport interface ProcessBlockTiming {\n totalMs: number;\n handlerMs: number;\n flushMs: number;\n}\n\nexport interface ProcessBlockResult {\n blockHeight: number;\n matched: number;\n processed: number;\n errors: number;\n skipped: boolean;\n timing?: ProcessBlockTiming;\n}\n\n/**\n * Process a single block through a single subgraph's pipeline.\n *\n * Flow:\n * 1. Load block + txs + events from DB\n * 2. Run source matcher\n * 3. Run handlers with SubgraphContext\n * 4. Flush context (commit writes atomically)\n * 5. Update subgraph.last_processed_block\n */\nexport interface PreloadedBlockData {\n block: import(\"@secondlayer/shared/db\").Block;\n txs: import(\"@secondlayer/shared/db\").Transaction[];\n events: import(\"@secondlayer/shared/db\").Event[];\n}\n\nexport interface ProcessBlockOptions {\n /** Skip updating last_processed_block in DB (reindex batches this externally). */\n skipProgressUpdate?: boolean;\n /** Pre-loaded block data — skips DB reads when provided (used by batch catch-up). */\n preloaded?: PreloadedBlockData;\n}\n\nexport async function processBlock(\n subgraph: SubgraphDefinition,\n subgraphName: string,\n blockHeight: number,\n opts?: ProcessBlockOptions,\n): Promise<ProcessBlockResult> {\n const db = getDb();\n const blockStart = performance.now();\n const result: ProcessBlockResult = {\n blockHeight,\n matched: 0,\n processed: 0,\n errors: 0,\n skipped: false,\n };\n\n // 1. Load block (use pre-loaded data if available, otherwise fetch from DB)\n let block, txs, evts;\n if (opts?.preloaded) {\n block = opts.preloaded.block;\n txs = opts.preloaded.txs;\n evts = opts.preloaded.events;\n } else {\n block = await db\n .selectFrom(\"blocks\")\n .selectAll()\n .where(\"height\", \"=\", blockHeight)\n .executeTakeFirst();\n\n if (!block) {\n logger.warn(\"Block not found for subgraph processing\", { subgraph: subgraphName, blockHeight });\n result.skipped = true;\n return result;\n }\n\n if (!block.canonical) {\n logger.debug(\"Skipping non-canonical block\", { subgraph: subgraphName, blockHeight });\n result.skipped = true;\n return result;\n }\n\n // 2. Load txs + events\n txs = await db\n .selectFrom(\"transactions\")\n .selectAll()\n .where(\"block_height\", \"=\", blockHeight)\n .execute();\n\n evts = await db\n .selectFrom(\"events\")\n .selectAll()\n .where(\"block_height\", \"=\", blockHeight)\n .execute();\n }\n\n // 3. Match source\n const matched = matchSources(subgraph.sources, txs, evts);\n result.matched = matched.length;\n\n if (matched.length === 0) {\n if (!opts?.skipProgressUpdate) {\n await updateSubgraphStatus(db, subgraphName, \"active\", blockHeight);\n }\n return result;\n }\n\n // 4. Create context and run handlers\n // Use cached schema_name (fetched once per subgraph, not per block)\n let schemaName = schemaNameCache.get(subgraphName);\n if (!schemaName) {\n const subgraphRecord = await db\n .selectFrom(\"subgraphs\")\n .select(\"schema_name\")\n .where(\"name\", \"=\", subgraphName)\n .executeTakeFirst();\n schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);\n schemaNameCache.set(subgraphName, schemaName);\n }\n const blockMeta: BlockMeta = {\n height: block.height,\n hash: block.hash,\n timestamp: block.timestamp,\n burnBlockHeight: block.burn_block_height,\n };\n const initialTx: TxMeta = {\n txId: \"\",\n sender: \"\",\n type: \"\",\n status: \"\",\n };\n\n // Wrap entire block processing in a single transaction\n let handlerMs = 0;\n let flushMs = 0;\n\n await db.transaction().execute(async (tx: Transaction<Database>) => {\n const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx);\n\n const handlerStart = performance.now();\n const runResult = await runHandlers(subgraph, matched, ctx);\n handlerMs = performance.now() - handlerStart;\n\n result.processed = runResult.processed;\n result.errors = runResult.errors;\n\n // 5. Flush writes\n if (ctx.pendingOps > 0) {\n const flushStart = performance.now();\n await ctx.flush();\n flushMs = performance.now() - flushStart;\n }\n\n // 6. Update progress + health metrics (same transaction)\n if (!opts?.skipProgressUpdate) {\n const status = runResult.errors > 0 && runResult.processed === 0 ? \"error\" : \"active\";\n await updateSubgraphStatus(tx, subgraphName, status, blockHeight);\n }\n\n if (!opts?.skipProgressUpdate && (runResult.processed > 0 || runResult.errors > 0)) {\n const lastError = runResult.errors > 0\n ? `${runResult.errors} error(s) at block ${blockHeight}`\n : undefined;\n await recordSubgraphProcessed(tx, subgraphName, runResult.processed, runResult.errors, lastError);\n }\n });\n\n const totalMs = performance.now() - blockStart;\n result.timing = {\n totalMs: Math.round(totalMs),\n handlerMs: Math.round(handlerMs),\n flushMs: Math.round(flushMs),\n };\n\n // 7. Row count warning — sample every 1000 blocks\n if (blockHeight % 1000 === 0) {\n try {\n const tables = Object.keys(subgraph.schema);\n for (const table of tables) {\n const { rows } = await sql.raw(\n `SELECT COUNT(*) as count FROM \"${schemaName}\".\"${table}\"`,\n ).execute(db);\n const count = Number((rows[0] as Record<string, unknown>).count);\n if (count >= 10_000_000) {\n logger.warn(\"Subgraph table exceeds 10M rows\", { subgraph: subgraphName, table, count });\n }\n }\n } catch {\n // Table may not exist yet\n }\n }\n\n return result;\n}\n",
11
11
  "// Re-export canonical pgSchemaName from shared\nexport { pgSchemaName } from \"@secondlayer/shared/db/queries/subgraphs\";\n"
12
12
  ],
13
- "mappings": ";;;;AAsEO,SAAS,SAAS,CAAC,QAAgC;AAAA,EACxD,IAAI,OAAO,UAAU;AAAA,IACnB,IAAI,OAAO;AAAA,MAAU,OAAO,GAAG,OAAO,aAAa,OAAO;AAAA,IAC1D,IAAI,OAAO;AAAA,MAAO,OAAO,GAAG,OAAO,aAAa,OAAO;AAAA,IACvD,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,IAAI,OAAO;AAAA,IAAM,OAAO,OAAO;AAAA,EAC/B,OAAO;AAAA;;;AC7ET;AAEA;AA4BA,SAAS,kBAAkB,CAAC,MAAoB;AAAA,EAC9C,IAAI,CAAC,sBAAsB,KAAK,IAAI,GAAG;AAAA,IACrC,MAAM,IAAI,MAAM,wBAAwB,MAAM;AAAA,EAChD;AAAA;AAAA;AAQK,MAAM,gBAAgB;AAAA,EAClB;AAAA,EACD;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAiB,CAAC;AAAA,EAEnC,WAAW,CACT,IACA,cACA,gBACA,OACA,IACA;AAAA,IACA,KAAK,KAAK;AAAA,IACV,KAAK,eAAe;AAAA,IACpB,KAAK,iBAAiB;AAAA,IACtB,KAAK,QAAQ;AAAA,IACb,KAAK,MAAM;AAAA;AAAA,MAGT,EAAE,GAAW;AAAA,IACf,OAAO,KAAK;AAAA;AAAA,EAId,KAAK,CAAC,IAAkB;AAAA,IACtB,KAAK,MAAM;AAAA;AAAA,EAKb,MAAM,CAAC,OAAe,KAAoC;AAAA,IACxD,KAAK,cAAc,KAAK;AAAA,IACxB,KAAK,IAAI,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM,IAAI,CAAC;AAAA;AAAA,EAGpD,MAAM,CACJ,OACA,OACA,KACM;AAAA,IACN,KAAK,cAAc,KAAK;AAAA,IACxB,KAAK,IAAI,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM,OAAO,IAAI,CAAC;AAAA;AAAA,EAG3D,MAAM,CACJ,OACA,KACA,KACM;AAAA,IACN,KAAK,cAAc,KAAK;AAAA,IACxB,MAAM,WAAW,KAAK,eAAe;AAAA,IACrC,MAAM,aAAa,OAAO,KAAK,GAAG;AAAA,IAGlC,MAAM,sBAAsB,SAAS,YAAY,KAC/C,CAAC,OAAO,GAAG,WAAW,WAAW,UAAU,GAAG,MAAM,CAAC,MAAM,WAAW,SAAS,CAAC,CAAC,CACnF;AAAA,IAEA,IAAI,qBAAqB;AAAA,MAEvB,KAAK,IAAI,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM,KAAK,QAAQ,KAAK,cAAc,WAAW,EAAE,CAAC;AAAA,IAC7F,EAAO;AAAA,MAEL,OAAO,KAAK,wEAAwE;AAAA,QAClF;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,MACD,KAAK,IAAI,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM,KAAK,QAAQ,KAAK,uBAAuB,YAAY,sBAAsB,IAAI,EAAE,CAAC;AAAA;AAAA;AAAA,EAInI,MAAM,CAAC,OAAe,OAAsC;AAAA,IAC1D,KAAK,cAAc,KAAK;AAAA,IACxB,KAAK,IAAI,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM,MAAM,CAAC;AAAA;AAAA,OAKhD,QAAO,CACX,OACA,OACyC;AAAA,IACzC,KAAK,cAAc,KAAK;AAAA,IACxB,MAAM,iBAAiB,IAAI,KAAK,kBAAkB;AAAA,IAClD,QAAQ,WAAW,iBAAiB,KAAK;AAAA,IACzC,MAAM,QAAQ,iBAAiB,wBAAwB;AAAA,IACvD,QAAQ,SAAS,MAAM,IAAI,IAAI,KAAK,EAAE,QAAQ,KAAK,EAAE;AAAA,IACrD,MAAM,MAAO,KAAmC,MAAM;AAAA,IACtD,OAAO,MAAM,KAAK,UAAU,OAAO,GAAG,IAAI;AAAA;AAAA,OAGtC,SAAQ,CACZ,OACA,OACoC;AAAA,IACpC,KAAK,cAAc,KAAK;AAAA,IACxB,MAAM,iBAAiB,IAAI,KAAK,kBAAkB;AAAA,IAClD,QAAQ,WAAW,iBAAiB,KAAK;AAAA,IACzC,MAAM,QAAQ,iBAAiB,wBAAwB;AAAA,IACvD,QAAQ,SAAS,MAAM,IAAI,IAAI,KAAK,EAAE,QAAQ,KAAK,EAAE;AAAA,IACrD,OAAQ,KAAmC,IAAI,CAAC,MAAM,KAAK,UAAU,OAAO,CAAC,CAAC;AAAA;AAAA,EAIxE,SAAS,CAAC,OAAe,KAAuD;AAAA,IACtF,MAAM,WAAW,KAAK,eAAe;AAAA,IACrC,IAAI,CAAC;AAAA,MAAU,OAAO;AAAA,IACtB,MAAM,SAAS,KAAK,IAAI;AAAA,IACxB,YAAY,KAAK,QAAQ,OAAO,QAAQ,SAAS,OAAO,GAAG;AAAA,MACzD,KAAK,IAAI,SAAS,UAAU,IAAI,SAAS,UAAU,OAAO,OAAO,SAAS,UAAU;AAAA,QAClF,OAAO,OAAO,OAAO,OAAO,IAAc;AAAA,MAC5C;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,MAML,UAAU,GAAW;AAAA,IACvB,OAAO,KAAK,IAAI;AAAA;AAAA,OAOZ,MAAK,GAAoB;AAAA,IAC7B,IAAI,KAAK,IAAI,WAAW;AAAA,MAAG,OAAO;AAAA,IAElC,MAAM,aAAa,CAAC,GAAG,KAAK,GAAG;AAAA,IAC/B,KAAK,IAAI,SAAS;AAAA,IAElB,MAAM,aAAa,KAAK,gBAAgB,UAAU;AAAA,IAGlD,IAAI,mBAAmB,KAAK,IAAI;AAAA,MAC9B,WAAW,QAAQ,YAAY;AAAA,QAC7B,MAAM,IAAI,IAAI,IAAI,EAAE,QAAQ,KAAK,EAAE;AAAA,MACrC;AAAA,IACF,EAAO;AAAA,MACL,MAAO,KAAK,GAAwB,YAAY,EAAE,QAAQ,OAAO,OAAO;AAAA,QACtE,WAAW,QAAQ,YAAY;AAAA,UAC7B,MAAM,IAAI,IAAI,IAAI,EAAE,QAAQ,EAAE;AAAA,QAChC;AAAA,OACD;AAAA;AAAA,IAGH,OAAO,WAAW;AAAA;AAAA,EAIZ,eAAe,CAAC,KAA0B;AAAA,IAChD,MAAM,aAAuB,CAAC;AAAA,IAE9B,WAAW,MAAM,KAAK;AAAA,MACpB,MAAM,iBAAiB,IAAI,KAAK,kBAAkB,GAAG;AAAA,MAErD,QAAQ,GAAG;AAAA,aACJ,UAAU;AAAA,UACb,MAAM,aAAa,GAAG,KAAK;AAAA,UAC3B,MAAM,eAAe,GAAG,KAAK;AAAA,UAC7B,MAAM,cAAc,GAAG,KAAK;AAAA,UAC5B,MAAM,OAAO,KAAK,GAAG,KAAK;AAAA,UAC1B,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK;AAAA,UAGZ,KAAK,gBAAgB,KAAK,MAAM;AAAA,UAChC,KAAK,SAAS,KAAK,IAAI;AAAA,UACvB,KAAK,cAAc;AAAA,UAEnB,MAAM,OAAO,OAAO,KAAK,IAAI;AAAA,UAC7B,KAAK,QAAQ,kBAAkB;AAAA,UAC/B,MAAM,OAAO,KAAK,IAAI,CAAC,MACrB,KAAK,OAAO,UAAU,UAAU,cAAc,KAAK,EAAE,CACvD;AAAA,UACA,IAAI,OAAO,eAAe,mBAAmB,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,IAAI,cAAc,KAAK,KAAK,IAAI;AAAA,UAE5G,IAAI,cAAc,WAAW,SAAS,GAAG;AAAA,YACvC,MAAM,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,SAAS,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAAA,YACnF,IAAI,WAAW,SAAS,GAAG;AAAA,cACzB,MAAM,aAAa,WAAW,IAAI,CAAC,MAAM,IAAI,kBAAkB,IAAI;AAAA,cACnE,QAAQ,iBAAiB,WAAW,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,IAAI,oBAAoB,WAAW,KAAK,IAAI;AAAA,YAC5G,EAAO;AAAA,cACL,QAAQ,iBAAiB,WAAW,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,IAAI;AAAA;AAAA,UAEtE,EAAO,SAAI,gBAAgB,aAAa,CAIxC;AAAA,UAEA,WAAW,KAAK,IAAI;AAAA,UACpB;AAAA,QACF;AAAA,aACK,UAAU;AAAA,UACb,MAAM,aAAa,OAAO,QAAQ,GAAG,GAAI;AAAA,UACzC,WAAW,QAAQ,EAAE,OAAO,mBAAmB,CAAC,CAAC;AAAA,UACjD,MAAM,aAAa,WAAW,IAC5B,EAAE,GAAG,OAAO,IAAI,QAAQ,cAAc,CAAC,GACzC;AAAA,UACA,QAAQ,WAAW,iBAAiB,GAAG,IAAI;AAAA,UAC3C,WAAW,KACT,UAAU,sBAAsB,WAAW,KAAK,IAAI,WAAW,QACjE;AAAA,UACA;AAAA,QACF;AAAA,aACK,UAAU;AAAA,UACb,QAAQ,WAAW,iBAAiB,GAAG,IAAI;AAAA,UAC3C,WAAW,KAAK,eAAe,wBAAwB,QAAQ;AAAA,UAC/D;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,IAEA,OAAO;AAAA;AAAA,EAGD,aAAa,CAAC,OAAqB;AAAA,IACzC,IAAI,CAAC,KAAK,eAAe,QAAQ;AAAA,MAC/B,MAAM,IAAI,MACR,UAAU,oDAAoD,OAAO,KAAK,KAAK,cAAc,EAAE,KAAK,IAAI,IAC1G;AAAA,IACF;AAAA;AAEJ;AAIA,SAAS,aAAa,CAAC,OAAwB;AAAA,EAC7C,IAAI,UAAU,QAAQ,UAAU;AAAA,IAAW,OAAO;AAAA,EAClD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU;AAAA,IAAU,OAAO,OAAO,KAAK;AAAA,EAC/E,IAAI,OAAO,UAAU;AAAA,IAAW,OAAO,QAAQ,SAAS;AAAA,EACxD,IAAI,OAAO,UAAU;AAAA,IAAU,OAAO,IAAI,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA,EAElF,OAAO,IAAI,OAAO,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA;AAG7C,SAAS,gBAAgB,CAAC,OAGxB;AAAA,EACA,MAAM,UAAU,OAAO,QAAQ,KAAK;AAAA,EACpC,IAAI,QAAQ,WAAW;AAAA,IAAG,OAAO,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EAAE;AAAA,EAE9D,QAAQ,QAAQ,EAAE,OAAO,mBAAmB,CAAC,CAAC;AAAA,EAC9C,MAAM,QAAQ,QAAQ,IAAI,EAAE,GAAG,OAAO,IAAI,QAAQ,cAAc,CAAC,GAAG;AAAA,EACpE,OAAO,EAAE,QAAQ,MAAM,KAAK,OAAO,GAAG,QAAQ,CAAC,EAAE;AAAA;;;ACzRnD,SAAS,YAAY,CAAC,OAAe,SAA0B;AAAA,EAC7D,IAAI,CAAC,QAAQ,SAAS,GAAG;AAAA,IAAG,OAAO,UAAU;AAAA,EAC7C,MAAM,QAAQ,QACX,QAAQ,qBAAqB,MAAM,EACnC,QAAQ,OAAO,IAAI;AAAA,EACtB,OAAO,IAAI,OAAO,IAAI,QAAQ,EAAE,KAAK,KAAK;AAAA;AAS5C,SAAS,WAAW,CAClB,QACA,cACA,YACa;AAAA,EACb,MAAM,UAAuB,CAAC;AAAA,EAC9B,MAAM,MAAM,UAAU,MAAM;AAAA,EAE5B,WAAW,MAAM,cAAc;AAAA,IAE7B,IAAI,OAAO,MAAM;AAAA,MACf,IAAI,CAAC,aAAa,GAAG,MAAM,OAAO,IAAI;AAAA,QAAG;AAAA,MAEzC,MAAM,WAAW,WAAW,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,MAG9C,IAAI,gBAAgB;AAAA,MAGpB,IAAI,OAAO,cAAc,WAAW;AAAA,QAClC,MAAM,eAAe,cAAc,OAAO,CAAC,MAAM;AAAA,UAC/C,MAAM,OAAO,EAAE;AAAA,UACf,MAAM,YAAY,MAAM;AAAA,UACxB,IAAI,cAAc;AAAA,YAAW,OAAO;AAAA,UACpC,MAAM,SAAS,OAAO,SAAS;AAAA,UAC/B,OAAO,UAAU,OAAO;AAAA,SACzB;AAAA,QACD,IAAI,aAAa,WAAW;AAAA,UAAG;AAAA,QAC/B,gBAAgB;AAAA,MAClB;AAAA,MAEA,QAAQ,KAAK,EAAE,IAAI,QAAQ,eAAe,WAAW,IAAI,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,IAGA,IAAI,OAAO,UAAU;AAAA,MACnB,MAAM,kBAAkB,GAAG,eAAe,aAAa,GAAG,aAAa,OAAO,QAAQ;AAAA,MAGtF,IAAI,OAAO,YAAY,GAAG,eAAe;AAAA,QACvC,IAAI,CAAC,aAAa,GAAG,eAAe,OAAO,QAAQ;AAAA,UAAG;AAAA,MACxD,EAAO,SAAI,OAAO,YAAY,CAAC,GAAG,eAAe;AAAA,QAC/C;AAAA,MACF;AAAA,MAEA,MAAM,WAAW,WAAW,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,MAC9C,IAAI,gBAAgB;AAAA,MAEpB,IAAI,CAAC,iBAAiB;AAAA,QAEpB,gBAAgB,SAAS,OAAO,CAAC,MAAM;AAAA,UACrC,MAAM,OAAO,EAAE;AAAA,UACf,MAAM,qBAAqB,MAAM;AAAA,UACjC,OAAO,sBAAsB,aAAa,oBAAoB,OAAO,QAAS;AAAA,SAC/E;AAAA,QACD,IAAI,cAAc,WAAW;AAAA,UAAG;AAAA,MAClC;AAAA,MAGA,IAAI,OAAO,OAAO;AAAA,QAChB,gBAAgB,cAAc,OAAO,CAAC,MAAM;AAAA,UAC1C,IAAI,aAAa,EAAE,MAAM,OAAO,KAAM;AAAA,YAAG,OAAO;AAAA,UAChD,MAAM,OAAO,EAAE;AAAA,UACf,MAAM,QAAQ,MAAM;AAAA,UACpB,OAAO,QAAQ,aAAa,OAAO,OAAO,KAAM,IAAI;AAAA,SACrD;AAAA,MACH;AAAA,MAEA,IAAI,mBAAmB,cAAc,SAAS,GAAG;AAAA,QAC/C,QAAQ,KAAK,EAAE,IAAI,QAAQ,eAAe,WAAW,IAAI,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAOF,SAAS,YAAY,CAC1B,SACA,cACA,QACa;AAAA,EAEb,MAAM,aAAa,IAAI;AAAA,EACvB,WAAW,SAAS,QAAQ;AAAA,IAC1B,MAAM,OAAO,WAAW,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,IAC7C,KAAK,KAAK,KAAK;AAAA,IACf,WAAW,IAAI,MAAM,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,OAAO,IAAI;AAAA,EACjB,MAAM,UAAuB,CAAC;AAAA,EAE9B,WAAW,UAAU,SAAS;AAAA,IAC5B,MAAM,UAAU,YAAY,QAAQ,cAAc,UAAU;AAAA,IAC5D,WAAW,SAAS,SAAS;AAAA,MAC3B,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,MAAM;AAAA,MAC7C,IAAI,CAAC,KAAK,IAAI,SAAS,GAAG;AAAA,QACxB,KAAK,IAAI,SAAS;AAAA,QAClB,QAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;;;ACvIT;AAMO,SAAS,kBAAkB,CAAC,KAAsB;AAAA,EACvD,IAAI;AAAA,IACF,MAAM,WAAW,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,IACvD,MAAM,KAAK,cAAc,QAAQ;AAAA,IACjC,OAAO,SAAS,EAAE;AAAA,IAClB,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;AAQJ,SAAS,eAAe,CAAC,MAAwB;AAAA,EACtD,IAAI,OAAO,SAAS,YAAY,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS,IAAI;AAAA,IACzE,OAAO,mBAAmB,IAAI;AAAA,EAChC;AAAA,EAEA,IAAI,MAAM,QAAQ,IAAI,GAAG;AAAA,IACvB,OAAO,KAAK,IAAI,eAAe;AAAA,EACjC;AAAA,EAEA,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAAA,IAC7C,MAAM,UAAmC,CAAC;AAAA,IAC1C,YAAY,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;AAAA,MAC/C,QAAQ,OAAO,gBAAgB,KAAK;AAAA,IACtC;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,OAAO;AAAA;AAMF,SAAS,kBAAkB,CAAC,MAA2B;AAAA,EAC5D,OAAO,KAAK,IAAI,kBAAkB;AAAA;;;AC5CpC,mBAAS;AACT;AAOA,IAAM,0BAA0B;AAWhC,SAAS,cAAc,CAAC,UAA0C,KAAa;AAAA,EAC7E,OAAO,SAAS,QAAQ,SAAS,QAAQ;AAAA;AAW3C,eAAsB,WAAW,CAC/B,UACA,SACA,KACA,MACoB;AAAA,EACpB,IAAI,YAAY;AAAA,EAChB,IAAI,SAAS;AAAA,EACb,MAAM,YAAY,MAAM,kBAAkB;AAAA,EAE1C,aAAa,IAAI,QAAQ,2BAAe,SAAS;AAAA,IAC/C,MAAM,UAAU,eAAe,SAAS,UAAU,UAAS;AAAA,IAC3D,IAAI,CAAC,SAAS;AAAA,MACZ,QAAO,KAAK,mCAAmC,EAAE,UAAU,SAAS,MAAM,uBAAW,MAAM,GAAG,MAAM,CAAC;AAAA,MACrG;AAAA,IACF;AAAA,IAEA,IAAI,MAAM;AAAA,MACR,MAAM,GAAG;AAAA,MACT,QAAQ,GAAG;AAAA,MACX,MAAM,GAAG;AAAA,MACT,QAAQ,GAAG;AAAA,IACb,CAAC;AAAA,IAGD,IAAI,OAAO,WAAW,GAAG;AAAA,MACvB,IAAI;AAAA,QACF,MAAM,YAAqC;AAAA,UACzC,IAAI;AAAA,YACF,MAAM,GAAG;AAAA,YACT,QAAQ,GAAG;AAAA,YACX,MAAM,GAAG;AAAA,YACT,QAAQ,GAAG;AAAA,YACX,YAAY,GAAG;AAAA,YACf,cAAc,GAAG;AAAA,UACnB;AAAA,QACF;AAAA,QACA,MAAM,QAAQ,WAAW,GAAG;AAAA,QAC5B;AAAA,QACA,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,QAAO,MAAM,0BAA0B;AAAA,UACrC,UAAU,SAAS;AAAA,UACnB;AAAA,UACA,MAAM,GAAG;AAAA,UACT,OAAO,gBAAgB,GAAG;AAAA,QAC5B,CAAC;AAAA;AAAA,MAEH;AAAA,IACF;AAAA,IAEA,WAAW,SAAS,QAAQ;AAAA,MAC1B,IAAI,UAAU,WAAW;AAAA,QACvB,QAAO,MAAM,+DAA+D;AAAA,UAC1E,UAAU,SAAS;AAAA,UACnB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD,OAAO,EAAE,WAAW,OAAO;AAAA,MAC7B;AAAA,MAEA,IAAI;AAAA,QACF,MAAM,UAAU,gBAAgB,MAAM,IAAI;AAAA,QAC1C,MAAM,eAAwC;AAAA,aACzC;AAAA,UACH,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,UAClB,aAAa,MAAM;AAAA,UACnB,IAAI;AAAA,YACF,MAAM,GAAG;AAAA,YACT,QAAQ,GAAG;AAAA,YACX,MAAM,GAAG;AAAA,YACT,QAAQ,GAAG;AAAA,YACX,YAAY,GAAG;AAAA,YACf,cAAc,GAAG;AAAA,UACnB;AAAA,QACF;AAAA,QAEA,MAAM,QAAQ,cAAc,GAAG;AAAA,QAC/B;AAAA,QACA,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,QAAO,MAAM,0BAA0B;AAAA,UACrC,UAAU,SAAS;AAAA,UACnB;AAAA,UACA,MAAM,GAAG;AAAA,UACT,SAAS,MAAM;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,OAAO,gBAAgB,GAAG;AAAA,QAC5B,CAAC;AAAA;AAAA,IAEL;AAAA,EACF;AAAA,EAEA,OAAO,EAAE,WAAW,OAAO;AAAA;;;AC7H7B,gBAAS;AACT;AACA,mBAAS;AACT;;;ACFA;;;ADuCA,eAAsB,YAAY,CAChC,UACA,cACA,aACA,MAC6B;AAAA,EAC7B,MAAM,KAAK,MAAM;AAAA,EACjB,MAAM,aAAa,YAAY,IAAI;AAAA,EACnC,MAAM,SAA6B;AAAA,IACjC;AAAA,IACA,SAAS;AAAA,IACT,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EAGA,MAAM,QAAQ,MAAM,GACjB,WAAW,QAAQ,EACnB,UAAU,EACV,MAAM,UAAU,KAAK,WAAW,EAChC,iBAAiB;AAAA,EAEpB,IAAI,CAAC,OAAO;AAAA,IACV,QAAO,KAAK,2CAA2C,EAAE,UAAU,cAAc,YAAY,CAAC;AAAA,IAC9F,OAAO,UAAU;AAAA,IACjB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,CAAC,MAAM,WAAW;AAAA,IACpB,QAAO,MAAM,gCAAgC,EAAE,UAAU,cAAc,YAAY,CAAC;AAAA,IACpF,OAAO,UAAU;AAAA,IACjB,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,MAAM,MAAM,GACf,WAAW,cAAc,EACzB,UAAU,EACV,MAAM,gBAAgB,KAAK,WAAW,EACtC,QAAQ;AAAA,EAEX,MAAM,OAAO,MAAM,GAChB,WAAW,QAAQ,EACnB,UAAU,EACV,MAAM,gBAAgB,KAAK,WAAW,EACtC,QAAQ;AAAA,EAGX,MAAM,UAAU,aAAa,SAAS,SAAS,KAAK,IAAI;AAAA,EACxD,OAAO,UAAU,QAAQ;AAAA,EAEzB,IAAI,QAAQ,WAAW,GAAG;AAAA,IACxB,IAAI,CAAC,MAAM,oBAAoB;AAAA,MAC7B,MAAM,qBAAqB,IAAI,cAAc,UAAU,WAAW;AAAA,IACpE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAIA,MAAM,iBAAiB,MAAM,GAC1B,WAAW,WAAW,EACtB,OAAO,aAAa,EACpB,MAAM,QAAQ,KAAK,YAAY,EAC/B,iBAAiB;AAAA,EACpB,MAAM,aAAa,gBAAgB,eAAe,aAAa,YAAY;AAAA,EAC3E,MAAM,YAAuB;AAAA,IAC3B,QAAQ,MAAM;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM;AAAA,IACjB,iBAAiB,MAAM;AAAA,EACzB;AAAA,EACA,MAAM,YAAoB;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EAGA,IAAI,YAAY;AAAA,EAChB,IAAI,UAAU;AAAA,EAEd,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,OAA8B;AAAA,IAClE,MAAM,MAAM,IAAI,gBAAgB,IAAI,YAAY,SAAS,QAAQ,WAAW,SAAS;AAAA,IAErF,MAAM,eAAe,YAAY,IAAI;AAAA,IACrC,MAAM,YAAY,MAAM,YAAY,UAAU,SAAS,GAAG;AAAA,IAC1D,YAAY,YAAY,IAAI,IAAI;AAAA,IAEhC,OAAO,YAAY,UAAU;AAAA,IAC7B,OAAO,SAAS,UAAU;AAAA,IAG1B,IAAI,IAAI,aAAa,GAAG;AAAA,MACtB,MAAM,aAAa,YAAY,IAAI;AAAA,MACnC,MAAM,IAAI,MAAM;AAAA,MAChB,UAAU,YAAY,IAAI,IAAI;AAAA,IAChC;AAAA,IAGA,IAAI,CAAC,MAAM,oBAAoB;AAAA,MAC7B,MAAM,SAAS,UAAU,SAAS,KAAK,UAAU,cAAc,IAAI,UAAU;AAAA,MAC7E,MAAM,qBAAqB,IAAI,cAAc,QAAQ,WAAW;AAAA,IAClE;AAAA,IAEA,IAAI,CAAC,MAAM,uBAAuB,UAAU,YAAY,KAAK,UAAU,SAAS,IAAI;AAAA,MAClF,MAAM,YAAY,UAAU,SAAS,IACjC,GAAG,UAAU,4BAA4B,gBACzC;AAAA,MACJ,MAAM,wBAAwB,IAAI,cAAc,UAAU,WAAW,UAAU,QAAQ,SAAS;AAAA,IAClG;AAAA,GACD;AAAA,EAED,MAAM,UAAU,YAAY,IAAI,IAAI;AAAA,EACpC,OAAO,SAAS;AAAA,IACd,SAAS,KAAK,MAAM,OAAO;AAAA,IAC3B,WAAW,KAAK,MAAM,SAAS;AAAA,IAC/B,SAAS,KAAK,MAAM,OAAO;AAAA,EAC7B;AAAA,EAGA,IAAI,cAAc,SAAS,GAAG;AAAA,IAC5B,IAAI;AAAA,MACF,MAAM,SAAS,OAAO,KAAK,SAAS,MAAM;AAAA,MAC1C,WAAW,SAAS,QAAQ;AAAA,QAC1B,QAAQ,SAAS,MAAM,KAAI,IACzB,kCAAkC,gBAAgB,QACpD,EAAE,QAAQ,EAAE;AAAA,QACZ,MAAM,QAAQ,OAAQ,KAAK,GAA+B,KAAK;AAAA,QAC/D,IAAI,SAAS,KAAY;AAAA,UACvB,QAAO,KAAK,mCAAmC,EAAE,UAAU,cAAc,OAAO,MAAM,CAAC;AAAA,QACzF;AAAA,MACF;AAAA,MACA,MAAM;AAAA,EAGV;AAAA,EAEA,OAAO;AAAA;",
14
- "debugId": "11059A8A65310A0964756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "AFA4E266F1631E6464756E2164756E21",
15
15
  "names": []
16
16
  }
@@ -71,8 +71,8 @@ interface SubgraphDefinition {
71
71
  }
72
72
  /**
73
73
  * Catch a subgraph up from its last_processed_block to the chain tip.
74
- * Re-reads lastProcessedBlock from DB to avoid stale values.
75
- * Skips if a catch-up is already in progress for this subgraph.
74
+ * Uses batch loading (3 queries per batch instead of 3 per block) and
75
+ * pipeline prefetching (loads next batch while processing current).
76
76
  */
77
77
  declare function catchUpSubgraph(subgraph: SubgraphDefinition, subgraphName: string): Promise<number>;
78
78
  export { catchUpSubgraph };
@@ -122,53 +122,83 @@ class SubgraphContext {
122
122
  }
123
123
  return opsToFlush.length;
124
124
  }
125
+ prepareInsert(op) {
126
+ const upsertKeys = op.data._upsert_keys;
127
+ const data = { ...op.data };
128
+ delete data._upsert_keys;
129
+ delete data._upsert_fallback_keys;
130
+ delete data._upsert_fallback_set;
131
+ data._block_height = this.block.height;
132
+ data._tx_id = this._tx.txId;
133
+ data._created_at = "NOW()";
134
+ const cols = Object.keys(data);
135
+ cols.forEach(validateColumnName);
136
+ const vals = cols.map((c) => data[c] === "NOW()" ? "NOW()" : escapeLiteral(data[c]));
137
+ const batchKey = `${op.table}:${[...cols].sort().join(",")}:${upsertKeys ? [...upsertKeys].sort().join(",") : ""}`;
138
+ return { data, cols, vals, upsertKeys, batchKey };
139
+ }
125
140
  buildStatements(ops) {
126
141
  const statements = [];
142
+ let currentBatch = null;
143
+ let currentBatchKey = "";
144
+ const flushInsertBatch = () => {
145
+ if (!currentBatch)
146
+ return;
147
+ const qualifiedTable = `"${this.pgSchemaName}"."${currentBatch.table}"`;
148
+ const colList = currentBatch.cols.map((c) => `"${c}"`).join(", ");
149
+ let rows = currentBatch.rows;
150
+ if (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {
151
+ const keyIndices = currentBatch.upsertKeys.map((k) => currentBatch.cols.indexOf(k));
152
+ const seen = new Map;
153
+ for (let i = 0;i < rows.length; i++) {
154
+ const key = keyIndices.map((ki) => rows[i][ki]).join("\x00");
155
+ seen.set(key, i);
156
+ }
157
+ if (seen.size < rows.length) {
158
+ rows = Array.from(seen.values()).map((i) => rows[i]);
159
+ }
160
+ }
161
+ const valuesList = rows.map((r) => `(${r.join(", ")})`).join(", ");
162
+ let stmt = `INSERT INTO ${qualifiedTable} (${colList}) VALUES ${valuesList}`;
163
+ if (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {
164
+ const updateCols = currentBatch.cols.filter((c) => !currentBatch.upsertKeys.includes(c) && !c.startsWith("_"));
165
+ if (updateCols.length > 0) {
166
+ const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`);
167
+ stmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ${setClauses.join(", ")}`;
168
+ } else {
169
+ stmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `"${k}"`).join(", ")}) DO NOTHING`;
170
+ }
171
+ }
172
+ statements.push(stmt);
173
+ currentBatch = null;
174
+ currentBatchKey = "";
175
+ };
127
176
  for (const op of ops) {
128
177
  const qualifiedTable = `"${this.pgSchemaName}"."${op.table}"`;
129
- switch (op.kind) {
130
- case "insert": {
131
- const upsertKeys = op.data._upsert_keys;
132
- const fallbackKeys = op.data._upsert_fallback_keys;
133
- const fallbackSet = op.data._upsert_fallback_set;
134
- const data = { ...op.data };
135
- delete data._upsert_keys;
136
- delete data._upsert_fallback_keys;
137
- delete data._upsert_fallback_set;
138
- data._block_height = this.block.height;
139
- data._tx_id = this._tx.txId;
140
- data._created_at = "NOW()";
141
- const cols = Object.keys(data);
142
- cols.forEach(validateColumnName);
143
- const vals = cols.map((c) => data[c] === "NOW()" ? "NOW()" : escapeLiteral(data[c]));
144
- let stmt = `INSERT INTO ${qualifiedTable} (${cols.map((c) => `"${c}"`).join(", ")}) VALUES (${vals.join(", ")})`;
145
- if (upsertKeys && upsertKeys.length > 0) {
146
- const updateCols = cols.filter((c) => !upsertKeys.includes(c) && !c.startsWith("_"));
147
- if (updateCols.length > 0) {
148
- const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`);
149
- stmt += ` ON CONFLICT (${upsertKeys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ${setClauses.join(", ")}`;
150
- } else {
151
- stmt += ` ON CONFLICT (${upsertKeys.map((k) => `"${k}"`).join(", ")}) DO NOTHING`;
152
- }
153
- } else if (fallbackKeys && fallbackSet) {}
154
- statements.push(stmt);
155
- break;
178
+ if (op.kind === "insert") {
179
+ const { cols, vals, upsertKeys, batchKey } = this.prepareInsert(op);
180
+ if (batchKey === currentBatchKey && currentBatch) {
181
+ currentBatch.rows.push(vals);
182
+ } else {
183
+ flushInsertBatch();
184
+ currentBatch = { table: op.table, cols, rows: [vals], upsertKeys };
185
+ currentBatchKey = batchKey;
156
186
  }
157
- case "update": {
187
+ } else {
188
+ flushInsertBatch();
189
+ if (op.kind === "update") {
158
190
  const setEntries = Object.entries(op.set);
159
191
  setEntries.forEach(([k]) => validateColumnName(k));
160
192
  const setClauses = setEntries.map(([k, v]) => `"${k}" = ${escapeLiteral(v)}`);
161
193
  const { clause } = buildWhereClause(op.data);
162
194
  statements.push(`UPDATE ${qualifiedTable} SET ${setClauses.join(", ")} WHERE ${clause}`);
163
- break;
164
- }
165
- case "delete": {
195
+ } else if (op.kind === "delete") {
166
196
  const { clause } = buildWhereClause(op.data);
167
197
  statements.push(`DELETE FROM ${qualifiedTable} WHERE ${clause}`);
168
- break;
169
198
  }
170
199
  }
171
200
  }
201
+ flushInsertBatch();
172
202
  return statements;
173
203
  }
174
204
  validateTable(table) {
@@ -418,6 +448,7 @@ import { updateSubgraphStatus, recordSubgraphProcessed } from "@secondlayer/shar
418
448
  import { pgSchemaName } from "@secondlayer/shared/db/queries/subgraphs";
419
449
 
420
450
  // src/runtime/block-processor.ts
451
+ var schemaNameCache = new Map;
421
452
  async function processBlock(subgraph, subgraphName, blockHeight, opts) {
422
453
  const db = getDb();
423
454
  const blockStart = performance.now();
@@ -428,19 +459,26 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
428
459
  errors: 0,
429
460
  skipped: false
430
461
  };
431
- const block = await db.selectFrom("blocks").selectAll().where("height", "=", blockHeight).executeTakeFirst();
432
- if (!block) {
433
- logger3.warn("Block not found for subgraph processing", { subgraph: subgraphName, blockHeight });
434
- result.skipped = true;
435
- return result;
436
- }
437
- if (!block.canonical) {
438
- logger3.debug("Skipping non-canonical block", { subgraph: subgraphName, blockHeight });
439
- result.skipped = true;
440
- return result;
462
+ let block, txs, evts;
463
+ if (opts?.preloaded) {
464
+ block = opts.preloaded.block;
465
+ txs = opts.preloaded.txs;
466
+ evts = opts.preloaded.events;
467
+ } else {
468
+ block = await db.selectFrom("blocks").selectAll().where("height", "=", blockHeight).executeTakeFirst();
469
+ if (!block) {
470
+ logger3.warn("Block not found for subgraph processing", { subgraph: subgraphName, blockHeight });
471
+ result.skipped = true;
472
+ return result;
473
+ }
474
+ if (!block.canonical) {
475
+ logger3.debug("Skipping non-canonical block", { subgraph: subgraphName, blockHeight });
476
+ result.skipped = true;
477
+ return result;
478
+ }
479
+ txs = await db.selectFrom("transactions").selectAll().where("block_height", "=", blockHeight).execute();
480
+ evts = await db.selectFrom("events").selectAll().where("block_height", "=", blockHeight).execute();
441
481
  }
442
- const txs = await db.selectFrom("transactions").selectAll().where("block_height", "=", blockHeight).execute();
443
- const evts = await db.selectFrom("events").selectAll().where("block_height", "=", blockHeight).execute();
444
482
  const matched = matchSources(subgraph.sources, txs, evts);
445
483
  result.matched = matched.length;
446
484
  if (matched.length === 0) {
@@ -449,8 +487,12 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
449
487
  }
450
488
  return result;
451
489
  }
452
- const subgraphRecord = await db.selectFrom("subgraphs").select("schema_name").where("name", "=", subgraphName).executeTakeFirst();
453
- const schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);
490
+ let schemaName = schemaNameCache.get(subgraphName);
491
+ if (!schemaName) {
492
+ const subgraphRecord = await db.selectFrom("subgraphs").select("schema_name").where("name", "=", subgraphName).executeTakeFirst();
493
+ schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);
494
+ schemaNameCache.set(subgraphName, schemaName);
495
+ }
454
496
  const blockMeta = {
455
497
  height: block.height,
456
498
  hash: block.hash,
@@ -578,8 +620,62 @@ class StatsAccumulator {
578
620
  import { getDb as getDb2 } from "@secondlayer/shared/db";
579
621
  import { logger as logger4 } from "@secondlayer/shared/logger";
580
622
  import { getSubgraph } from "@secondlayer/shared/db/queries/subgraphs";
623
+
624
+ // src/runtime/batch-loader.ts
625
+ async function loadBlockRange(db, fromHeight, toHeight) {
626
+ const [blocks, txs, events] = await Promise.all([
627
+ db.selectFrom("blocks").selectAll().where("height", ">=", fromHeight).where("height", "<=", toHeight).where("canonical", "=", true).execute(),
628
+ db.selectFrom("transactions").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute(),
629
+ db.selectFrom("events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute()
630
+ ]);
631
+ const txsByHeight = new Map;
632
+ for (const tx of txs) {
633
+ const h = Number(tx.block_height);
634
+ const list = txsByHeight.get(h) ?? [];
635
+ list.push(tx);
636
+ txsByHeight.set(h, list);
637
+ }
638
+ const eventsByHeight = new Map;
639
+ for (const evt of events) {
640
+ const h = Number(evt.block_height);
641
+ const list = eventsByHeight.get(h) ?? [];
642
+ list.push(evt);
643
+ eventsByHeight.set(h, list);
644
+ }
645
+ const result = new Map;
646
+ for (const block of blocks) {
647
+ const h = Number(block.height);
648
+ result.set(h, {
649
+ block,
650
+ txs: txsByHeight.get(h) ?? [],
651
+ events: eventsByHeight.get(h) ?? []
652
+ });
653
+ }
654
+ return result;
655
+ }
656
+ function avgEventsPerBlock(batch) {
657
+ if (batch.size === 0)
658
+ return 0;
659
+ let totalEvents = 0;
660
+ for (const data of batch.values()) {
661
+ totalEvents += data.events.length;
662
+ }
663
+ return totalEvents / batch.size;
664
+ }
665
+
666
+ // src/runtime/catchup.ts
581
667
  var LOG_INTERVAL = 1000;
668
+ var DEFAULT_BATCH_SIZE = 500;
669
+ var MIN_BATCH_SIZE = 100;
670
+ var MAX_BATCH_SIZE = 1000;
582
671
  var catchingUp = new Set;
672
+ function adjustBatchSize(current, avgEvents) {
673
+ if (avgEvents > 50)
674
+ return Math.max(Math.round(current * 0.5), MIN_BATCH_SIZE);
675
+ if (avgEvents < 10)
676
+ return Math.min(Math.round(current * 1.5), MAX_BATCH_SIZE);
677
+ return current;
678
+ }
583
679
  async function catchUpSubgraph(subgraph, subgraphName) {
584
680
  if (catchingUp.has(subgraphName))
585
681
  return 0;
@@ -606,24 +702,59 @@ async function catchUpSubgraph(subgraph, subgraphName) {
606
702
  });
607
703
  const stats = new StatsAccumulator(subgraphName, subgraphRow.api_key_id, true);
608
704
  let processed = 0;
609
- for (let height = startBlock;height <= chainTip; height++) {
610
- const result = await processBlock(subgraph, subgraphName, height);
611
- processed++;
612
- if (result.timing) {
613
- stats.record(result.timing, result.processed);
614
- if (stats.shouldFlush()) {
615
- await stats.flush(db);
616
- }
705
+ let batchSize = DEFAULT_BATCH_SIZE;
706
+ let currentHeight = startBlock;
707
+ let nextBatchPromise = loadBlockRange(db, currentHeight, Math.min(currentHeight + batchSize - 1, chainTip));
708
+ while (currentHeight <= chainTip) {
709
+ const batch = await nextBatchPromise;
710
+ const batchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
711
+ const nextStart = batchEnd + 1;
712
+ if (nextStart <= chainTip) {
713
+ const nextEnd = Math.min(nextStart + batchSize - 1, chainTip);
714
+ nextBatchPromise = loadBlockRange(db, nextStart, nextEnd);
617
715
  }
618
- if (processed % LOG_INTERVAL === 0) {
619
- logger4.info("Subgraph catch-up progress", {
620
- subgraph: subgraphName,
621
- processed,
622
- total: totalBlocks,
623
- currentBlock: height,
624
- pct: Math.round(processed / totalBlocks * 100)
625
- });
716
+ for (let height = currentHeight;height <= batchEnd; height++) {
717
+ const blockData = batch.get(height);
718
+ if (!blockData) {
719
+ processed++;
720
+ continue;
721
+ }
722
+ let result;
723
+ try {
724
+ result = await processBlock(subgraph, subgraphName, height, {
725
+ preloaded: blockData
726
+ });
727
+ } catch (err) {
728
+ logger4.error("Block processing error during catch-up", {
729
+ subgraph: subgraphName,
730
+ blockHeight: height,
731
+ error: err instanceof Error ? err.message : String(err)
732
+ });
733
+ const { updateSubgraphStatus: updateSubgraphStatus2 } = await import("@secondlayer/shared/db/queries/subgraphs");
734
+ await updateSubgraphStatus2(db, subgraphName, "active", height).catch(() => {});
735
+ processed++;
736
+ continue;
737
+ }
738
+ processed++;
739
+ if (result.timing) {
740
+ stats.record(result.timing, result.processed);
741
+ if (stats.shouldFlush()) {
742
+ await stats.flush(db);
743
+ }
744
+ }
745
+ if (processed % LOG_INTERVAL === 0) {
746
+ logger4.info("Subgraph catch-up progress", {
747
+ subgraph: subgraphName,
748
+ processed,
749
+ total: totalBlocks,
750
+ currentBlock: height,
751
+ pct: Math.round(processed / totalBlocks * 100)
752
+ });
753
+ }
626
754
  }
755
+ const avg = avgEventsPerBlock(batch);
756
+ batchSize = adjustBatchSize(batchSize, avg);
757
+ currentHeight = batchEnd + 1;
627
758
  }
628
759
  await stats.flush(db);
629
760
  logger4.info("Subgraph catch-up complete", {
@@ -639,5 +770,5 @@ export {
639
770
  catchUpSubgraph
640
771
  };
641
772
 
642
- //# debugId=2F1E08A57DC75EE464756E2164756E21
773
+ //# debugId=ECEE17CC2A59B3A164756E2164756E21
643
774
  //# sourceMappingURL=catchup.js.map