Skip to content

Add pendingStake Field for Transcoders in Subgraph #158

@rickstaa

Description

@rickstaa

Problem Description

Currently, the bondedAmount field in the Livepeer subgraph accurately reflects a delegator’s or orchestrator’s bonded stake as of the last explicit bonding transaction (Bond, Unbond, Rebond, TransferBond). However, it does not include unclaimed rewards, which can lead to discrepancies when comparing with on-chain views (e.g., Arbiscan).

Example:

  • Subgraph bondedAmount: 1.002563476329049571 LPT
  • On-chain actual stake: 2.536529849800865 LPT

This difference arises because the bondedAmount is static and does not dynamically include accumulated but unclaimed rewards.

While the bondedAmount is correct, users and applications often need to display the total effective stake (i.e., bonded amount plus pending rewards) to match what is visible on-chain.

Proposed Solution

Introduce a new field, pendingStake, in the subgraph, only for transcoders (orchestrators). This field will represent the total stake for the orchestrator, including unclaimed rewards.

It is not feasible to add pendingStake for delegators, as individual delegator pending stake is tracked internally in BondingManager and is not available from emitted events.

Implementation Plan

  1. Schema Update

    Add a pendingStake field to the Transcoder entity:

    type Transcoder @entity {
      id: ID!
      totalStake: BigDecimal!
      bondedAmount: BigDecimal!
      pendingStake: BigDecimal! # New field
      ...
    }
  2. Reward Event Handling

    Update the Reward event handler to calculate and update pendingStake for the transcoder.

    // src/mappings/bondingManager.ts
    export function reward(event: Reward): void {
        let transcoder = Transcoder.load(event.params.transcoder.toHex());
        if (!transcoder) return;
    
        let bondingManager = BondingManager.bind(event.address);
    
        // Compute transcoder pending stake
        let transcoderPendingStake = convertToDecimal(
            bondingManager.pendingStake(
                Address.fromString(transcoder.id),
                event.params.round
            )
        );
    
        transcoder.pendingStake = transcoderPendingStake;
        transcoder.save();
    }
  3. GraphQL Query Example

    Users can then query the orchestrator’s bondedAmount and pendingStake:

    {
      transcoder(id: "0x5bdeedca9c6346b0ce6b17ffa8227a4dace37039") {
        bondedAmount
        pendingStake
      }
    }
  4. Testing and Validation

    • Ensure pendingStake updates correctly when Reward events are triggered.
    • Validate against on-chain values (e.g., Arbiscan) for orchestrators.

Benefits

  • Accurate Display: Provides a real-time view of an orchestrator’s effective total stake.
  • Improved Transparency: Aligns subgraph data with on-chain reality for orchestrators.
  • Minimal Overhead: Builds on existing reward event handling logic already in place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions