Add per-Transcoder delegatorCount field to schema
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5
- Forks
- 7
- Avg merge
- 4h 1m
- Merged PRs (30d)
- 6
Description
## Problem
The `Transcoder` entity exposes its `delegators` only as a `@derivedFrom` collection. To learn how many unique delegators an orchestrator has, a client must paginate the `Delegator` entity (`where: { delegate: $orchestrator }`) using keyset pagination on `id`, because The Graph caps `first: 1000` and `skip: 5000`.
This is workable for a single orchestrator's detail page but breaks down for any view that needs the count across many orchestrators at once (e.g. the orchestrator list view in [`livepeer/explorer`](https://github.com/livepeer/explorer)). It also makes the per-orchestrator count an O(N/1000) operation client-side instead of a single field read.
`Protocol`, `Round`, and `Day` already expose `delegatorsCount: BigInt!` — `Transcoder` is the obvious gap.
## Proposal
Add a `delegatorCount` field to the `Transcoder` entity and maintain it in the bonding-related event handlers.
### Schema change
```graphql
type Transcoder @entity {
# ...existing fields...
"Number of unique delegators currently bonded to this transcoder"
delegatorCount: BigInt!
}
```
### Mapping logic
Increment / decrement `transcoder.delegatorCount` in the bonding manager event handlers, mirroring the patterns already used for `Protocol.delegatorsCount`:
- **Bond** (delegator with no prior delegate, or switching delegates): increment the new delegate's `delegatorCount`; if switching, decrement the old delegate's `delegatorCount`.
- **Unbond / Rebond** (full unbond to zero `bondedAmount`): decrement the delegate's `delegatorCount`.
- **TransferBond**: decrement the sender's delegate's count if the sender fully unbonds as a result; increment the receiver's delegate's count if this is the receiver's first bond to that delegate.
### Edge cases to confirm
- A self-delegating transcoder counts itself as a delegator (consistent with how `delegators` derives today, since the transcoder also has a `Delegator` entity for itself). Document this in the field comment.
- Partial unbonds that leave `bondedAmount > 0` must **not** decrement.
- Rebonding from an unbonding lock that brings a previously-zeroed delegator back must increment.
## Acceptance criteria
- [ ] `Transcoder.delegatorCount: BigInt!` exists in `schema.graphql`.
- [ ] Increment / decrement logic is wired in all bonding event handlers and covered by tests / fixtures consistent with how `Protocol.delegatorsCount` is tested.
- [ ] Backfill is correct from a full resync against historical chain data (sum of all `Transcoder.delegatorCount` equals `Protocol.delegatorsCount`).
- [ ] Field is documented in `schema.graphql` with a comment matching the style of neighbouring fields.
## Motivation / downstream
Unblocks [livepeer/explorer#106](https://github.com/livepeer/explorer/issues/106), which currently has to paginate to compute this count, and unlocks surfacing delegator counts in the orchestrator list view (not viable today because per-orchestrator pagination per row is too expensive).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with schema.graphql and the existing Protocol.delegatorsCount implementation, then trace the bonding manager event handlers and their related tests or fixtures. Confirm how Bond, Unbond, Rebond, and TransferBond update delegate state, including self-delegation and partial unbond cases. Done means the field is documented, all handlers and tests are updated, and a full historical resync produces matching totals.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, typescript
- Domain
- backend-api-design, blockchain
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100