Skip to content

v0.17.0

Latest

Choose a tag to compare

@github-actions github-actions released this 26 Oct 08:14
· 2 commits to main since this release

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, but accounts::double(x) lowered through the generic path rule to accounts.double(x), which check accepted and graph build rejected with Cannot find name 'accounts'. The qualifier is now checked against the declaring module and dropped in the output, and redstart test resolves the same call.
  • redstart test reported failures against the wrong file. A failure inside a handler or helper was located in the file holding the test block, at the line and column of the real fault, so main.red:16:31 was printed as accounts.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, and from is reserved. The error now names the reserved word and suggests from_.
  • Some(x) was emitted as a call to an undefined function. An Option<T> lowers to graph-ts's T | null, so Some is the identity constructor. It fell through to the generic call path instead and emitted Some(x) literally, which check accepted and only graph build rejected. None was already handled.
  • Matching an Option emitted a loose != null, crashing the AssemblyScript compiler. graph-ts gives BigInt, BigDecimal, Bytes and Address an @operator('!=') taking two of themselves, so comparing one to null sends asc into compileBinaryOverload, 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 nullable BigInt field - a nullable tick is the common one - hit this.
  • Entity.create(…) / Entity.loadOrCreate(…) only lowered in let position. As a bare statement (Swap.create(id, { … }), the "record this event and move on" shape) or in a return, it emitted Entity.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 the graft: block and features: [grafting], since graph-node rejects a graft that is not declared as a feature. Previously listed in porting.md under 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 with the graft base is invalid: deployment not found.
  • mutable on 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. mutable opts out, immutable still 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 until mutable existed: a misspelled mutible left 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, and mutable + immutable / mutable + timeseries are rejected as contradictory.
  • E073, duplicate function. Two fns of the same name, in one module or two, collided in the flat mappings.ts and failed only inside graph build. Each name must now be unique across the project.
  • E072, call to undefined function. redstart check reported no errors for a project calling helpers that exist nowhere in the module tree; only verify caught it, as an AssemblyScript Cannot find name from inside graph 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, and check is the fast inner loop: it is what redstart dev re-runs on save and what check --json hands an agent. A bare name(…) call is now resolved against every fn declared 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 at Entity.create(id, { … }). A module-qualified mod::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: the log namespace. log.debug/info/warning/error evaluate their arguments and yield unit; log.critical fails 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, .value and .gasPrice (plus gasLimit, gasUsed, nonce, index) on the mock transaction, which carried only .hash.
  • redstart test: numeric and string surface. BigInt.fromI32/fromString/fromByteArray and BigDecimal.fromString; pow, mod, leftShift, rightShift, neg, equals/notEqual/lt/gt/le/ge; BigDecimal arithmetic, which previously fell through to the BigInt path and silently failed; startsWith, endsWith, includes, slice, charAt, concat, split, toLowerCase, toUpperCase, and .length on strings and byte strings; push on 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.