feat: track state-change block and canceler on IndexingAgreement#7
Closed
MoonBoi9001 wants to merge 3 commits into
Closed
feat: track state-change block and canceler on IndexingAgreement#7MoonBoi9001 wants to merge 3 commits into
MoonBoi9001 wants to merge 3 commits into
Conversation
704daf4 to
b4c94d8
Compare
b4c94d8 to
60ec575
Compare
MoonBoi9001
added a commit
that referenced
this pull request
Apr 23, 2026
Drop the branches: [main] filter so stacked PRs whose base is another branch in the same repo (e.g. PR #7 stacked on this one) still get build-and-test runs. Keep the push trigger narrow to main so CI does not fire on every force-push across feature branches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9bafd57 to
8360209
Compare
MoonBoi9001
added a commit
that referenced
this pull request
May 7, 2026
Drop the branches: [main] filter so stacked PRs whose base is another branch in the same repo (e.g. PR #7 stacked on this one) still get build-and-test runs. Keep the push trigger narrow to main so CI does not fire on every force-push across feature branches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c18a47d to
ec72172
Compare
8360209 to
a9024b6
Compare
Add `lastStateChangeBlock` so consumers can poll for agreements that moved since a given block, and `canceledBy` (taken from the SubgraphService event's canceledOnBehalfOf) so operator-initiated cancels capture the real signer, not just the enum. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The audit dropped redundant on-chain timestamps from the Agreement events and added OfferCancelled, but the subgraph still subscribed to pre-audit signatures so every handler stayed silent. Update ABI, yaml, and mappings; subscribe to OfferCancelled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OfferStored fires for both OFFER_TYPE_NEW and OFFER_TYPE_UPDATE, but the handler treated the second event as a no-op and dropped the update. Refresh both fields on every event; keep createdAt pinned to the first OFFER_TYPE_NEW so consumers can still see the initial. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3000a93 to
fdd2084
Compare
MoonBoi9001
added a commit
that referenced
this pull request
May 11, 2026
Drop the branches: [main] filter so stacked PRs whose base is another branch in the same repo (e.g. PR #7 stacked on this one) still get build-and-test runs. Keep the push trigger narrow to main so CI does not fire on every force-push across feature branches. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Motivation
The
IndexingAgreemententity currently captures the full business state of an agreement -- payer, indexer, pricing, timestamps of major transitions -- but two gaps make it awkward to consume as a source of truth for state reconciliation.First, there is no block-indexed marker of the most recent state change. The existing
lastUpdatedAttimestamp is only written inhandleAgreementUpdated, so pollinglastUpdatedAt_gtwould miss accepts, cancels, and collections. Consumers that want a delta-style "what moved since block N" have to either iterate every entity on every poll or fall back to reading the event-log entities (which cuts against the aggregated-entity direction of PR #5).Second, when an agreement is canceled the entity records
state = CanceledByServiceProvider | CanceledByPayerbut loses the actual signer address. Most cancels come directly from the payer or the indexer so the enum is sufficient, but in production an operator can sign on behalf of either party and the enum collapses that to just the party category. Dipper's chain_listener compares the canceler address to its own signer address to decide whether a cancel was self-initiated or not -- without the address on the entity, that check has to fall back to the event-log entity.Summary
lastStateChangeBlock: BigInt!toIndexingAgreement. Every handler that transitions state stamps it withevent.block.number:handleAgreementAccepted/Canceled/Updated/RCACollectedon the RecurringCollector data source, andhandleIndexingAgreementAccepted/Canceled/Updatedon the SubgraphService data source.createOrLoadIndexingAgreementinitialises it to zero.canceledBy: Bytes!toIndexingAgreement, initialised toBytes.empty()and written in a newhandleIndexingAgreementCanceledhandler that readscanceledOnBehalfOffrom the SubgraphService event. The RecurringCollector handler continues to set thestateenum; neither handler overwrites the other's field.IndexingAgreementCanceledon the SubgraphService data source insubgraph.template.yaml.handleIndexingAgreementCanceledtest that verifiescanceledBycaptures a distinct operator address (not inferred from payer/indexer) and thatlastStateChangeBlockis stamped. Existing accept and update tests gainlastStateChangeBlockassertions.Both new fields are additive and backwards-compatible: existing consumers that don't read them see no change, and new consumers that filter on
lastStateChangeBlock_gtor readcanceledByget the delta-friendly shape they need.Generated with Claude Code