func (k Keeper) GetAssetSupply(ctx sdk.Context, denom string) (assetSupply types.AssetSupply, found bool) {
	store := ctx.KVStore(k.storeKey)
	bz := store.Get(types.GetAssetSupplyKey(denom))
	if bz == nil {
		return types.AssetSupply{}, false
	}
	k.cdc.MustUnmarshal(bz, &assetSupply)
	return assetSupply, true
}
GetAssetSupply gets an asset's current supply from the store.
package keeper
import (
	"time"
	gogotypes "github.com/gogo/protobuf/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	"github.com/irisnet/irismod/modules/htlc/types"
)
func (k Keeper) IncrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	limit, err := k.GetSupplyLimit(ctx, coin.Denom)
	if err != nil {
		return err
	}
	supplyLimit := sdk.NewCoin(coin.Denom, limit.Limit)
	if supplyLimit.IsLT(supply.CurrentSupply.Add(coin)) {
		return sdkerrors.Wrapf(
			types.ErrExceedsSupplyLimit,
			"increase %s, asset supply %s, limit %s",
			coin, supply.CurrentSupply, supplyLimit,
		)
	}
	if limit.TimeLimited {
		timeBasedSupplyLimit := sdk.NewCoin(coin.Denom, limit.TimeBasedLimit)
		if timeBasedSupplyLimit.IsLT(supply.TimeLimitedCurrentSupply.Add(coin)) {
			return sdkerrors.Wrapf(
				types.ErrExceedsTimeBasedSupplyLimit,
				"increase %s, current time-based asset supply %s, limit %s",
				coin, supply.TimeLimitedCurrentSupply, timeBasedSupplyLimit,
			)
		}
		supply.TimeLimitedCurrentSupply = supply.TimeLimitedCurrentSupply.Add(coin)
	}
	supply.CurrentSupply = supply.CurrentSupply.Add(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) DecrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	if supply.CurrentSupply.Amount.Sub(coin.Amount).IsNegative() {
		return sdkerrors.Wrapf(types.ErrInvalidCurrentSupply, "decrease %s, asset supply %s", coin, supply.CurrentSupply)
	}
	supply.CurrentSupply = supply.CurrentSupply.Sub(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) IncrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	totalSupply := supply.CurrentSupply.Add(supply.IncomingSupply)
	limit, err := k.GetSupplyLimit(ctx, coin.Denom)
	if err != nil {
		return err
	}
	supplyLimit := sdk.NewCoin(coin.Denom, limit.Limit)
	if supplyLimit.IsLT(totalSupply.Add(coin)) {
		return sdkerrors.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, totalSupply, supplyLimit)
	}
	if limit.TimeLimited {
		timeLimitedTotalSupply := supply.TimeLimitedCurrentSupply.Add(supply.IncomingSupply)
		timeBasedSupplyLimit := sdk.NewCoin(coin.Denom, limit.TimeBasedLimit)
		if timeBasedSupplyLimit.IsLT(timeLimitedTotalSupply.Add(coin)) {
			return sdkerrors.Wrapf(
				types.ErrExceedsTimeBasedSupplyLimit,
				"increase %s, time-based asset supply %s, limit %s",
				coin, supply.TimeLimitedCurrentSupply, timeBasedSupplyLimit,
			)
		}
	}
	supply.IncomingSupply = supply.IncomingSupply.Add(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) DecrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	if supply.IncomingSupply.Amount.Sub(coin.Amount).IsNegative() {
		return sdkerrors.Wrapf(types.ErrInvalidIncomingSupply, "decrease %s, incoming supply %s", coin, supply.IncomingSupply)
	}
	supply.IncomingSupply = supply.IncomingSupply.Sub(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) IncrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	if supply.CurrentSupply.IsLT(supply.OutgoingSupply.Add(coin)) {
		return sdkerrors.Wrapf(
			types.ErrExceedsAvailableSupply,
			"swap amount %s, available supply %s",
			coin, supply.CurrentSupply.Amount.Sub(supply.OutgoingSupply.Amount),
		)
	}
	supply.OutgoingSupply = supply.OutgoingSupply.Add(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) DecrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
	supply, found := k.GetAssetSupply(ctx, coin.Denom)
	if !found {
		return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
	}
	if supply.OutgoingSupply.Amount.Sub(coin.Amount).IsNegative() {
		return sdkerrors.Wrapf(types.ErrInvalidOutgoingSupply, "decrease %s, outgoing supply %s", coin, supply.OutgoingSupply)
	}
	supply.OutgoingSupply = supply.OutgoingSupply.Sub(coin)
	k.SetAssetSupply(ctx, supply, coin.Denom)
	return nil
}
func (k Keeper) CreateNewAssetSupply(ctx sdk.Context, denom string) types.AssetSupply {
	supply := types.NewAssetSupply(
		sdk.NewCoin(denom, sdk.ZeroInt()), sdk.NewCoin(denom, sdk.ZeroInt()),
		sdk.NewCoin(denom, sdk.ZeroInt()), sdk.NewCoin(denom, sdk.ZeroInt()), time.Duration(0),
	)
	k.SetAssetSupply(ctx, supply, denom)
	return supply
}
func (k Keeper) UpdateTimeBasedSupplyLimits(ctx sdk.Context) {
	assets, found := k.GetAssets(ctx)
	if !found {
		return
	}
	previousBlockTime, found := k.GetPreviousBlockTime(ctx)
	if !found {
		previousBlockTime = ctx.BlockTime()
		k.SetPreviousBlockTime(ctx, previousBlockTime)
	}
	timeElapsed := ctx.BlockTime().Sub(previousBlockTime)
	for _, asset := range assets {
		supply, found := k.GetAssetSupply(ctx, asset.Denom)
		if !found {
			supply = k.CreateNewAssetSupply(ctx, asset.Denom)
		}
		newTimeElapsed := supply.TimeElapsed + timeElapsed
		if asset.SupplyLimit.TimeLimited && newTimeElapsed < asset.SupplyLimit.TimePeriod {
			supply.TimeElapsed = newTimeElapsed
		} else {
			supply.TimeElapsed = time.Duration(0)
			supply.TimeLimitedCurrentSupply = sdk.NewCoin(asset.Denom, sdk.ZeroInt())
		}
		k.SetAssetSupply(ctx, supply, asset.Denom)
	}
	k.SetPreviousBlockTime(ctx, ctx.BlockTime())
}