Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: clean up and tests 1 of n #203

Merged
merged 2 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 9 additions & 20 deletions pkg/rewards/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/types"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"

contractrewardscoordinator "github.com/Layr-Labs/eigenlayer-contracts/pkg/bindings/IRewardsCoordinator"
Expand All @@ -36,22 +35,13 @@ import (
"github.com/urfave/cli/v2"
)

type ClaimConfig struct {
Network string
RPCUrl string
EarnerAddress gethcommon.Address
RecipientAddress gethcommon.Address
ClaimerAddress gethcommon.Address
Output string
OutputType string
Broadcast bool
TokenAddresses []gethcommon.Address
RewardsCoordinatorAddress gethcommon.Address
ClaimTimestamp string
ChainID *big.Int
ProofStoreBaseURL string
Environment string
SignerConfig *types.SignerConfig
type elChainReader interface {
GetDistributionRootsLength(opts *bind.CallOpts) (*big.Int, error)
GetRootIndexFromHash(opts *bind.CallOpts, hash [32]byte) (uint32, error)
GetCurrentClaimableDistributionRoot(
opts *bind.CallOpts,
) (rewardscoordinator.IRewardsCoordinatorDistributionRoot, error)
CurrRewardsCalculationEndTimestamp(opts *bind.CallOpts) (uint32, error)
}

func ClaimCmd(p utils.Prompter) *cli.Command {
Expand Down Expand Up @@ -123,7 +113,7 @@ func Claim(cCtx *cli.Context, p utils.Prompter) error {
http.DefaultClient,
)

claimDate, rootIndex, err := getClaimDistributionRoot(ctx, config.ClaimTimestamp, df, elReader, logger)
claimDate, rootIndex, err := getClaimDistributionRoot(ctx, config.ClaimTimestamp, elReader, logger)
if err != nil {
return eigenSdkUtils.WrapError("failed to get claim distribution root", err)
}
Expand Down Expand Up @@ -275,8 +265,7 @@ func Claim(cCtx *cli.Context, p utils.Prompter) error {
func getClaimDistributionRoot(
ctx context.Context,
claimTimestamp string,
df *httpProofDataFetcher.HttpProofDataFetcher,
elReader *elcontracts.ChainReader,
elReader elChainReader,
logger logging.Logger,
) (string, uint32, error) {
if claimTimestamp == "latest" {
Expand Down
170 changes: 170 additions & 0 deletions pkg/rewards/claim_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,101 @@
package rewards

import (
"context"
"errors"
"flag"
"math/big"
"os"
"sort"
"testing"
"time"

"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/testutils"

rewardscoordinator "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IRewardsCoordinator"
"github.com/Layr-Labs/eigensdk-go/logging"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"

"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v2"
)

type fakeELReader struct {
roots []rewardscoordinator.IRewardsCoordinatorDistributionRoot
}

func newFakeELReader(now time.Time) *fakeELReader {
roots := make([]rewardscoordinator.IRewardsCoordinatorDistributionRoot, 0)
rootOne := rewardscoordinator.IRewardsCoordinatorDistributionRoot{
Root: [32]byte{0x01},
RewardsCalculationEndTimestamp: uint32(now.Add(-time.Hour).Unix()),
ActivatedAt: uint32(now.Add(time.Hour).Unix()),
Disabled: false,
}

// This is the current claimable distribution root
rootTwo := rewardscoordinator.IRewardsCoordinatorDistributionRoot{
Root: [32]byte{0x02},
RewardsCalculationEndTimestamp: uint32(now.Add(48 * -time.Hour).Unix()),
ActivatedAt: uint32(now.Add(-24 * time.Hour).Unix()),
Disabled: false,
}

rootThree := rewardscoordinator.IRewardsCoordinatorDistributionRoot{
Root: [32]byte{0x03},
RewardsCalculationEndTimestamp: uint32(now.Add(32 * -time.Hour).Unix()),
ActivatedAt: uint32(now.Add(-12 * time.Minute).Unix()),
Disabled: true,
}

roots = append(roots, rootOne, rootTwo, rootThree)
// ascending sort order
sort.Slice(roots, func(i, j int) bool {
return roots[i].ActivatedAt < roots[j].ActivatedAt
})
return &fakeELReader{
roots: roots,
}
}

func (f *fakeELReader) GetDistributionRootsLength(opts *bind.CallOpts) (*big.Int, error) {
return big.NewInt(int64(len(f.roots))), nil
}

func (f *fakeELReader) GetRootIndexFromHash(opts *bind.CallOpts, hash [32]byte) (uint32, error) {
for i, root := range f.roots {
if root.Root == hash {
return uint32(i), nil
}
}
return 0, nil
}

func (f *fakeELReader) GetCurrentClaimableDistributionRoot(
opts *bind.CallOpts,
) (rewardscoordinator.IRewardsCoordinatorDistributionRoot, error) {
// iterate from end to start since we want the latest active root
// and the roots are sorted in ascending order of activation time
for i := len(f.roots) - 1; i >= 0; i-- {
if !f.roots[i].Disabled && f.roots[i].ActivatedAt < uint32(time.Now().Unix()) {
return f.roots[i], nil
}
}

return rewardscoordinator.IRewardsCoordinatorDistributionRoot{}, errors.New("no active distribution root found")
}

func (f *fakeELReader) CurrRewardsCalculationEndTimestamp(opts *bind.CallOpts) (uint32, error) {
rootLen, err := f.GetDistributionRootsLength(opts)
if err != nil {
return 0, err
}
return f.roots[rootLen.Uint64()-1].RewardsCalculationEndTimestamp, nil
}

func TestReadAndValidateConfig_NoRecipientProvided(t *testing.T) {
earnerAddress := testutils.GenerateRandomEthereumAddressString()
fs := flag.NewFlagSet("test", flag.ContinueOnError)
Expand Down Expand Up @@ -52,3 +133,92 @@ func TestReadAndValidateConfig_RecipientProvided(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, common.HexToAddress(recipientAddress), config.RecipientAddress)
}

func TestReadAndValidateConfig_NoClaimerProvided(t *testing.T) {
earnerAddress := testutils.GenerateRandomEthereumAddressString()
fs := flag.NewFlagSet("test", flag.ContinueOnError)
fs.String(flags.ETHRpcUrlFlag.Name, "rpc", "")
fs.String(EarnerAddressFlag.Name, earnerAddress, "")
fs.String(RewardsCoordinatorAddressFlag.Name, "0x1234", "")
fs.String(ClaimTimestampFlag.Name, "latest", "")
fs.String(ProofStoreBaseURLFlag.Name, "dummy-url", "")
cliCtx := cli.NewContext(nil, fs, nil)

logger := logging.NewJsonSLogger(os.Stdout, &logging.SLoggerOptions{})

config, err := readAndValidateClaimConfig(cliCtx, logger)

assert.NoError(t, err)
assert.Equal(t, common.HexToAddress(earnerAddress), config.ClaimerAddress)
}

func TestReadAndValidateConfig_ClaimerProvided(t *testing.T) {
claimerAddress := testutils.GenerateRandomEthereumAddressString()
fs := flag.NewFlagSet("test", flag.ContinueOnError)
fs.String(flags.ETHRpcUrlFlag.Name, "rpc", "")
fs.String(ClaimerAddressFlag.Name, claimerAddress, "")
fs.String(RewardsCoordinatorAddressFlag.Name, "0x1234", "")
fs.String(ClaimTimestampFlag.Name, "latest", "")
fs.String(ProofStoreBaseURLFlag.Name, "dummy-url", "")
cliCtx := cli.NewContext(nil, fs, nil)

logger := logging.NewJsonSLogger(os.Stdout, &logging.SLoggerOptions{})

config, err := readAndValidateClaimConfig(cliCtx, logger)

assert.NoError(t, err)
assert.Equal(t, common.HexToAddress(claimerAddress), config.ClaimerAddress)
}

func TestGetClaimDistributionRoot(t *testing.T) {
now := time.Now()

tests := []struct {
name string
claimTimestamp string
expectErr bool
expectedClaimDate string
expectedRootIndex uint32
}{
{
name: "latest root",
claimTimestamp: "latest",
expectErr: false,
expectedClaimDate: now.Add(-time.Hour).UTC().Format(time.DateOnly),
expectedRootIndex: 2,
},
{
name: "latest active root",
claimTimestamp: "latest_active",
expectErr: false,
expectedClaimDate: now.Add(-48 * time.Hour).UTC().Format(time.DateOnly),
expectedRootIndex: 0,
},
{
name: "none of them",
claimTimestamp: "none",
expectErr: true,
},
}

reader := newFakeELReader(now)
logger := logging.NewJsonSLogger(os.Stdout, &logging.SLoggerOptions{})

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
claimDate, rootIndex, err := getClaimDistributionRoot(
context.Background(),
tt.claimTimestamp,
reader,
logger,
)
if tt.expectErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedClaimDate, claimDate)
assert.Equal(t, tt.expectedRootIndex, rootIndex)
})
}
}
15 changes: 0 additions & 15 deletions pkg/rewards/setclaimer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package rewards
import (
"context"
"fmt"
"math/big"
"sort"

"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/types"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
Expand All @@ -23,19 +21,6 @@ import (
"github.com/urfave/cli/v2"
)

type SetClaimerConfig struct {
ClaimerAddress gethcommon.Address
Network string
RPCUrl string
Broadcast bool
RewardsCoordinatorAddress gethcommon.Address
ChainID *big.Int
SignerConfig *types.SignerConfig
EarnerAddress gethcommon.Address
Output string
OutputType string
}

func SetClaimerCmd(p utils.Prompter) *cli.Command {
setClaimerCmd := &cli.Command{
Name: "set-claimer",
Expand Down
10 changes: 0 additions & 10 deletions pkg/rewards/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@ const (
GetEarnedTokensForStrategyEndpoint = "grpc/eigenlayer.RewardsService/GetEarnedTokensForStrategy"
)

type ShowConfig struct {
EarnerAddress gethcommon.Address
NumberOfDays int64
Network string
Environment string
ClaimType ClaimType
ChainID *big.Int
Output string
}

func ShowCmd(p utils.Prompter) *cli.Command {
showCmd := &cli.Command{
Name: "show",
Expand Down
48 changes: 47 additions & 1 deletion pkg/rewards/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package rewards

import "math/big"
import (
"math/big"

"github.com/Layr-Labs/eigenlayer-cli/pkg/types"
gethcommon "github.com/ethereum/go-ethereum/common"
)

type RewardResponse struct {
Rewards []Reward `json:"rewards"`
Expand Down Expand Up @@ -37,3 +42,44 @@ type NormalizedUnclaimedReward struct {
TokenAddress string `csv:"tokenAddress"`
WeiAmount *big.Int `csv:"weiAmount"`
}

type ClaimConfig struct {
Network string
RPCUrl string
EarnerAddress gethcommon.Address
RecipientAddress gethcommon.Address
ClaimerAddress gethcommon.Address
Output string
OutputType string
Broadcast bool
TokenAddresses []gethcommon.Address
RewardsCoordinatorAddress gethcommon.Address
ClaimTimestamp string
ChainID *big.Int
ProofStoreBaseURL string
Environment string
SignerConfig *types.SignerConfig
}

type SetClaimerConfig struct {
ClaimerAddress gethcommon.Address
Network string
RPCUrl string
Broadcast bool
RewardsCoordinatorAddress gethcommon.Address
ChainID *big.Int
SignerConfig *types.SignerConfig
EarnerAddress gethcommon.Address
Output string
OutputType string
}

type ShowConfig struct {
EarnerAddress gethcommon.Address
NumberOfDays int64
Network string
Environment string
ClaimType ClaimType
ChainID *big.Int
Output string
}
Loading