feat: index corporate actions, checkpoints, ballots and relayer subsidies; merge external-agent entities and retire TransferManager - #356
Draft
prashantasdeveloper wants to merge 7 commits into
Conversation
Handles CAInitiated, CARemoved, RecordDateChanged, CALinkedToDoc, DefaultTargetIdentitiesChanged, DefaultWithholdingTaxChanged and DidWithholdingTaxChanged. New CorporateAction and CorporateActionDefaultConfig entities. CAInitiated and the CorporateAction struct are shape-identical v4.1.3-v8.0.0 (docs/reference/event-shape-verification.md); only Ticker->AssetId at 7.x, already handled by getAssetId/getCaIdValue. MaxDetailsLengthChanged stays unregistered (chain config, no entity), as does the removed CAATransferred event (superseded by external agents pre-6.0, per docs/implementation/06-corporate-actions.md). src/decode/shapes/corporateActions.ts also registers the checkpoint and corporateBallot shapes landing in the next two commits — one cohesive shape-registration file for the domain rather than an artificial split.
New Checkpoint and CheckpointSchedule entities. Handles CheckpointCreated, ScheduleCreated and ScheduleRemoved. ScheduleCreated/ScheduleRemoved are the one real version change in this domain: arity 3->4 at v6.0.0 (ScheduleId inserted at index 2, payload StoredSchedule -> ScheduleCheckpoints). Registered as a two-entry shape in src/decode/shapes/corporateActions.ts; parseSchedule decodes either era, with a regression test asserting both arities decode correctly and a mismatched arity throws. MaximumSchedulesComplexityChanged stays unregistered (chain config, no entity).
New CorporateBallot and CorporateBallotVote entities. Handles Created, MetaChanged, RangeChanged, RCVChanged, Removed and VoteCast — all six events are shape-identical across every checked spec version (docs/reference/event-shape-verification.md), so no version branching here.
New Subsidy entity. The relayer pallet was renamed paying-key -> subsidy at a clean v8.0.0 boundary (verified against pallets/relayer/src/lib.rs at v6.3.0/v7.0.0/v7.4.0/v8.0.0); pre-v8 events carry a leading EventDid that v8 events drop. Both eras are handled — pre-v8 is the bulk of relayer history on mainnet — via AuthorizedPayingKey/AcceptedPayingKey/RemovedPayingKey/UpdatedPolyxLimit and ApprovedSubsidy/AcceptedSubsidy/RemovedSubsidy/RemovedPendingSubsidy/ SubsidyDebited/UpdatedPolyxLimit, each pair sharing one handler. UpdatedPolyxLimit is the one arity change (5 args pre-v8, 4 at v8+), covered by a decode regression test.
TickerExternalAgent -> AssetAgent (caller -> identity), and TickerExternalAgentHistory -> AssetAgentHistory (type: String! -> AgentHistoryType! enum) — these two duplicated their write path (both fire on the same externalagents events), which is what actually merges. TickerExternalAgentAction -> AssetAgentAction is a straight rename with an unchanged shape: it is driven from a 20-pallet lookup table on every chain event, not from externalagents, and answers a different question (what an agent did, not who is an agent), so it stays its own entity — caller stays caller there, deliberately asymmetric with AssetAgent.identity. AgentGroup gains the asset relation it was missing entirely (defect G). AgentGroupMembership.member is now an Identity relation instead of a bare String. permissions stays a JSON-in-a-string String, not the PermissionsJson jsonField this was originally going to become: that type's shape was built for the secondary-key permission model, and an AgentGroup's ExtrinsicPermissions is a different, richer on-chain structure that would need a lossy flattening to fit it. See the schema docstrings. AssetAgent.group/.permissions are populated by AgentAdded but not kept current by GroupChanged yet (only AssetAgentHistory is) — noted in mapExternalAgent.ts. BREAKING CHANGE: TickerExternalAgent renamed to AssetAgent (caller field renamed to identity); TickerExternalAgentHistory renamed to AssetAgentHistory (type field is now the AgentHistoryType enum, was String); TickerExternalAgentAction renamed to AssetAgentAction (no field changes); AgentGroupMembership.member is now an Identity relation instead of a String. SDK queries tickerExternalAgents, tickerExternalAgentHistories and tickerExternalAgentActions all need updating to the renamed root fields, and callerId filters/selections on the first need to become identityId. Needs a coordinated SDK/portal release — see the PR description.
TransferManager was documented deprecated in its own schema comment in favour of TransferCompliance, yet both were written unconditionally for the same pre-v5 statistics events. Neither is queried by either consumer (the SDK reads transfer restrictions from chain) — confirmed against docs/reference/consumer-queries.md. Removes the TransferManager entity, its Asset.transferManagers derived field, and mapTransferManager.ts. TransferRestrictionTypeEnum is kept: handleStatisticTransferManagerAdded and the surviving exemption handlers in mapStatistics.ts still use it for the pre-v5 percentage/count StatType and TransferComplianceExemption model. BREAKING CHANGE: the TransferManager entity and the transferManagers query (including Asset.transferManagers) are removed. Confirmed unused by both the SDK and the portal, so no consumer query changes, but it is a schema removal.
…d assetAgentActions.test.ts
registerShape('relayer', X, [{ from: V8, fields: [...] }]) repeated the same
two field lists across five event names; adds introducedAt/registerShapes to
registry.ts (siblings of stable/discontinuedAt) and uses them instead.
|
prashantasdeveloper
added this pull request to stack #358
September 15, 2026 08:23
prashantasdeveloper
marked this pull request as draft
September 15, 2026 10:29
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.



What's in each commit
feat: index corporate actions—CorporateAction+CorporateActionDefaultConfigentities.
CAInitiated,CARemoved,RecordDateChanged,CALinkedToDoc,DefaultTargetIdentitiesChanged,DefaultWithholdingTaxChanged,DidWithholdingTaxChanged.feat: index checkpoints and schedules—Checkpoint+CheckpointScheduleentities.CheckpointCreated,ScheduleCreated,ScheduleRemoved. The one real version change in thiswhole domain:
ScheduleCreated/ScheduleRemovedwent 3→4 args at chain v6.0.0 (ScheduleIdinserted, payload type changed) — handled as a two-entry decode shape, with a regression test
asserting both arities decode and a mismatch throws.
feat: index corporate ballots—CorporateBallot+CorporateBallotVoteentities.Created,MetaChanged,RangeChanged,RCVChanged,Removed,VoteCast— shape-identicalacross every checked spec version, no version work.
feat: index the Subsidy/Relayer pallet— newSubsidyentity. Therelayerpallet hadzero indexer coverage despite full SDK support. Renamed paying-key → subsidy at chain v8.0.0;
both eras are handled, since pre-v8 is the bulk of relayer history on any live chain.
feat!: merge the TickerExternalAgent entities(breaking) —TickerExternalAgent→AssetAgent,TickerExternalAgentHistory→AssetAgentHistory(these two duplicated theirwrite path, which is what actually merges);
TickerExternalAgentAction→AssetAgentAction(straight rename, unchanged shape — it answers a different question and is driven from an
unrelated 20-pallet event table).
AgentGroupgains theassetrelation it was missingentirely;
AgentGroupMembership.memberis now anIdentityrelation instead of a bare string.feat!: retire the TransferManager dual model(breaking) — removes theTransferManagerentity, its
Asset.transferManagersderived field, and its writer. It was documented deprecatedin its own schema comment yet still written unconditionally; neither consumer queries it.
Commits 1–4 are purely additive — new entities and events that didn't exist before, no existing
query changes. Commits 5–6 are breaking schema changes.
Consumer impact
Commits 1–4: none. New entities, new coverage, nothing existing changes shape.
Commit 5 needs a coordinated SDK/portal release. Both consumers query all three renamed
entities:
tickerExternalAgentsassetAgentscallerIdfilters/selections →identityIdtickerExternalAgentHistoriesassetAgentHistoriestypeis now theAgentHistoryTypeenum (was a plain string)tickerExternalAgentActionsassetAgentActionspermissionsonAssetAgent/AssetAgentHistorystays a JSON-encoded string, not a typedjsonField — see the docstring on
AssetAgentinschema.graphqlfor why (the existingPermissionsJsonshape was built for a different on-chain permission model and doesn't fit anAgentGroup'sExtrinsicPermissionswithout a lossy flattening).Commit 6: no consumer query changes. Confirmed neither the SDK nor the portal queries
transferManagerstoday. It's a schema removal, hence theBREAKING CHANGEfooter, but nothingdownstream needs to change.
Verification
yarn codegen && yarn typecheck && yarn lint && yarn test:unitall pass (571 unit tests, 53suites), plus
yarn build(validates everyproject.tshandler name resolves) and the10-index-per-entity cap check across the whole schema. A fixture test exists for every new
handler. Full genesis resync was not run for this PR (out of scope for the bar here, matching how
earlier phases were verified) — worth doing before merge given how central corporate actions and
checkpoints are to the securities domain.