Skip to content

Commit

Permalink
Merge pull request #1866 from lavanet/CNS-command-to-check-pools
Browse files Browse the repository at this point in the history
feat: add pool-rewards-breakdown command
  • Loading branch information
omerlavanet authored Dec 25, 2024
2 parents 9895046 + 410a091 commit 6c35934
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/lavad/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func main() {
testCmd.AddCommand(rpcprovider.CreateTestRPCProviderCobraCommand())
testCmd.AddCommand(statetracker.CreateEventsCobraCommand())
testCmd.AddCommand(utilscli.NewMultiSendTxCmd())
testCmd.AddCommand(utilscli.NewMultiCheckCmd())
testCmd.AddCommand(utilscli.NewQueryTotalGasCmd())

cmd.OverwriteFlagDefaults(rootCmd, map[string]string{
Expand Down
110 changes: 110 additions & 0 deletions utils/cli/multicheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package cli

import (
"encoding/csv"
"fmt"
"os"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/spf13/cobra"
)

func NewMultiCheckCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "multi-check [file.csv]",
Short: `queries the balances of an account against the csv file`,
Long: `queries the balances of an account against the csv file`,
Example: `lavad test multi-check output.csv
lavad test multi-check output.csv`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
retries, _ := cmd.Flags().GetInt(RPCRetriesFlagName)
bankQuerier := banktypes.NewQueryClient(clientCtx)

// Open the CSV file
file, err := os.Open(args[0])
if err != nil {
return err
}
defer file.Close()

// Create a new CSV reader
reader := csv.NewReader(file)

// Read all records
records, err := reader.ReadAll()
if err != nil {
return err
}

queryBalanceWithRetries := func(addr sdk.AccAddress) (*banktypes.QueryAllBalancesResponse, error) {
for i := 0; i < retries; i++ {
res, err := bankQuerier.AllBalances(cmd.Context(), &banktypes.QueryAllBalancesRequest{Address: addr.String()})
if err == nil {
// utils.LavaFormatDebug("query balance", utils.Attribute{Key: "address", Value: addr.String()}, utils.Attribute{Key: "balance", Value: res.Balances})
return res, nil
}
// else {
// utils.LavaFormatError("failed to query balance", err, utils.Attribute{Key: "address", Value: addr.String()})
// }
}
return nil, err
}

recordsLen := len(records)
lessThan := 0
others := 0
errors := 0
for i := 0; i < len(records); i++ {
fmt.Printf("\rProgress: %d/%d errors: %d, lessThan:%d, others:%d", i+1, recordsLen, errors, lessThan, others)
coins, err := sdk.ParseCoinsNormalized(records[i][1])
if err != nil {
fmt.Printf("failed decoding coins record %d\n", i)
return err
}

if coins.IsZero() {
fmt.Printf("invalid coins record %d\n", i)
return fmt.Errorf("must send positive amount")
}
toAddr, err := sdk.AccAddressFromBech32(records[i][0])
if err != nil {
return err
}

res, err := queryBalanceWithRetries(toAddr)
if err != nil || res == nil {
errors++
// utils.LavaFormatError("failed to query balance", err, utils.Attribute{Key: "address", Value: toAddr.String()})
continue
}
found, coin := coins.Find("ulava")
if found {
found, resCoin := res.Balances.Find("ulava")
if found && !resCoin.IsNil() && resCoin.IsGTE(coin) {
// this wallet has enough balance
others++
} else {
// fmt.Printf("wallet %s has less than expected\n", toAddr.String())
lessThan++
}
}
}
fmt.Printf("\n---- results ----\n\n")
fmt.Printf("less than: %d others: %d\n", lessThan, others)
return nil
},
}

cmd.Flags().Int(RPCRetriesFlagName, 3, "number of retries on rpc error")
flags.AddTxFlagsToCmd(cmd)

return cmd
}
1 change: 1 addition & 0 deletions x/subscription/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command {
cmd.AddCommand(CmdQueryParams())
cmd.AddCommand(CmdCurrent())
cmd.AddCommand(CmdEstimatedProviderRewards())
cmd.AddCommand(CmdPoolRewards())
cmd.AddCommand(CmdEstimatedValidatorsRewards())
cmd.AddCommand(CmdTrackedCuUsage())

Expand Down
119 changes: 119 additions & 0 deletions x/subscription/client/cli/query_estimated_rewards.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package cli

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/v4/utils"
dualstakingtypes "github.com/lavanet/lava/v4/x/dualstaking/types"
epochstoragetypes "github.com/lavanet/lava/v4/x/epochstorage/types"
"github.com/lavanet/lava/v4/x/subscription/types"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -62,3 +67,117 @@ func CmdEstimatedProviderRewards() *cobra.Command {

return cmd
}

func CmdPoolRewards() *cobra.Command {
cmd := &cobra.Command{
Use: "pool-rewards-breakdown",
Short: "Calculates estimated rewards for all pools",
Long: `estimate the total rewards a pool will give to all providers if the month ends now`,
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := types.NewQueryClient(clientCtx)

// get all provider addresses
provider := ""
epochStorageEueryClient := epochstoragetypes.NewQueryClient(clientCtx)
res, err := epochStorageEueryClient.ProviderMetaData(cmd.Context(), &epochstoragetypes.QueryProviderMetaDataRequest{Provider: provider})
if err != nil {
return err
}
addresses := []string{}

for _, meta := range res.GetMetaData() {
addresses = append(addresses, meta.GetProvider())
}
runEstimateWithRetries := func(req types.QueryEstimatedProviderRewardsRequest) (*types.QueryEstimatedRewardsResponse, error) {
res, err := queryClient.EstimatedProviderRewards(cmd.Context(), &req)
if err != nil {
res, err = queryClient.EstimatedProviderRewards(cmd.Context(), &req)
if err != nil {
res, err = queryClient.EstimatedProviderRewards(cmd.Context(), &req)
if err != nil {
return nil, err
}
}
}
return res, err
}

summary := map[string]types.EstimatedRewardInfo{}
total := sdk.DecCoins{}
for idx, provider := range addresses {
fmt.Printf("\rProgress: %d/%d", idx+1, len(addresses))
req := types.QueryEstimatedProviderRewardsRequest{Provider: provider}
res, err := runEstimateWithRetries(req)
if err != nil {
utils.LavaFormatError("failed to query provider", err, utils.Attribute{Key: "provider", Value: provider})
continue
}
total = summarizeForRes(res, summary, total)
dualStakingQueryClient := dualstakingtypes.NewQueryClient(clientCtx)
resDel, err := dualStakingQueryClient.ProviderDelegators(cmd.Context(), &dualstakingtypes.QueryProviderDelegatorsRequest{Provider: provider})
if err != nil {
resDel, err = dualStakingQueryClient.ProviderDelegators(cmd.Context(), &dualstakingtypes.QueryProviderDelegatorsRequest{Provider: provider})
if err != nil {
resDel, err = dualStakingQueryClient.ProviderDelegators(cmd.Context(), &dualstakingtypes.QueryProviderDelegatorsRequest{Provider: provider})
if err != nil {
return err
}
}
}
delegations := resDel.GetDelegations()
delLen := len(delegations)
for idx2, del := range delegations {
delegatorName := del.Delegator
fmt.Printf("\rProgress: %d/%d %d/%d: %s", idx+1, len(addresses), idx2+1, delLen, delegatorName)
req := types.QueryEstimatedProviderRewardsRequest{Provider: provider, AmountDelegator: delegatorName}
res, err := runEstimateWithRetries(req)
if err != nil {
utils.LavaFormatError("failed to query delegator rewards", err, utils.LogAttr("provider", provider), utils.LogAttr("delegator", delegatorName))
continue
}
total = summarizeForRes(res, summary, total)
}
}
fmt.Printf("\n---- results ----\n\n")
info := []types.EstimatedRewardInfo{}
for _, sumEntry := range summary {
info = append(info, sumEntry)
}
printMe := &types.QueryEstimatedRewardsResponse{
Info: info,
Total: total,
}
return clientCtx.PrintProto(printMe)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

func summarizeForRes(res *types.QueryEstimatedRewardsResponse, summary map[string]types.EstimatedRewardInfo, total sdk.DecCoins) sdk.DecCoins {
info := res.Info
for _, entry := range info {
if _, ok := summary[entry.Source]; !ok {
summary[entry.Source] = entry
} else {
entryIn := summary[entry.Source]
coinsArr := entry.Amount
for _, coin := range coinsArr {
entryIn.Amount = entryIn.Amount.Add(coin)
}
summary[entry.Source] = entryIn
}
}
for _, coin := range res.Total {
total = total.Add(coin)
}
return total
}

0 comments on commit 6c35934

Please sign in to comment.