diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index 2390f2681..185084f62 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -35,26 +35,10 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { // ExportGenesis returns the bank module's genesis state. func (k BaseKeeper) ExportGenesis(ctx sdk.Context) types.GenesisState { - balancesSet := make(map[string]sdk.Coins) - - k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool { - balancesSet[addr.String()] = balancesSet[addr.String()].Add(balance) - return false - }) - - balances := []types.Balance{} - - for addrStr, coins := range balancesSet { - addr, err := sdk.AccAddressFromBech32(addrStr) - if err != nil { - panic(fmt.Errorf("failed to convert address from string: %w", err)) - } - - balances = append(balances, types.Balance{ - Address: addr, - Coins: coins, - }) - } - - return types.NewGenesisState(k.GetParams(ctx), balances, k.GetSupply(ctx).GetTotal(), k.GetAllDenomMetaData(ctx)) + return types.NewGenesisState( + k.GetParams(ctx), + k.GetAccountsBalances(ctx), + k.GetSupply(ctx).GetTotal(), + k.GetAllDenomMetaData(ctx), + ) } diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go index 68a476565..727c2b699 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -22,6 +22,7 @@ type ViewKeeper interface { HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + GetAccountsBalances(ctx sdk.Context) []types.Balance GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins @@ -67,6 +68,32 @@ func (k BaseViewKeeper) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk return balances.Sort() } +// GetAccountsBalances returns all the accounts balances from the store. +func (k BaseViewKeeper) GetAccountsBalances(ctx sdk.Context) []types.Balance { + balances := make([]types.Balance, 0) + mapAddressToBalancesIdx := make(map[string]int) + + k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool { + idx, ok := mapAddressToBalancesIdx[addr.String()] + if ok { + // address is already on the set of accounts balances + balances[idx].Coins = balances[idx].Coins.Add(balance) + balances[idx].Coins.Sort() + return false + } + + accountBalance := types.Balance{ + Address: addr, + Coins: sdk.NewCoins(balance), + } + balances = append(balances, accountBalance) + mapAddressToBalancesIdx[addr.String()] = len(balances) - 1 + return false + }) + + return balances +} + // GetBalance returns the balance of a specific denomination for a given account // by address. func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {