Lorenz Herzberger 7a3ccccc7a
119 create dao msg to mint plmnt on demand (#122)
* add mint address to config file
* ignite scaffold type mint-request beneficiary amount liquid-tx-hash --module dao
* add mintrequest stores
* rename mint_request.go
* add unit tests for mint request store
* ignite scaffold message mint-token mint-request:MintRequest --module dao
* add ante handler for mint address
* add msg validation for mint request
* fix staticcheck error
* ignite scaffold query get-mint-requests-by-hash hash --response mint-request:MintRequest --module dao
* add a query for mint request and additional validation for msg server
* add mock for mint unit testing
* add unit test for mint token msg server
* add unit tests for query mint requests by hash
* ignite scaffold query mint-requests-by-address address --response mint-requests:MintRequests --module dao
* implement query mint requests by address and unit tests
* add e2e test for token mint

---------

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
2023-10-05 15:38:53 +02:00

142 lines
4.1 KiB
Go

package keeper
import (
"fmt"
"cosmossdk.io/math"
"github.com/cometbft/cometbft/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/x/dao/types"
)
type (
Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey
memKey storetypes.StoreKey
challengeKey storetypes.StoreKey
mintRequestHashKey storetypes.StoreKey
mintRequestAddressKey storetypes.StoreKey
paramstore paramtypes.Subspace
bankKeeper types.BankKeeper
accountKeeper types.AccountKeeper
}
)
func NewKeeper(
cdc codec.BinaryCodec,
storeKey,
memKey storetypes.StoreKey,
challengeKey storetypes.StoreKey,
mintRequestHashKey storetypes.StoreKey,
mintRequestAddressKey storetypes.StoreKey,
ps paramtypes.Subspace,
bankKeeper types.BankKeeper,
accountKeeper types.AccountKeeper,
) *Keeper {
// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}
return &Keeper{
cdc: cdc,
storeKey: storeKey,
memKey: memKey,
challengeKey: challengeKey,
mintRequestHashKey: mintRequestHashKey,
mintRequestAddressKey: mintRequestAddressKey,
paramstore: ps,
bankKeeper: bankKeeper,
accountKeeper: accountKeeper,
}
}
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}
func (k Keeper) DistributeCollectedFees(ctx sdk.Context) {
ctx = sdk.UnwrapSDKContext(ctx)
conf := config.GetConfig()
balances := make(map[string]math.Int)
totalStake := math.ZeroInt()
k.accountKeeper.IterateAccounts(ctx, func(acc authtypes.AccountI) bool {
addr := acc.GetAddress()
balance := k.bankKeeper.SpendableCoins(ctx, addr)
found, stake := balance.Find(conf.StakeDenom)
if found {
totalStake = totalStake.Add(stake.Amount)
balances[addr.String()] = stake.Amount
}
return false
})
distAddr := k.accountKeeper.GetModuleAddress(disttypes.ModuleName)
distSpendableCoins := k.bankKeeper.SpendableCoins(ctx, distAddr)
found, coinToDistribute := distSpendableCoins.Find(conf.FeeDenom)
if found {
err := k.processBalances(ctx, balances, totalStake, coinToDistribute)
if err != nil {
ctx.Logger().Error("Error processing balances:", err)
}
}
}
// Check if the address is blocked
func (k Keeper) isAddressBlocked(accAddress sdk.AccAddress) bool {
return k.bankKeeper.BlockedAddr(accAddress)
}
// Send coins from the module to the account
func (k Keeper) sendCoinsFromModuleToAccount(ctx sdk.Context, accAddress sdk.AccAddress, coinClaim sdk.Coin) error {
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, disttypes.ModuleName, accAddress, sdk.NewCoins(coinClaim))
}
// Calculate the claim for an address
func calculateClaimForAddress(stake math.Int, totalStake math.Int, coinToDistribute sdk.Coin) sdk.Dec {
decTotalAmountToDistribute := sdk.NewDecFromInt(coinToDistribute.Amount)
decTotalStake := sdk.NewDecFromInt(totalStake)
decStake := sdk.NewDecFromInt(stake)
share := decStake.Quo(decTotalStake)
return decTotalAmountToDistribute.Mul(share)
}
func (k Keeper) processBalances(ctx sdk.Context, balances map[string]math.Int, totalStake math.Int, coinToDistribute sdk.Coin) error {
conf := config.GetConfig()
for addr, stake := range balances {
claim := calculateClaimForAddress(stake, totalStake, coinToDistribute)
if claim.GTE(sdk.OneDec()) {
intClaim := claim.TruncateInt()
coinClaim := sdk.NewCoin(conf.FeeDenom, intClaim)
accAddress, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return err
}
if !k.isAddressBlocked(accAddress) {
err = k.sendCoinsFromModuleToAccount(ctx, accAddress, coinClaim)
if err != nil {
return err
}
}
}
}
return nil
}