@secondlayer/subgraphs 3.15.2 → 3.17.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.
@@ -434,11 +434,17 @@ type IsOptionalColumn<C> = C extends {
434
434
  default: string | number | boolean
435
435
  } ? true : false;
436
436
  /**
437
+ * Like `InferColumnType` but for WRITE inputs: numeric (`uint`/`int`) columns
438
+ * also accept a plain `number` (the runtime coerces to bigint). Reads stay
439
+ * strict `bigint` via `InferColumnType`, so handlers still get exact types back.
440
+ */
441
+ type WriteColumnType<C extends SubgraphColumn> = C["type"] extends "uint" | "int" ? C["nullable"] extends true ? bigint | number | null : bigint | number : InferColumnType<C>;
442
+ /**
437
443
  * Row shape accepted by `ctx.insert`. System columns (`_id`, `_blockHeight`,
438
444
  * `_txId`, `_createdAt`) are omitted — the runtime adds them. Nullable and
439
445
  * defaulted columns are optional; all others required.
440
446
  */
441
- type WriteRow<T extends SubgraphTable> = { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? never : K] : InferColumnType<T["columns"][K]> } & { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? K : never]? : InferColumnType<T["columns"][K]> };
447
+ type WriteRow<T extends SubgraphTable> = { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? never : K] : WriteColumnType<T["columns"][K]> } & { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? K : never]? : WriteColumnType<T["columns"][K]> };
442
448
  /** Computed-or-value row for `patchOrInsert` — each field may be a function of the existing row. */
443
449
  type PatchRow<T extends SubgraphTable> = { [K in keyof WriteRow<T>]? : WriteRow<T>[K] | ((existing: InferTableRow<T> | null) => unknown) };
444
450
  type TableName<S extends SubgraphSchema> = keyof S & string;
@@ -466,10 +472,20 @@ interface TypedSubgraphContext<S extends SubgraphSchema> {
466
472
  tx: TxMeta;
467
473
  insert<T extends TableName<S>>(table: T, row: WriteRow<S[T]>): void;
468
474
  update<T extends TableName<S>>(table: T, where: RowWhere<S, T>, set: Partial<WriteRow<S[T]>>): void;
469
- upsert<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, row: WriteRow<S[T]>): void;
475
+ upsert<
476
+ T extends TableName<S>,
477
+ K extends Partial<WriteRow<S[T]>>
478
+ >(table: T, key: K, row: Omit<WriteRow<S[T]>, keyof K> & Partial<WriteRow<S[T]>>): void;
470
479
  delete<T extends TableName<S>>(table: T, where: RowWhere<S, T>): void;
471
480
  patch<T extends TableName<S>>(table: T, where: RowWhere<S, T>, set: Partial<WriteRow<S[T]>>): void;
472
481
  patchOrInsert<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, row: PatchRow<S[T]> & Record<string, ComputedValue>): Promise<void>;
482
+ /**
483
+ * Atomic accumulator — `INSERT … ON CONFLICT (key) DO UPDATE SET col =
484
+ * COALESCE(col,0) + delta`. Deltas commute, so it's the reorg-safe primitive
485
+ * for running totals (per-cycle aggregates, balances). Requires a `uniqueKeys`
486
+ * constraint matching `key`; deltas may be `number` or `bigint`.
487
+ */
488
+ increment<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, deltas: Partial<Record<ColumnName<S, T>, bigint | number>>): void;
473
489
  findOne<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]> | null>;
474
490
  findMany<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]>[]>;
475
491
  formatUnits(value: bigint, decimals: number): string;
package/dist/src/index.js CHANGED
@@ -1433,7 +1433,9 @@ import { sql as sql3 } from "kysely";
1433
1433
 
1434
1434
  // src/runtime/block-source.ts
1435
1435
  import { getSourceDb } from "@secondlayer/shared/db";
1436
- import { IndexHttpClient } from "@secondlayer/shared/index-http";
1436
+ import {
1437
+ IndexHttpClient
1438
+ } from "@secondlayer/shared/index-http";
1437
1439
  import { logger as logger3 } from "@secondlayer/shared/logger";
1438
1440
 
1439
1441
  // src/runtime/batch-loader.ts
@@ -1512,6 +1514,22 @@ function reconstructTransaction(t) {
1512
1514
  created_at: new Date(0)
1513
1515
  };
1514
1516
  }
1517
+ function reconstructTxFromEventRow(e) {
1518
+ return {
1519
+ tx_id: e.tx_id,
1520
+ block_height: e.block_height,
1521
+ tx_index: e.tx_index ?? 0,
1522
+ type: e.tx_type ?? "",
1523
+ sender: e.tx_sender ?? "",
1524
+ status: e.tx_status ?? "success",
1525
+ contract_id: e.tx_contract_id ?? null,
1526
+ function_name: e.tx_function_name ?? null,
1527
+ function_args: [],
1528
+ raw_result: null,
1529
+ raw_tx: "",
1530
+ created_at: new Date(0)
1531
+ };
1532
+ }
1515
1533
  function reconstructEvent(e) {
1516
1534
  const base = {
1517
1535
  id: `${e.tx_id}#${e.event_index}`,
@@ -1637,6 +1655,17 @@ function sourceFilters(subgraph) {
1637
1655
  const sources = subgraph.sources;
1638
1656
  return Array.isArray(sources) ? sources : Object.values(sources);
1639
1657
  }
1658
+ function needsTransactionData(subgraph) {
1659
+ return sourceFilters(subgraph).some((f) => TX_SOURCE_TYPES.has(f.type));
1660
+ }
1661
+ function synthesizeTxsFromEvents(events) {
1662
+ const byId = new Map;
1663
+ for (const e of events) {
1664
+ if (!byId.has(e.tx_id))
1665
+ byId.set(e.tx_id, reconstructTxFromEventRow(e));
1666
+ }
1667
+ return [...byId.values()];
1668
+ }
1640
1669
  function indexEventTypesForFilterTypes(filterTypes) {
1641
1670
  if (filterTypes.some((t) => TX_SOURCE_TYPES.has(t))) {
1642
1671
  return ALL_INDEX_EVENT_TYPES;
@@ -1670,10 +1699,12 @@ class PublicApiBlockSource {
1670
1699
  http;
1671
1700
  eventTypes;
1672
1701
  probeTargets;
1673
- constructor(http, eventTypes, probeTargets) {
1702
+ needsTransactions;
1703
+ constructor(http, eventTypes, probeTargets, needsTransactions = true) {
1674
1704
  this.http = http;
1675
1705
  this.eventTypes = eventTypes;
1676
1706
  this.probeTargets = probeTargets;
1707
+ this.needsTransactions = needsTransactions;
1677
1708
  }
1678
1709
  async nextDataHeight(afterHeight, untilHeight) {
1679
1710
  if (!this.probeTargets?.length)
@@ -1686,10 +1717,11 @@ class PublicApiBlockSource {
1686
1717
  return this.http.getIndexTip();
1687
1718
  }
1688
1719
  async loadBlockRange(fromHeight, toHeight) {
1689
- const [blocks, txs, eventLists] = await Promise.all([
1720
+ const withTx = !this.needsTransactions;
1721
+ const [blocks, txRows, eventLists] = await Promise.all([
1690
1722
  this.http.walkBlocks(fromHeight, toHeight),
1691
- this.http.walkTransactions(fromHeight, toHeight),
1692
- Promise.all(this.eventTypes.map((t) => this.http.walkEvents(t, fromHeight, toHeight)))
1723
+ this.needsTransactions ? this.http.walkTransactions(fromHeight, toHeight) : Promise.resolve([]),
1724
+ Promise.all(this.eventTypes.map((t) => this.http.walkEvents(t, fromHeight, toHeight, withTx)))
1693
1725
  ]);
1694
1726
  const map = new Map;
1695
1727
  for (const b of blocks) {
@@ -1699,8 +1731,9 @@ class PublicApiBlockSource {
1699
1731
  events: []
1700
1732
  });
1701
1733
  }
1734
+ const txs = this.needsTransactions ? txRows.map(reconstructTransaction) : synthesizeTxsFromEvents(eventLists.flat());
1702
1735
  for (const t of txs) {
1703
- map.get(t.block_height)?.txs.push(reconstructTransaction(t));
1736
+ map.get(t.block_height)?.txs.push(t);
1704
1737
  }
1705
1738
  for (const list of eventLists) {
1706
1739
  for (const e of list) {
@@ -1765,7 +1798,7 @@ function buildHttpClient() {
1765
1798
  }
1766
1799
  function resolveBlockSource(subgraph) {
1767
1800
  if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph && isStreamsIndexEligible(subgraph)) {
1768
- return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph), canSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined), postgresBlockSource);
1801
+ return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph), canSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined, needsTransactionData(subgraph)), postgresBlockSource);
1769
1802
  }
1770
1803
  if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph) {
1771
1804
  logger3.debug("Subgraph not streams-index eligible, using DB tap", {
@@ -4037,5 +4070,5 @@ export {
4037
4070
  ByoBreakingChangeError
4038
4071
  };
4039
4072
 
4040
- //# debugId=D13A7E4F60723ACE64756E2164756E21
4073
+ //# debugId=F6E8980AB9FF4A2864756E2164756E21
4041
4074
  //# sourceMappingURL=index.js.map