cosmos-sdk/x/bank/simulation/msg_factory.go
mergify[bot] 8823508147
feat(sims): Add sims2 framework and factory methods (backport #21613) (#21752)
Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
2024-09-17 10:04:02 +00:00

88 lines
3.0 KiB
Go

package simulation
import (
"context"
"slices"
"cosmossdk.io/x/bank/types"
"github.com/cosmos/cosmos-sdk/simsx"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func MsgSendFactory() simsx.SimMsgFactoryFn[*types.MsgSend] {
return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSend) {
from := testData.AnyAccount(reporter, simsx.WithSpendableBalance())
to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from))
coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins())
return []simsx.SimAccount{from}, types.NewMsgSend(from.AddressBech32, to.AddressBech32, coins)
}
}
func MsgMultiSendFactory() simsx.SimMsgFactoryFn[*types.MsgMultiSend] {
return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgMultiSend) {
r := testData.Rand()
var (
sending = make([]types.Input, 1)
receiving = make([]types.Output, r.Intn(3)+1)
senderAcc = make([]simsx.SimAccount, len(sending))
totalSentCoins sdk.Coins
uniqueAccountsFilter = simsx.UniqueAccounts()
)
for i := range sending {
// generate random input fields, ignore to address
from := testData.AnyAccount(reporter, simsx.WithSpendableBalance(), uniqueAccountsFilter)
if reporter.IsSkipped() {
return nil, nil
}
coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins())
// set signer privkey
senderAcc[i] = from
// set next input and accumulate total sent coins
sending[i] = types.NewInput(from.AddressBech32, coins)
totalSentCoins = totalSentCoins.Add(coins...)
}
for i := range receiving {
receiver := testData.AnyAccount(reporter)
if reporter.IsSkipped() {
return nil, nil
}
var outCoins sdk.Coins
// split total sent coins into random subsets for output
if i == len(receiving)-1 {
// last one receives remaining amount
outCoins = totalSentCoins
} else {
// take random subset of remaining coins for output
// and update remaining coins
outCoins = r.SubsetCoins(totalSentCoins)
totalSentCoins = totalSentCoins.Sub(outCoins...)
}
receiving[i] = types.NewOutput(receiver.AddressBech32, outCoins)
}
// remove any entries that have no coins
receiving = slices.DeleteFunc(receiving, func(o types.Output) bool {
return o.Address == "" || o.Coins.Empty()
})
return senderAcc, &types.MsgMultiSend{Inputs: sending, Outputs: receiving}
}
}
// MsgUpdateParamsFactory creates a gov proposal for param updates
func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] {
return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) {
params := types.DefaultParams()
params.DefaultSendEnabled = testData.Rand().Intn(2) == 0
return nil, &types.MsgUpdateParams{
Authority: testData.ModuleAccountAddress(reporter, "gov"),
Params: params,
}
}
}