envio 3.15.0-subgraph → 3.16.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.
Files changed (186) hide show
  1. package/README.md +40 -34
  2. package/evm.schema.json +3 -3
  3. package/fuel.schema.json +2 -2
  4. package/index.d.ts +3 -3
  5. package/licenses/README.md +1 -1
  6. package/package.json +9 -10
  7. package/src/Batch.res.mjs +5 -5
  8. package/src/BatchProcessing.res +1 -0
  9. package/src/BatchProcessing.res.mjs +1 -0
  10. package/src/Bin.res +0 -7
  11. package/src/Bin.res.mjs +0 -8
  12. package/src/ChainFetching.res +17 -456
  13. package/src/ChainFetching.res.mjs +33 -404
  14. package/src/ChainState.res +48 -83
  15. package/src/ChainState.res.mjs +83 -115
  16. package/src/ChainState.resi +0 -26
  17. package/src/Clock.res +57 -0
  18. package/src/Clock.res.mjs +72 -0
  19. package/src/Config.res +7 -16
  20. package/src/Config.res.mjs +4 -11
  21. package/src/ContractRegisterContext.res +6 -3
  22. package/src/ContractRegisterContext.res.mjs +2 -4
  23. package/src/Core.res +5 -136
  24. package/src/Core.res.mjs +1 -90
  25. package/src/CrossChainState.res +2 -8
  26. package/src/CrossChainState.res.mjs +3 -3
  27. package/src/Ecosystem.res +4 -7
  28. package/src/Ecosystem.res.mjs +8 -8
  29. package/src/EffectState.res +10 -2
  30. package/src/EffectState.res.mjs +8 -4
  31. package/src/EffectState.resi +3 -1
  32. package/src/EntityId.res +2 -7
  33. package/src/EntityId.res.mjs +1 -8
  34. package/src/EntityTables.res +4 -1
  35. package/src/EntityTables.res.mjs +1 -1
  36. package/src/Env.res +0 -16
  37. package/src/Env.res.mjs +0 -11
  38. package/src/EventProcessing.res +1 -38
  39. package/src/EventProcessing.res.mjs +1 -28
  40. package/src/FetchState.res +160 -319
  41. package/src/FetchState.res.mjs +182 -292
  42. package/src/FinalizeBackfill.res +2 -4
  43. package/src/FinalizeBackfill.res.mjs +3 -4
  44. package/src/HandlerLoader.res +15 -39
  45. package/src/HandlerLoader.res.mjs +8 -27
  46. package/src/HandlerRegister.res +0 -4
  47. package/src/HandlerRegister.res.mjs +2 -5
  48. package/src/HandlerRegister.resi +0 -2
  49. package/src/InMemoryTable.res +17 -16
  50. package/src/InMemoryTable.res.mjs +14 -15
  51. package/src/IndexerState.res +28 -4
  52. package/src/IndexerState.res.mjs +19 -6
  53. package/src/IndexerState.resi +4 -0
  54. package/src/Internal.res +0 -110
  55. package/src/Internal.res.mjs +1 -115
  56. package/src/LoadLayer.res +21 -47
  57. package/src/LoadLayer.res.mjs +47 -72
  58. package/src/LoadLayer.resi +0 -26
  59. package/src/Main.res +1 -14
  60. package/src/Main.res.mjs +3 -4
  61. package/src/Persistence.res +3 -23
  62. package/src/Persistence.res.mjs +3 -3
  63. package/src/Rollback.res +0 -1
  64. package/src/Rollback.res.mjs +1 -1
  65. package/src/RunScope.res +0 -3
  66. package/src/SafeCheckpointTracking.res +4 -4
  67. package/src/SafeCheckpointTracking.res.mjs +1 -1
  68. package/src/SimulateItems.res +26 -42
  69. package/src/SimulateItems.res.mjs +16 -40
  70. package/src/StagedRows.res +106 -0
  71. package/src/StagedRows.res.mjs +102 -0
  72. package/src/Staging.res +32 -14
  73. package/src/Staging.res.mjs +17 -20
  74. package/src/Storage.res +277 -998
  75. package/src/Storage.res.mjs +216 -731
  76. package/src/Supervisor.res +75 -56
  77. package/src/Supervisor.res.mjs +55 -26
  78. package/src/TestIndexer.res +22 -27
  79. package/src/TestIndexer.res.mjs +20 -17
  80. package/src/Throttler.res +15 -8
  81. package/src/Throttler.res.mjs +9 -6
  82. package/src/Throttler.resi +1 -1
  83. package/src/UserContext.res +46 -410
  84. package/src/UserContext.res.mjs +30 -318
  85. package/src/Utils.res +0 -23
  86. package/src/Utils.res.mjs +1 -17
  87. package/src/Writing.res +0 -1
  88. package/src/Writing.res.mjs +1 -1
  89. package/src/bindings/ClickHouse.res +0 -322
  90. package/src/bindings/ClickHouse.res.mjs +0 -338
  91. package/src/bindings/StorageClient.res +107 -175
  92. package/src/bindings/StorageClient.res.mjs +19 -8
  93. package/src/bindings/Vitest.res +0 -26
  94. package/src/bindings/Vitest.res.mjs +0 -3
  95. package/src/db/Table.res +24 -150
  96. package/src/db/Table.res.mjs +38 -272
  97. package/src/sources/AddressSet.res +0 -2
  98. package/src/sources/AddressStore.res +0 -3
  99. package/src/sources/ChainSources.res +2 -0
  100. package/src/sources/ChainSources.res.mjs +2 -2
  101. package/src/sources/EvmChain.res +4 -7
  102. package/src/sources/EvmChain.res.mjs +5 -4
  103. package/src/sources/EvmHyperSyncSource.res +2 -2
  104. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  105. package/src/sources/EvmRpcClient.res +13 -3
  106. package/src/sources/EvmRpcClient.res.mjs +4 -3
  107. package/src/sources/EvmRpcWs.res +4 -3
  108. package/src/sources/EvmRpcWs.res.mjs +2 -2
  109. package/src/sources/HeightFeed.res +31 -10
  110. package/src/sources/HeightFeed.res.mjs +10 -6
  111. package/src/sources/HeightStream.res +32 -17
  112. package/src/sources/HeightStream.res.mjs +10 -10
  113. package/src/sources/HyperSync.res +1 -2
  114. package/src/sources/HyperSync.res.mjs +1 -2
  115. package/src/sources/HyperSyncSSE.res +4 -6
  116. package/src/sources/HyperSyncSSE.res.mjs +2 -2
  117. package/src/sources/RpcSource.res +10 -1
  118. package/src/sources/RpcSource.res.mjs +4 -3
  119. package/src/sources/Source.res +3 -0
  120. package/src/sources/SourceManager.res +85 -104
  121. package/src/sources/SourceManager.res.mjs +18 -37
  122. package/src/sources/SourceManager.resi +3 -5
  123. package/src/sources/StartBlockResolver.res +1 -0
  124. package/src/sources/StartBlockResolver.res.mjs +4 -3
  125. package/src/sources/SvmHyperSyncSource.res +2 -2
  126. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  127. package/svm.schema.json +3 -3
  128. package/src/EffectCacheLookup.res +0 -98
  129. package/src/EffectCacheLookup.res.mjs +0 -116
  130. package/src/PgWriting.res +0 -36
  131. package/src/PgWriting.res.mjs +0 -34
  132. package/src/PreloadLookahead.res +0 -184
  133. package/src/PreloadLookahead.res.mjs +0 -197
  134. package/src/SubgraphLog.res +0 -19
  135. package/src/SubgraphLog.res.mjs +0 -26
  136. package/src/SyncWrites.res +0 -101
  137. package/src/SyncWrites.res.mjs +0 -98
  138. package/src/db/IndexDefinition.res +0 -47
  139. package/src/db/IndexDefinition.res.mjs +0 -60
  140. package/src/sources/CallSource.res +0 -274
  141. package/src/sources/CallSource.res.mjs +0 -196
  142. package/src/subgraph/abi-types.ts +0 -84
  143. package/src/subgraph/aggregations.ts +0 -745
  144. package/src/subgraph/as-package.ts +0 -143
  145. package/src/subgraph/assemblyscript-regex.ts +0 -67
  146. package/src/subgraph/assemblyscript.ts +0 -731
  147. package/src/subgraph/blocks.ts +0 -398
  148. package/src/subgraph/calls-source.ts +0 -702
  149. package/src/subgraph/calls.ts +0 -258
  150. package/src/subgraph/conformance.ts +0 -106
  151. package/src/subgraph/errors.ts +0 -85
  152. package/src/subgraph/graft.ts +0 -73
  153. package/src/subgraph/graph-cli-worker.mjs +0 -35
  154. package/src/subgraph/graph-cli.ts +0 -900
  155. package/src/subgraph/graph-node-decimal.ts +0 -199
  156. package/src/subgraph/graph-ts-enums.ts +0 -28
  157. package/src/subgraph/graph-ts-types/VERSION +0 -2
  158. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
  159. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
  160. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
  161. package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
  162. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
  163. package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
  164. package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
  165. package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
  166. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  167. package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
  168. package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
  169. package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
  170. package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
  171. package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
  172. package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
  173. package/src/subgraph/graph-ts-types/index.d.ts +0 -102
  174. package/src/subgraph/graph-ts.ts +0 -4280
  175. package/src/subgraph/hosts.ts +0 -554
  176. package/src/subgraph/log.ts +0 -28
  177. package/src/subgraph/receipts.ts +0 -184
  178. package/src/subgraph/register-slots.ts +0 -93
  179. package/src/subgraph/rollup.ts +0 -109
  180. package/src/subgraph/rpc.ts +0 -337
  181. package/src/subgraph/runtime.ts +0 -2060
  182. package/src/subgraph/scope.ts +0 -177
  183. package/src/subgraph/stats.ts +0 -42
  184. package/src/subgraph/template-instances.ts +0 -66
  185. package/src/subgraph/toolchain.ts +0 -327
  186. package/src/subgraph/transient.ts +0 -176
@@ -1,258 +0,0 @@
1
- /**
2
- * `Contract.bind(x).foo()` -> an envio effect, encoded and decoded with
3
- * alloy, as graph-node does.
4
- *
5
- * graph-node evaluates a mapping's contract calls against the block the event
6
- * came from, so the block number is part of the effect's input — and therefore
7
- * of its cache key, which is what makes a cached call safe to reuse.
8
- */
9
-
10
- import * as Sury from "rescript-schema";
11
- import { subgraphAbiDecode, subgraphAbiEncodeCall } from "../Core.res.mjs";
12
- import { createEffect } from "../Envio.res.mjs";
13
- import { missingRpcMessage } from "./errors.ts";
14
- import { rpcClient } from "./rpc.ts";
15
- import { parseSignature } from "./abi-types.ts";
16
- import { isRevert, untilAnswered } from "./transient.ts";
17
- import { info } from "./log.ts";
18
-
19
- export type CallInput = {
20
- chainId: number;
21
- address: string;
22
- signature: string;
23
- args: unknown[];
24
- blockNumber: number;
25
- };
26
-
27
- export type CallOutput = {
28
- reverted: boolean;
29
- values: unknown[] | null;
30
- };
31
-
32
- /**
33
- * A batch commits only once every contract call its handlers make is in, and a
34
- * call-heavy backfill's first batch can wait minutes on thousands of them with
35
- * nothing else to show, which reads as a hang. While calls are
36
- * outstanding, how many were answered is logged now and then.
37
- */
38
- const progress = { started: 0, answered: 0, reportedAnswered: 0, timer: undefined as NodeJS.Timeout | undefined };
39
-
40
- function progressIntervalMs(): number {
41
- const value = Number(process.env.ENVIO_SUBGRAPH_PROGRESS_LOG_MS);
42
- return Number.isFinite(value) && value > 0 ? value : 30_000;
43
- }
44
-
45
- function reportProgress() {
46
- const waiting = progress.started - progress.answered;
47
- if (waiting <= 0) {
48
- clearInterval(progress.timer);
49
- progress.timer = undefined;
50
- return;
51
- }
52
- const interval = progressIntervalMs();
53
- const span = interval >= 1000 ? `${Math.round(interval / 1000)}s` : `${interval}ms`;
54
- info(
55
- `Envio Subgraph: ${progress.answered - progress.reportedAnswered} contract calls answered in the last ` +
56
- `${span}, ${waiting} waiting. The batch is written once its handlers' calls are all in.`,
57
- );
58
- progress.reportedAnswered = progress.answered;
59
- }
60
-
61
- function trackCall<T>(call: Promise<T>): Promise<T> {
62
- progress.started++;
63
- if (!progress.timer) {
64
- progress.timer = setInterval(reportProgress, progressIntervalMs());
65
- progress.timer.unref();
66
- }
67
- const settle = () => {
68
- progress.answered++;
69
- };
70
- call.then(settle, settle);
71
- return call;
72
- }
73
-
74
- /**
75
- * Functions whose answer a contract does not change once it has given one that
76
- * isn't empty: token metadata, a pair's tokens, a registry's factory. A mapping
77
- * asks them again at every block it handles (a token's `decimals()` on every
78
- * swap of every pair that holds it, a factory's `getPair(a, b)` on every sync)
79
- * and the effect cache keys a call by block, so each ask was an RPC request.
80
- * Once one has been answered at block B with a value, any block from B on gets
81
- * that value without a request. Only a non-empty answer counts: a zero address
82
- * or an empty string is "not there yet" (`getPair` before the pair exists,
83
- * `symbol()` before the token is deployed), and a revert is never shared.
84
- * A proxy that changes its `name()` later is the one case this gets wrong;
85
- * ENVIO_SUBGRAPH_EXACT_CALLS=1 asks every call at its own block instead.
86
- */
87
- export const STABLE_FUNCTIONS = new Set([
88
- "name",
89
- "symbol",
90
- "decimals",
91
- "NAME",
92
- "SYMBOL",
93
- "DECIMALS",
94
- "token0",
95
- "token1",
96
- "factory",
97
- "getPair",
98
- "comptroller",
99
- "underlying",
100
- ]);
101
-
102
- type Shared = { block: number; output: string };
103
-
104
- /** The call without its block: what stays true from the block it was first answered at. */
105
- function stableKey(input: CallInput): string | undefined {
106
- if (process.env.ENVIO_SUBGRAPH_EXACT_CALLS === "1") return undefined;
107
- if (!STABLE_FUNCTIONS.has(parseSignature(input.signature).name)) return undefined;
108
- // An address argument is the same one whatever its checksum casing.
109
- const args = input.args.map((arg) => (/^s:0x[0-9a-fA-F]*$/.test(String(arg)) ? String(arg).toLowerCase() : arg));
110
- return JSON.stringify([input.chainId, input.address.toLowerCase(), input.signature, args]);
111
- }
112
-
113
- const sharedAnswers = new Map<string, Shared>();
114
- const sharedInFlight = new Map<string, { block: number; settled: Promise<void> }>();
115
- const SHARED_ANSWERS_LIMIT = 200_000;
116
-
117
- /** Reset between test indexers, which each bring their own chain. */
118
- export function resetSharedCalls() {
119
- sharedAnswers.clear();
120
- sharedInFlight.clear();
121
- }
122
-
123
- function remember(key: string, block: number, output: string) {
124
- const answer = JSON.parse(output) as CallOutput;
125
- // A zero address or an empty string is "not there yet"; a revert says nothing.
126
- const empty = (answer.values ?? []).every((v) => typeof v === "string" && /^s:(0x0*)?$/i.test(v));
127
- if (answer.reverted || !answer.values || empty) return;
128
- const earlier = sharedAnswers.get(key);
129
- if (earlier && earlier.block <= block) return;
130
- if (sharedAnswers.size >= SHARED_ANSWERS_LIMIT) sharedAnswers.clear();
131
- sharedAnswers.set(key, { block, output });
132
- }
133
-
134
- /**
135
- * A stable function's answer from an earlier block, one still being asked for
136
- * (waited on, then reused if it turns out to be a value), or `ask`.
137
- */
138
- export async function shareAcrossBlocks(input: CallInput, ask: () => Promise<string>): Promise<string> {
139
- const key = stableKey(input);
140
- if (key === undefined) return ask();
141
- const known = sharedAnswers.get(key);
142
- if (known && known.block <= input.blockNumber) return known.output;
143
-
144
- const running = sharedInFlight.get(key);
145
- if (running && running.block <= input.blockNumber) {
146
- await running.settled;
147
- const after = sharedAnswers.get(key);
148
- if (after && after.block <= input.blockNumber) return after.output;
149
- }
150
-
151
- const asked = ask();
152
- const entry = { block: input.blockNumber, settled: asked.then(() => undefined, () => undefined) };
153
- if (!sharedInFlight.has(key) || sharedInFlight.get(key)!.block > input.blockNumber) {
154
- sharedInFlight.set(key, entry);
155
- }
156
- try {
157
- const output = await asked;
158
- remember(key, input.blockNumber, output);
159
- return output;
160
- } finally {
161
- if (sharedInFlight.get(key) === entry) sharedInFlight.delete(key);
162
- }
163
- }
164
-
165
- /** An argument as the addon reads it: an integer as its decimal string. */
166
- function jsonArg(value: unknown): unknown {
167
- if (typeof value === "bigint") return value.toString();
168
- if (Array.isArray(value)) return value.map(jsonArg);
169
- return value;
170
- }
171
-
172
- const hexBytes = (hex: string) => Buffer.from(hex.replace(/^0x/, ""), "hex");
173
-
174
- async function askNode(rpcUrls: string[], input: CallInput): Promise<string> {
175
- const { name, inputs, outputs } = parseSignature(input.signature);
176
- const data = subgraphAbiEncodeCall(name, `(${inputs})`, input.args.map(decodeArg).map(jsonArg));
177
-
178
- const result = await trackCall(
179
- untilAnswered(
180
- `${input.signature} on ${input.address} at block ${input.blockNumber}`,
181
- async () => {
182
- try {
183
- return await rpcClient(rpcUrls).call({ to: input.address, data, blockNumber: input.blockNumber });
184
- } catch (error) {
185
- if (isRevert(error)) return null;
186
- throw error;
187
- }
188
- },
189
- { deadline: false },
190
- ),
191
- );
192
- if (result === null) {
193
- return JSON.stringify({ reverted: true, values: null });
194
- }
195
-
196
- try {
197
- // graph-ts returns one `ethereum.Value` per ABI output. A single
198
- // tuple/struct is therefore `[tuple]`, not the flattened fields —
199
- // generated bindings call `result[0].toTuple()`.
200
- const values = subgraphAbiDecode(`(${outputs})`, hexBytes(result), true) as unknown[];
201
- return JSON.stringify({ reverted: false, values: values.map(encodeArg) });
202
- } catch {
203
- // Output the declared signature can't decode counts as a failed call,
204
- // which is what lets a mapping retry through a different ABI — the
205
- // bytes32-vs-string ERC20 name is the case every token subgraph hits. A
206
- // function answering no bytes at all is the same: the account has no code.
207
- return JSON.stringify({ reverted: true, values: null });
208
- }
209
- }
210
-
211
- export function makeCallEffect(rpcUrls: string[], recall: (encoded: string) => string | undefined = () => undefined) {
212
- return createEffect(
213
- {
214
- name: "envio_subgraph_eth_call",
215
- // Both sides travel as JSON text: the cache key is then the exact call
216
- // description, and the cached row is readable.
217
- input: Sury.string,
218
- output: Sury.string,
219
- rateLimit: false,
220
- cache: true,
221
- crossChain: false,
222
- },
223
- async ({ input: encoded }: { input: string }) => {
224
- // The register pass asked the same question at fetch time; its answer
225
- // is the same one, and asking twice doubled a factory's calls.
226
- const recalled = recall(encoded);
227
- if (recalled !== undefined) return recalled;
228
- const input = JSON.parse(encoded) as CallInput;
229
- if (rpcUrls.length === 0) {
230
- throw new Error(missingRpcMessage(input.signature));
231
- }
232
- return shareAcrossBlocks(input, () => askNode(rpcUrls, input));
233
- },
234
- );
235
- }
236
-
237
- /** Effect inputs/outputs travel as strings, tagged so the type survives. */
238
- export function encodeArg(value: unknown): string {
239
- if (typeof value === "bigint") return `i:${value.toString()}`;
240
- if (typeof value === "boolean") return `b:${value ? "1" : "0"}`;
241
- if (Array.isArray(value)) return `a:${JSON.stringify(value.map(encodeArg))}`;
242
- return `s:${String(value)}`;
243
- }
244
-
245
- export function decodeArg(value: string): unknown {
246
- const tag = value.slice(0, 2);
247
- const body = value.slice(2);
248
- switch (tag) {
249
- case "i:":
250
- return BigInt(body);
251
- case "b:":
252
- return body === "1";
253
- case "a:":
254
- return (JSON.parse(body) as string[]).map(decodeArg);
255
- default:
256
- return body;
257
- }
258
- }
@@ -1,106 +0,0 @@
1
- /**
2
- * The shim, checked against the types a subgraph developer codes against.
3
- *
4
- * A subgraph's mappings are type-checked by `asc` against
5
- * `@graphprotocol/graph-ts`, and then run by this shim. Nothing else makes the
6
- * two agree, so a gap shows up as green types and a runtime error — the worst
7
- * feedback loop there is. This file closes it.
8
- *
9
- * The declarations come from the real package (see
10
- * `scripts/generate-graph-ts-types.mjs`). Every export is walked, and within
11
- * each class and namespace every static and every instance member, so a gap is
12
- * named down to the member — `ethereum.Value.fromAddress` — rather than hidden
13
- * behind a suppression covering a whole namespace. This file is type-checked,
14
- * never run.
15
- */
16
-
17
- import type * as GraphTs from "./graph-ts-types/index.js";
18
- import type * as Shim from "./graph-ts.ts";
19
-
20
- /** A class's statics: a mapped type drops the construct signature (see `Constructs`). */
21
- type Statics<T> = { [K in keyof T as K extends "prototype" ? never : K]: T[K] };
22
-
23
- type Agrees<Real, Ours, Path extends string> = [Ours] extends [Real] ? never : Path;
24
-
25
- /**
26
- * A public constructor the shim's has to accept, named `Path()` — a mapping
27
- * can build an `ethereum.Event` itself. A protected one isn't a construct
28
- * signature, so it is never compared.
29
- */
30
- type Constructs<Real, Ours, Path extends string> = [Real] extends [abstract new (...args: infer Args) => any]
31
- ? [Ours] extends [abstract new (...args: infer OursArgs) => any]
32
- ? // By arity: a shorter parameter list is assignable to a longer one, and
33
- // would take the arguments a mapping passes without a word. The types
34
- // themselves can't be compared this way round — graph-ts' `BigInt` is a
35
- // `Uint8Array`, the shim's isn't — and the members already are.
36
- number extends OursArgs["length"]
37
- ? never
38
- : OursArgs["length"] extends Args["length"]
39
- ? never
40
- : `${Path}()`
41
- : `${Path}()`
42
- : never;
43
-
44
- /**
45
- * Deep enough to reach `ethereum.Value.fromAddress`, and no deeper: a member
46
- * past that is compared whole, which still catches any disagreement inside it.
47
- */
48
- type Member<Real, Ours, Path extends string, Depth extends unknown[]> = Depth["length"] extends 2
49
- ? Agrees<Real, Ours, Path>
50
- : // `any` would take every branch below at once.
51
- 0 extends 1 & Real
52
- ? Agrees<Real, Ours, Path>
53
- : // Bracketed so a union — an enum, `boolean` — is compared whole.
54
- [Real] extends [(...args: any) => any]
55
- ? Agrees<Real, Ours, Path>
56
- : // A class, even one whose constructor is protected.
57
- [Real] extends [{ prototype: infer RealInstance }]
58
- ? [Ours] extends [{ prototype: infer OursInstance }]
59
- ?
60
- | Constructs<Real, Ours, Path>
61
- | Gaps<Statics<Real>, Statics<Ours>, `${Path}.`, [...Depth, unknown]>
62
- | Gaps<RealInstance, OursInstance, `${Path}#`, [...Depth, unknown]>
63
- : Path
64
- : [Real] extends [object]
65
- ? Gaps<Real, Ours, `${Path}.`, [...Depth, unknown]>
66
- : Agrees<Real, Ours, Path>;
67
-
68
- /** Where `Ours` lacks or disagrees with `Real`, by path. */
69
- type Gaps<Real, Ours, Path extends string, Depth extends unknown[] = []> = {
70
- [K in keyof Real & string]-?: K extends keyof Ours
71
- ? Member<Real[K], Ours[K], `${Path}${K}`, Depth>
72
- : `${Path}${K}`;
73
- }[keyof Real & string];
74
-
75
- type Found = Gaps<typeof GraphTs, typeof Shim, "">;
76
-
77
- /** Every gap the shim knows it has, and why. */
78
- type KnownGap =
79
- // Chains envio doesn't index in subgraph mode: their namespaces refuse a read.
80
- | "arweave.Block"
81
- | "arweave.ProofOfAccess"
82
- | "arweave.Tag"
83
- | "arweave.Transaction"
84
- | "arweave.TransactionWithBlockPtr"
85
- // Refused at runtime: a YAML parser isn't shipped with the shim.
86
- | `yaml.${string}`
87
- | `YAMLValue${string}`
88
- | `YAMLTaggedValue${string}`
89
- // graph-ts declares `CallResult._value` private, which no other declaration
90
- // can match; the shim's is structurally the same.
91
- | "ethereum.CallResult.fromValue"
92
- | "ethereum.SmartContract#tryCall"
93
- // Constructors only the shim itself calls. graph-ts' BigInt inherits
94
- // Uint8Array's and is built through its statics; the others are declared
95
- // without one, and a mapping gets each from a call, a parse or `fromValue`.
96
- | "BigInt()"
97
- | "ethereum.CallResult()"
98
- | "Result()"
99
- | "JSONValue()";
100
-
101
- /** A known gap no longer found, whose entry should go. */
102
- type Closed<Gap> = Gap extends unknown ? ([Extract<Found, Gap>] extends [never] ? Gap : never) : never;
103
-
104
- // Keyed so a failure lists each path as a missing property.
105
- export const unlisted: Record<Exclude<Found, KnownGap>, "a gap KnownGap doesn't list"> = {};
106
- export const closed: Record<Closed<KnownGap>, "a KnownGap entry that no longer applies"> = {};
@@ -1,85 +0,0 @@
1
- const ISSUES_URL = "https://github.com/enviodev/hyperindex/issues";
2
-
3
- /**
4
- * Subgraph mode ships under its own npm dist-tag (see `publish.yml`), so
5
- * `envio@latest` would move a project off it.
6
- */
7
- const UPGRADE_COMMAND = "pnpm add -D envio@subgraph";
8
-
9
- /** A feature we recognise and deliberately don't implement. */
10
- export function unsupported(feature: string, location: string, why?: string): Error {
11
- return new Error(
12
- `Envio Subgraph doesn't support ${feature} yet${why ? `: ${why}` : ""}.\n` +
13
- ` Found in ${location}.\n` +
14
- `First, make sure you're on the newest Envio Subgraph release — support may have landed:\n` +
15
- ` ${UPGRADE_COMMAND}\n` +
16
- `If you're up to date and need this feature, please open an issue (existing\n` +
17
- `issues welcome a 👍 — demand drives prioritization):\n ${ISSUES_URL}`,
18
- );
19
- }
20
-
21
- /** Something we don't recognise at all: newer than us, or a typo. */
22
- export function unknown(thing: string, location: string): Error {
23
- return new Error(
24
- `Envio Subgraph doesn't know ${thing}.\n` +
25
- ` Found in ${location}.\n` +
26
- `This may be a feature newer than this envio version understands, or a typo.\n` +
27
- `First, make sure you're on the newest Envio Subgraph release:\n` +
28
- ` ${UPGRADE_COMMAND}\n` +
29
- `If you're up to date and this is a real subgraph feature, please open an\n` +
30
- `issue so we can add it: ${ISSUES_URL}`,
31
- );
32
- }
33
-
34
- const RPC_ENV_VAR = "ENVIO_SUBGRAPH_RPC";
35
-
36
- /** §6b: contract calls need an endpoint HyperSync and HyperRPC don't serve. */
37
- export function missingRpcMessage(callSite: string): string {
38
- return (
39
- `This subgraph performs contract calls (${callSite}), which need an\n` +
40
- `RPC endpoint — HyperSync and HyperRPC serve logs and blocks, not eth_call.\n` +
41
- `Set one in .env or the environment:\n` +
42
- ` ${RPC_ENV_VAR}=https://...\n` +
43
- `Advanced (matches envio's rpc config; single entry or array):\n` +
44
- ` ${RPC_ENV_VAR}={"url":"https://...","for":"fallback","headers":{...}}`
45
- );
46
- }
47
-
48
- /**
49
- * Names a trap must answer for rather than refuse. AS-compiled mappings never
50
- * feature-detect, so nothing legitimate reaches these — but `console.log`,
51
- * `await` and `JSON.stringify` do, and they must not explode.
52
- */
53
- const PASSTHROUGH = new Set([
54
- "then",
55
- "toJSON",
56
- "constructor",
57
- "valueOf",
58
- "toString",
59
- "inspect",
60
- "nodeType",
61
- "$$typeof",
62
- "@@__IMMUTABLE_ITERABLE__@@",
63
- ]);
64
-
65
- function isPassthrough(prop: PropertyKey): boolean {
66
- return typeof prop === "symbol" || PASSTHROUGH.has(prop as string);
67
- }
68
-
69
- export const PROTOTYPE_PASSTHROUGH = PASSTHROUGH;
70
-
71
- /**
72
- * Full Proxy for a graph-ts namespace object. Future graph-ts APIs are
73
- * unenumerable, so only a `get` trap can catch them; these are cold paths, so
74
- * the trap cost doesn't matter.
75
- */
76
- export function strictNamespace<T extends object>(name: string, target: T): T {
77
- return new Proxy(target, {
78
- get(target, prop, receiver) {
79
- if (prop in target || isPassthrough(prop)) {
80
- return Reflect.get(target, prop, receiver);
81
- }
82
- throw unknown(`the graph-ts API ${name}.${String(prop)}`, `a mapping handler`);
83
- },
84
- });
85
- }
@@ -1,73 +0,0 @@
1
- export type Graft = { base: string; block: number };
2
-
3
- type Manifest = { startBlocks: number[]; graft: Graft | null };
4
-
5
- const GATEWAYS = [
6
- "https://api.thegraph.com/ipfs/api/v0/cat?arg=",
7
- "https://ipfs.network.thegraph.com/api/v0/cat?arg=",
8
- ];
9
- const MAX_CHAIN = 8;
10
-
11
- async function fetchFromGateways(hash: string): Promise<string | null> {
12
- for (const gateway of GATEWAYS) {
13
- try {
14
- const response = await fetch(gateway + hash, {
15
- method: "POST",
16
- signal: AbortSignal.timeout(8000),
17
- });
18
- if (response.ok) return await response.text();
19
- } catch {
20
- // try the next gateway
21
- }
22
- }
23
- return null;
24
- }
25
-
26
- /** The start blocks and graft of a deployment manifest, read without a YAML parser. */
27
- export function readManifest(text: string): Manifest {
28
- const startBlocks = [...text.matchAll(/^\s*startBlock:\s*["']?(\d+)/gm)].map((m) => Number(m[1]));
29
- const block = /^graft:\s*\n((?:[ \t]+.*\n?)+)/m.exec(text)?.[1] ?? "";
30
- const base = /^\s*base:\s*["']?(Qm[A-Za-z0-9]+)/m.exec(block)?.[1];
31
- const at = /^\s*block:\s*["']?(\d+)/m.exec(block)?.[1];
32
- return { startBlocks, graft: base && at ? { base, block: Number(at) } : null };
33
- }
34
-
35
- /**
36
- * graph-node copies the base deployment's data up to the graft block, and the
37
- * manifest on IPFS is the only record of where that base started. If it
38
- * started earlier than any data source here does, a re-index from these start
39
- * blocks is missing everything in between; the numbers go in the warning.
40
- * Returns null when the base can't be read (offline, pruned from IPFS).
41
- */
42
- export async function graftBaseNotice(
43
- graft: Graft,
44
- ownStartBlocks: number[],
45
- fetchManifest: (hash: string) => Promise<string | null> = fetchFromGateways,
46
- ): Promise<string | null> {
47
- let earliest: number | null = null;
48
- let hash: string | null = graft.base;
49
- for (let depth = 0; hash && depth < MAX_CHAIN; depth++) {
50
- const text = await fetchManifest(hash);
51
- if (text === null) return null;
52
- const manifest = readManifest(text);
53
- if (manifest.startBlocks.length > 0) {
54
- const lowest = Math.min(...manifest.startBlocks);
55
- earliest = earliest === null ? lowest : Math.min(earliest, lowest);
56
- }
57
- hash = manifest.graft?.base ?? null;
58
- }
59
- if (earliest === null) return null;
60
- const own = ownStartBlocks.length > 0 ? Math.min(...ownStartBlocks) : 0;
61
- if (earliest < own) {
62
- return (
63
- `WARNING, DATA IS MISSING: the graft base ${graft.base} (read from IPFS) starts at block ` +
64
- `${earliest}, but the earliest startBlock here is ${own}. Blocks ${earliest} to ${own - 1} ` +
65
- `are in the grafted deployment and will not be indexed. Lower the startBlock of the data ` +
66
- `sources to ${earliest} to rebuild that history.`
67
- );
68
- }
69
- return (
70
- `The graft base ${graft.base} (read from IPFS) starts at block ${earliest}, not after this ` +
71
- `manifest's earliest startBlock ${own}: a re-index covers the same blocks.`
72
- );
73
- }
@@ -1,35 +0,0 @@
1
- // Runs one graph-cli command, as its own bin would, on the thread
2
- // `graph-cli.ts` sized for it. Plain JavaScript: the TypeScript loader envio
3
- // registers doesn't reach worker threads.
4
- import { parentPort, workerData } from "node:worker_threads";
5
- import path from "node:path";
6
- import { pathToFileURL } from "node:url";
7
-
8
- const { packageDir, command, argv } = workerData;
9
-
10
- let ok = true;
11
- try {
12
- const commandFile = path.join(packageDir, "dist", "commands", `${command}.js`);
13
- const exported = await import(pathToFileURL(commandFile).href);
14
- // graph-cli before 0.93 is CommonJS compiled from TypeScript: an ES import
15
- // hands back `module.exports`, so the class is its `default`, one level down.
16
- const Command = [exported.default, exported.default?.default].find(
17
- (candidate) => typeof candidate?.run === "function",
18
- );
19
- if (Command === undefined) {
20
- throw new Error(
21
- `Envio Subgraph couldn't find a runnable \`graph ${command}\` in ${commandFile}`,
22
- );
23
- }
24
- await Command.run(argv, packageDir);
25
- // A generation failure is reported through the exit code, not a throw.
26
- ok = process.exitCode === undefined || process.exitCode === 0;
27
- } catch (error) {
28
- // oclif ends a successful command early by throwing an exit of 0.
29
- if (error?.oclif?.exit !== 0) {
30
- console.error(error?.message ?? error);
31
- ok = false;
32
- }
33
- }
34
- process.exitCode = 0;
35
- parentPort.postMessage(ok);