Repository navigation
Subgraph mode: compatibility fixes from real subgraphs (wildcard data sources, register-pass scope, struct params, encode, …) - #1732
Closed
moose-code wants to merge 49 commits into
Conversation
graph-node matches a data source with no source.address against every contract's logs; ENS's Resolver is one data source for every resolver anyone deploys. It was translated to an address-less contract that nothing ever registers an address for, so all of its handlers silently ran zero times. Its handlers (and their register pass) now register as wildcard; a log matching an addressed data source too runs both, as on graph-node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The register pass reran every handler of every source at fetch time whenever the manifest had templates, against a store that reads null, and with it every contract call the handler makes. A pool's swap handler creates nothing, so the rerun only cost RPC: Venus and Aave spent most of their budget there. The addon now follows each handler through the mapping's module graph (top-level functions, classes, variables, relative imports and re-exports, into generated/templates.ts) and keeps the pass only for the ones that can reach DataSourceTemplate.create. Whatever it can't see counts as a create, so a wrong answer costs a pass, never a missed registration. ENVIO_SUBGRAPH_REGISTER_ALL_HANDLERS=1 restores the old behaviour. Concurrent register passes now share one in-flight request per op, so a block's factory events read the factory once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
envio's decoder keys a tuple by its components' names when the ABI names them (Nouns' NounCreated seed, SSV's ValidatorAdded cluster); the shim read it by position, so every field was undefined and, every parameter being converted together, even the struct's siblings threw. A keyed tuple is now read in ABI order, for a struct and for a struct array. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docs promise `[<url>|{...}]`, a JSON array mixing both, but the array
deserialized straight into RpcSelection::List(Vec<Rpc>), so
`["https://a","https://b"]` was refused before indexing started (Nouns,
CryptoPunks, Notional, Venus all hit it). A string in the array is now
an entry with only its url, the same as a bare URL on its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was a refusal, though the compat doc lists it as supported, and Nouns hashes every proposal's content with it (calcEncodedProposalHash), linking candidates to proposals through that hash. It is graph-node's ethabi::encode(&[token]), Solidity's abi.encode of one value: the ABI type is derived from the value's kinds and encoded with viem. A token carries no integer width and every integer takes a full word, so 256 bits encodes the same bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s' constructors A mapping can build these itself: Notional's polling block handler synthesizes an event with new ethereum.Event(address, 0, 0, null, block, new ethereum.Transaction(...), [], null). The shim's Event constructor was its own internal (raw, kind), so the event came back empty, and Block and Transaction had no constructor at all. They now take graph-ts' public arguments; the runtime builds its events through makeEvent, and its blank chain objects without arguments. Event fields are settable, as graph-ts' are. conformance.ts dropped construct signatures with the rest of a class's statics, so it never saw this. It now compares every public constructor's arity with graph-ts' and lists the four only the shim constructs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The register pass reruns a mapping against a store that reads null, only to collect dataSource.create() calls, but its log.* calls went to the real logger. Notional printed 190+ 'Token not found' errors from it that graph-node never would. The compat doc already says writes and logs are no-ops there; now logs are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
ens.nameByHash asked a hardcoded api.ensrainbow.io, which is gone (its Railway app answers 404 'Application not found'), as is every other hosted instance, so the ENS subgraph could not run at all without patching envio. - ENVIO_SUBGRAPH_ENS_RAINBOW_URL names the heal endpoint; 'off' skips lookups. - A 404 is a miss only when it is ENSRainbow's own 'Label not found'. - A service that keeps failing (5 attempts, or a foreign 404) answers null, as graph-node does without a rainbow table, for 5 minutes, with one warning, and those nulls are not cached. - At most 32 lookups are in flight: a registry backfill asks a million. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shim returned hex, so Aave's event.params.id.toString() == 'POOL' never held and its Pool and PoolConfigurator were silently never created, and a bytes32 ERC20 symbol fallback (MKR) was stored as 0x4d4b52... in Uniswap. It now decodes UTF-8 lossily and trims the trailing NULs of a fixed-size buffer, as graph-node does. Value.displayData() keeps hex for bytes, as graph-ts' does. The IPFS test asserted the old hex for ipfs.cat(...).toString(); it now expects the file's text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The register pass ran creating handlers at fetch time against a store that read null for everything, which lost Aave's tokens two ways: handleReserveInitialized loads an entity an earlier event saved before it calls ATokenContract.create(), so the load was null, the mapping threw first, and no aToken address was ever registered (every aToken event silently skipped); and handleProxyCreated creates, then loads and throws on null, which was fatal because something was already registered. Register-pass writes now go to a store of the pass's own, versioned by the writing event's position; a read sees the latest write from a strictly earlier event on its chain (200k entities, then dropped back to null). A round's writes are kept only once it completes, so replays don't leak them. A mapping that throws in the pass keeps what it registered before the throw; the handler pass surfaces real errors. The same store is what lets Venus's getOrCreateMarket and Uniswap's Token.load find what an earlier factory event saved, instead of making every contract call again at every event. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A subgraph in a yarn or npm workspace has its graph-cli hoisted to the workspace root. envio looked only in the package's own node_modules and said graph-cli wasn't installed (Polymarket, Venus, PancakeSwap, and in the sweep Multyr, Algebra, Autonolas, UMA). It now walks up the way Node resolution does, and puts every ancestor's node_modules/.bin on the codegen script's PATH. graph-cli 0.2x predates oclif and has no dist/commands/ to run in-process (GMX, PancakeSwap); its gluegun bin is spawned instead, with the same arguments and heap. fromSubgraph gained projectDir, to put a project inside a workspace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two things asc accepts that Node didn't, from the sweep: - AssemblyScript's DataView has setUint64/getUint64 (and the Int64 pair) over u64/i64; JavaScript's only setBigUint64 and friends. Ekubo builds every pool id that way and failed on its first event. They are now aliased onto DataView.prototype when missing. - matchstick-as re-exports graph-ts' log, and Beefy's mappings import it from there; it now resolves to the shim like graph-ts. typeConversion.bytesToString trims trailing NULs like Bytes.toString(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilure The real api.ensrainbow.io fails the TLS handshake (Railway serves its own certificate for the name), which reads as 'fetch failed' and was retried like a network blip: an ENS backfill started thousands of lookups at once, each backing off five times, and logged 15k warnings before the first one gave up. A certificate or DNS failure now takes the service for down at once, and lookups already backing off stop as soon as one has. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… parallel Requested blocks closer than 10,000 apart are fetched as one HyperSync range, which is paged one response at a time. A polling handler every 1,600 blocks merged every invocation of a batch into one range: Notional's 1,978 timestamps were one sequential scan over 3.2M blocks, each awaited for about 38 s. A merged range now spans at most 20,000 blocks, and up to 8 ranges are fetched at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ler pass A creating handler's calls ran twice: once in the fetch-time register pass, whose answers stay in its own memo, and again in the handler pass through the eth_call effect. Uniswap v3's handlePoolCreated paid every token call twice. The effect now answers from the register pass's memo when it holds the same call at the same block, and envio's effect cache persists it from there as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only JSON-RPC -32005 counted as a rate limit by code. blastapi answers -32097, sometimes worded 'exceeded its compute units per second capacity' with no 'rate limit' in it, and that failure stopped the indexer (Aave, Venus, Uniswap v3 field tests). -32097 and Alchemy's -32090 now count too, as do 'capacity' and 'limit exceeded' wordings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s register passes Venus saves its Comptroller in a once block handler, and getOrCreateMarket reads it before it creates the VToken template. Block handlers get no register pass, so the read was null, the mapping threw before the create, and no market was ever indexed: the bounded field-test window registered nothing but the Comptroller. A once handler now runs in register mode, at its block and ahead of every log there, before the first register pass of its chain, so its writes are in the register store. Register host ops also get the real chain id now; a block timestamp in the register pass asked chain 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A manifest's mapping file can re-export handlers written in other files (SSV's src/mapping.ts does). The generated event class a handler declares is exported by the module the handler is written in, and the runtime only looked at the manifest's file, so a re-exported handler got a bare ethereum.Event: its params lost graph codegen's getters, a struct read through them was undefined, and saving it failed with 'Cannot convert undefined to a BigInt'. The classes are now read from every project module the load hook compiled, keyed by the handler function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es an i64 The shim holds an i64 as a bigint. AssemblyScript widens an integer literal to i64 next to one, so p2p.me's timestamp.toI64() * 1000 is i64 arithmetic, but JavaScript refuses to mix a bigint with a number and the first event failed. +, -, * and % now widen an integer to bigint when the other side is one, and an i64 division with an integer on the other side stays an i64 division. AssemblyScript's Date takes and sets its time as an i64, which JavaScript's refuses as a bigint: the global Date accepts one in subgraph mode, and gains AssemblyScript's Date.fromString. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d call reuse Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generated code's directory is read off the mappings' imports of schema/templates, but only the manifest's own files were read. Uniswap v4's only re-export handlers written next to them, so envio guessed generated/, codegen wrote there, and the mappings' ../types/schema never existed. The scan now follows relative imports breadth first from the manifest's files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… ipfs.map as a create - AssemblyScript takes a decorator on a top-level function or variable (Beefy writes @inline above its helpers), which TypeScript's grammar refuses: every Beefy mapping failed to load. Such decorators are blanked to spaces before parsing, keeping every source-map offset. - The register store evicts its least recently used entity past 50k (4 versions each) instead of clearing everything at 200k, so a factory's own entity stays and memory stays bounded. - ipfs.map calls back into a mapping function named by a string, which the create analysis can't follow, so a handler using ipfs counts as one that may create. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On graph-node, Account.tokens @derivedFrom(field: "owners") over Token.owners: [Account!]! holds every token whose list contains the account. envio's lookups only match a column equal to a value, so store.loadRelated silently answered an empty list. It now refuses, naming the field, rather than answering wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s class - The transformer needs enum evaluation from the semantic pass to compile an enum, and panicked without it — inside the addon, which aborted the whole indexer (Uniswap v4's ChainId enum). - graph-cli 0.2x's tuple getters and old entity loads cast with `x as Foo` where newer codegen writes changetype<Foo>(x): the same reinterpret, which stripped as a type left a bare tuple without the generated getters (GMX's eventData.addressItems was undefined). Such a cast now retags onto the class like changetype, except that a value already of the class, or a subclass, keeps its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
graph codegen reads a struct array as x.toTupleArray<Struct>(), and in AssemblyScript each element is that Struct, with its getters. The type argument is erased in JavaScript, so the elements were bare tuples and every getter on them read undefined: GMX's event data lookups never matched and its MarketTokenTemplate.create got null. The transform now wraps such a call (and toTupleMatrix) in a helper that retags each tuple onto the class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m the queue At most 16 RPC requests are in flight and the rest queue in the gate. untilAnswered wrapped every attempt in the request deadline, queue wait included, so a backlog timed out before it was ever sent, was asked again at the back of the queue, and was eventually sent twice: Venus's register pass logged 46k timeouts for 3.3k requests actually sent, and made no progress (retest-01). The gate already gives each request the deadline once it holds a slot, so gated attempts (contract calls, balances, code, RPC block reads, ENS lookups) no longer get a second one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ph-node does graph-node returns the log's index in its block for transactionLogIndex (chain/ethereum/src/trigger.rs, since b95c6953): Geth never set the per-transaction index, and subgraphs read it only to tell logs apart. Aave v3 reads it at 54 call sites to build entity ids, and was refused on the first. The pinned unsupported-refusal text moves to event.receipt.logs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
graph-node runs none of a data source's handlers past its endBlock (has_expired), while the other data sources on its network and every template instance keep indexing. envio ends whole chains, so the runtime drops a static data source's events after its endBlock (event and register-pass handlers) and bounds its polling block handlers with _lte. Used by autonolas predict-polymarket (v1 exchange retired at 86750000 beside open-ended sources) and Beefy (a one-block ConfigBinder source). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The translator now records the manifest's file name (manifestFile) when --config/ENVIO_CONFIG names one other than subgraph.yaml (Uniswap v3's v3-subgraph.yaml). graph codegen and the dev type check ran on subgraph.yaml regardless; they now run on that file, defaulting to subgraph.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… entity A batch's register passes run concurrently, and a pass's writes reach the register store only when it completes. So every Comptroller event in Venus's first batch missed the Market an earlier event of the batch was still creating, and repeated its ~20 creation calls at its own block: 9.3k distinct (call, block) keys before the first event (retest-02). A pass that misses an entity an earlier, still-running pass of its chain also missed now waits for the earliest such pass once, then reads again: the per-entity order graph-node's sequential processing gives. Independent events stay concurrent, and a key nobody ends up writing costs one wait. Waits only go to earlier passes, so they can't cycle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moose-code
added a commit
that referenced
this pull request
Oct 14, 2026
flaunch's BidWall1 data source lists `source.addresses:` and was refused as an
unknown manifest field. graph-node has no such field: its ethereum `Source`
(graph/src/data/subgraph/mod.rs) carries `address` only and doesn't deny
unknown keys, so the list is dropped and the data source has no address, which
graph-node indexes as a wildcard over every emitter. graph-cli would reject the
key ("Unexpected key in map"), but it skips manifest validation entirely when
the manifest has a file data source, as flaunch's does.
The key is now accepted and, like graph-node, not used: the data source gets
no address, so the same events are indexed as on The Graph. (Wildcard data
sources run through #1732's runtime change.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dules A mapping library is AssemblyScript too, and the commonest ones don't load as TypeScript: OpenZeppelin's subgraphs pull in @amxx/graphprotocol-utils, which declares 'class string extends String' in a namespace (mento, aavegotchi-core, forta); @protofire/subgraph-toolkit puts @inline on top-level functions; some files import the same graph-ts name twice (gammaswap). envio ran its AssemblyScript pass on the project's own files only, and Node refuses even to strip types under node_modules. The load hook now passes every .ts module under node_modules except envio's own package and declaration files through the AssemblyScript pass, and the pass turns a class named after a built-in type into a class expression bound to a constant of that name, which TypeScript's grammar takes and reads the same from outside. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…port Envio Cloud drops a project's generated/ and recreates it empty before the build, and envio skipped graph codegen whenever the directory existed, so the pod crash-looped on the mappings' ../generated/schema imports. The runtime now checks the generated files the mappings import (followed through re-exports), and builds the directory when any is missing, empty included; the codegen preflight looks for schema.ts, not the directory. When the generated code is complete but graph-cli can't be found to rebuild it, startup warns that it runs as committed and may be stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… them graph-ts reads a BigInt's minimal two's-complement little-endian bytes, zero-padded, so -1 (the byte 0xff) is 255 and only a value whose bytes don't fit overflows. The shim refused every negative to toU32 (Clober's (tick.toU32() << 8) >> 8 failed) and returned toU64 unchanged, negative. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
|
Pushed 34 more commits (head
All 59 Subgraph test files and the replay stress test pass. Not for merge during the hackathon. @DZakh, review when you have time. 🤖 Generated with Claude Code |
… its topic envio's decoder hands every bytesN over as the 32-byte word it was encoded in, topic or body, so ENS InterfaceChanged.interfaceID (indexed bytes4) was stored as 0x7ba18ba1 padded to 32 bytes. graph-node keeps the first N bytes. An indexed string, bytes, array or tuple is only its topic hash, which graph-node hands over as a 32-byte FixedBytes and graph codegen reads with toBytes(); the shim typed it as the declared type, so the generated getter of an indexed string threw "Ethereum value is not bytes". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… after it Dolomite's AmmPair template was never registered, so every AMM event was lost without a word. Its admin handler saves each Token after a contract call; the factory's handleNewPair, at a later block, loads the pair's Token (`as Token`) before PairTemplate.create(). The register passes of a batch run concurrently, so the factory's pass read the Token while the admin's pass still waited on its call, got null, threw before the create, and the throw is forgiven in the register pass. The wait added for Venus covers only an earlier pass that has already missed the same entity. A read that misses while an earlier pass of its chain is still running now marks the pass provisional: when it ends, thrown or not, it waits until every earlier pass of its chain has settled and runs again, its first run's writes dropped (a create it made stands). The import analysis was right all along: it marks handleNewPair as creating. Dolomite (arbitrum, 28,220,369 to 28,300,000): 3 AmmPair addresses registered (was 0); AmmMint 1, AmmTrade 5, AmmLiquidityPosition 1 and the pairs' reserves equal the network's at 28,300,000 (were 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…istered Only the register pass registers a template address, at fetch time; the handler pass's create() is a no-op. When the two disagree — the register pass threw on an entity that only a handler without a register pass saved, or there is no register pass at all, as for a polling block handler — the template's events were lost without a word (Dolomite's AmmPair). The handler pass now checks its creates against what the register passes registered and warns once per address, naming the data source, template, address and block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dolomite generates into src/types, where templates.ts sits beside a templates/ directory, and imports its template under an alias because a schema entity has the same name. The analysis follows that import to the create (Dolomite's lost AmmPair events were a register-pass race, fixed separately); this pins the shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uniswap v2 ran 4.3x slower than on envio@3.14.0-subgraph, CPU-bound (retest-06). A profile put 55% of the time in BigDecimal: normalize() padded every coefficient to 34 digits and stripped the zeros off again one bigint division at a time; powers of ten were recomputed with 10n ** n; the bit length came from a binary string; division appended its 100 digits one division each; and every value eagerly built the BigNumber it carries, from a printed string. exponentToBigDecimal's times(10) loop alone was 40% of the run. Same values, by different means: a coefficient of 34 digits or fewer only loses its own trailing zeros; powers of ten come from a table; a positive's digit count starts from log10; division is one division of num * 10 ** extra (an early stop shows as trailing zeros); comparisons work on the coefficients; the BigNumber is made on first use and carries its decimal, so an entity read back from memory isn't printed and parsed again; repeated literals parse once. The second normalization of each result stays: graph-node normalizes a value again whenever it crosses back from AssemblyScript into its host (FromAscObj -> BigDecimal::new), and that pass changes a negative the first left at 35 digits. The bigdecimal 0.1.2 vector generator now models that round trip and adds 511 vectors for the shapes a fast path could get wrong (powers of ten, trailing zeros, 33-36 digit results, negatives at a power of two, carries, exact and repeating division, zeros): 911 vectors, all equal. A differential run against the previous code agreed on 1.6M operations. Uniswap v2 window 10,000,834 to 10,250,000 (unmodified repo, same box and proxy): 383 ev/s before (150,690 events in 420 s, not finished), 1,654 ev/s after (window of 411,332 events done in 276 s); published 3.14.0-subgraph 1,731 ev/s, 273 s. envio subgraph diff vs the network (GmSczqdC) at 10,250,000: 15/15 types, 427,478 ids, 1,139 sampled, 0 field mismatches (the published build: 720). This changes #1626's own graph-node-decimal.ts (F21, 8566fa6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…by == AssemblyScript's Array#includes, indexOf and lastIndexOf compare each element with ==, which for BigInt, BigDecimal and Bytes/Address is graph-ts' overloaded value comparison; JavaScript's compare identity. ENS's handleMulticoinAddrChanged guards its push with `if (!coinTypes.includes(coinType))`, so every setAddr on the multicoin resolver appended another "60": 473 of 3,302 resolvers with coinTypes held duplicates by block 9,000,000 (network: none). Found by verifying E1 with envio subgraph diff. The AssemblyScript pass routes those three calls (one or two arguments, no spread, not optional or on super) through the operators helper, which searches an array for a value with an == overload by that overload, with AssemblyScript's fromIndex rules, and leaves strings, typed arrays and primitive searches to JavaScript. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
|
6 more commits (head
Checks: 67 🤖 Generated with Claude Code |
moose-code
added a commit
that referenced
this pull request
Oct 14, 2026
…ntegration The only commit not already merged from fixer3's local branch is 45aff07 (E5 includes/indexOf/lastIndexOf by ==); it sits beside sg-tail-b's as-casts and sg-blocks' pow in assemblyscript.ts/.rs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rsync A fresh agent signed in to Envio Cloud can mint its HyperSync token with one command instead of a second sign-in at envio.dev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moose-code
added a commit
that referenced
this pull request
Oct 15, 2026
…ntegration Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Merged |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Subgraph-mode compatibility fixes, found by running real public subgraphs on
envio@3.14.0-subgraph. This targets #1626's branch. It is a draft for review and not for merge during the hackathon.There are 42 commits, one per fix, and each has a test under
packages/envio-tests/test/(orcargo test). Three commits are fixer2's patches from #1735, with their authorship kept. Checks at787e30446:cargo fmt, clippy-D warnings,cargo test --lib(1008),pnpm check-graph-ts, all 63test/Subgraph*files (175 tests) and the replay stress test.Silent wrong data
59888d95csource.addressis a wildcard, as on graph-node. Before this, ENSResolver's 11 handlers ran 0 times672686641save()merges onto the stored entity, as on graph-node: an unset field keeps its value and an explicit null clears it. Before this it replaced the entitydf61e8e296d3e2d8a7Bytes.toString()is UTF-8. This fixes Aave's"POOL"id and bytes32 symbolse25774fc4tx.hash856ca741715169dbdaevent.transactionLogIndex= log index, as on graph-nodeRegister pass (
dataSource.create) and RPC053d129d9131420ef8,0fc590756,0b2a98a54,fc9f88741,e7b3d2deconcehandlers are primed into it (Venus). A pass waits for an earlier creator of the same entity. Call answers are reused in the handler pass.ipfs.mapcounts as a create966672bae,e81bd98cd,6d57bc840,a90d060c6ENVIO_SUBGRAPH_RPCaccepts bare URL strings. Rate-limit codes are treated as transient. The deadline starts once a request holds a gate slot, so a queued backlog no longer double-sends. Progress is logged while a batch waits on callscced3554e,fc167ee6fendBlockc8992bbd5,efc31ef91ENVIO_SUBGRAPH_ENS_RAINBOW_URL, oroff. A dead service answers null with one warningAssemblyScript / graph-ts runtime
c6b9563e4and2a6d95fb3(struct params and tuple arrays);3af3e1645(ethereum.encode);e8f121b7f(publicethereum.*constructors);665879aef(i64 arithmetic andDate);2c144715e(DataView u64 andmatchstick-asimports);0dba8aa91(re-exported handlers);9477d8566(TSenum, and getters throughascasts);ec9fb0dfc(a siblingascast reads a copy);3c058090e(the AS pass runs on mapping libraries in node_modules);787e30446(BigInt.toU32/toU64of negatives);bfd4b0ba1(nolog.*lines from the register pass).Codegen and Envio Cloud
cc38dab80(hoisted and pre-oclif graph-cli);a1fb8b671(the generated-dir lookup follows re-exports);fe13904a8(codegen runs on the manifest given with--config);9e34722a2(envio codegenrefuses likestartwhen it can't build);9918a53e2(a startup line says where to query);eb468ab82: the Cloud operator ships an emptygenerated/, which the runtime now rebuilds, and it warns about a stale committed one.Before → after
Unmodified repos, run in a block window.
AddrChanged2,212 equals the network deployment's 2,212, with identical ids.Not fixed
Timestamploses microseconds.🤖 Generated with Claude Code