From a19c591a6e0c76f8cf214db7c0c20598de53c088 Mon Sep 17 00:00:00 2001 From: Sean McGary Date: Wed, 22 Jan 2025 13:15:26 -0600 Subject: [PATCH] feat: ListClaimedRewardsByBlockRange and GetClaimedRewardsByBlock rpcs --- go.mod | 2 +- go.sum | 2 + pkg/rpcServer/rewardsHandlers.go | 47 +++++++++++++++++++- pkg/service/rewardsDataService/rewards.go | 53 +++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 7b447d82..631d9f10 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/DataDog/datadog-go/v5 v5.5.0 github.com/Layr-Labs/eigenlayer-contracts v0.4.1-holesky-pepe.0.20240813143901-00fc4b95e9c1 github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.13 - github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122185055-8ce2cc7afa86 + github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122190013-01d27f288892 github.com/ethereum/go-ethereum v1.14.9 github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index ffa7483c..efdbb302 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/Layr-Labs/protocol-apis v1.1.1-0.20250121193118-8112817d1079 h1:B1b9g github.com/Layr-Labs/protocol-apis v1.1.1-0.20250121193118-8112817d1079/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122185055-8ce2cc7afa86 h1:XfVh8deohE3LYXAjYOAjzD4wRPNgbIP3OjV6Syy0FIw= github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122185055-8ce2cc7afa86/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= +github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122190013-01d27f288892 h1:OJs2VEsSVhdrPcS+CcX6sWr2UOIYhFY473y0+QDaq/4= +github.com/Layr-Labs/protocol-apis v1.1.1-0.20250122190013-01d27f288892/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= diff --git a/pkg/rpcServer/rewardsHandlers.go b/pkg/rpcServer/rewardsHandlers.go index cee4fb3b..309f3071 100644 --- a/pkg/rpcServer/rewardsHandlers.go +++ b/pkg/rpcServer/rewardsHandlers.go @@ -4,6 +4,7 @@ import ( "context" "errors" rewardsV1 "github.com/Layr-Labs/protocol-apis/gen/protos/eigenlayer/sidecar/v1/rewards" + "github.com/Layr-Labs/sidecar/pkg/metaState/types" "github.com/Layr-Labs/sidecar/pkg/rewards" "github.com/Layr-Labs/sidecar/pkg/rewardsCalculatorQueue" "github.com/Layr-Labs/sidecar/pkg/service/rewardsDataService" @@ -240,8 +241,52 @@ func (rpc *RpcServer) GetSummarizedRewardsForEarner(ctx context.Context, req *re return nil, status.Error(codes.Unimplemented, "method GetSummarizedRewardsForEarner not implemented") } +// GetClaimedRewardsByBlock returns the claimed rewards for an earner for a specific block. func (rpc *RpcServer) GetClaimedRewardsByBlock(ctx context.Context, req *rewardsV1.GetClaimedRewardsByBlockRequest) (*rewardsV1.GetClaimedRewardsByBlockResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetClaimedRewardsByBlock not implemented") + blockHeight := req.GetBlockHeight() + + claims, err := rpc.rewardsDataService.ListClaimedRewardsByBlockRange(ctx, "", blockHeight, blockHeight) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &rewardsV1.GetClaimedRewardsByBlockResponse{ + Rewards: utils.Map(claims, func(c *types.RewardsClaimed, i uint64) *rewardsV1.ClaimedReward { + return &rewardsV1.ClaimedReward{ + Earner: c.Earner, + Claimer: c.Claimer, + Token: c.Token, + BlockNumber: c.BlockNumber, + } + }), + }, nil +} + +// ListClaimedRewardsByBlockRange returns the claimed rewards for each block in the given range (inclusive of start and end block heights). +func (rpc *RpcServer) ListClaimedRewardsByBlockRange(ctx context.Context, req *rewardsV1.ListClaimedRewardsByBlockRangeRequest) (*rewardsV1.ListClaimedRewardsByBlockRangeResponse, error) { + earner := req.GetEarnerAddress() + startBlockHeight := req.GetStartBlockHeight() + endBlockHeight := req.GetEndBlockHeight() + + if earner == "" { + return nil, status.Error(codes.InvalidArgument, "earner address is required") + } + + claims, err := rpc.rewardsDataService.ListClaimedRewardsByBlockRange(ctx, earner, startBlockHeight, endBlockHeight) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &rewardsV1.ListClaimedRewardsByBlockRangeResponse{ + Rewards: utils.Map(claims, func(c *types.RewardsClaimed, i uint64) *rewardsV1.ClaimedReward { + return &rewardsV1.ClaimedReward{ + Earner: c.Earner, + Claimer: c.Claimer, + Token: c.Token, + BlockNumber: c.BlockNumber, + } + }), + }, nil } func (rpc *RpcServer) ListDistributionRoots(ctx context.Context, req *rewardsV1.ListDistributionRootsRequest) (*rewardsV1.ListDistributionRootsResponse, error) { diff --git a/pkg/service/rewardsDataService/rewards.go b/pkg/service/rewardsDataService/rewards.go index 18e2ce49..93f4a951 100644 --- a/pkg/service/rewardsDataService/rewards.go +++ b/pkg/service/rewardsDataService/rewards.go @@ -3,7 +3,9 @@ package rewardsDataService import ( "context" "database/sql" + "fmt" "github.com/Layr-Labs/sidecar/internal/config" + "github.com/Layr-Labs/sidecar/pkg/metaState/types" "github.com/Layr-Labs/sidecar/pkg/rewards" "github.com/Layr-Labs/sidecar/pkg/rewards/rewardsTypes" "github.com/Layr-Labs/sidecar/pkg/service/baseDataService" @@ -75,3 +77,54 @@ func (rds *RewardsDataService) GetTotalClaimedRewards(ctx context.Context, earne } return claimedAmounts, nil } + +// ListClaimedRewardsByBlockRange returns a list of claimed rewards for a given earner within a block range. +// +// If earner is an empty string, all claimed rewards within the block range are returned. +func (rds *RewardsDataService) ListClaimedRewardsByBlockRange( + ctx context.Context, + earner string, + startBlockHeight uint64, + endBlockHeight uint64, +) ([]*types.RewardsClaimed, error) { + if endBlockHeight == 0 { + return nil, fmt.Errorf("endBlockHeight must be greater than 0") + } + if endBlockHeight < startBlockHeight { + return nil, fmt.Errorf("endBlockHeight must be greater than or equal to startBlockHeight") + } + + query := ` + select + rc.root, + rc.earner, + rc.claimer, + rc.recipient, + rc.token, + rc.claimed_amount, + rc.transaction_hash, + rc.block_number, + rc.log_index + from rewards_claimed as rc + where + block_number >= @startBlockHeight + and block_number <= @endBlockHeight + ` + args := []interface{}{ + sql.Named("startBlockHeight", startBlockHeight), + sql.Named("endBlockHeight", endBlockHeight), + } + if earner != "" { + query += " and earner = @earner" + args = append(args, sql.Named("earner", earner)) + } + query += " order by block_number, log_index" + + claimedRewards := make([]*types.RewardsClaimed, 0) + res := rds.db.Raw(query, args...).Scan(&claimedRewards) + + if res.Error != nil { + return nil, res.Error + } + return claimedRewards, nil +}