Skip to content

Delegation Summary for delegator#18

Closed
0xVoronov wants to merge 3 commits intomasterfrom
feature/delegation-info
Closed

Delegation Summary for delegator#18
0xVoronov wants to merge 3 commits intomasterfrom
feature/delegation-info

Conversation

@0xVoronov
Copy link
Copy Markdown
Collaborator

@0xVoronov 0xVoronov commented Feb 19, 2026

What was implemented

  • New endpoint GET /v1/rewards/delegators/{address}/summary returning delegation and staking summary for an account (delegator or contract).
  • Optional query parameter legacy (default true) for account resolution (deprecation/migration).

Response body

  • summary - Delegation and staking status: delegate, balances, staking per validators, rewards by validator and by cycle (cycles newest-first), cycle and validator counts.
  • actualRewards - Actual rewards: delegation payouts, staking restakes, expected/pending amounts, per-validator breakdown with payment status (fully_paid, pending, underpaid, overpaid), list of staking reward events.
  • estimatedNextPayout, avgPayoutIntervalDays, lastVote - Estimated next payout, average payout interval, last vote.

Implementation

  • DelegationSummaryService aggregates data from AccountRepository, RewardsRepository, StakingRepository, OperationRepository (including delegation payouts and optional payouts from configured validator payout addresses).
  • DelegationConfig (section Delegation in appsettings): ValidatorPayoutAddresses - validator → alternative payout addresses; payouts from these addresses are counted as that validator’s payouts.
  • Response is cached by path + legacy.
  • New models under Mvkt.Api/Models/DelegationInfo/: DelegationInfo, DelegationSummary, ActualRewards, and related DTOs.

Tests

  • TestDelegationSummaryQueries: full response structure, non-existent address (200 + empty summary), legacy=true/false, contract (originator), rewardsByCycle order (desc), structure of allStakingRewardEvents and byValidator, allowed payment status values.

@0xVoronov 0xVoronov self-assigned this Feb 19, 2026
@0xVoronov
Copy link
Copy Markdown
Collaborator Author

Passed! - Failed: 0, Passed: 79, Skipped: 0, Total: 79, Duration: 2 s - Mvkt.Api.Tests.dll (net7.0) @TristanAllaire

@0xVoronov
Copy link
Copy Markdown
Collaborator Author

0xVoronov commented Feb 19, 2026

{
  "summary": {
    "isDelegating": true,
    "delegatedValidator": {
      "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
    },
    "delegatedBalance": 1692176031042,
    "delegationTime": "2026-01-08T12:59:49Z",
    "isStaking": true,
    "stakedValidators": [
      {
        "baker": {
          "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
        },
        "stakedBalance": 1681000000000
      }
    ],
    "totalStakedBalance": 1681000000000,
    "totalRewardsEarned": 11348190541,
    "rewardsByValidator": [
      {
        "validator": {
          "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
        },
        "totalRewards": 11348190541,
        "cycleCount": 14,
        "firstCycle": 45,
        "lastCycle": 58,
        "totalStakingRewards": 9654903735,
        "totalDelegationRewards": 1693286806,
        "isCurrentValidator": true
      }
    ],
    "rewardsByCycle": [
      {
        "cycle": 58,
        "rewards": 0,
        "delegatedBalance": 873884116,
        "stakedBalance": 1690673978101,
        "validator": {
          "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
        },
        "stakingRewards": 0,
        "delegationRewards": 0
      },
      ...
      {
        "cycle": 45,
        "rewards": 728742898,
        "delegatedBalance": 392200107338,
        "stakedBalance": 800335382962,
        "validator": {
          "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
        },
        "stakingRewards": 627916741,
        "delegationRewards": 100826157
      }
    ],
    "stakingPercentage": 99.3395467825461,
    "delegationPercentage": 100,
    "totalValidatorsUsed": 1,
    "currentValidatorCount": 1,
    "pastValidatorCount": 0,
    "firstRewardCycle": 45,
    "lastRewardCycle": 58,
    "totalCyclesWithRewards": 14
  },
  "actualRewards": {
    "totalActualRewards": 11348190541,
    "delegationPayouts": 1693286806,
    "delegationPayoutCount": 11,
    "stakingRewardsRestaked": 9654903735,
    "stakingRestakeCount": 12,
    "expectedDelegationRewards": 1187963556,
    "expectedStakingRewards": 9654903735,
    "expectedTotalRewards": 10842867291,
    "pendingDelegation": 0,
    "pendingStaking": 0,
    "pendingTotal": 0,
    "byValidator": [
      {
        "address": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ",
        "expectedStakingRewards": 9654903735,
        "expectedDelegationRewards": 1187963556,
        "expectedTotalGross": 10842867291,
        "actualDelegationPayouts": 1693286806,
        "actualStakingRestaked": 9654903735,
        "actualTotalReceived": 11348190541,
        "pendingDelegation": 0,
        "pendingStaking": 0,
        "pendingTotal": 0,
        "paymentStatus": "fully_paid",
        "paymentPercentage": 100,
        "cycleCount": 14,
        "firstCycle": 45,
        "lastCycle": 58,
        "stakingRewardsByCycle": [
          {
            "cycle": 56,
            "amount": 564158207
          },
          ...
          {
            "cycle": 45,
            "amount": 627916741
          }
        ],
        "stakingRestakeEventCount": 12,
        "delegationByCycle": [
          {
            "cycle": 56,
            "expectedReward": 1794137,
            "status": "overpaid",
            "validatorAddress": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
          },
          ....
          {
            "cycle": 45,
            "expectedReward": 100826157,
            "status": "paid",
            "validatorAddress": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
          }
        ]
      }
    ],
    "allStakingRewardEvents": [
      {
        "cycle": 56,
        "amount": 564158207,
        "validatorAddress": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
      },
      ...
      {
        "cycle": 45,
        "amount": 627916741,
        "validatorAddress": "mv1MtuibrK2PZpbJLhe1zkxfLq9HXwRsFWuZ"
      }
    ],
    "firstRewardDate": "2026-01-18T14:28:54Z",
    "lastRewardDate": "2026-02-16T01:25:04Z"
  },
  "estimatedNextPayout": "2026-02-17T08:27:37.1818181Z",
  "avgPayoutIntervalDays": 1.2934396043771
}

/// <summary>
/// Summary of rewards for a specific cycle
/// </summary>
public class CycleRewardSummary
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate of DelegatorRewards

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, they are not duplicates, because DelegatorRewards is the input model the service uses, and CycleRewardSummary is the output DTO that is derived from DelegatorRewards and returned to the client. It contains aggregated data from DelegatorRewards

new CycleRewardSummary
{
    Cycle = r.Cycle,
    Rewards = stakingReward + delegationReward,
    DelegatedBalance = r.DelegatedBalance,
    StakedBalance = r.StakedBalance,
    Validator = new Alias { Address = r.Baker?.Address, Name = r.Baker?.Name },
    StakingRewards = stakingReward,
    DelegationRewards = delegationReward
};

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 23, 2026

Deploying mvkt-atlasnet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3f13123
Status: ✅  Deploy successful!
Preview URL: https://4abdb95b.mvkt-atlasnet.pages.dev
Branch Preview URL: https://feature-delegation-info.mvkt-atlasnet.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying mvkt-mainnet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3f13123
Status: ✅  Deploy successful!
Preview URL: https://5e52d375.mvkt.pages.dev
Branch Preview URL: https://feature-delegation-info.mvkt.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying mvkt-basenet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3f13123
Status: ✅  Deploy successful!
Preview URL: https://cdc19b90.mvkt-basenet.pages.dev
Branch Preview URL: https://feature-delegation-info.mvkt-basenet.pages.dev

View logs

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

/// <summary>
/// Validator address
/// </summary>
public string Address { get; set; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the Alias table be used there?

"AllowedHosts": "*"
"AllowedHosts": "*",
"Delegation": {
"ValidatorPayoutAddresses": {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain this. Listing all validator payment addresses by hand per mvkt instance is something no one will do + payment addresses are dynamic

/// <summary>
/// Validator address
/// </summary>
public string ValidatorAddress { get; set; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the Alias table be used there?

/// <summary>
/// Baker (validator) address
/// </summary>
public string BakerAddress { get; set; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the Alias table be used there?

@0xVoronov
Copy link
Copy Markdown
Collaborator Author

This logic will be moved to the mvkt-bff service. @TristanAllaire

@0xVoronov 0xVoronov closed this Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants