@secondlayer/shared 6.18.0 → 6.19.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,9 +3,9 @@
3
3
  "sources": ["../src/index-internal-auth.ts", "../src/index-http.ts"],
4
4
  "sourcesContent": [
5
5
  "// Internal service credential for first-party consumers of /v1/index over HTTP\n// (e.g. the subgraph processor's PublicApiBlockSource). Seeded into the Index\n// token store as an enterprise tenant with NO account_id, so these reads are\n// unmetered (Index metering gates on account_id). Mirrors the Streams internal\n// key (packages/indexer/src/l2/internal-auth.ts). Lives in shared so both the\n// API (seed) and the subgraph processor (consumer) import it without a cycle.\nexport const INDEX_INTERNAL_TENANT_ID = \"tenant_index_internal\";\n\nconst DEFAULT_INDEX_INTERNAL_API_KEY = \"sk-sl_index_internal\";\n\nexport function defaultInternalIndexApiKey(): string {\n\treturn process.env.INDEX_INTERNAL_API_KEY || DEFAULT_INDEX_INTERNAL_API_KEY;\n}\n",
6
- "import { defaultInternalIndexApiKey } from \"./index-internal-auth.ts\";\n\n/**\n * Low-level transport for the public Index (`/v1/index`) + Streams clock\n * (`/v1/streams`) HTTP APIs: cursor-paginated reads, tip, reorgs. Lives in\n * `shared` (a leaf both the SDK and the subgraph runtime depend on) so the wire\n * format has one home and no package cycle. The SDK's ergonomic client should\n * eventually consume these row types too (see the plan's convergence task).\n *\n * This is intentionally minimal — just the GETs the subgraph runtime's\n * PublicApiBlockSource needs. It is NOT the SDK's full client (walk/consume/\n * retries/auth resolution).\n */\n\nconst PAGE_LIMIT = 1000;\n\ntype Envelope<K extends string, T> = {\n\t[P in K]: T[];\n} & { next_cursor: string | null };\n\n// ── Index API wire shapes (single source of truth) ─────────────────────────\nexport type IndexBlockRow = {\n\tblock_height: number;\n\tblock_hash: string;\n\tparent_hash: string;\n\tburn_block_height: number;\n\tburn_block_hash: string | null;\n\tblock_time: string | null;\n};\n\ntype IndexEventCommon = {\n\tblock_height: number;\n\ttx_id: string;\n\tevent_index: number;\n\tcontract_id: string | null;\n};\n\nexport type IndexEventRow = IndexEventCommon &\n\t(\n\t\t| {\n\t\t\t\tevent_type: \"ft_transfer\" | \"ft_mint\" | \"ft_burn\";\n\t\t\t\tasset_identifier: string;\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tamount: string;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"nft_transfer\" | \"nft_mint\" | \"nft_burn\";\n\t\t\t\tasset_identifier: string;\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tvalue: string;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"stx_transfer\" | \"stx_mint\" | \"stx_burn\";\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tamount: string;\n\t\t\t\tmemo?: string | null;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"stx_lock\";\n\t\t\t\tsender: string;\n\t\t\t\tamount: string;\n\t\t\t\tpayload: { unlock_height: string | null };\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"print\";\n\t\t\t\tpayload: {\n\t\t\t\t\ttopic: string | null;\n\t\t\t\t\tvalue: unknown;\n\t\t\t\t\traw_value: string | null;\n\t\t\t\t};\n\t\t }\n\t);\n\nexport type IndexTransactionRow = {\n\ttx_id: string;\n\tblock_height: number;\n\ttx_index: number;\n\ttx_type: string;\n\tsender: string;\n\tstatus: string;\n\tcontract_call?: {\n\t\tcontract_id: string;\n\t\tfunction_name: string;\n\t\tfunction_args_hex?: string[] | null;\n\t\tresult_hex?: string | null;\n\t} | null;\n\tsmart_contract?: { contract_id: string | null } | null;\n};\n\nexport type StreamsReorgRow = {\n\tdetected_at: string;\n\tfork_point_height: number;\n\torphaned_range: { from: string; to: string };\n\tnew_canonical_tip: string;\n};\n\nexport type IndexHttpOptions = {\n\t/** Base URL for /v1/index (the decoded data plane). */\n\tindexBaseUrl: string;\n\t/** Bearer for /v1/index. Defaults to the internal enterprise key. */\n\tindexApiKey?: string;\n\t/** Base URL for /v1/streams (the canonical clock). */\n\tstreamsBaseUrl: string;\n\t/** Bearer for /v1/streams (internal enterprise key). */\n\tstreamsApiKey: string;\n};\n\nexport class IndexHttpClient {\n\tprivate readonly indexBaseUrl: string;\n\tprivate readonly indexApiKey: string;\n\tprivate readonly streamsBaseUrl: string;\n\tprivate readonly streamsApiKey: string;\n\n\tconstructor(opts: IndexHttpOptions) {\n\t\tthis.indexBaseUrl = opts.indexBaseUrl.replace(/\\/+$/, \"\");\n\t\tthis.indexApiKey = opts.indexApiKey ?? defaultInternalIndexApiKey();\n\t\tthis.streamsBaseUrl = opts.streamsBaseUrl.replace(/\\/+$/, \"\");\n\t\tthis.streamsApiKey = opts.streamsApiKey;\n\t}\n\n\tprivate async get<T>(url: string, apiKey: string): Promise<T> {\n\t\t// Index reads are anon — omit the header entirely when no key is set, so\n\t\t// an empty key reads anonymously rather than 401-ing as an invalid bearer.\n\t\tconst res = await fetch(url, {\n\t\t\theaders: apiKey ? { authorization: `Bearer ${apiKey}` } : {},\n\t\t});\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`GET ${url} → ${res.status} ${await res.text()}`);\n\t\t}\n\t\treturn (await res.json()) as T;\n\t}\n\n\t/** Drain a cursor-paginated Index collection over [fromHeight, toHeight]. */\n\tprivate async walk<K extends string, T>(\n\t\tpath: string,\n\t\tkey: K,\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t\textraParams: Record<string, string> = {},\n\t): Promise<T[]> {\n\t\tconst out: T[] = [];\n\t\tlet cursor: string | null = null;\n\t\tdo {\n\t\t\tconst params = new URLSearchParams({\n\t\t\t\tto_height: String(toHeight),\n\t\t\t\tlimit: String(PAGE_LIMIT),\n\t\t\t\t...extraParams,\n\t\t\t});\n\t\t\t// from_height and cursor are mutually exclusive — anchor the first page\n\t\t\t// by height, then page forward by cursor only.\n\t\t\tif (cursor) params.set(\"cursor\", cursor);\n\t\t\telse params.set(\"from_height\", String(fromHeight));\n\t\t\tconst env: Envelope<K, T> = await this.get(\n\t\t\t\t`${this.indexBaseUrl}${path}?${params}`,\n\t\t\t\tthis.indexApiKey,\n\t\t\t);\n\t\t\tout.push(...env[key]);\n\t\t\tcursor = env.next_cursor;\n\t\t} while (cursor);\n\t\treturn out;\n\t}\n\n\twalkBlocks(fromHeight: number, toHeight: number): Promise<IndexBlockRow[]> {\n\t\treturn this.walk<\"blocks\", IndexBlockRow>(\n\t\t\t\"/v1/index/blocks\",\n\t\t\t\"blocks\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t);\n\t}\n\n\twalkEvents(\n\t\teventType: string,\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<IndexEventRow[]> {\n\t\treturn this.walk<\"events\", IndexEventRow>(\n\t\t\t\"/v1/index/events\",\n\t\t\t\"events\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t\t{ event_type: eventType },\n\t\t);\n\t}\n\n\twalkTransactions(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<IndexTransactionRow[]> {\n\t\treturn this.walk<\"transactions\", IndexTransactionRow>(\n\t\t\t\"/v1/index/transactions\",\n\t\t\t\"transactions\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t);\n\t}\n\n\t/** Canonical tip height from the Streams clock. */\n\tasync getStreamsTip(): Promise<number> {\n\t\tconst tip = await this.get<{ block_height: number }>(\n\t\t\t`${this.streamsBaseUrl}/v1/streams/tip`,\n\t\t\tthis.streamsApiKey,\n\t\t);\n\t\treturn Number(tip.block_height) || 0;\n\t}\n\n\t/**\n\t * Highest block height the Index data plane can serve (tip is inline in every\n\t * envelope). This is the data-availability bound — a consumer must not\n\t * process past it, even if the Streams clock is ahead.\n\t */\n\tasync getIndexTip(): Promise<number> {\n\t\tconst env = await this.get<{ tip: { block_height: number } }>(\n\t\t\t`${this.indexBaseUrl}/v1/index/blocks?limit=1`,\n\t\t\tthis.indexApiKey,\n\t\t);\n\t\treturn Number(env.tip?.block_height) || 0;\n\t}\n\n\t/** Reorgs since a resume token (wall-clock `detected_at`-keyed). */\n\tasync listReorgs(\n\t\tsince: string,\n\t): Promise<{ reorgs: StreamsReorgRow[]; next_since: string | null }> {\n\t\tconst params = new URLSearchParams({ since });\n\t\treturn this.get(\n\t\t\t`${this.streamsBaseUrl}/v1/streams/reorgs?${params}`,\n\t\t\tthis.streamsApiKey,\n\t\t);\n\t}\n}\n"
6
+ "import { defaultInternalIndexApiKey } from \"./index-internal-auth.ts\";\n\n/**\n * Low-level transport for the public Index (`/v1/index`) + Streams clock\n * (`/v1/streams`) HTTP APIs: cursor-paginated reads, tip, reorgs. Lives in\n * `shared` (a leaf both the SDK and the subgraph runtime depend on) so the wire\n * format has one home and no package cycle. The SDK's ergonomic client should\n * eventually consume these row types too (see the plan's convergence task).\n *\n * This is intentionally minimal — just the GETs the subgraph runtime's\n * PublicApiBlockSource needs. It is NOT the SDK's full client (walk/consume/\n * retries/auth resolution).\n */\n\nconst PAGE_LIMIT = 1000;\n\ntype Envelope<K extends string, T> = {\n\t[P in K]: T[];\n} & { next_cursor: string | null };\n\n// ── Index API wire shapes (single source of truth) ─────────────────────────\nexport type IndexBlockRow = {\n\tblock_height: number;\n\tblock_hash: string;\n\tparent_hash: string;\n\tburn_block_height: number;\n\tburn_block_hash: string | null;\n\tblock_time: string | null;\n};\n\ntype IndexEventCommon = {\n\tblock_height: number;\n\ttx_id: string;\n\tevent_index: number;\n\tcontract_id: string | null;\n};\n\nexport type IndexEventRow = IndexEventCommon &\n\t(\n\t\t| {\n\t\t\t\tevent_type: \"ft_transfer\" | \"ft_mint\" | \"ft_burn\";\n\t\t\t\tasset_identifier: string;\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tamount: string;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"nft_transfer\" | \"nft_mint\" | \"nft_burn\";\n\t\t\t\tasset_identifier: string;\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tvalue: string;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"stx_transfer\" | \"stx_mint\" | \"stx_burn\";\n\t\t\t\tsender?: string;\n\t\t\t\trecipient?: string;\n\t\t\t\tamount: string;\n\t\t\t\tmemo?: string | null;\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"stx_lock\";\n\t\t\t\tsender: string;\n\t\t\t\tamount: string;\n\t\t\t\tpayload: { unlock_height: string | null };\n\t\t }\n\t\t| {\n\t\t\t\tevent_type: \"print\";\n\t\t\t\tpayload: {\n\t\t\t\t\ttopic: string | null;\n\t\t\t\t\tvalue: unknown;\n\t\t\t\t\traw_value: string | null;\n\t\t\t\t};\n\t\t }\n\t);\n\nexport type IndexTransactionRow = {\n\ttx_id: string;\n\tblock_height: number;\n\tblock_time?: string | null;\n\tburn_block_height?: number | null;\n\ttx_index: number;\n\ttx_type: string;\n\tsender: string;\n\tstatus: string;\n\tcontract_call?: {\n\t\tcontract_id: string;\n\t\tfunction_name: string;\n\t\tfunction_args_hex?: string[] | null;\n\t\tresult_hex?: string | null;\n\t} | null;\n\tsmart_contract?: { contract_id: string | null } | null;\n};\n\nexport type StreamsReorgRow = {\n\tdetected_at: string;\n\tfork_point_height: number;\n\torphaned_range: { from: string; to: string };\n\tnew_canonical_tip: string;\n};\n\nexport type IndexHttpOptions = {\n\t/** Base URL for /v1/index (the decoded data plane). */\n\tindexBaseUrl: string;\n\t/** Bearer for /v1/index. Defaults to the internal enterprise key. */\n\tindexApiKey?: string;\n\t/** Base URL for /v1/streams (the canonical clock). */\n\tstreamsBaseUrl: string;\n\t/** Bearer for /v1/streams (internal enterprise key). */\n\tstreamsApiKey: string;\n};\n\nexport class IndexHttpClient {\n\tprivate readonly indexBaseUrl: string;\n\tprivate readonly indexApiKey: string;\n\tprivate readonly streamsBaseUrl: string;\n\tprivate readonly streamsApiKey: string;\n\n\tconstructor(opts: IndexHttpOptions) {\n\t\tthis.indexBaseUrl = opts.indexBaseUrl.replace(/\\/+$/, \"\");\n\t\tthis.indexApiKey = opts.indexApiKey ?? defaultInternalIndexApiKey();\n\t\tthis.streamsBaseUrl = opts.streamsBaseUrl.replace(/\\/+$/, \"\");\n\t\tthis.streamsApiKey = opts.streamsApiKey;\n\t}\n\n\tprivate async get<T>(url: string, apiKey: string): Promise<T> {\n\t\t// Index reads are anon — omit the header entirely when no key is set, so\n\t\t// an empty key reads anonymously rather than 401-ing as an invalid bearer.\n\t\tconst res = await fetch(url, {\n\t\t\theaders: apiKey ? { authorization: `Bearer ${apiKey}` } : {},\n\t\t});\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`GET ${url} → ${res.status} ${await res.text()}`);\n\t\t}\n\t\treturn (await res.json()) as T;\n\t}\n\n\t/** Fetch a single cursor page of an Index collection. */\n\tprivate async getPage<K extends string, T>(\n\t\tpath: string,\n\t\tkey: K,\n\t\tparams: URLSearchParams,\n\t): Promise<{ items: T[]; next_cursor: string | null }> {\n\t\tconst env: Envelope<K, T> = await this.get(\n\t\t\t`${this.indexBaseUrl}${path}?${params}`,\n\t\t\tthis.indexApiKey,\n\t\t);\n\t\treturn { items: env[key], next_cursor: env.next_cursor };\n\t}\n\n\t/** Drain a cursor-paginated Index collection over [fromHeight, toHeight]. */\n\tprivate async walk<K extends string, T>(\n\t\tpath: string,\n\t\tkey: K,\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t\textraParams: Record<string, string> = {},\n\t): Promise<T[]> {\n\t\tconst out: T[] = [];\n\t\tlet cursor: string | null = null;\n\t\tdo {\n\t\t\tconst params = new URLSearchParams({\n\t\t\t\tto_height: String(toHeight),\n\t\t\t\tlimit: String(PAGE_LIMIT),\n\t\t\t\t...extraParams,\n\t\t\t});\n\t\t\t// from_height and cursor are mutually exclusive — anchor the first page\n\t\t\t// by height, then page forward by cursor only.\n\t\t\tif (cursor) params.set(\"cursor\", cursor);\n\t\t\telse params.set(\"from_height\", String(fromHeight));\n\t\t\tconst { items, next_cursor } = await this.getPage<K, T>(\n\t\t\t\tpath,\n\t\t\t\tkey,\n\t\t\t\tparams,\n\t\t\t);\n\t\t\tout.push(...items);\n\t\t\tcursor = next_cursor;\n\t\t} while (cursor);\n\t\treturn out;\n\t}\n\n\t/**\n\t * Fetch ONE page of contract-call transactions filtered to `contractId`.\n\t * Unlike walk(), this does NOT drain — the caller pages by feeding back\n\t * next_cursor — so a sparse high-volume filter (e.g. a single contract over\n\t * all history) costs one request per batch, not O(all-history) per tick.\n\t * `cursor` is exclusive (rows strictly after it); on the first call pass\n\t * `fromHeight` to anchor the backfill start instead.\n\t */\n\tasync fetchContractCalls(\n\t\tcontractId: string,\n\t\topts: {\n\t\t\ttoHeight: number;\n\t\t\tcursor?: string | null;\n\t\t\tfromHeight?: number;\n\t\t\tlimit?: number;\n\t\t},\n\t): Promise<{\n\t\ttransactions: IndexTransactionRow[];\n\t\tnext_cursor: string | null;\n\t}> {\n\t\tconst params = new URLSearchParams({\n\t\t\tto_height: String(opts.toHeight),\n\t\t\tlimit: String(opts.limit ?? PAGE_LIMIT),\n\t\t\tcontract_id: contractId,\n\t\t});\n\t\tif (opts.cursor) params.set(\"cursor\", opts.cursor);\n\t\telse params.set(\"from_height\", String(opts.fromHeight ?? 0));\n\t\tconst { items, next_cursor } = await this.getPage<\n\t\t\t\"transactions\",\n\t\t\tIndexTransactionRow\n\t\t>(\"/v1/index/transactions\", \"transactions\", params);\n\t\treturn { transactions: items, next_cursor };\n\t}\n\n\twalkBlocks(fromHeight: number, toHeight: number): Promise<IndexBlockRow[]> {\n\t\treturn this.walk<\"blocks\", IndexBlockRow>(\n\t\t\t\"/v1/index/blocks\",\n\t\t\t\"blocks\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t);\n\t}\n\n\twalkEvents(\n\t\teventType: string,\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<IndexEventRow[]> {\n\t\treturn this.walk<\"events\", IndexEventRow>(\n\t\t\t\"/v1/index/events\",\n\t\t\t\"events\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t\t{ event_type: eventType },\n\t\t);\n\t}\n\n\twalkTransactions(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<IndexTransactionRow[]> {\n\t\treturn this.walk<\"transactions\", IndexTransactionRow>(\n\t\t\t\"/v1/index/transactions\",\n\t\t\t\"transactions\",\n\t\t\tfromHeight,\n\t\t\ttoHeight,\n\t\t);\n\t}\n\n\t/** Canonical tip height from the Streams clock. */\n\tasync getStreamsTip(): Promise<number> {\n\t\tconst tip = await this.get<{ block_height: number }>(\n\t\t\t`${this.streamsBaseUrl}/v1/streams/tip`,\n\t\t\tthis.streamsApiKey,\n\t\t);\n\t\treturn Number(tip.block_height) || 0;\n\t}\n\n\t/**\n\t * Highest block height the Index data plane can serve (tip is inline in every\n\t * envelope). This is the data-availability bound — a consumer must not\n\t * process past it, even if the Streams clock is ahead.\n\t */\n\tasync getIndexTip(): Promise<number> {\n\t\tconst env = await this.get<{ tip: { block_height: number } }>(\n\t\t\t`${this.indexBaseUrl}/v1/index/blocks?limit=1`,\n\t\t\tthis.indexApiKey,\n\t\t);\n\t\treturn Number(env.tip?.block_height) || 0;\n\t}\n\n\t/** Reorgs since a resume token (wall-clock `detected_at`-keyed). */\n\tasync listReorgs(\n\t\tsince: string,\n\t): Promise<{ reorgs: StreamsReorgRow[]; next_since: string | null }> {\n\t\tconst params = new URLSearchParams({ since });\n\t\treturn this.get(\n\t\t\t`${this.streamsBaseUrl}/v1/streams/reorgs?${params}`,\n\t\t\tthis.streamsApiKey,\n\t\t);\n\t}\n}\n"
7
7
  ],
8
- "mappings": ";;;;;;;;;;;;;;;;;AAMO,IAAM,2BAA2B;AAExC,IAAM,iCAAiC;AAEhC,SAAS,0BAA0B,GAAW;AAAA,EACpD,OAAO,QAAQ,IAAI,0BAA0B;AAAA;;;ACG9C,IAAM,aAAa;AAAA;AAgGZ,MAAM,gBAAgB;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,MAAwB;AAAA,IACnC,KAAK,eAAe,KAAK,aAAa,QAAQ,QAAQ,EAAE;AAAA,IACxD,KAAK,cAAc,KAAK,eAAe,2BAA2B;AAAA,IAClE,KAAK,iBAAiB,KAAK,eAAe,QAAQ,QAAQ,EAAE;AAAA,IAC5D,KAAK,gBAAgB,KAAK;AAAA;AAAA,OAGb,IAAM,CAAC,KAAa,QAA4B;AAAA,IAG7D,MAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC5B,SAAS,SAAS,EAAE,eAAe,UAAU,SAAS,IAAI,CAAC;AAAA,IAC5D,CAAC;AAAA,IACD,IAAI,CAAC,IAAI,IAAI;AAAA,MACZ,MAAM,IAAI,MAAM,OAAO,SAAQ,IAAI,UAAU,MAAM,IAAI,KAAK,GAAG;AAAA,IAChE;AAAA,IACA,OAAQ,MAAM,IAAI,KAAK;AAAA;AAAA,OAIV,KAAyB,CACtC,MACA,KACA,YACA,UACA,cAAsC,CAAC,GACxB;AAAA,IACf,MAAM,MAAW,CAAC;AAAA,IAClB,IAAI,SAAwB;AAAA,IAC5B,GAAG;AAAA,MACF,MAAM,SAAS,IAAI,gBAAgB;AAAA,QAClC,WAAW,OAAO,QAAQ;AAAA,QAC1B,OAAO,OAAO,UAAU;AAAA,WACrB;AAAA,MACJ,CAAC;AAAA,MAGD,IAAI;AAAA,QAAQ,OAAO,IAAI,UAAU,MAAM;AAAA,MAClC;AAAA,eAAO,IAAI,eAAe,OAAO,UAAU,CAAC;AAAA,MACjD,MAAM,MAAsB,MAAM,KAAK,IACtC,GAAG,KAAK,eAAe,QAAQ,UAC/B,KAAK,WACN;AAAA,MACA,IAAI,KAAK,GAAG,IAAI,IAAI;AAAA,MACpB,SAAS,IAAI;AAAA,IACd,SAAS;AAAA,IACT,OAAO;AAAA;AAAA,EAGR,UAAU,CAAC,YAAoB,UAA4C;AAAA,IAC1E,OAAO,KAAK,KACX,oBACA,UACA,YACA,QACD;AAAA;AAAA,EAGD,UAAU,CACT,WACA,YACA,UAC2B;AAAA,IAC3B,OAAO,KAAK,KACX,oBACA,UACA,YACA,UACA,EAAE,YAAY,UAAU,CACzB;AAAA;AAAA,EAGD,gBAAgB,CACf,YACA,UACiC;AAAA,IACjC,OAAO,KAAK,KACX,0BACA,gBACA,YACA,QACD;AAAA;AAAA,OAIK,cAAa,GAAoB;AAAA,IACtC,MAAM,MAAM,MAAM,KAAK,IACtB,GAAG,KAAK,iCACR,KAAK,aACN;AAAA,IACA,OAAO,OAAO,IAAI,YAAY,KAAK;AAAA;AAAA,OAQ9B,YAAW,GAAoB;AAAA,IACpC,MAAM,MAAM,MAAM,KAAK,IACtB,GAAG,KAAK,wCACR,KAAK,WACN;AAAA,IACA,OAAO,OAAO,IAAI,KAAK,YAAY,KAAK;AAAA;AAAA,OAInC,WAAU,CACf,OACoE;AAAA,IACpE,MAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;AAAA,IAC5C,OAAO,KAAK,IACX,GAAG,KAAK,oCAAoC,UAC5C,KAAK,aACN;AAAA;AAEF;",
9
- "debugId": "E1C3D9E21DD5904564756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "D7EA6E24A653E5AE64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -918,6 +918,12 @@ type Env = EnvSchemaOutput & {
918
918
  enabledNetworks: ("mainnet" | "testnet")[]
919
919
  };
920
920
  declare function getEnv(): Env;
921
+ /**
922
+ * PoX-4 stacking decoder is ON by default — `/v1/index/stacking` is part of the
923
+ * public surface, so the decoder that fills `pox4_calls` runs unless explicitly
924
+ * opted out with `POX4_DECODER_ENABLED=false` (mirrors the sBTC decoder policy).
925
+ */
926
+ declare function isPox4DecoderEnabled(): boolean;
921
927
  import { RawBuilder } from "kysely";
922
928
  /**
923
929
  * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.
@@ -938,6 +944,45 @@ declare function parseJsonb<T = unknown>(value: unknown): T;
938
944
  import { Kysely } from "kysely";
939
945
  import postgres from "postgres";
940
946
  import { sql } from "kysely";
947
+ import { Selectable as Selectable2 } from "kysely";
948
+ /** Widen a single scalar to its driver-accurate read shape. */
949
+ type NumericAsText<T> = T extends number ? number | string : T extends Date ? Date | string : T;
950
+ /**
951
+ * Driver-accurate read-row type: pick selected columns `K` from table `T`'s
952
+ * Selectable shape, then widen each to what postgres.js actually returns.
953
+ * Computed/aliased columns not on the table interface must be intersected on
954
+ * separately at the call site.
955
+ */
956
+ type DbReadRow<
957
+ T extends keyof Database,
958
+ K extends keyof Selectable2<Database[T]>
959
+ > = { [P in K] : NumericAsText<Selectable2<Database[T]>[P]> };
960
+ declare const SOURCE_READ_COLUMNS: {
961
+ readonly blocks: readonly ["burn_block_hash", "burn_block_height", "canonical", "hash", "height", "parent_hash", "timestamp"]
962
+ readonly decoded_events: readonly ["amount", "asset_identifier", "block_height", "canonical", "contract_id", "cursor", "event_index", "event_type", "memo", "payload", "recipient", "sender", "tx_id", "tx_index", "value"]
963
+ readonly transactions: readonly ["block_height", "contract_id", "function_args", "function_name", "raw_result", "raw_tx", "sender", "status", "tx_id", "tx_index", "type"]
964
+ readonly mempool_transactions: readonly ["contract_id", "function_args", "function_name", "raw_tx", "received_at", "sender", "seq", "tx_id", "type"]
965
+ readonly pox4_calls: readonly ["aggregated_amount_ustx", "aggregated_signer_index", "amount_ustx", "auth_allowed", "auth_id", "auth_period", "auth_topic", "block_height", "block_time", "burn_block_height", "caller", "canonical", "cursor", "delegate_to", "end_cycle", "function_name", "lock_period", "max_amount", "pox_addr_btc", "pox_addr_hashbytes", "pox_addr_version", "result_ok", "reward_cycle", "signer_key", "signer_signature", "source_cursor", "stacker", "start_cycle", "tx_id", "tx_index"]
966
+ readonly sbtc_events: readonly ["amount", "bitcoin_txid", "block_height", "block_time", "burn_hash", "burn_height", "canonical", "cursor", "event_index", "fee", "governance_contract_type", "governance_new_contract", "max_fee", "output_index", "recipient_btc_hashbytes", "recipient_btc_version", "request_id", "sender", "signer_address", "signer_aggregate_pubkey", "signer_bitmap", "signer_keys_count", "signer_threshold", "sweep_txid", "topic", "tx_id", "tx_index"]
967
+ readonly sbtc_token_events: readonly ["amount", "block_height", "block_time", "canonical", "cursor", "event_index", "event_type", "memo", "recipient", "sender", "tx_id", "tx_index"]
968
+ readonly bns_name_events: readonly ["block_height", "block_time", "bns_id", "canonical", "cursor", "event_index", "fqn", "hashed_salted_fqn_preorder", "imported_at", "name", "namespace", "owner", "preordered_by", "registered_at", "renewal_height", "stx_burn", "topic", "tx_id", "tx_index"]
969
+ readonly bns_namespace_events: readonly ["block_height", "block_time", "canonical", "cursor", "event_index", "launched_at", "lifetime", "manager", "manager_frozen", "manager_transfers_disabled", "namespace", "price_frozen", "price_function", "revealed_at", "status", "tx_id", "tx_index"]
970
+ readonly bns_marketplace_events: readonly ["action", "block_height", "block_time", "bns_id", "canonical", "commission", "cursor", "event_index", "price_ustx", "tx_id", "tx_index"]
971
+ readonly bns_names: readonly ["bns_id", "fqn", "last_event_at", "last_event_cursor", "name", "namespace", "owner", "registered_at", "renewal_height"]
972
+ readonly bns_namespaces: readonly ["last_event_at", "last_event_cursor", "launched_at", "lifetime", "manager", "manager_frozen", "name_count", "namespace", "price_frozen"]
973
+ readonly burn_block_rewards: readonly ["amount_sats", "burn_amount", "burn_block_hash", "burn_block_height", "canonical", "cursor", "recipient_btc", "reward_index"]
974
+ readonly burn_block_reward_slots: readonly ["burn_block_hash", "burn_block_height", "canonical", "cursor", "holder_btc", "slot_index"]
975
+ readonly events: readonly ["block_height", "data", "event_index", "tx_id", "type"]
976
+ readonly chain_reorgs: readonly ["detected_at"]
977
+ };
978
+ /**
979
+ * Boot guard: if the chain/control split is requested (`SOURCE_DATABASE_URL` or
980
+ * `TARGET_DATABASE_URL` set) but both still resolve to the same DB — a typo, or
981
+ * a stray `DATABASE_URL` masking the intent — the split silently collapses and
982
+ * chain + control plane share one instance. Surface it loudly. Fail-soft (no
983
+ * throw) so a misconfig doesn't brick startup; logs make it obvious.
984
+ */
985
+ declare function assertDbSplit(): void;
941
986
  /**
942
987
  * Kysely instance for the SOURCE DB (block/tx/event reads from the shared
943
988
  * indexer). Resolution: `SOURCE_DATABASE_URL || DATABASE_URL`.
@@ -1594,6 +1639,10 @@ type DecodedEventType = (typeof DECODED_EVENT_TYPES)[number];
1594
1639
  * a bare const-to-const alias. */
1595
1640
  declare const STREAMS_EVENT_TYPES: typeof DECODED_EVENT_TYPES;
1596
1641
  type StreamsEventType = DecodedEventType;
1642
+ declare const STREAMS_DB_EVENT_TYPES: readonly ["stx_transfer_event", "stx_mint_event", "stx_burn_event", "stx_lock_event", "ft_transfer_event", "ft_mint_event", "ft_burn_event", "nft_transfer_event", "nft_mint_event", "nft_burn_event", "smart_contract_event", "contract_event"];
1643
+ type StreamsDbEventType = (typeof STREAMS_DB_EVENT_TYPES)[number];
1644
+ declare const DB_TO_STREAMS_EVENT_TYPE: Record<StreamsDbEventType, StreamsEventType>;
1645
+ declare const STREAMS_TO_DB_EVENT_TYPES: Record<StreamsEventType, readonly StreamsDbEventType[]>;
1597
1646
  /**
1598
1647
  * Block finality, anchored to the burn (Bitcoin) chain.
1599
1648
  *
@@ -1666,4 +1715,4 @@ declare function publicKeyPemFromPrivate(privateKeyPem: string): string;
1666
1715
  declare function ed25519KeyId(publicKeyPem: string): string;
1667
1716
  declare function signEd25519(payload: string, privateKey: KeyObject): string;
1668
1717
  declare function verifyEd25519(payload: string, signatureBase64: string, publicKey: KeyObject): boolean;
1669
- export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getErrorMessage, getEnv, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, finalizedBurnHeight, encodeStreamsCursor, exports_ed25519 as ed25519, decodeStreamsCursor, exports_hmac as crypto, closeDb, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphResourceWarning, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, StreamsEventType, StreamsCursor, SessionsTable, Session, ServiceHeartbeatsTable, SecondLayerError, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcEventsTable, SbtcEventTopic, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, STREAMS_EVENT_TYPES, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, PrintEventFilterSchema, PrintEventFilter, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventsArchiveTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, EMPTY_RANGE_EVENT_INDEX_SENTINEL, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DecodedEventsTable, DecodedEventType, DeadRow, DeadLetterEventsTable, DatabaseError, Database, DEFAULT_BTC_CONFIRMATIONS, DECODED_EVENT_TYPES, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractsTable, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, Contract, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, CODE_TO_STATUS, CHAIN_TRIGGER_TYPES, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
1718
+ export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, isPox4DecoderEnabled, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getErrorMessage, getEnv, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, finalizedBurnHeight, encodeStreamsCursor, exports_ed25519 as ed25519, decodeStreamsCursor, exports_hmac as crypto, closeDb, assertDbSplit, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphResourceWarning, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, StreamsEventType, StreamsDbEventType, StreamsCursor, SessionsTable, Session, ServiceHeartbeatsTable, SecondLayerError, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcEventsTable, SbtcEventTopic, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, STREAMS_TO_DB_EVENT_TYPES, STREAMS_EVENT_TYPES, STREAMS_DB_EVENT_TYPES, SOURCE_READ_COLUMNS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, PrintEventFilterSchema, PrintEventFilter, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NumericAsText, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventsArchiveTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, EMPTY_RANGE_EVENT_INDEX_SENTINEL, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DecodedEventsTable, DecodedEventType, DeadRow, DeadLetterEventsTable, DbReadRow, DatabaseError, Database, DEFAULT_BTC_CONFIRMATIONS, DECODED_EVENT_TYPES, DB_TO_STREAMS_EVENT_TYPE, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractsTable, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, Contract, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, CODE_TO_STATUS, CHAIN_TRIGGER_TYPES, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
package/dist/src/index.js CHANGED
@@ -56,6 +56,9 @@ function getEnv() {
56
56
  cachedEnv = { ...result.data, enabledNetworks };
57
57
  return cachedEnv;
58
58
  }
59
+ function isPox4DecoderEnabled() {
60
+ return process.env.POX4_DECODER_ENABLED !== "false";
61
+ }
59
62
  // src/logger.ts
60
63
  var LOG_LEVELS = {
61
64
  debug: 0,
@@ -150,6 +153,232 @@ import { Kysely } from "kysely";
150
153
  import { PostgresJSDialect } from "kysely-postgres-js";
151
154
  import postgres from "postgres";
152
155
  import { sql as sql2 } from "kysely";
156
+
157
+ // src/db/source-read-columns.ts
158
+ var SOURCE_READ_COLUMNS = {
159
+ blocks: [
160
+ "burn_block_hash",
161
+ "burn_block_height",
162
+ "canonical",
163
+ "hash",
164
+ "height",
165
+ "parent_hash",
166
+ "timestamp"
167
+ ],
168
+ decoded_events: [
169
+ "amount",
170
+ "asset_identifier",
171
+ "block_height",
172
+ "canonical",
173
+ "contract_id",
174
+ "cursor",
175
+ "event_index",
176
+ "event_type",
177
+ "memo",
178
+ "payload",
179
+ "recipient",
180
+ "sender",
181
+ "tx_id",
182
+ "tx_index",
183
+ "value"
184
+ ],
185
+ transactions: [
186
+ "block_height",
187
+ "contract_id",
188
+ "function_args",
189
+ "function_name",
190
+ "raw_result",
191
+ "raw_tx",
192
+ "sender",
193
+ "status",
194
+ "tx_id",
195
+ "tx_index",
196
+ "type"
197
+ ],
198
+ mempool_transactions: [
199
+ "contract_id",
200
+ "function_args",
201
+ "function_name",
202
+ "raw_tx",
203
+ "received_at",
204
+ "sender",
205
+ "seq",
206
+ "tx_id",
207
+ "type"
208
+ ],
209
+ pox4_calls: [
210
+ "aggregated_amount_ustx",
211
+ "aggregated_signer_index",
212
+ "amount_ustx",
213
+ "auth_allowed",
214
+ "auth_id",
215
+ "auth_period",
216
+ "auth_topic",
217
+ "block_height",
218
+ "block_time",
219
+ "burn_block_height",
220
+ "caller",
221
+ "canonical",
222
+ "cursor",
223
+ "delegate_to",
224
+ "end_cycle",
225
+ "function_name",
226
+ "lock_period",
227
+ "max_amount",
228
+ "pox_addr_btc",
229
+ "pox_addr_hashbytes",
230
+ "pox_addr_version",
231
+ "result_ok",
232
+ "reward_cycle",
233
+ "signer_key",
234
+ "signer_signature",
235
+ "source_cursor",
236
+ "stacker",
237
+ "start_cycle",
238
+ "tx_id",
239
+ "tx_index"
240
+ ],
241
+ sbtc_events: [
242
+ "amount",
243
+ "bitcoin_txid",
244
+ "block_height",
245
+ "block_time",
246
+ "burn_hash",
247
+ "burn_height",
248
+ "canonical",
249
+ "cursor",
250
+ "event_index",
251
+ "fee",
252
+ "governance_contract_type",
253
+ "governance_new_contract",
254
+ "max_fee",
255
+ "output_index",
256
+ "recipient_btc_hashbytes",
257
+ "recipient_btc_version",
258
+ "request_id",
259
+ "sender",
260
+ "signer_address",
261
+ "signer_aggregate_pubkey",
262
+ "signer_bitmap",
263
+ "signer_keys_count",
264
+ "signer_threshold",
265
+ "sweep_txid",
266
+ "topic",
267
+ "tx_id",
268
+ "tx_index"
269
+ ],
270
+ sbtc_token_events: [
271
+ "amount",
272
+ "block_height",
273
+ "block_time",
274
+ "canonical",
275
+ "cursor",
276
+ "event_index",
277
+ "event_type",
278
+ "memo",
279
+ "recipient",
280
+ "sender",
281
+ "tx_id",
282
+ "tx_index"
283
+ ],
284
+ bns_name_events: [
285
+ "block_height",
286
+ "block_time",
287
+ "bns_id",
288
+ "canonical",
289
+ "cursor",
290
+ "event_index",
291
+ "fqn",
292
+ "hashed_salted_fqn_preorder",
293
+ "imported_at",
294
+ "name",
295
+ "namespace",
296
+ "owner",
297
+ "preordered_by",
298
+ "registered_at",
299
+ "renewal_height",
300
+ "stx_burn",
301
+ "topic",
302
+ "tx_id",
303
+ "tx_index"
304
+ ],
305
+ bns_namespace_events: [
306
+ "block_height",
307
+ "block_time",
308
+ "canonical",
309
+ "cursor",
310
+ "event_index",
311
+ "launched_at",
312
+ "lifetime",
313
+ "manager",
314
+ "manager_frozen",
315
+ "manager_transfers_disabled",
316
+ "namespace",
317
+ "price_frozen",
318
+ "price_function",
319
+ "revealed_at",
320
+ "status",
321
+ "tx_id",
322
+ "tx_index"
323
+ ],
324
+ bns_marketplace_events: [
325
+ "action",
326
+ "block_height",
327
+ "block_time",
328
+ "bns_id",
329
+ "canonical",
330
+ "commission",
331
+ "cursor",
332
+ "event_index",
333
+ "price_ustx",
334
+ "tx_id",
335
+ "tx_index"
336
+ ],
337
+ bns_names: [
338
+ "bns_id",
339
+ "fqn",
340
+ "last_event_at",
341
+ "last_event_cursor",
342
+ "name",
343
+ "namespace",
344
+ "owner",
345
+ "registered_at",
346
+ "renewal_height"
347
+ ],
348
+ bns_namespaces: [
349
+ "last_event_at",
350
+ "last_event_cursor",
351
+ "launched_at",
352
+ "lifetime",
353
+ "manager",
354
+ "manager_frozen",
355
+ "name_count",
356
+ "namespace",
357
+ "price_frozen"
358
+ ],
359
+ burn_block_rewards: [
360
+ "amount_sats",
361
+ "burn_amount",
362
+ "burn_block_hash",
363
+ "burn_block_height",
364
+ "canonical",
365
+ "cursor",
366
+ "recipient_btc",
367
+ "reward_index"
368
+ ],
369
+ burn_block_reward_slots: [
370
+ "burn_block_hash",
371
+ "burn_block_height",
372
+ "canonical",
373
+ "cursor",
374
+ "holder_btc",
375
+ "slot_index"
376
+ ],
377
+ events: ["block_height", "data", "event_index", "tx_id", "type"],
378
+ chain_reorgs: ["detected_at"]
379
+ };
380
+
381
+ // src/db/index.ts
153
382
  var DEFAULT_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
154
383
  var pools = new Map;
155
384
  var poolSeq = 0;
@@ -182,6 +411,18 @@ function resolveSourceUrl() {
182
411
  function resolveTargetUrl() {
183
412
  return process.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
184
413
  }
414
+ function assertDbSplit() {
415
+ const wantsSplit = !!(process.env.SOURCE_DATABASE_URL || process.env.TARGET_DATABASE_URL);
416
+ if (!wantsSplit)
417
+ return;
418
+ if (resolveSourceUrl() === resolveTargetUrl()) {
419
+ const msg = "DB split requested but SOURCE_DATABASE_URL === TARGET_DATABASE_URL (check for a typo or a stray DATABASE_URL fallback)";
420
+ if (false)
421
+ ;
422
+ else
423
+ console.warn(`⚠️ ${msg}`);
424
+ }
425
+ }
185
426
  function getOrCreatePool(url) {
186
427
  const existing = pools.get(url);
187
428
  if (existing) {
@@ -1212,6 +1453,48 @@ var DECODED_EVENT_TYPES = [
1212
1453
  "print"
1213
1454
  ];
1214
1455
  var STREAMS_EVENT_TYPES = DECODED_EVENT_TYPES;
1456
+ // src/db-event-types.ts
1457
+ var STREAMS_DB_EVENT_TYPES = [
1458
+ "stx_transfer_event",
1459
+ "stx_mint_event",
1460
+ "stx_burn_event",
1461
+ "stx_lock_event",
1462
+ "ft_transfer_event",
1463
+ "ft_mint_event",
1464
+ "ft_burn_event",
1465
+ "nft_transfer_event",
1466
+ "nft_mint_event",
1467
+ "nft_burn_event",
1468
+ "smart_contract_event",
1469
+ "contract_event"
1470
+ ];
1471
+ var DB_TO_STREAMS_EVENT_TYPE = {
1472
+ stx_transfer_event: "stx_transfer",
1473
+ stx_mint_event: "stx_mint",
1474
+ stx_burn_event: "stx_burn",
1475
+ stx_lock_event: "stx_lock",
1476
+ ft_transfer_event: "ft_transfer",
1477
+ ft_mint_event: "ft_mint",
1478
+ ft_burn_event: "ft_burn",
1479
+ nft_transfer_event: "nft_transfer",
1480
+ nft_mint_event: "nft_mint",
1481
+ nft_burn_event: "nft_burn",
1482
+ smart_contract_event: "print",
1483
+ contract_event: "print"
1484
+ };
1485
+ var STREAMS_TO_DB_EVENT_TYPES = {
1486
+ stx_transfer: ["stx_transfer_event"],
1487
+ stx_mint: ["stx_mint_event"],
1488
+ stx_burn: ["stx_burn_event"],
1489
+ stx_lock: ["stx_lock_event"],
1490
+ ft_transfer: ["ft_transfer_event"],
1491
+ ft_mint: ["ft_mint_event"],
1492
+ ft_burn: ["ft_burn_event"],
1493
+ nft_transfer: ["nft_transfer_event"],
1494
+ nft_mint: ["nft_mint_event"],
1495
+ nft_burn: ["nft_burn_event"],
1496
+ print: ["smart_contract_event", "contract_event"]
1497
+ };
1215
1498
  // src/finality.ts
1216
1499
  var DEFAULT_BTC_CONFIRMATIONS = 6;
1217
1500
  function finalizedBurnHeight(burnTipHeight, confirmations = DEFAULT_BTC_CONFIRMATIONS) {
@@ -1300,6 +1583,7 @@ export {
1300
1583
  parseJsonb,
1301
1584
  logger,
1302
1585
  jsonb,
1586
+ isPox4DecoderEnabled,
1303
1587
  getTargetDb,
1304
1588
  getSourceDb,
1305
1589
  getRawClientFor,
@@ -1318,6 +1602,7 @@ export {
1318
1602
  decodeStreamsCursor,
1319
1603
  exports_hmac as crypto,
1320
1604
  closeDb,
1605
+ assertDbSplit,
1321
1606
  VersionConflictError,
1322
1607
  ValidationError,
1323
1608
  UpdateSubscriptionRequestSchema,
@@ -1338,7 +1623,10 @@ export {
1338
1623
  SUBSCRIPTION_RUNTIMES,
1339
1624
  SUBSCRIPTION_FORMATS,
1340
1625
  SUBSCRIPTION_FILTER_OPERATORS,
1626
+ STREAMS_TO_DB_EVENT_TYPES,
1341
1627
  STREAMS_EVENT_TYPES,
1628
+ STREAMS_DB_EVENT_TYPES,
1629
+ SOURCE_READ_COLUMNS,
1342
1630
  ReplaySubscriptionRequestSchema,
1343
1631
  RateLimitError,
1344
1632
  PrintEventFilterSchema,
@@ -1358,6 +1646,7 @@ export {
1358
1646
  DatabaseError,
1359
1647
  DEFAULT_BTC_CONFIRMATIONS,
1360
1648
  DECODED_EVENT_TYPES,
1649
+ DB_TO_STREAMS_EVENT_TYPE,
1361
1650
  CreateSubscriptionRequestSchema,
1362
1651
  ContractDeployFilterSchema,
1363
1652
  ContractCallFilterSchema,
@@ -1367,5 +1656,5 @@ export {
1367
1656
  AuthenticationError
1368
1657
  };
1369
1658
 
1370
- //# debugId=A2EF93E9235ADDCA64756E2164756E21
1659
+ //# debugId=DA391FC32E755E3A64756E2164756E21
1371
1660
  //# sourceMappingURL=index.js.map