@secondlayer/subgraphs 4.0.5 → 4.1.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.
@@ -1714,6 +1714,167 @@ function avgEventsPerBlock(batch) {
1714
1714
  return totalEvents / batch.size;
1715
1715
  }
1716
1716
 
1717
+ // src/runtime/observer-http-source.ts
1718
+ var OBSERVER_HTTP_EXPORT_PATH = "/internal/observer-events";
1719
+ function stripTrailingSlash(url) {
1720
+ return url.replace(/\/+$/, "");
1721
+ }
1722
+ function blockTimestamp(payload) {
1723
+ for (const value of [
1724
+ payload.timestamp,
1725
+ payload.block_time,
1726
+ payload.burn_block_time,
1727
+ payload.burn_block_timestamp
1728
+ ]) {
1729
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
1730
+ return value;
1731
+ }
1732
+ }
1733
+ return 0;
1734
+ }
1735
+ function eventData(event) {
1736
+ if (typeof event.type === "string" && event.type in event) {
1737
+ return event[event.type] ?? {};
1738
+ }
1739
+ return {};
1740
+ }
1741
+ function mapNewBlockPayloadToBlockData(payload) {
1742
+ const p = payload;
1743
+ if (typeof p.block_height !== "number" || !Number.isFinite(p.block_height) || typeof p.index_block_hash !== "string" || p.index_block_hash.length === 0) {
1744
+ throw new Error("observer /new_block payload missing block_height or index_block_hash");
1745
+ }
1746
+ const height = p.block_height;
1747
+ const block = {
1748
+ height,
1749
+ hash: p.block_hash ?? "",
1750
+ parent_hash: p.parent_block_hash ?? "",
1751
+ burn_block_height: p.burn_block_height ?? 0,
1752
+ burn_block_hash: p.burn_block_hash ?? null,
1753
+ index_block_hash: p.index_block_hash,
1754
+ timestamp: blockTimestamp(p),
1755
+ canonical: true,
1756
+ created_at: new Date(0)
1757
+ };
1758
+ const txs = (p.transactions ?? []).map((tx) => {
1759
+ let contractId = null;
1760
+ let functionName = null;
1761
+ if (tx.tx_type === "contract_call" && tx.contract_call) {
1762
+ contractId = tx.contract_call.contract_id ?? null;
1763
+ functionName = tx.contract_call.function_name ?? null;
1764
+ } else if (tx.tx_type === "smart_contract" && tx.smart_contract) {
1765
+ contractId = tx.smart_contract.contract_id ?? null;
1766
+ }
1767
+ return {
1768
+ tx_id: tx.txid ?? "",
1769
+ block_height: height,
1770
+ tx_index: tx.tx_index ?? 0,
1771
+ type: tx.tx_type ?? "",
1772
+ sender: tx.sender_address ?? "",
1773
+ status: tx.status ?? "success",
1774
+ contract_id: contractId,
1775
+ function_name: functionName,
1776
+ function_args: [],
1777
+ raw_result: tx.raw_result ?? null,
1778
+ raw_tx: tx.raw_tx ?? "",
1779
+ created_at: new Date(0)
1780
+ };
1781
+ });
1782
+ const events = (p.events ?? []).map((event) => {
1783
+ const txId = event.txid ?? "";
1784
+ const eventIndex = event.event_index ?? 0;
1785
+ return {
1786
+ id: `${txId}#${eventIndex}`,
1787
+ tx_id: txId,
1788
+ block_height: height,
1789
+ event_index: eventIndex,
1790
+ type: event.type ?? "",
1791
+ data: eventData(event),
1792
+ created_at: new Date(0)
1793
+ };
1794
+ });
1795
+ return { block, txs, events };
1796
+ }
1797
+
1798
+ class ObserverHttpBlockSource {
1799
+ baseUrl;
1800
+ token;
1801
+ fetchFn;
1802
+ constructor(opts) {
1803
+ this.baseUrl = stripTrailingSlash(opts.baseUrl);
1804
+ this.token = opts.token ?? null;
1805
+ this.fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
1806
+ }
1807
+ headers() {
1808
+ if (!this.token)
1809
+ return {};
1810
+ return { Authorization: `Bearer ${this.token}` };
1811
+ }
1812
+ async getTip() {
1813
+ const res = await this.fetchFn(`${this.baseUrl}${OBSERVER_HTTP_EXPORT_PATH}/tip`, { headers: this.headers() });
1814
+ if (!res.ok) {
1815
+ throw new Error(`observer tip HTTP ${res.status}: ${await res.text().catch(() => "")}`);
1816
+ }
1817
+ let body;
1818
+ try {
1819
+ body = await res.json();
1820
+ } catch (err) {
1821
+ throw new Error(`observer tip invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
1822
+ }
1823
+ if (typeof body.block_height !== "number" || !Number.isFinite(body.block_height)) {
1824
+ throw new Error("observer tip missing block_height");
1825
+ }
1826
+ return body.block_height;
1827
+ }
1828
+ async loadBlockRange(fromHeight, toHeight) {
1829
+ const result = new Map;
1830
+ let afterHeight = fromHeight > 0 ? fromHeight - 1 : undefined;
1831
+ let afterIndexBlockHash;
1832
+ for (;; ) {
1833
+ const url = new URL(`${this.baseUrl}${OBSERVER_HTTP_EXPORT_PATH}`);
1834
+ url.searchParams.set("path", "/new_block");
1835
+ url.searchParams.set("limit", "100");
1836
+ if (afterHeight != null) {
1837
+ url.searchParams.set("after_height", String(afterHeight));
1838
+ }
1839
+ if (afterIndexBlockHash) {
1840
+ url.searchParams.set("after_index_block_hash", afterIndexBlockHash);
1841
+ }
1842
+ const res = await this.fetchFn(url.toString(), {
1843
+ headers: this.headers()
1844
+ });
1845
+ if (!res.ok) {
1846
+ throw new Error(`observer events HTTP ${res.status}: ${await res.text().catch(() => "")}`);
1847
+ }
1848
+ let body;
1849
+ try {
1850
+ body = await res.json();
1851
+ } catch (err) {
1852
+ throw new Error(`observer events invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
1853
+ }
1854
+ let pastTo = false;
1855
+ for (const message of body.events ?? []) {
1856
+ if (message.path === "/new_burn_block")
1857
+ continue;
1858
+ const height = message.payload?.block_height;
1859
+ if (typeof height === "number" && height > toHeight) {
1860
+ pastTo = true;
1861
+ break;
1862
+ }
1863
+ const data = mapNewBlockPayloadToBlockData(message.payload);
1864
+ const h = data.block.height;
1865
+ if (h >= fromHeight && h <= toHeight) {
1866
+ result.set(h, data);
1867
+ }
1868
+ }
1869
+ if (pastTo || body.next == null)
1870
+ break;
1871
+ afterHeight = body.next.after_height;
1872
+ afterIndexBlockHash = body.next.after_index_block_hash;
1873
+ }
1874
+ return result;
1875
+ }
1876
+ }
1877
+
1717
1878
  // src/runtime/reconstruct.ts
1718
1879
  function isoToUnixSeconds(iso) {
1719
1880
  if (!iso)
@@ -2027,6 +2188,16 @@ function buildHttpClient() {
2027
2188
  return createInternalIndexHttpClient();
2028
2189
  }
2029
2190
  function resolveBlockSource(subgraph) {
2191
+ if (process.env.SUBGRAPH_SOURCE === "observer-http") {
2192
+ const baseUrl = process.env.OBSERVER_HTTP_URL;
2193
+ if (!baseUrl) {
2194
+ throw new Error("SUBGRAPH_SOURCE=observer-http requires OBSERVER_HTTP_URL");
2195
+ }
2196
+ return new ObserverHttpBlockSource({
2197
+ baseUrl,
2198
+ token: process.env.OBSERVER_HTTP_EXPORT_TOKEN || null
2199
+ });
2200
+ }
2030
2201
  if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph && isStreamsIndexEligible(subgraph)) {
2031
2202
  return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph), canSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined, needsTransactionData(subgraph)), postgresBlockSource);
2032
2203
  }
@@ -4410,5 +4581,5 @@ var shutdown = async () => {
4410
4581
  process.on("SIGINT", shutdown);
4411
4582
  process.on("SIGTERM", shutdown);
4412
4583
 
4413
- //# debugId=1C46E62809A182EC64756E2164756E21
4584
+ //# debugId=558E953FA1762C2B64756E2164756E21
4414
4585
  //# sourceMappingURL=service.js.map