0g-chain/x/precisebank/testutil/suite.go
drklee3 409841c79c
feat(x/precisebank): Implement SendCoins (#1923)
Implements methods SendCoins, SendCoinsFromModuleToAccount, SendCoinsFromAccountToModule
2024-06-17 10:53:41 -07:00

152 lines
5.1 KiB
Go

package testutil
import (
"time"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/tmhash"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
tmversion "github.com/cometbft/cometbft/proto/tendermint/version"
tmtime "github.com/cometbft/cometbft/types/time"
"github.com/cometbft/cometbft/version"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
"github.com/stretchr/testify/suite"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/precisebank/keeper"
"github.com/kava-labs/kava/x/precisebank/types"
)
type Suite struct {
suite.Suite
App app.TestApp
Ctx sdk.Context
BankKeeper bankkeeper.Keeper
AccountKeeper authkeeper.AccountKeeper
Keeper keeper.Keeper
}
func (suite *Suite) SetupTest() {
tApp := app.NewTestApp()
suite.Ctx = tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()})
suite.App = tApp
suite.BankKeeper = tApp.GetBankKeeper()
suite.AccountKeeper = tApp.GetAccountKeeper()
suite.Keeper = tApp.GetPrecisebankKeeper()
cdc := suite.App.AppCodec()
coins := sdk.NewCoins(sdk.NewInt64Coin("ukava", 1000_000_000_000_000_000))
authGS := app.NewFundedGenStateWithSameCoins(cdc, coins, []sdk.AccAddress{})
gs := app.GenesisState{}
suite.App.InitializeFromGenesisStates(authGS, gs)
// consensus key - needed to set up evm module
consPriv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
consAddress := sdk.ConsAddress(consPriv.PubKey().Address())
// InitializeFromGenesisStates commits first block so we start at 2 here
suite.Ctx = suite.App.NewContext(false, tmproto.Header{
Height: suite.App.LastBlockHeight() + 1,
ChainID: app.TestChainId,
Time: time.Now().UTC(),
ProposerAddress: consAddress.Bytes(),
Version: tmversion.Consensus{
Block: version.BlockProtocol,
},
LastBlockId: tmproto.BlockID{
Hash: tmhash.Sum([]byte("block_id")),
PartSetHeader: tmproto.PartSetHeader{
Total: 11,
Hash: tmhash.Sum([]byte("partset_header")),
},
},
AppHash: tmhash.Sum([]byte("app")),
DataHash: tmhash.Sum([]byte("data")),
EvidenceHash: tmhash.Sum([]byte("evidence")),
ValidatorsHash: tmhash.Sum([]byte("validators")),
NextValidatorsHash: tmhash.Sum([]byte("next_validators")),
ConsensusHash: tmhash.Sum([]byte("consensus")),
LastResultsHash: tmhash.Sum([]byte("last_result")),
})
}
func (suite *Suite) Commit() {
_ = suite.App.Commit()
header := suite.Ctx.BlockHeader()
header.Height += 1
suite.App.BeginBlock(abci.RequestBeginBlock{
Header: header,
})
// update ctx
suite.Ctx = suite.App.NewContext(false, header)
}
// MintToAccount mints coins to an account with the x/precisebank methods. This
// must be used when minting extended coins, ie. akava coins. This depends on
// the methods to be properly tested to be implemented correctly.
func (suite *Suite) MintToAccount(addr sdk.AccAddress, amt sdk.Coins) {
accBalancesBefore := suite.GetAllBalances(addr)
err := suite.Keeper.MintCoins(suite.Ctx, minttypes.ModuleName, amt)
suite.Require().NoError(err)
err = suite.Keeper.SendCoinsFromModuleToAccount(suite.Ctx, minttypes.ModuleName, addr, amt)
suite.Require().NoError(err)
// Double check balances are correctly minted and sent to account
accBalancesAfter := suite.GetAllBalances(addr)
netIncrease := accBalancesAfter.Sub(accBalancesBefore...)
suite.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease)
suite.T().Logf("minted %s to %s", amt, addr)
}
// GetAllBalances returns all the account balances for the given account address.
// This returns the extended coin balance if the account has a non-zero balance,
// WITHOUT the integer coin balance.
func (suite *Suite) GetAllBalances(addr sdk.AccAddress) sdk.Coins {
// Get all balances for an account
bankBalances := suite.BankKeeper.GetAllBalances(suite.Ctx, addr)
// Remove integer coins from the balance
for _, coin := range bankBalances {
if coin.Denom == types.IntegerCoinDenom {
bankBalances = bankBalances.Sub(coin)
}
}
// Replace the integer coin with the extended coin, from x/precisebank
extendedBal := suite.Keeper.GetBalance(suite.Ctx, addr, types.ExtendedCoinDenom)
return bankBalances.Add(extendedBal)
}
// ConvertCoinsToExtendedCoinDenom converts sdk.Coins that includes Integer denoms
// to sdk.Coins that includes Extended denoms of the same amount. This is useful
// for testing to make sure only extended amounts are compared instead of double
// counting balances.
func ConvertCoinsToExtendedCoinDenom(coins sdk.Coins) sdk.Coins {
integerCoinAmt := coins.AmountOf(types.IntegerCoinDenom)
if integerCoinAmt.IsZero() {
return coins
}
// Remove the integer coin from the coins
integerCoin := sdk.NewCoin(types.IntegerCoinDenom, integerCoinAmt)
// Add the equivalent extended coin to the coins
extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom, integerCoinAmt.Mul(types.ConversionFactor()))
return coins.Sub(integerCoin).Add(extendedCoin)
}