Repository navigation
Most of this was found by porting the PancakeSwap Infinity CL subgraph (a real 2,097-line
AssemblyScript subgraph, not an example) in nuthatch-org/pancakeswap-infinity-cl-redstart.
Fixed
- A module-qualified helper call emitted an undefined namespace (#6). Helpers are emitted flat into
mappings.ts, butaccounts::double(x)lowered through the generic path rule toaccounts.double(x), whichcheckaccepted andgraph buildrejected withCannot find name 'accounts'. The qualifier is now checked against the declaring module and dropped in the output, andredstart testresolves the same call. redstart testreported failures against the wrong file. A failure inside a handler or helper was located in the file holding thetestblock, at the line and column of the real fault, somain.red:16:31was printed asaccounts.red:16:31. The location now comes from the module the failing code belongs to.- A keyword used as a binding name said only "expected an identifier".
let from = …is the natural first line of a transfer handler, andfromis reserved. The error now names the reserved word and suggestsfrom_. Some(x)was emitted as a call to an undefined function. AnOption<T>lowers to graph-ts'sT | null, soSomeis the identity constructor. It fell through to the generic call path instead and emittedSome(x)literally, whichcheckaccepted and onlygraph buildrejected.Nonewas already handled.- Matching an
Optionemitted a loose!= null, crashing the AssemblyScript compiler. graph-ts givesBigInt,BigDecimal,BytesandAddressan@operator('!=')taking two of themselves, so comparing one tonullsendsascintocompileBinaryOverload, where it fails an internal assertion and aborts the whole build with no line number and no recoverable diagnostic. Null tests are now strict!==, which skips overload resolution and is the correct test for a nullable reference. Any subgraph with a nullableBigIntfield - a nullabletickis the common one - hit this. Entity.create(…)/Entity.loadOrCreate(…)only lowered inletposition. As a bare statement (Swap.create(id, { … }), the "record this event and move on" shape) or in areturn, it emittedEntity.create(id, /* record */)- a static graph-ts does not have, with the record literal replaced by a comment. Both positions now expand into a temporary, guarded so that<Template>.create(addr)still spawns a data source: in statement position the two are textually identical.
Added
graft { base, block }. Start from another deployment's entity store instead of indexing from scratch, which is what a port of a live subgraph almost always wants: re-syncing a busy chain from deployment takes days. Emits both thegraft:block andfeatures: [grafting], since graph-node rejects a graft that is not declared as a feature. Previously listed inporting.mdunder Things that will not translate. Note that only graph-node validates a graft, at deploy time, and only a node already holding the base can perform one — Subgraph Studio holds only what is deployed to Studio and refuses withthe graft base is invalid: deployment not found.mutableon an entity, to decline the append-only inference. The §4.3 optimisation infers@entity(immutable: true)for an entity nothing loads back. That changes graph-node's storage layout, so a schema that must stay compatible with a graft base could not use it — and had no way to say so.mutableopts out,immutablestill opts in, and a timeseries cannot opt out and now says so rather than silently ignoring it.E006, unknown entity modifiers. They were silently ignored, which was tolerable untilmutableexisted: a misspelledmutibleleft the inference in place, turned the entity immutable, and made the subgraph un-graftable with no diagnostic anywhere. Unknown modifiers are now an error with a "did you mean" suggestion, andmutable+immutable/mutable+timeseriesare rejected as contradictory.E073, duplicate function. Twofns of the same name, in one module or two, collided in the flatmappings.tsand failed only insidegraph build. Each name must now be unique across the project.E072, call to undefined function.redstart checkreportedno errorsfor a project calling helpers that exist nowhere in the module tree; onlyverifycaught it, as an AssemblyScriptCannot find namefrom insidegraph build- no Redstart source line, and only after codegen. That is the worst place for it, because an unresolved call is the single most common thing a half-finished port has, andcheckis the fast inner loop: it is whatredstart devre-runs on save and whatcheck --jsonhands an agent. A barename(…)call is now resolved against everyfndeclared anywhere in the project, and a miss is an error at the call site. The fix-it is tailored: a case-only mismatch suggests the declared spelling, and an entity name called as a function points atEntity.create(id, { … }). A module-qualifiedmod::helper(…)is resolved against that module (from the root, or relative to the caller), so a qualifier naming the wrong module is the same error, with a fix-it pointing at the bare call. Every other call shape (Entity.load,<Contract>.bind,<Template>.create,log.info,BigInt.fromI32) was never at risk. The catalogue is 37 codes (31 errors, 6 warnings).redstart test: thelognamespace.log.debug/info/warning/errorevaluate their arguments and yield unit;log.criticalfails the test, since in graph-node it terminates the handler. A handler that logged could not be tested at all before.redstart test: the transaction fields the porting guide documents..from,.to,.valueand.gasPrice(plusgasLimit,gasUsed,nonce,index) on the mock transaction, which carried only.hash.redstart test: numeric and string surface.BigInt.fromI32/fromString/fromByteArrayandBigDecimal.fromString;pow,mod,leftShift,rightShift,neg,equals/notEqual/lt/gt/le/ge;BigDecimalarithmetic, which previously fell through to theBigIntpath and silently failed;startsWith,endsWith,includes,slice,charAt,concat,split,toLowerCase,toUpperCase, and.lengthon strings and byte strings;pushon arrays. Any subgraph doing real arithmetic was untestable natively.assertMissing(Entity, id). Asserts an entity was not written. A test that only checks a handler did not abort asserts nothing; this is what makes it a test.