From 8ff02d704d17135b0114041743fadf452ab357be Mon Sep 17 00:00:00 2001 From: Jiri Date: Tue, 15 Oct 2024 15:24:41 +0200 Subject: [PATCH] Info command --- app/upgrade_cudos.go | 138 ++++++++++++++++++++---------- app/upgrade_cudos_distribution.go | 50 +++++------ cmd/fetchd/cmd/cudos_merge.go | 123 +++++++++++++++++++++++++- 3 files changed, 241 insertions(+), 70 deletions(-) diff --git a/app/upgrade_cudos.go b/app/upgrade_cudos.go index c53f60a4..7bea9a1b 100644 --- a/app/upgrade_cudos.go +++ b/app/upgrade_cudos.go @@ -111,10 +111,12 @@ type GenesisData struct { Prefix string BondDenom string - Accounts *OrderedMap[string, *AccountInfo] - Contracts *OrderedMap[string, *ContractInfo] - IbcAccounts *OrderedMap[string, *IBCInfo] - Delegations *OrderedMap[string, *OrderedMap[string, sdk.Int]] + Accounts *OrderedMap[string, *AccountInfo] + Contracts *OrderedMap[string, *ContractInfo] + IbcAccounts *OrderedMap[string, *IBCInfo] + Delegations *OrderedMap[string, *OrderedMap[string, sdk.Int]] + UnbondedDelegations *OrderedMap[string, *OrderedMap[string, sdk.Int]] + UnbondingDelegations *OrderedMap[string, *OrderedMap[string, sdk.Int]] Validators *OrderedMap[string, *ValidatorInfo] BondedPoolAddress string @@ -333,11 +335,16 @@ func ParseGenesisData(jsonData map[string]interface{}, genDoc *tmtypes.GenesisDo return nil, fmt.Errorf("failed to get validators map: %w", err) } - genesisData.Delegations, err = parseGenesisDelegations(genesisData.Validators, genesisData.Contracts, cudosCfg) + genesisData.Delegations, genesisData.UnbondedDelegations, err = parseGenesisDelegations(genesisData.Validators, genesisData.Contracts, cudosCfg) if err != nil { return nil, fmt.Errorf("failed to get delegations map: %w", err) } + genesisData.UnbondingDelegations, err = parseGenesisUnbondingDelegations(genesisData.Validators, genesisData.Contracts, cudosCfg) + if err != nil { + return nil, fmt.Errorf("failed to get unbonding delegations map: %w", err) + } + distributionInfo, err := parseGenesisDistribution(jsonData, genesisData.Accounts) if err != nil { return nil, fmt.Errorf("failed to get distribution module map: %w", err) @@ -585,22 +592,24 @@ func parseGenesisAccounts(jsonData map[string]interface{}, contractAccountMap *O return accountMap, nil } -func parseGenesisDelegations(validators *OrderedMap[string, *ValidatorInfo], contracts *OrderedMap[string, *ContractInfo], cudosCfg *CudosMergeConfig) (*OrderedMap[string, *OrderedMap[string, sdk.Int]], error) { +func parseGenesisDelegations(validators *OrderedMap[string, *ValidatorInfo], contracts *OrderedMap[string, *ContractInfo], cudosCfg *CudosMergeConfig) (*OrderedMap[string, *OrderedMap[string, sdk.Int]], *OrderedMap[string, *OrderedMap[string, sdk.Int]], error) { // Handle delegations delegatedBalanceMap := NewOrderedMap[string, *OrderedMap[string, sdk.Int]]() + unbondingDelegatedBalanceMap := NewOrderedMap[string, *OrderedMap[string, sdk.Int]]() + for i := range validators.Iterate() { validatorOperatorAddress, validator := i.Key, i.Value - for j := range validator.delegations.Iterate() { + for j := range validator.Delegations.Iterate() { delegatorAddress, delegation := j.Key, j.Value resolvedDelegatorAddress, err := resolveIfContractAddressWithFallback(delegatorAddress, contracts, cudosCfg) if err != nil { - return nil, err + return nil, nil, err } currentValidatorInfo := validators.MustGet(validatorOperatorAddress) - delegatorTokens := currentValidatorInfo.TokensFromShares(delegation.shares).TruncateInt() + delegatorTokens := currentValidatorInfo.TokensFromShares(delegation.Shares).TruncateInt() if delegatorTokens.IsZero() { // This happens when number of shares is less than 1 @@ -608,49 +617,92 @@ func parseGenesisDelegations(validators *OrderedMap[string, *ValidatorInfo], con } // Subtract balance from bonded or not-bonded pool - if currentValidatorInfo.status == BondedStatus { + if currentValidatorInfo.Status == BondedStatus { // Store delegation to delegated map resolvedDelegatorMap, _ := delegatedBalanceMap.GetOrSetDefault(resolvedDelegatorAddress, NewOrderedMap[string, sdk.Int]()) resolvedDelegator, _ := resolvedDelegatorMap.GetOrSetDefault(validatorOperatorAddress, sdk.NewInt(0)) resolvedDelegatorMap.Set(validatorOperatorAddress, resolvedDelegator.Add(delegatorTokens)) delegatedBalanceMap.Set(resolvedDelegatorAddress, resolvedDelegatorMap) + } else { + // Store delegation to delegated map + resolvedDelegatorMap, _ := unbondingDelegatedBalanceMap.GetOrSetDefault(resolvedDelegatorAddress, NewOrderedMap[string, sdk.Int]()) + resolvedDelegator, _ := resolvedDelegatorMap.GetOrSetDefault(validatorOperatorAddress, sdk.NewInt(0)) + resolvedDelegatorMap.Set(validatorOperatorAddress, resolvedDelegator.Add(delegatorTokens)) + unbondingDelegatedBalanceMap.Set(resolvedDelegatorAddress, resolvedDelegatorMap) + } + } + } + + return delegatedBalanceMap, unbondingDelegatedBalanceMap, nil +} + +func parseGenesisUnbondingDelegations(validators *OrderedMap[string, *ValidatorInfo], contracts *OrderedMap[string, *ContractInfo], cudosCfg *CudosMergeConfig) (*OrderedMap[string, *OrderedMap[string, sdk.Int]], error) { + // Handle delegations + unbondedDelegatedBalanceMap := NewOrderedMap[string, *OrderedMap[string, sdk.Int]]() + + for i := range validators.Iterate() { + validatorOperatorAddress, validator := i.Key, i.Value + + for j := range validator.UnbondingDelegations.Iterate() { + delegatorAddress, delegation := j.Key, j.Value + + resolvedDelegatorAddress, err := resolveIfContractAddressWithFallback(delegatorAddress, contracts, cudosCfg) + if err != nil { + return nil, err } + + delegatorTokens := sdk.NewInt(0) + + for _, entry := range delegation.Entries { + delegatorTokens = delegatorTokens.Add(entry.Balance) + } + + if delegatorTokens.IsZero() { + // This happens when number of shares is less than 1 + continue + } + + // Store delegation to delegated map + resolvedDelegatorMap, _ := unbondedDelegatedBalanceMap.GetOrSetDefault(resolvedDelegatorAddress, NewOrderedMap[string, sdk.Int]()) + resolvedDelegator, _ := resolvedDelegatorMap.GetOrSetDefault(validatorOperatorAddress, sdk.NewInt(0)) + resolvedDelegatorMap.Set(validatorOperatorAddress, resolvedDelegator.Add(delegatorTokens)) + unbondedDelegatedBalanceMap.Set(resolvedDelegatorAddress, resolvedDelegatorMap) } } - return delegatedBalanceMap, nil + return unbondedDelegatedBalanceMap, nil } type DelegationInfo struct { - delegatorAddress string - shares sdk.Dec + DelegatorAddress string + Shares sdk.Dec } type UnbondingDelegationInfo struct { - delegatorAddress string - entries []*UnbondingDelegationEntry + DelegatorAddress string + Entries []*UnbondingDelegationEntry } type UnbondingDelegationEntry struct { - balance sdk.Int - initialBalance sdk.Int - creationHeight uint64 - completionTime string + Balance sdk.Int + InitialBalance sdk.Int + CreationHeight uint64 + CompletionTime string } type ValidatorInfo struct { - stake sdk.Int - shares sdk.Dec - status string - operatorAddress string - consensusPubkey cryptotypes.PubKey - delegations *OrderedMap[string, *DelegationInfo] - unbondingDelegations *OrderedMap[string, *UnbondingDelegationInfo] + Stake sdk.Int + Shares sdk.Dec + Status string + OperatorAddress string + ConsensusPubkey cryptotypes.PubKey + Delegations *OrderedMap[string, *DelegationInfo] + UnbondingDelegations *OrderedMap[string, *UnbondingDelegationInfo] } func (v ValidatorInfo) TokensFromShares(shares sdk.Dec) sdk.Dec { - return (shares.MulInt(v.stake)).Quo(v.shares) + return (shares.MulInt(v.Stake)).Quo(v.Shares) } func parseGenesisValidators(jsonData map[string]interface{}) (*OrderedMap[string, *ValidatorInfo], error) { @@ -687,13 +739,13 @@ func parseGenesisValidators(jsonData map[string]interface{}) (*OrderedMap[string } validatorInfoMap.SetNew(operatorAddress, &ValidatorInfo{ - stake: tokensInt, - shares: validatorSharesDec, - status: status, - operatorAddress: operatorAddress, - consensusPubkey: decodedConsensusPubkey, - delegations: NewOrderedMap[string, *DelegationInfo](), - unbondingDelegations: NewOrderedMap[string, *UnbondingDelegationInfo](), + Stake: tokensInt, + Shares: validatorSharesDec, + Status: status, + OperatorAddress: operatorAddress, + ConsensusPubkey: decodedConsensusPubkey, + Delegations: NewOrderedMap[string, *DelegationInfo](), + UnbondingDelegations: NewOrderedMap[string, *UnbondingDelegationInfo](), }) } @@ -711,7 +763,7 @@ func parseGenesisValidators(jsonData map[string]interface{}) (*OrderedMap[string } validator := validatorInfoMap.MustGet(validatorAddress) - validator.delegations.SetNew(delegatorAddress, &DelegationInfo{delegatorAddress: delegatorAddress, shares: delegatorSharesDec}) + validator.Delegations.SetNew(delegatorAddress, &DelegationInfo{DelegatorAddress: delegatorAddress, Shares: delegatorSharesDec}) } unbondingDelegations := staking["unbonding_delegations"].([]interface{}) @@ -740,11 +792,11 @@ func parseGenesisValidators(jsonData map[string]interface{}) (*OrderedMap[string completionTime := entryMap["completion_time"].(string) - unbondingDelegationEntries = append(unbondingDelegationEntries, &UnbondingDelegationEntry{balance: balance, initialBalance: initialBalance, creationHeight: creationHeight, completionTime: completionTime}) + unbondingDelegationEntries = append(unbondingDelegationEntries, &UnbondingDelegationEntry{Balance: balance, InitialBalance: initialBalance, CreationHeight: creationHeight, CompletionTime: completionTime}) } validator := validatorInfoMap.MustGet(validatorAddress) - validator.unbondingDelegations.SetNew(delegatorAddress, &UnbondingDelegationInfo{delegatorAddress: delegatorAddress, entries: unbondingDelegationEntries}) + validator.UnbondingDelegations.SetNew(delegatorAddress, &UnbondingDelegationInfo{DelegatorAddress: delegatorAddress, Entries: unbondingDelegationEntries}) } return validatorInfoMap, nil @@ -755,7 +807,7 @@ func withdrawGenesisStakingDelegations(logger log.Logger, genesisData *GenesisDa for i := range genesisData.Validators.Iterate() { validatorOperatorAddress, validator := i.Key, i.Value - for j := range validator.delegations.Iterate() { + for j := range validator.Delegations.Iterate() { delegatorAddress, delegation := j.Key, j.Value resolvedDelegatorAddress, err := resolveIfContractAddressWithFallback(delegatorAddress, genesisData.Contracts, cudosCfg) @@ -764,7 +816,7 @@ func withdrawGenesisStakingDelegations(logger log.Logger, genesisData *GenesisDa } currentValidatorInfo := genesisData.Validators.MustGet(validatorOperatorAddress) - delegatorTokens := currentValidatorInfo.TokensFromShares(delegation.shares).TruncateInt() + delegatorTokens := currentValidatorInfo.TokensFromShares(delegation.Shares).TruncateInt() // Move balance to delegator Address delegatorBalance := sdk.NewCoins(sdk.NewCoin(genesisData.BondDenom, delegatorTokens)) @@ -775,7 +827,7 @@ func withdrawGenesisStakingDelegations(logger log.Logger, genesisData *GenesisDa } // Subtract balance from bonded or not-bonded pool - if currentValidatorInfo.status == BondedStatus { + if currentValidatorInfo.Status == BondedStatus { // Move balance from bonded pool to delegator err := moveGenesisBalance(genesisData, genesisData.BondedPoolAddress, resolvedDelegatorAddress, delegatorBalance, "bonded_delegation", manifest, cudosCfg) if err != nil { @@ -795,7 +847,7 @@ func withdrawGenesisStakingDelegations(logger log.Logger, genesisData *GenesisDa } // Handle unbonding delegations - for j := range validator.unbondingDelegations.Iterate() { + for j := range validator.UnbondingDelegations.Iterate() { delegatorAddress, unbondingDelegation := j.Key, j.Value resolvedDelegatorAddress, err := resolveIfContractAddressWithFallback(delegatorAddress, genesisData.Contracts, cudosCfg) @@ -803,8 +855,8 @@ func withdrawGenesisStakingDelegations(logger log.Logger, genesisData *GenesisDa return err } - for _, entry := range unbondingDelegation.entries { - unbondingDelegationBalance := sdk.NewCoins(sdk.NewCoin(genesisData.BondDenom, entry.balance)) + for _, entry := range unbondingDelegation.Entries { + unbondingDelegationBalance := sdk.NewCoins(sdk.NewCoin(genesisData.BondDenom, entry.Balance)) // Move unbonding balance from not-bonded pool to delegator Address err := moveGenesisBalance(genesisData, genesisData.NotBondedPoolAddress, resolvedDelegatorAddress, unbondingDelegationBalance, "unbonding_delegation", manifest, cudosCfg) diff --git a/app/upgrade_cudos_distribution.go b/app/upgrade_cudos_distribution.go index 55d17519..cac16832 100644 --- a/app/upgrade_cudos_distribution.go +++ b/app/upgrade_cudos_distribution.go @@ -332,10 +332,10 @@ func withdrawGenesisDistributionRewards(logger log.Logger, genesisData *GenesisD delegatorStartInfo := genesisData.DistributionInfo.DelegatorStartingInfos.MustGet(validatorOpertorAddr) - endingPeriod := updateValidatorData(genesisData.DistributionInfo, validator) + endingPeriod := UpdateValidatorData(genesisData.DistributionInfo, validator) for _, delegatorAddr := range delegatorStartInfo.Keys() { - delegation := validator.delegations.MustGet(delegatorAddr) + delegation := validator.Delegations.MustGet(delegatorAddr) _, err := withdrawDelegationRewards(logger, genesisData, validator, delegation, endingPeriod, blockHeight, cudosCfg, manifest) if err != nil { @@ -441,7 +441,7 @@ func calculateDelegationRewardsBetween(distributionInfo *DistributionInfo, val * // return staking * (ending - starting) - operatorRewards := distributionInfo.ValidatorHistoricalRewards.MustGet(val.operatorAddress) + operatorRewards := distributionInfo.ValidatorHistoricalRewards.MustGet(val.OperatorAddress) starting := operatorRewards.MustGet(startingPeriod) ending := operatorRewards.MustGet(endingPeriod) @@ -490,10 +490,10 @@ func IterateValidatorSlashEventsBetween(distributionInfo *DistributionInfo, val } // calculate the total rewards accrued by a delegation -func calculateDelegationRewards(blockHeight uint64, distributionInfo *DistributionInfo, val *ValidatorInfo, del *DelegationInfo, endingPeriod uint64) (rewards sdk.DecCoins, err error) { +func CalculateDelegationRewards(blockHeight uint64, distributionInfo *DistributionInfo, val *ValidatorInfo, del *DelegationInfo, endingPeriod uint64) (rewards sdk.DecCoins, err error) { // fetch starting info for delegation - delStartingInfo := distributionInfo.DelegatorStartingInfos.MustGet(val.operatorAddress) - startingInfo := delStartingInfo.MustGet(del.delegatorAddress) + delStartingInfo := distributionInfo.DelegatorStartingInfos.MustGet(val.OperatorAddress) + startingInfo := delStartingInfo.MustGet(del.DelegatorAddress) if startingInfo.height == blockHeight { // started this height, no rewards yet @@ -515,7 +515,7 @@ func calculateDelegationRewards(blockHeight uint64, distributionInfo *Distributi // for them for the stake sanity check below. endingHeight := blockHeight if endingHeight > startingHeight { - err := IterateValidatorSlashEventsBetween(distributionInfo, val.operatorAddress, startingHeight, endingHeight, + err := IterateValidatorSlashEventsBetween(distributionInfo, val.OperatorAddress, startingHeight, endingHeight, func(height uint64, event *ValidatorSlashEvent) (stop bool, err error) { endingPeriod := event.validatorPeriod if endingPeriod > startingPeriod { @@ -541,7 +541,7 @@ func calculateDelegationRewards(blockHeight uint64, distributionInfo *Distributi // equal to current stake here. We cannot use Equals because stake is truncated // when multiplied by slash fractions (see above). We could only use equals if // we had arbitrary-precision rationals. - currentStake := val.TokensFromShares(del.shares) + currentStake := val.TokensFromShares(del.Shares) if stake.GT(currentStake) { // AccountI for rounding inconsistencies between: @@ -571,7 +571,7 @@ func calculateDelegationRewards(blockHeight uint64, distributionInfo *Distributi return sdk.DecCoins{}, fmt.Errorf("calculated final stake for delegator %s greater than current stake"+ "\n\tfinal stake:\t%s"+ "\n\tcurrent stake:\t%s", - del.delegatorAddress, stake, currentStake) + del.DelegatorAddress, stake, currentStake) } } @@ -597,19 +597,19 @@ func (d DistributionInfo) GetDelegatorWithdrawAddr(delAddr string) string { func withdrawDelegationRewards(logger log.Logger, genesisData *GenesisData, val *ValidatorInfo, del *DelegationInfo, endingPeriod uint64, blockHeight uint64, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) (sdk.Coins, error) { // check existence of delegator starting info - genesisData.DistributionInfo.DelegatorStartingInfos.Has(val.operatorAddress) - StartingInfoMap, exists := genesisData.DistributionInfo.DelegatorStartingInfos.Get(val.operatorAddress) - if !exists || !StartingInfoMap.Has(del.delegatorAddress) { + genesisData.DistributionInfo.DelegatorStartingInfos.Has(val.OperatorAddress) + StartingInfoMap, exists := genesisData.DistributionInfo.DelegatorStartingInfos.Get(val.OperatorAddress) + if !exists || !StartingInfoMap.Has(del.DelegatorAddress) { return nil, fmt.Errorf("delegator starting info not found") } // end current period and calculate rewards //endingPeriod := k.IncrementValidatorPeriod(ctx, val) - rewardsRaw, err := calculateDelegationRewards(blockHeight, genesisData.DistributionInfo, val, del, endingPeriod) + rewardsRaw, err := CalculateDelegationRewards(blockHeight, genesisData.DistributionInfo, val, del, endingPeriod) if err != nil { return nil, err } - outstanding := genesisData.DistributionInfo.OutstandingRewards.MustGet(val.operatorAddress) + outstanding := genesisData.DistributionInfo.OutstandingRewards.MustGet(val.OperatorAddress) // defensive edge case may happen on the very final digits // of the decCoins due to operation order of the distribution mechanism. @@ -618,8 +618,8 @@ func withdrawDelegationRewards(logger log.Logger, genesisData *GenesisData, val if logger != nil { logger.Error( "rounding error withdrawing rewards from validator", - "delegator", del.delegatorAddress, - "validator", val.operatorAddress, + "delegator", del.DelegatorAddress, + "validator", val.OperatorAddress, "got", rewards.String(), "expected", rewardsRaw.String(), ) @@ -631,7 +631,7 @@ func withdrawDelegationRewards(logger log.Logger, genesisData *GenesisData, val // add coins to user account if !finalRewards.IsZero() { - withdrawAddr := genesisData.DistributionInfo.GetDelegatorWithdrawAddr(del.delegatorAddress) + withdrawAddr := genesisData.DistributionInfo.GetDelegatorWithdrawAddr(del.DelegatorAddress) // SendCoinsFromModuleToAccount err := moveGenesisBalance(genesisData, genesisData.DistributionInfo.DistributionModuleAccountAddress, withdrawAddr, finalRewards, "delegation_reward", manifest, cudosCfg) @@ -643,7 +643,7 @@ func withdrawDelegationRewards(logger log.Logger, genesisData *GenesisData, val // update the outstanding rewards and the community pool only if the // transaction was successful - genesisData.DistributionInfo.OutstandingRewards.Set(val.operatorAddress, outstanding.Sub(rewards)) + genesisData.DistributionInfo.OutstandingRewards.Set(val.OperatorAddress, outstanding.Sub(rewards)) genesisData.DistributionInfo.FeePool.CommunityPool = genesisData.DistributionInfo.FeePool.CommunityPool.Add(remainder...) // decrement reference count of starting period @@ -682,31 +682,31 @@ func withdrawDelegationRewards(logger log.Logger, genesisData *GenesisData, val } // Code based on IncrementValidatorPeriod -func updateValidatorData(distributionInfo *DistributionInfo, val *ValidatorInfo) uint64 { +func UpdateValidatorData(distributionInfo *DistributionInfo, val *ValidatorInfo) uint64 { // fetch current rewards - rewards := distributionInfo.ValidatorCurrentRewards.MustGet(val.operatorAddress) + rewards := distributionInfo.ValidatorCurrentRewards.MustGet(val.OperatorAddress) // calculate current ratio var current sdk.DecCoins - if val.stake.IsZero() { + if val.Stake.IsZero() { // can't calculate ratio for zero-token validators // ergo we instead add to the community pool - outstanding := distributionInfo.OutstandingRewards.MustGet(val.operatorAddress) + outstanding := distributionInfo.OutstandingRewards.MustGet(val.OperatorAddress) distributionInfo.FeePool.CommunityPool = distributionInfo.FeePool.CommunityPool.Add(rewards.reward...) outstanding = outstanding.Sub(rewards.reward) - distributionInfo.OutstandingRewards.Set(val.operatorAddress, outstanding) + distributionInfo.OutstandingRewards.Set(val.OperatorAddress, outstanding) current = sdk.DecCoins{} } else { // note: necessary to truncate so we don't allow withdrawing more rewards than owed - current = rewards.reward.QuoDecTruncate(val.stake.ToDec()) + current = rewards.reward.QuoDecTruncate(val.Stake.ToDec()) } // fetch historical rewards for last period //historical := k.GetValidatorHistoricalRewards(ctx, val.GetOperator(), rewards.Period-1).CumulativeRewardRatio - historicalValInfo := distributionInfo.ValidatorHistoricalRewards.MustGet(val.operatorAddress) + historicalValInfo := distributionInfo.ValidatorHistoricalRewards.MustGet(val.OperatorAddress) historical := historicalValInfo.MustGet(rewards.period - 1) // decrement reference count diff --git a/cmd/fetchd/cmd/cudos_merge.go b/cmd/fetchd/cmd/cudos_merge.go index 6c681d69..9592481b 100644 --- a/cmd/fetchd/cmd/cudos_merge.go +++ b/cmd/fetchd/cmd/cudos_merge.go @@ -5,10 +5,12 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/fetchai/fetchd/app" "github.com/spf13/cobra" "github.com/tendermint/tendermint/libs/log" + "math" "os" ) @@ -296,16 +298,133 @@ func ExtractAddressInfo(configFilePath string, GenesisFilePath string, address s } func printAccInfo(genesisData *app.GenesisData, address string, ctx client.Context) error { + totalAvailableBalance := sdk.NewCoins() + accountInfo, exists := genesisData.Accounts.Get(address) if !exists { - err := ctx.PrintString(fmt.Sprintf("Account %s doesn't exist", address)) + err := ctx.PrintString(fmt.Sprintf("Account %s doesn't exist\n", address)) if err != nil { return err } return nil } - print(accountInfo.Balance.String()) + err := ctx.PrintString(fmt.Sprintf("Account type: %s\n", accountInfo.AccountType)) + if err != nil { + return err + } + + if accountInfo.Name != "" { + err = ctx.PrintString(fmt.Sprintf("Account name: %s\n", accountInfo.Name)) + if err != nil { + return err + } + } + + if !accountInfo.OriginalVesting.IsZero() { + err = ctx.PrintString(fmt.Sprintf("Vested balance: %s\n", accountInfo.OriginalVesting)) + if err != nil { + return err + } + } + + // Get bank balance + totalAvailableBalance = totalAvailableBalance.Add(accountInfo.Balance...) + err = ctx.PrintString(fmt.Sprintf("Bank balance: %s\n", accountInfo.Balance)) + if err != nil { + return err + } + + // Bonded tokens + err = ctx.PrintString("Balance in delegations:\n") + if err != nil { + return err + } + if delegations, exists := genesisData.Delegations.Get(address); exists { + for i := range delegations.Iterate() { + validatorAddress, delegatedAmount := i.Key, i.Value + delegatedBalance := sdk.NewCoin(genesisData.BondDenom, delegatedAmount) + totalAvailableBalance = totalAvailableBalance.Add(delegatedBalance) + err = ctx.PrintString(fmt.Sprintf("%s, %s\n", validatorAddress, delegatedBalance)) + if err != nil { + return err + } + } + } + + // Unbonding tokens + err = ctx.PrintString("Balance in unbonding delegations:\n") + if err != nil { + return err + } + if delegations, exists := genesisData.UnbondingDelegations.Get(address); exists { + for i := range delegations.Iterate() { + validatorAddress, delegatedAmount := i.Key, i.Value + delegatedBalance := sdk.NewCoin(genesisData.BondDenom, delegatedAmount) + totalAvailableBalance = totalAvailableBalance.Add(delegatedBalance) + err = ctx.PrintString(fmt.Sprintf("%s, %s\n", validatorAddress, delegatedBalance)) + if err != nil { + return err + } + } + } + + // Unbonded tokens + err = ctx.PrintString("Balance in unbonded delegations:\n") + if err != nil { + return err + } + if delegations, exists := genesisData.UnbondedDelegations.Get(address); exists { + for i := range delegations.Iterate() { + validatorAddress, delegatedAmount := i.Key, i.Value + delegatedBalance := sdk.NewCoin(genesisData.BondDenom, delegatedAmount) + totalAvailableBalance = totalAvailableBalance.Add(delegatedBalance) + err = ctx.PrintString(fmt.Sprintf("%s, %s\n", validatorAddress, delegatedBalance)) + if err != nil { + return err + } + } + } + + // Get distribution module rewards + err = ctx.PrintString("Rewards:\n") + if err != nil { + return err + } + blockHeight := uint64(math.MaxUint64) + for _, validatorOpertorAddr := range genesisData.DistributionInfo.DelegatorStartingInfos.Keys() { + validator := genesisData.Validators.MustGet(validatorOpertorAddr) + + delegatorStartInfo := genesisData.DistributionInfo.DelegatorStartingInfos.MustGet(validatorOpertorAddr) + + endingPeriod := app.UpdateValidatorData(genesisData.DistributionInfo, validator) + + if !delegatorStartInfo.Has(address) { + continue + } + delegation := validator.Delegations.MustGet(address) + + rewardsRaw, err := app.CalculateDelegationRewards(blockHeight, genesisData.DistributionInfo, validator, delegation, endingPeriod) + if err != nil { + return err + } + reward, _ := rewardsRaw.TruncateDecimal() + + if !reward.IsZero() { + + totalAvailableBalance = totalAvailableBalance.Add(reward...) + + err = ctx.PrintString(fmt.Sprintf("%s, %s\n", validatorOpertorAddr, reward)) + if err != nil { + return err + } + } + } + + err = ctx.PrintString(fmt.Sprintf("Total available balance: %s\n", totalAvailableBalance)) + if err != nil { + return err + } return nil }