github.com/cosmos/cosmos-sdk@v0.50.10/types/dec_coin_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/suite"
     8  
     9  	"cosmossdk.io/math"
    10  
    11  	sdk "github.com/cosmos/cosmos-sdk/types"
    12  )
    13  
    14  type decCoinTestSuite struct {
    15  	suite.Suite
    16  }
    17  
    18  func TestDecCoinTestSuite(t *testing.T) {
    19  	suite.Run(t, new(decCoinTestSuite))
    20  }
    21  
    22  func (s *decCoinTestSuite) TestNewDecCoin() {
    23  	s.Require().NotPanics(func() {
    24  		sdk.NewInt64DecCoin(testDenom1, 5)
    25  	})
    26  	s.Require().NotPanics(func() {
    27  		sdk.NewInt64DecCoin(testDenom1, 0)
    28  	})
    29  	s.Require().NotPanics(func() {
    30  		sdk.NewInt64DecCoin(strings.ToUpper(testDenom1), 5)
    31  	})
    32  	s.Require().Panics(func() {
    33  		sdk.NewInt64DecCoin(testDenom1, -5)
    34  	})
    35  }
    36  
    37  func (s *decCoinTestSuite) TestNewDecCoinFromDec() {
    38  	s.Require().NotPanics(func() {
    39  		sdk.NewDecCoinFromDec(testDenom1, math.LegacyNewDec(5))
    40  	})
    41  	s.Require().NotPanics(func() {
    42  		sdk.NewDecCoinFromDec(testDenom1, math.LegacyZeroDec())
    43  	})
    44  	s.Require().NotPanics(func() {
    45  		sdk.NewDecCoinFromDec(strings.ToUpper(testDenom1), math.LegacyNewDec(5))
    46  	})
    47  	s.Require().Panics(func() {
    48  		sdk.NewDecCoinFromDec(testDenom1, math.LegacyNewDec(-5))
    49  	})
    50  }
    51  
    52  func (s *decCoinTestSuite) TestNewDecCoinFromCoin() {
    53  	s.Require().NotPanics(func() {
    54  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, math.NewInt(5)})
    55  	})
    56  	s.Require().NotPanics(func() {
    57  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, math.NewInt(0)})
    58  	})
    59  	s.Require().NotPanics(func() {
    60  		sdk.NewDecCoinFromCoin(sdk.Coin{strings.ToUpper(testDenom1), math.NewInt(5)})
    61  	})
    62  	s.Require().Panics(func() {
    63  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, math.NewInt(-5)})
    64  	})
    65  }
    66  
    67  func (s *decCoinTestSuite) TestDecCoinIsPositive() {
    68  	dc := sdk.NewInt64DecCoin(testDenom1, 5)
    69  	s.Require().True(dc.IsPositive())
    70  
    71  	dc = sdk.NewInt64DecCoin(testDenom1, 0)
    72  	s.Require().False(dc.IsPositive())
    73  }
    74  
    75  func (s *decCoinTestSuite) TestAddDecCoin() {
    76  	decCoinA1 := sdk.NewDecCoinFromDec(testDenom1, math.LegacyNewDecWithPrec(11, 1))
    77  	decCoinA2 := sdk.NewDecCoinFromDec(testDenom1, math.LegacyNewDecWithPrec(22, 1))
    78  	decCoinB1 := sdk.NewDecCoinFromDec(testDenom2, math.LegacyNewDecWithPrec(11, 1))
    79  
    80  	// regular add
    81  	res := decCoinA1.Add(decCoinA1)
    82  	s.Require().Equal(decCoinA2, res, "sum of coins is incorrect")
    83  
    84  	// bad denom add
    85  	s.Require().Panics(func() {
    86  		decCoinA1.Add(decCoinB1)
    87  	}, "expected panic on sum of different denoms")
    88  }
    89  
    90  func (s *decCoinTestSuite) TestAddDecCoins() {
    91  	one := math.LegacyNewDec(1)
    92  	zero := math.LegacyNewDec(0)
    93  	two := math.LegacyNewDec(2)
    94  
    95  	cases := []struct {
    96  		inputOne sdk.DecCoins
    97  		inputTwo sdk.DecCoins
    98  		expected sdk.DecCoins
    99  	}{
   100  		{sdk.DecCoins{{testDenom1, one}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, one}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, two}, {testDenom2, two}}},
   101  		{sdk.DecCoins{{testDenom1, zero}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins{{testDenom2, one}}},
   102  		{sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins(nil)},
   103  	}
   104  
   105  	for tcIndex, tc := range cases {
   106  		res := tc.inputOne.Add(tc.inputTwo...)
   107  		s.Require().Equal(tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
   108  	}
   109  }
   110  
   111  func (s *decCoinTestSuite) TestFilteredZeroDecCoins() {
   112  	cases := []struct {
   113  		name     string
   114  		input    sdk.DecCoins
   115  		original string
   116  		expected string
   117  		panic    bool
   118  	}{
   119  		{
   120  			name: "all greater than zero",
   121  			input: sdk.DecCoins{
   122  				{"testa", math.LegacyNewDec(1)},
   123  				{"testb", math.LegacyNewDec(2)},
   124  				{"testc", math.LegacyNewDec(3)},
   125  				{"testd", math.LegacyNewDec(4)},
   126  				{"teste", math.LegacyNewDec(5)},
   127  			},
   128  			original: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   129  			expected: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   130  			panic:    false,
   131  		},
   132  		{
   133  			name: "zero coin in middle",
   134  			input: sdk.DecCoins{
   135  				{"testa", math.LegacyNewDec(1)},
   136  				{"testb", math.LegacyNewDec(2)},
   137  				{"testc", math.LegacyNewDec(0)},
   138  				{"testd", math.LegacyNewDec(4)},
   139  				{"teste", math.LegacyNewDec(5)},
   140  			},
   141  			original: "1.000000000000000000testa,2.000000000000000000testb,0.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   142  			expected: "1.000000000000000000testa,2.000000000000000000testb,4.000000000000000000testd,5.000000000000000000teste",
   143  			panic:    false,
   144  		},
   145  		{
   146  			name: "zero coin end (unordered)",
   147  			input: sdk.DecCoins{
   148  				{"teste", math.LegacyNewDec(5)},
   149  				{"testc", math.LegacyNewDec(3)},
   150  				{"testa", math.LegacyNewDec(1)},
   151  				{"testd", math.LegacyNewDec(4)},
   152  				{"testb", math.LegacyNewDec(0)},
   153  			},
   154  			original: "5.000000000000000000teste,3.000000000000000000testc,1.000000000000000000testa,4.000000000000000000testd,0.000000000000000000testb",
   155  			expected: "1.000000000000000000testa,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   156  			panic:    false,
   157  		},
   158  
   159  		{
   160  			name: "panic when same denoms in multiple coins",
   161  			input: sdk.DecCoins{
   162  				{"testa", math.LegacyNewDec(5)},
   163  				{"testa", math.LegacyNewDec(3)},
   164  				{"testa", math.LegacyNewDec(1)},
   165  				{"testd", math.LegacyNewDec(4)},
   166  				{"testb", math.LegacyNewDec(2)},
   167  			},
   168  			original: "5.000000000000000000teste,3.000000000000000000testc,1.000000000000000000testa,4.000000000000000000testd,0.000000000000000000testb",
   169  			expected: "1.000000000000000000testa,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   170  			panic:    true,
   171  		},
   172  	}
   173  
   174  	for _, tt := range cases {
   175  		if tt.panic {
   176  			s.Require().Panics(func() { sdk.NewDecCoins(tt.input...) }, "Should panic due to multiple coins with same denom")
   177  		} else {
   178  			undertest := sdk.NewDecCoins(tt.input...)
   179  			s.Require().Equal(tt.expected, undertest.String(), "NewDecCoins must return expected results")
   180  			s.Require().Equal(tt.original, tt.input.String(), "input must be unmodified and match original")
   181  		}
   182  	}
   183  }
   184  
   185  func (s *decCoinTestSuite) TestIsValid() {
   186  	tests := []struct {
   187  		coin       sdk.DecCoin
   188  		expectPass bool
   189  		msg        string
   190  	}{
   191  		{
   192  			sdk.NewDecCoin("mytoken", math.NewInt(10)),
   193  			true,
   194  			"valid coins should have passed",
   195  		},
   196  		{
   197  			sdk.DecCoin{Denom: "BTC", Amount: math.LegacyNewDec(10)},
   198  			true,
   199  			"valid uppercase denom",
   200  		},
   201  		{
   202  			sdk.DecCoin{Denom: "Bitcoin", Amount: math.LegacyNewDec(10)},
   203  			true,
   204  			"valid mixed case denom",
   205  		},
   206  		{
   207  			sdk.DecCoin{Denom: "btc", Amount: math.LegacyNewDec(-10)},
   208  			false,
   209  			"negative amount",
   210  		},
   211  	}
   212  
   213  	for _, tc := range tests {
   214  		tc := tc
   215  		if tc.expectPass {
   216  			s.Require().True(tc.coin.IsValid(), tc.msg)
   217  		} else {
   218  			s.Require().False(tc.coin.IsValid(), tc.msg)
   219  		}
   220  	}
   221  }
   222  
   223  func (s *decCoinTestSuite) TestSubDecCoin() {
   224  	tests := []struct {
   225  		coin       sdk.DecCoin
   226  		expectPass bool
   227  		msg        string
   228  	}{
   229  		{
   230  			sdk.NewDecCoin("mytoken", math.NewInt(20)),
   231  			true,
   232  			"valid coins should have passed",
   233  		},
   234  		{
   235  			sdk.NewDecCoin("othertoken", math.NewInt(20)),
   236  			false,
   237  			"denom mismatch",
   238  		},
   239  		{
   240  			sdk.NewDecCoin("mytoken", math.NewInt(9)),
   241  			false,
   242  			"negative amount",
   243  		},
   244  	}
   245  
   246  	decCoin := sdk.NewDecCoin("mytoken", math.NewInt(10))
   247  
   248  	for _, tc := range tests {
   249  		tc := tc
   250  		if tc.expectPass {
   251  			equal := tc.coin.Sub(decCoin)
   252  			s.Require().Equal(equal, decCoin, tc.msg)
   253  		} else {
   254  			s.Require().Panics(func() { tc.coin.Sub(decCoin) }, tc.msg)
   255  		}
   256  	}
   257  }
   258  
   259  func (s *decCoinTestSuite) TestSubDecCoins() {
   260  	tests := []struct {
   261  		coins      sdk.DecCoins
   262  		expectPass bool
   263  		msg        string
   264  	}{
   265  		{
   266  			sdk.NewDecCoinsFromCoins(sdk.NewCoin("mytoken", math.NewInt(10)), sdk.NewCoin("btc", math.NewInt(20)), sdk.NewCoin("eth", math.NewInt(30))),
   267  			true,
   268  			"sorted coins should have passed",
   269  		},
   270  		{
   271  			sdk.DecCoins{sdk.NewDecCoin("mytoken", math.NewInt(10)), sdk.NewDecCoin("btc", math.NewInt(20)), sdk.NewDecCoin("eth", math.NewInt(30))},
   272  			false,
   273  			"unorted coins should panic",
   274  		},
   275  		{
   276  			sdk.DecCoins{sdk.DecCoin{Denom: "BTC", Amount: math.LegacyNewDec(10)}, sdk.NewDecCoin("eth", math.NewInt(15)), sdk.NewDecCoin("mytoken", math.NewInt(5))},
   277  			false,
   278  			"invalid denoms",
   279  		},
   280  	}
   281  
   282  	decCoins := sdk.NewDecCoinsFromCoins(sdk.NewCoin("btc", math.NewInt(10)), sdk.NewCoin("eth", math.NewInt(15)), sdk.NewCoin("mytoken", math.NewInt(5)))
   283  
   284  	for _, tc := range tests {
   285  		tc := tc
   286  		if tc.expectPass {
   287  			equal := tc.coins.Sub(decCoins)
   288  			s.Require().Equal(equal, decCoins, tc.msg)
   289  		} else {
   290  			s.Require().Panics(func() { tc.coins.Sub(decCoins) }, tc.msg)
   291  		}
   292  	}
   293  }
   294  
   295  func (s *decCoinTestSuite) TestSortDecCoins() {
   296  	good := sdk.DecCoins{
   297  		sdk.NewInt64DecCoin("gas", 1),
   298  		sdk.NewInt64DecCoin("mineral", 1),
   299  		sdk.NewInt64DecCoin("tree", 1),
   300  	}
   301  	empty := sdk.DecCoins{
   302  		sdk.NewInt64DecCoin("gold", 0),
   303  	}
   304  	badSort1 := sdk.DecCoins{
   305  		sdk.NewInt64DecCoin("tree", 1),
   306  		sdk.NewInt64DecCoin("gas", 1),
   307  		sdk.NewInt64DecCoin("mineral", 1),
   308  	}
   309  	badSort2 := sdk.DecCoins{ // both are after the first one, but the second and third are in the wrong order
   310  		sdk.NewInt64DecCoin("gas", 1),
   311  		sdk.NewInt64DecCoin("tree", 1),
   312  		sdk.NewInt64DecCoin("mineral", 1),
   313  	}
   314  	badAmt := sdk.DecCoins{
   315  		sdk.NewInt64DecCoin("gas", 1),
   316  		sdk.NewInt64DecCoin("tree", 0),
   317  		sdk.NewInt64DecCoin("mineral", 1),
   318  	}
   319  	dup := sdk.DecCoins{
   320  		sdk.NewInt64DecCoin("gas", 1),
   321  		sdk.NewInt64DecCoin("gas", 1),
   322  		sdk.NewInt64DecCoin("mineral", 1),
   323  	}
   324  	cases := []struct {
   325  		name          string
   326  		coins         sdk.DecCoins
   327  		before, after bool // valid before/after sort
   328  	}{
   329  		{"valid coins", good, true, true},
   330  		{"empty coins", empty, false, false},
   331  		{"unsorted coins (1)", badSort1, false, true},
   332  		{"unsorted coins (2)", badSort2, false, true},
   333  		{"zero amount coins", badAmt, false, false},
   334  		{"duplicate coins", dup, false, false},
   335  	}
   336  
   337  	for _, tc := range cases {
   338  		s.Require().Equal(tc.before, tc.coins.IsValid(), "coin validity is incorrect before sorting; %s", tc.name)
   339  		tc.coins.Sort()
   340  		s.Require().Equal(tc.after, tc.coins.IsValid(), "coin validity is incorrect after sorting;  %s", tc.name)
   341  	}
   342  }
   343  
   344  func (s *decCoinTestSuite) TestDecCoinsValidate() {
   345  	testCases := []struct {
   346  		input        sdk.DecCoins
   347  		expectedPass bool
   348  	}{
   349  		{sdk.DecCoins{}, true},
   350  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, true},
   351  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(100000)}}, true},
   352  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(-5)}}, false},
   353  		{sdk.DecCoins{sdk.DecCoin{"BTC", math.LegacyNewDec(5)}}, true},
   354  		{sdk.DecCoins{sdk.DecCoin{"0BTC", math.LegacyNewDec(5)}}, false},
   355  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}, sdk.DecCoin{"B", math.LegacyNewDec(100000)}}, false},
   356  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(-100000)}}, false},
   357  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(-5)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(100000)}}, false},
   358  		{sdk.DecCoins{sdk.DecCoin{"BTC", math.LegacyNewDec(5)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(100000)}}, true},
   359  		{sdk.DecCoins{sdk.DecCoin{"0BTC", math.LegacyNewDec(5)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(100000)}}, false},
   360  	}
   361  
   362  	for i, tc := range testCases {
   363  		err := tc.input.Validate()
   364  		if tc.expectedPass {
   365  			s.Require().NoError(err, "unexpected result for test case #%d, input: %v", i, tc.input)
   366  		} else {
   367  			s.Require().Error(err, "unexpected result for test case #%d, input: %v", i, tc.input)
   368  		}
   369  	}
   370  }
   371  
   372  func (s *decCoinTestSuite) TestParseDecCoins() {
   373  	testCases := []struct {
   374  		input          string
   375  		expectedResult sdk.DecCoins
   376  		expectedErr    bool
   377  	}{
   378  		{"", nil, false},
   379  		{"4stake", sdk.DecCoins{sdk.NewDecCoinFromDec("stake", math.LegacyNewDecFromInt(math.NewInt(4)))}, false},
   380  		{"5.5atom,4stake", sdk.DecCoins{
   381  			sdk.NewDecCoinFromDec("atom", math.LegacyNewDecWithPrec(5500000000000000000, math.LegacyPrecision)),
   382  			sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(4)),
   383  		}, false},
   384  		{"0.0stake", sdk.DecCoins{}, false}, // remove zero coins
   385  		{"10.0btc,1.0atom,20.0btc", nil, true},
   386  		{
   387  			"0.004STAKE",
   388  			sdk.DecCoins{sdk.NewDecCoinFromDec("STAKE", math.LegacyNewDecWithPrec(4000000000000000, math.LegacyPrecision))},
   389  			false,
   390  		},
   391  		{
   392  			"0.004stake",
   393  			sdk.DecCoins{sdk.NewDecCoinFromDec("stake", math.LegacyNewDecWithPrec(4000000000000000, math.LegacyPrecision))},
   394  			false,
   395  		},
   396  		{
   397  			"5.04atom,0.004stake",
   398  			sdk.DecCoins{
   399  				sdk.NewDecCoinFromDec("atom", math.LegacyNewDecWithPrec(5040000000000000000, math.LegacyPrecision)),
   400  				sdk.NewDecCoinFromDec("stake", math.LegacyNewDecWithPrec(4000000000000000, math.LegacyPrecision)),
   401  			},
   402  			false,
   403  		},
   404  		{
   405  			"0.0stake,0.004stake,5.04atom", // remove zero coins
   406  			sdk.DecCoins{
   407  				sdk.NewDecCoinFromDec("atom", math.LegacyNewDecWithPrec(5040000000000000000, math.LegacyPrecision)),
   408  				sdk.NewDecCoinFromDec("stake", math.LegacyNewDecWithPrec(4000000000000000, math.LegacyPrecision)),
   409  			},
   410  			false,
   411  		},
   412  	}
   413  
   414  	for i, tc := range testCases {
   415  		res, err := sdk.ParseDecCoins(tc.input)
   416  		if tc.expectedErr {
   417  			s.Require().Error(err, "expected error for test case #%d, input: %v", i, tc.input)
   418  		} else {
   419  			s.Require().NoError(err, "unexpected error for test case #%d, input: %v", i, tc.input)
   420  			s.Require().Equal(tc.expectedResult, res, "unexpected result for test case #%d, input: %v", i, tc.input)
   421  		}
   422  	}
   423  }
   424  
   425  func (s *decCoinTestSuite) TestDecCoinsString() {
   426  	testCases := []struct {
   427  		input    sdk.DecCoins
   428  		expected string
   429  	}{
   430  		{sdk.DecCoins{}, ""},
   431  		{
   432  			sdk.DecCoins{
   433  				sdk.NewDecCoinFromDec("atom", math.LegacyNewDecWithPrec(5040000000000000000, math.LegacyPrecision)),
   434  				sdk.NewDecCoinFromDec("stake", math.LegacyNewDecWithPrec(4000000000000000, math.LegacyPrecision)),
   435  			},
   436  			"5.040000000000000000atom,0.004000000000000000stake",
   437  		},
   438  	}
   439  
   440  	for i, tc := range testCases {
   441  		out := tc.input.String()
   442  		s.Require().Equal(tc.expected, out, "unexpected result for test case #%d, input: %v", i, tc.input)
   443  	}
   444  }
   445  
   446  func (s *decCoinTestSuite) TestDecCoinsIntersect() {
   447  	testCases := []struct {
   448  		input1         string
   449  		input2         string
   450  		expectedResult string
   451  	}{
   452  		{"", "", ""},
   453  		{"1.0stake", "", ""},
   454  		{"1.0stake", "1.0stake", "1.0stake"},
   455  		{"", "1.0stake", ""},
   456  		{"1.0stake", "", ""},
   457  		{"2.0stake,1.0trope", "1.9stake", "1.9stake"},
   458  		{"2.0stake,1.0trope", "2.1stake", "2.0stake"},
   459  		{"2.0stake,1.0trope", "0.9trope", "0.9trope"},
   460  		{"2.0stake,1.0trope", "1.9stake,0.9trope", "1.9stake,0.9trope"},
   461  		{"2.0stake,1.0trope", "1.9stake,0.9trope,20.0other", "1.9stake,0.9trope"},
   462  		{"2.0stake,1.0trope", "1.0other", ""},
   463  	}
   464  
   465  	for i, tc := range testCases {
   466  		in1, err := sdk.ParseDecCoins(tc.input1)
   467  		s.Require().NoError(err, "unexpected parse error in %v", i)
   468  		in2, err := sdk.ParseDecCoins(tc.input2)
   469  		s.Require().NoError(err, "unexpected parse error in %v", i)
   470  		exr, err := sdk.ParseDecCoins(tc.expectedResult)
   471  		s.Require().NoError(err, "unexpected parse error in %v", i)
   472  		s.Require().True(in1.Intersect(in2).Equal(exr), "in1.cap(in2) != exr in %v", i)
   473  	}
   474  }
   475  
   476  func (s *decCoinTestSuite) TestDecCoinsTruncateDecimal() {
   477  	decCoinA := sdk.NewDecCoinFromDec("bar", math.LegacyMustNewDecFromStr("5.41"))
   478  	decCoinB := sdk.NewDecCoinFromDec("foo", math.LegacyMustNewDecFromStr("6.00"))
   479  
   480  	testCases := []struct {
   481  		input          sdk.DecCoins
   482  		truncatedCoins sdk.Coins
   483  		changeCoins    sdk.DecCoins
   484  	}{
   485  		{sdk.DecCoins{}, sdk.Coins(nil), sdk.DecCoins(nil)},
   486  		{
   487  			sdk.DecCoins{decCoinA, decCoinB},
   488  			sdk.Coins{sdk.NewInt64Coin(decCoinA.Denom, 5), sdk.NewInt64Coin(decCoinB.Denom, 6)},
   489  			sdk.DecCoins{sdk.NewDecCoinFromDec(decCoinA.Denom, math.LegacyMustNewDecFromStr("0.41"))},
   490  		},
   491  		{
   492  			sdk.DecCoins{decCoinB},
   493  			sdk.Coins{sdk.NewInt64Coin(decCoinB.Denom, 6)},
   494  			sdk.DecCoins(nil),
   495  		},
   496  	}
   497  
   498  	for i, tc := range testCases {
   499  		truncatedCoins, changeCoins := tc.input.TruncateDecimal()
   500  		s.Require().Equal(
   501  			tc.truncatedCoins, truncatedCoins,
   502  			"unexpected truncated coins; tc #%d, input: %s", i, tc.input,
   503  		)
   504  		s.Require().Equal(
   505  			tc.changeCoins, changeCoins,
   506  			"unexpected change coins; tc #%d, input: %s", i, tc.input,
   507  		)
   508  	}
   509  }
   510  
   511  func (s *decCoinTestSuite) TestDecCoinsQuoDecTruncate() {
   512  	x := math.LegacyMustNewDecFromStr("1.00")
   513  	y := math.LegacyMustNewDecFromStr("10000000000000000000.00")
   514  
   515  	testCases := []struct {
   516  		coins  sdk.DecCoins
   517  		input  math.LegacyDec
   518  		result sdk.DecCoins
   519  		panics bool
   520  	}{
   521  		{sdk.DecCoins{}, math.LegacyZeroDec(), sdk.DecCoins(nil), true},
   522  		{sdk.DecCoins{sdk.NewDecCoinFromDec("foo", x)}, y, sdk.DecCoins(nil), false},
   523  		{sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}, math.LegacyNewDec(2), sdk.DecCoins{sdk.NewDecCoinFromDec("foo", math.LegacyMustNewDecFromStr("2.5"))}, false},
   524  	}
   525  
   526  	for i, tc := range testCases {
   527  		tc := tc
   528  		if tc.panics {
   529  			s.Require().Panics(func() { tc.coins.QuoDecTruncate(tc.input) })
   530  		} else {
   531  			res := tc.coins.QuoDecTruncate(tc.input)
   532  			s.Require().Equal(tc.result, res, "unexpected result; tc #%d, coins: %s, input: %s", i, tc.coins, tc.input)
   533  		}
   534  	}
   535  }
   536  
   537  func (s *decCoinTestSuite) TestNewDecCoinsWithIsValid() {
   538  	fake1 := append(sdk.NewDecCoins(sdk.NewDecCoin("mytoken", math.NewInt(10))), sdk.DecCoin{Denom: "10BTC", Amount: math.LegacyNewDec(10)})
   539  	fake2 := append(sdk.NewDecCoins(sdk.NewDecCoin("mytoken", math.NewInt(10))), sdk.DecCoin{Denom: "BTC", Amount: math.LegacyNewDec(-10)})
   540  
   541  	tests := []struct {
   542  		coin       sdk.DecCoins
   543  		expectPass bool
   544  		msg        string
   545  	}{
   546  		{
   547  			sdk.NewDecCoins(sdk.NewDecCoin("mytoken", math.NewInt(10))),
   548  			true,
   549  			"valid coins should have passed",
   550  		},
   551  		{
   552  			fake1,
   553  			false,
   554  			"invalid denoms",
   555  		},
   556  		{
   557  			fake2,
   558  			false,
   559  			"negative amount",
   560  		},
   561  	}
   562  
   563  	for _, tc := range tests {
   564  		tc := tc
   565  		if tc.expectPass {
   566  			s.Require().True(tc.coin.IsValid(), tc.msg)
   567  		} else {
   568  			s.Require().False(tc.coin.IsValid(), tc.msg)
   569  		}
   570  	}
   571  }
   572  
   573  func (s *decCoinTestSuite) TestNewDecCoinsWithZeroCoins() {
   574  	zeroCoins := append(sdk.NewCoins(sdk.NewCoin("mytoken", math.NewInt(0))), sdk.Coin{Denom: "wbtc", Amount: math.NewInt(10)})
   575  
   576  	tests := []struct {
   577  		coins        sdk.Coins
   578  		expectLength int
   579  	}{
   580  		{
   581  			sdk.NewCoins(sdk.NewCoin("mytoken", math.NewInt(10)), sdk.NewCoin("wbtc", math.NewInt(10))),
   582  			2,
   583  		},
   584  		{
   585  			zeroCoins,
   586  			1,
   587  		},
   588  	}
   589  
   590  	for _, tc := range tests {
   591  		tc := tc
   592  		s.Require().Equal(sdk.NewDecCoinsFromCoins(tc.coins...).Len(), tc.expectLength)
   593  	}
   594  }
   595  
   596  func (s *decCoinTestSuite) TestDecCoins_AddDecCoinWithIsValid() {
   597  	lengthTestDecCoins := sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", math.NewInt(10))).Add(sdk.DecCoin{Denom: "BTC", Amount: math.LegacyNewDec(10)})
   598  	s.Require().Equal(2, len(lengthTestDecCoins), "should be 2")
   599  
   600  	tests := []struct {
   601  		coin       sdk.DecCoins
   602  		expectPass bool
   603  		msg        string
   604  	}{
   605  		{
   606  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", math.NewInt(10))),
   607  			true,
   608  			"valid coins should have passed",
   609  		},
   610  		{
   611  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", math.NewInt(10))).Add(sdk.DecCoin{Denom: "0BTC", Amount: math.LegacyNewDec(10)}),
   612  			false,
   613  			"invalid denoms",
   614  		},
   615  		{
   616  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", math.NewInt(10))).Add(sdk.DecCoin{Denom: "BTC", Amount: math.LegacyNewDec(-10)}),
   617  			false,
   618  			"negative amount",
   619  		},
   620  	}
   621  
   622  	for _, tc := range tests {
   623  		tc := tc
   624  		if tc.expectPass {
   625  			s.Require().True(tc.coin.IsValid(), tc.msg)
   626  		} else {
   627  			s.Require().False(tc.coin.IsValid(), tc.msg)
   628  		}
   629  	}
   630  }
   631  
   632  func (s *decCoinTestSuite) TestDecCoins_Empty() {
   633  	testCases := []struct {
   634  		input          sdk.DecCoins
   635  		expectedResult bool
   636  		msg            string
   637  	}{
   638  		{sdk.DecCoins{}, true, "No coins as expected."},
   639  		{sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, false, "DecCoins is not empty"},
   640  	}
   641  
   642  	for _, tc := range testCases {
   643  		if tc.expectedResult {
   644  			s.Require().True(tc.input.Empty(), tc.msg)
   645  		} else {
   646  			s.Require().False(tc.input.Empty(), tc.msg)
   647  		}
   648  	}
   649  }
   650  
   651  func (s *decCoinTestSuite) TestDecCoins_GetDenomByIndex() {
   652  	testCases := []struct {
   653  		name           string
   654  		input          sdk.DecCoins
   655  		index          int
   656  		expectedResult string
   657  		expectedErr    bool
   658  	}{
   659  		{
   660  			"No DecCoins in Slice",
   661  			sdk.DecCoins{},
   662  			0,
   663  			"",
   664  			true,
   665  		},
   666  		{"When index out of bounds", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, 2, "", true},
   667  		{"When negative index", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, -1, "", true},
   668  		{
   669  			"Appropriate index case",
   670  			sdk.DecCoins{
   671  				sdk.DecCoin{testDenom1, math.LegacyNewDec(5)},
   672  				sdk.DecCoin{testDenom2, math.LegacyNewDec(57)},
   673  			},
   674  			1, testDenom2, false,
   675  		},
   676  	}
   677  
   678  	for i, tc := range testCases {
   679  		tc := tc
   680  		s.T().Run(tc.name, func(t *testing.T) {
   681  			if tc.expectedErr {
   682  				s.Require().Panics(func() { tc.input.GetDenomByIndex(tc.index) }, "Test should have panicked")
   683  			} else {
   684  				res := tc.input.GetDenomByIndex(tc.index)
   685  				s.Require().Equal(tc.expectedResult, res, "Unexpected result for test case #%d, expected output: %s, input: %v", i, tc.expectedResult, tc.input)
   686  			}
   687  		})
   688  	}
   689  }
   690  
   691  func (s *decCoinTestSuite) TestDecCoins_IsAllPositive() {
   692  	testCases := []struct {
   693  		name           string
   694  		input          sdk.DecCoins
   695  		expectedResult bool
   696  	}{
   697  		{"No Coins", sdk.DecCoins{}, false},
   698  
   699  		{"One Coin - Zero value", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(0)}}, false},
   700  
   701  		{"One Coin - Positive value", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, true},
   702  
   703  		{"One Coin - Negative value", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(-15)}}, false},
   704  
   705  		{"Multiple Coins - All positive value", sdk.DecCoins{
   706  			sdk.DecCoin{testDenom1, math.LegacyNewDec(51)},
   707  			sdk.DecCoin{testDenom1, math.LegacyNewDec(123)},
   708  			sdk.DecCoin{testDenom1, math.LegacyNewDec(50)},
   709  			sdk.DecCoin{testDenom1, math.LegacyNewDec(92233720)},
   710  		}, true},
   711  
   712  		{"Multiple Coins - Some negative value", sdk.DecCoins{
   713  			sdk.DecCoin{testDenom1, math.LegacyNewDec(51)},
   714  			sdk.DecCoin{testDenom1, math.LegacyNewDec(-123)},
   715  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   716  			sdk.DecCoin{testDenom1, math.LegacyNewDec(92233720)},
   717  		}, false},
   718  	}
   719  
   720  	for i, tc := range testCases {
   721  		tc := tc
   722  		s.T().Run(tc.name, func(t *testing.T) {
   723  			if tc.expectedResult {
   724  				s.Require().True(tc.input.IsAllPositive(), "Test case #%d: %s", i, tc.name)
   725  			} else {
   726  				s.Require().False(tc.input.IsAllPositive(), "Test case #%d: %s", i, tc.name)
   727  			}
   728  		})
   729  	}
   730  }
   731  
   732  func (s *decCoinTestSuite) TestDecCoin_IsLT() {
   733  	testCases := []struct {
   734  		name           string
   735  		coin           sdk.DecCoin
   736  		otherCoin      sdk.DecCoin
   737  		expectedResult bool
   738  		expectedPanic  bool
   739  	}{
   740  		{"Same Denom - Less than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(3)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(19)}, true, false},
   741  
   742  		{"Same Denom - Greater than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(343340)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(14)}, false, false},
   743  
   744  		{"Same Denom - Same as other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, false, false},
   745  
   746  		{"Different Denom - Less than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(3)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(19)}, true, true},
   747  
   748  		{"Different Denom - Greater than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(343340)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(14)}, true, true},
   749  
   750  		{"Different Denom - Same as other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(20)}, true, true},
   751  	}
   752  
   753  	for i, tc := range testCases {
   754  		s.T().Run(tc.name, func(t *testing.T) {
   755  			if tc.expectedPanic {
   756  				s.Require().Panics(func() { tc.coin.IsLT(tc.otherCoin) }, "Test case #%d: %s", i, tc.name)
   757  			} else {
   758  				res := tc.coin.IsLT(tc.otherCoin)
   759  				if tc.expectedResult {
   760  					s.Require().True(res, "Test case #%d: %s", i, tc.name)
   761  				} else {
   762  					s.Require().False(res, "Test case #%d: %s", i, tc.name)
   763  				}
   764  			}
   765  		})
   766  	}
   767  }
   768  
   769  func (s *decCoinTestSuite) TestDecCoin_IsGTE() {
   770  	testCases := []struct {
   771  		name           string
   772  		coin           sdk.DecCoin
   773  		otherCoin      sdk.DecCoin
   774  		expectedResult bool
   775  		expectedPanic  bool
   776  	}{
   777  		{"Same Denom - Less than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(3)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(19)}, false, false},
   778  
   779  		{"Same Denom - Greater than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(343340)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(14)}, true, false},
   780  
   781  		{"Same Denom - Same as other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, true, false},
   782  
   783  		{"Different Denom - Less than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(3)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(19)}, true, true},
   784  
   785  		{"Different Denom - Greater than other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(343340)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(14)}, true, true},
   786  
   787  		{"Different Denom - Same as other coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(20)}, sdk.DecCoin{testDenom2, math.LegacyNewDec(20)}, true, true},
   788  	}
   789  
   790  	for i, tc := range testCases {
   791  		tc := tc
   792  		s.T().Run(tc.name, func(t *testing.T) {
   793  			if tc.expectedPanic {
   794  				s.Require().Panics(func() { tc.coin.IsGTE(tc.otherCoin) }, "Test case #%d: %s", i, tc.name)
   795  			} else {
   796  				res := tc.coin.IsGTE(tc.otherCoin)
   797  				if tc.expectedResult {
   798  					s.Require().True(res, "Test case #%d: %s", i, tc.name)
   799  				} else {
   800  					s.Require().False(res, "Test case #%d: %s", i, tc.name)
   801  				}
   802  			}
   803  		})
   804  	}
   805  }
   806  
   807  func (s *decCoinTestSuite) TestDecCoins_IsZero() {
   808  	testCases := []struct {
   809  		name           string
   810  		coins          sdk.DecCoins
   811  		expectedResult bool
   812  	}{
   813  		{"No Coins", sdk.DecCoins{}, true},
   814  
   815  		{"One Coin - Zero value", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(0)}}, true},
   816  
   817  		{"One Coin - Positive value", sdk.DecCoins{sdk.DecCoin{testDenom1, math.LegacyNewDec(5)}}, false},
   818  
   819  		{"Multiple Coins - All zero value", sdk.DecCoins{
   820  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   821  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   822  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   823  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   824  		}, true},
   825  
   826  		{"Multiple Coins - Some positive value", sdk.DecCoins{
   827  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   828  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   829  			sdk.DecCoin{testDenom1, math.LegacyNewDec(0)},
   830  			sdk.DecCoin{testDenom1, math.LegacyNewDec(92233720)},
   831  		}, false},
   832  	}
   833  
   834  	for i, tc := range testCases {
   835  		tc := tc
   836  		s.T().Run(tc.name, func(t *testing.T) {
   837  			if tc.expectedResult {
   838  				s.Require().True(tc.coins.IsZero(), "Test case #%d: %s", i, tc.name)
   839  			} else {
   840  				s.Require().False(tc.coins.IsZero(), "Test case #%d: %s", i, tc.name)
   841  			}
   842  		})
   843  	}
   844  }
   845  
   846  func (s *decCoinTestSuite) TestDecCoins_MulDec() {
   847  	testCases := []struct {
   848  		name           string
   849  		coins          sdk.DecCoins
   850  		multiplier     math.LegacyDec
   851  		expectedResult sdk.DecCoins
   852  	}{
   853  		{"No Coins", sdk.DecCoins{}, math.LegacyNewDec(1), sdk.DecCoins(nil)},
   854  
   855  		{"Multiple coins - zero multiplier", sdk.DecCoins{
   856  			sdk.DecCoin{testDenom1, math.LegacyNewDec(10)},
   857  			sdk.DecCoin{testDenom1, math.LegacyNewDec(30)},
   858  		}, math.LegacyNewDec(0), sdk.DecCoins(nil)},
   859  
   860  		{"Multiple coins - positive multiplier", sdk.DecCoins{
   861  			sdk.DecCoin{testDenom1, math.LegacyNewDec(1)},
   862  			sdk.DecCoin{testDenom1, math.LegacyNewDec(2)},
   863  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   864  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
   865  		}, math.LegacyNewDec(2), sdk.DecCoins{
   866  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
   867  		}},
   868  
   869  		{"Multiple coins - negative multiplier", sdk.DecCoins{
   870  			sdk.DecCoin{testDenom1, math.LegacyNewDec(1)},
   871  			sdk.DecCoin{testDenom1, math.LegacyNewDec(2)},
   872  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   873  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
   874  		}, math.LegacyNewDec(-2), sdk.DecCoins{
   875  			sdk.DecCoin{testDenom1, math.LegacyNewDec(-20)},
   876  		}},
   877  
   878  		{"Multiple coins - Different denom", sdk.DecCoins{
   879  			sdk.DecCoin{testDenom1, math.LegacyNewDec(1)},
   880  			sdk.DecCoin{testDenom2, math.LegacyNewDec(2)},
   881  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   882  			sdk.DecCoin{testDenom2, math.LegacyNewDec(4)},
   883  		}, math.LegacyNewDec(2), sdk.DecCoins{
   884  			sdk.DecCoin{testDenom1, math.LegacyNewDec(8)},
   885  			sdk.DecCoin{testDenom2, math.LegacyNewDec(12)},
   886  		}},
   887  	}
   888  
   889  	for i, tc := range testCases {
   890  		tc := tc
   891  		s.T().Run(tc.name, func(t *testing.T) {
   892  			res := tc.coins.MulDec(tc.multiplier)
   893  			s.Require().Equal(tc.expectedResult, res, "Test case #%d: %s", i, tc.name)
   894  		})
   895  	}
   896  }
   897  
   898  func (s *decCoinTestSuite) TestDecCoins_MulDecTruncate() {
   899  	testCases := []struct {
   900  		name           string
   901  		coins          sdk.DecCoins
   902  		multiplier     math.LegacyDec
   903  		expectedResult sdk.DecCoins
   904  		expectedPanic  bool
   905  	}{
   906  		{"No Coins", sdk.DecCoins{}, math.LegacyNewDec(1), sdk.DecCoins(nil), false},
   907  
   908  		{"Multiple coins - zero multiplier", sdk.DecCoins{
   909  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(10, 3)},
   910  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(30, 2)},
   911  		}, math.LegacyNewDec(0), sdk.DecCoins{}, false},
   912  
   913  		{"Multiple coins - positive multiplier", sdk.DecCoins{
   914  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   915  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   916  		}, math.LegacyNewDec(1), sdk.DecCoins{
   917  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(3, 0)},
   918  		}, false},
   919  
   920  		{"Multiple coins - positive multiplier", sdk.DecCoins{
   921  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   922  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   923  		}, math.LegacyNewDec(-2), sdk.DecCoins{
   924  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(-6, 0)},
   925  		}, false},
   926  
   927  		{"Multiple coins - Different denom", sdk.DecCoins{
   928  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   929  			sdk.DecCoin{testDenom2, math.LegacyNewDecWithPrec(3333, 4)},
   930  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(15, 1)},
   931  			sdk.DecCoin{testDenom2, math.LegacyNewDecWithPrec(333, 4)},
   932  		}, math.LegacyNewDec(10), sdk.DecCoins{
   933  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(30, 0)},
   934  			sdk.DecCoin{testDenom2, math.LegacyNewDecWithPrec(3666, 3)},
   935  		}, false},
   936  	}
   937  
   938  	for i, tc := range testCases {
   939  		tc := tc
   940  		s.T().Run(tc.name, func(t *testing.T) {
   941  			if tc.expectedPanic {
   942  				s.Require().Panics(func() { tc.coins.MulDecTruncate(tc.multiplier) }, "Test case #%d: %s", i, tc.name)
   943  			} else {
   944  				res := tc.coins.MulDecTruncate(tc.multiplier)
   945  				s.Require().Equal(tc.expectedResult, res, "Test case #%d: %s", i, tc.name)
   946  			}
   947  		})
   948  	}
   949  }
   950  
   951  func (s *decCoinTestSuite) TestDecCoins_QuoDec() {
   952  	testCases := []struct {
   953  		name           string
   954  		coins          sdk.DecCoins
   955  		input          math.LegacyDec
   956  		expectedResult sdk.DecCoins
   957  		panics         bool
   958  	}{
   959  		{"No Coins", sdk.DecCoins{}, math.LegacyNewDec(1), sdk.DecCoins(nil), false},
   960  
   961  		{"Multiple coins - zero input", sdk.DecCoins{
   962  			sdk.DecCoin{testDenom1, math.LegacyNewDec(10)},
   963  			sdk.DecCoin{testDenom1, math.LegacyNewDec(30)},
   964  		}, math.LegacyNewDec(0), sdk.DecCoins(nil), true},
   965  
   966  		{"Multiple coins - positive input", sdk.DecCoins{
   967  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   968  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
   969  		}, math.LegacyNewDec(2), sdk.DecCoins{
   970  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(35, 1)},
   971  		}, false},
   972  
   973  		{"Multiple coins - negative input", sdk.DecCoins{
   974  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   975  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
   976  		}, math.LegacyNewDec(-2), sdk.DecCoins{
   977  			sdk.DecCoin{testDenom1, math.LegacyNewDecWithPrec(-35, 1)},
   978  		}, false},
   979  
   980  		{"Multiple coins - Different input", sdk.DecCoins{
   981  			sdk.DecCoin{testDenom1, math.LegacyNewDec(1)},
   982  			sdk.DecCoin{testDenom2, math.LegacyNewDec(2)},
   983  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
   984  			sdk.DecCoin{testDenom2, math.LegacyNewDec(4)},
   985  		}, math.LegacyNewDec(2), sdk.DecCoins{
   986  			sdk.DecCoin{testDenom1, math.LegacyNewDec(2)},
   987  			sdk.DecCoin{testDenom2, math.LegacyNewDec(3)},
   988  		}, false},
   989  	}
   990  
   991  	for i, tc := range testCases {
   992  		tc := tc
   993  		s.T().Run(tc.name, func(t *testing.T) {
   994  			if tc.panics {
   995  				s.Require().Panics(func() { tc.coins.QuoDec(tc.input) }, "Test case #%d: %s", i, tc.name)
   996  			} else {
   997  				res := tc.coins.QuoDec(tc.input)
   998  				s.Require().Equal(tc.expectedResult, res, "Test case #%d: %s", i, tc.name)
   999  			}
  1000  		})
  1001  	}
  1002  }
  1003  
  1004  func (s *decCoinTestSuite) TestDecCoin_IsEqual() {
  1005  	testCases := []struct {
  1006  		name           string
  1007  		coin           sdk.DecCoin
  1008  		otherCoin      sdk.DecCoin
  1009  		expectedResult bool
  1010  	}{
  1011  		{
  1012  			"Different Denom Same Amount",
  1013  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
  1014  			sdk.DecCoin{testDenom2, math.LegacyNewDec(20)},
  1015  			false,
  1016  		},
  1017  
  1018  		{
  1019  			"Different Denom Different Amount",
  1020  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
  1021  			sdk.DecCoin{testDenom2, math.LegacyNewDec(10)},
  1022  			false,
  1023  		},
  1024  
  1025  		{
  1026  			"Same Denom Different Amount",
  1027  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
  1028  			sdk.DecCoin{testDenom1, math.LegacyNewDec(10)},
  1029  			false,
  1030  		},
  1031  
  1032  		{
  1033  			"Same Denom Same Amount",
  1034  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
  1035  			sdk.DecCoin{testDenom1, math.LegacyNewDec(20)},
  1036  			true,
  1037  		},
  1038  	}
  1039  
  1040  	for i, tc := range testCases {
  1041  		s.T().Run(tc.name, func(t *testing.T) {
  1042  			res := tc.coin.IsEqual(tc.otherCoin)
  1043  			if tc.expectedResult {
  1044  				s.Require().True(res, "Test case #%d: %s", i, tc.name)
  1045  			} else {
  1046  				s.Require().False(res, "Test case #%d: %s", i, tc.name)
  1047  			}
  1048  		})
  1049  	}
  1050  }
  1051  
  1052  func (s *decCoinTestSuite) TestDecCoins_IsEqual() {
  1053  	testCases := []struct {
  1054  		name           string
  1055  		coinsA         sdk.DecCoins
  1056  		coinsB         sdk.DecCoins
  1057  		expectedResult bool
  1058  	}{
  1059  		{"Different length sets", sdk.DecCoins{
  1060  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
  1061  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
  1062  		}, sdk.DecCoins{
  1063  			sdk.DecCoin{testDenom1, math.LegacyNewDec(35)},
  1064  		}, false},
  1065  
  1066  		{"Same length - different denoms", sdk.DecCoins{
  1067  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
  1068  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
  1069  		}, sdk.DecCoins{
  1070  			sdk.DecCoin{testDenom2, math.LegacyNewDec(3)},
  1071  			sdk.DecCoin{testDenom2, math.LegacyNewDec(4)},
  1072  		}, false},
  1073  
  1074  		{"Same length - different amounts", sdk.DecCoins{
  1075  			sdk.DecCoin{testDenom1, math.LegacyNewDec(3)},
  1076  			sdk.DecCoin{testDenom1, math.LegacyNewDec(4)},
  1077  		}, sdk.DecCoins{
  1078  			sdk.DecCoin{testDenom1, math.LegacyNewDec(41)},
  1079  			sdk.DecCoin{testDenom1, math.LegacyNewDec(343)},
  1080  		}, false},
  1081  
  1082  		{"Same length - same amounts", sdk.DecCoins{
  1083  			sdk.DecCoin{testDenom1, math.LegacyNewDec(33)},
  1084  			sdk.DecCoin{testDenom1, math.LegacyNewDec(344)},
  1085  		}, sdk.DecCoins{
  1086  			sdk.DecCoin{testDenom1, math.LegacyNewDec(33)},
  1087  			sdk.DecCoin{testDenom1, math.LegacyNewDec(344)},
  1088  		}, true},
  1089  	}
  1090  
  1091  	for i, tc := range testCases {
  1092  		s.T().Run(tc.name, func(t *testing.T) {
  1093  			res := tc.coinsA.Equal(tc.coinsB)
  1094  			if tc.expectedResult {
  1095  				s.Require().True(res, "Test case #%d: %s", i, tc.name)
  1096  			} else {
  1097  				s.Require().False(res, "Test case #%d: %s", i, tc.name)
  1098  			}
  1099  		})
  1100  	}
  1101  }
  1102  
  1103  func (s *decCoinTestSuite) TestDecCoin_Validate() {
  1104  	var empty sdk.DecCoin
  1105  	testCases := []struct {
  1106  		name         string
  1107  		input        sdk.DecCoin
  1108  		expectedPass bool
  1109  	}{
  1110  		{"Uninitialized deccoin", empty, false},
  1111  
  1112  		{"Invalid denom string", sdk.DecCoin{"(){9**&})", math.LegacyNewDec(33)}, false},
  1113  
  1114  		{"Negative coin amount", sdk.DecCoin{testDenom1, math.LegacyNewDec(-33)}, false},
  1115  
  1116  		{"Valid coin", sdk.DecCoin{testDenom1, math.LegacyNewDec(33)}, true},
  1117  	}
  1118  
  1119  	for i, tc := range testCases {
  1120  		s.T().Run(tc.name, func(t *testing.T) {
  1121  			err := tc.input.Validate()
  1122  			if tc.expectedPass {
  1123  				s.Require().NoError(err, "unexpected result for test case #%d %s, input: %v", i, tc.name, tc.input)
  1124  			} else {
  1125  				s.Require().Error(err, "unexpected result for test case #%d %s, input: %v", i, tc.name, tc.input)
  1126  			}
  1127  		})
  1128  	}
  1129  }
  1130  
  1131  func (s *decCoinTestSuite) TestDecCoin_ParseDecCoin() {
  1132  	var empty sdk.DecCoin
  1133  	testCases := []struct {
  1134  		name           string
  1135  		input          string
  1136  		expectedResult sdk.DecCoin
  1137  		expectedErr    bool
  1138  	}{
  1139  		{"Empty input", "", empty, true},
  1140  
  1141  		{"Bad input", "✨🌟⭐", empty, true},
  1142  
  1143  		{"Invalid decimal coin", "9.3.0stake", empty, true},
  1144  
  1145  		{"Precision over limit", "9.11111111111111111111stake", empty, true},
  1146  
  1147  		{"Valid upper case denom", "9.3STAKE", sdk.DecCoin{"STAKE", math.LegacyNewDecWithPrec(93, 1)}, false},
  1148  
  1149  		{"Valid input - amount and denom separated by space", "9.3 stake", sdk.DecCoin{"stake", math.LegacyNewDecWithPrec(93, 1)}, false},
  1150  
  1151  		{"Valid input - amount and denom concatenated", "9.3stake", sdk.DecCoin{"stake", math.LegacyNewDecWithPrec(93, 1)}, false},
  1152  	}
  1153  
  1154  	for i, tc := range testCases {
  1155  		s.T().Run(tc.name, func(t *testing.T) {
  1156  			res, err := sdk.ParseDecCoin(tc.input)
  1157  			if tc.expectedErr {
  1158  				s.Require().Error(err, "expected error for test case #%d %s, input: %v", i, tc.name, tc.input)
  1159  			} else {
  1160  				s.Require().NoError(err, "unexpected error for test case #%d %s, input: %v", i, tc.name, tc.input)
  1161  				s.Require().Equal(tc.expectedResult, res, "unexpected result for test case #%d %s, input: %v", i, tc.name, tc.input)
  1162  			}
  1163  		})
  1164  	}
  1165  }