github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/dec_coin.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/tendermint/go-amino"
    10  
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // ----------------------------------------------------------------------------
    15  // Decimal Coin
    16  
    17  // DecCoin defines a coin which can have additional decimal points
    18  type DecCoin struct {
    19  	Denom  string `json:"denom"`
    20  	Amount Dec    `json:"amount"`
    21  }
    22  
    23  func (coin *DecCoin) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error {
    24  	var dataLen uint64 = 0
    25  	var subData []byte
    26  
    27  	for {
    28  		data = data[dataLen:]
    29  
    30  		if len(data) <= 0 {
    31  			break
    32  		}
    33  
    34  		pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0])
    35  		if err != nil {
    36  			return err
    37  		}
    38  		data = data[1:]
    39  
    40  		if aminoType == amino.Typ3_ByteLength {
    41  			var n int
    42  			dataLen, n, err = amino.DecodeUvarint(data)
    43  			if err != nil {
    44  				return err
    45  			}
    46  
    47  			data = data[n:]
    48  			if len(data) < int(dataLen) {
    49  				return errors.New("not enough data")
    50  			}
    51  			subData = data[:dataLen]
    52  		}
    53  
    54  		switch pos {
    55  		case 1:
    56  			coin.Denom = string(subData)
    57  		case 2:
    58  			err = coin.Amount.UnmarshalFromAmino(cdc, subData)
    59  			if err != nil {
    60  				return err
    61  			}
    62  		}
    63  	}
    64  	return nil
    65  }
    66  
    67  // NewDecCoin creates a new DecCoin instance from an Int.
    68  func NewDecCoin(denom string, amount Int) DecCoin {
    69  	if err := validate(denom, amount); err != nil {
    70  		panic(err)
    71  	}
    72  
    73  	return DecCoin{
    74  		Denom:  denom,
    75  		Amount: amount.ToDec(),
    76  	}
    77  }
    78  
    79  // NewDecCoinFromDec creates a new DecCoin instance from a Dec.
    80  func NewDecCoinFromDec(denom string, amount Dec) DecCoin {
    81  	mustValidateDenom(denom)
    82  
    83  	if amount.IsNegative() {
    84  		panic(fmt.Sprintf("negative decimal coin amount: %v\n", amount))
    85  	}
    86  
    87  	return DecCoin{
    88  		Denom:  denom,
    89  		Amount: amount,
    90  	}
    91  }
    92  
    93  // NewDecCoinFromCoin creates a new DecCoin from a Coin.
    94  func NewDecCoinFromCoin(coin Coin) DecCoin {
    95  	return coin
    96  
    97  	//if err := validate(coin.Denom, coin.Amount); err != nil {
    98  	//	panic(err)
    99  	//}
   100  	//
   101  	//return DecCoin{
   102  	//	Denom:  coin.Denom,
   103  	//	Amount: coin.Amount.ToDec(),
   104  	//}
   105  }
   106  
   107  // NewInt64DecCoin returns a new DecCoin with a denomination and amount. It will
   108  // panic if the amount is negative or denom is invalid.
   109  func NewInt64DecCoin(denom string, amount int64) DecCoin {
   110  	return NewDecCoin(denom, NewInt(amount))
   111  }
   112  
   113  // IsZero returns if the DecCoin amount is zero.
   114  func (coin DecCoin) IsZero() bool {
   115  	return coin.Amount.IsZero()
   116  }
   117  
   118  // IsGTE returns true if they are the same type and the receiver is
   119  // an equal or greater value.
   120  func (coin DecCoin) IsGTE(other DecCoin) bool {
   121  	if coin.Denom != other.Denom {
   122  		panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom))
   123  	}
   124  
   125  	return !coin.Amount.LT(other.Amount)
   126  }
   127  
   128  // IsLT returns true if they are the same type and the receiver is
   129  // a smaller value.
   130  func (coin DecCoin) IsLT(other DecCoin) bool {
   131  	if coin.Denom != other.Denom {
   132  		panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom))
   133  	}
   134  
   135  	return coin.Amount.LT(other.Amount)
   136  }
   137  
   138  // IsEqual returns true if the two sets of Coins have the same value.
   139  func (coin DecCoin) IsEqual(other DecCoin) bool {
   140  	if coin.Denom != other.Denom {
   141  		panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom))
   142  	}
   143  
   144  	return coin.Amount.Equal(other.Amount)
   145  }
   146  
   147  // Add adds amounts of two decimal coins with same denom.
   148  func (coin DecCoin) Add(coinB DecCoin) DecCoin {
   149  	if coin.Denom != coinB.Denom {
   150  		panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom))
   151  	}
   152  	return DecCoin{coin.Denom, coin.Amount.Add(coinB.Amount)}
   153  }
   154  
   155  // Sub subtracts amounts of two decimal coins with same denom.
   156  func (coin DecCoin) Sub(coinB DecCoin) DecCoin {
   157  	if coin.Denom != coinB.Denom {
   158  		panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom))
   159  	}
   160  	res := DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)}
   161  	if res.IsNegative() {
   162  		panic("negative decimal coin amount")
   163  	}
   164  	return res
   165  }
   166  
   167  // TruncateDecimal returns a Coin with a truncated decimal and a DecCoin for the
   168  // change. Note, the change may be zero.
   169  func (coin DecCoin) TruncateDecimal() (Coin, DecCoin) {
   170  	truncated := coin.Amount.TruncateInt()
   171  	change := coin.Amount.Sub(truncated.ToDec())
   172  	return NewCoin(coin.Denom, truncated), NewDecCoinFromDec(coin.Denom, change)
   173  }
   174  
   175  // TruncateWithPrec returns a Coin with a truncated coin and a DecCoin for the
   176  // change with prec, Note, the change may be zero.
   177  func (coin DecCoin) TruncateWithPrec(prec int64) (Coin, DecCoin) {
   178  	if prec < 0 || prec > Precision {
   179  		panic(fmt.Sprintf("prec range error, %d", prec))
   180  	}
   181  
   182  	tempTruncated := coin.Amount.TruncateWithPrec(prec)
   183  	truncated := NewDecFromIntWithPrec(tempTruncated, prec)
   184  	change := coin.Amount.Sub(truncated)
   185  	return NewCoin(coin.Denom, truncated), NewDecCoinFromDec(coin.Denom, change)
   186  }
   187  
   188  // IsPositive returns true if coin amount is positive.
   189  //
   190  // TODO: Remove once unsigned integers are used.
   191  func (coin DecCoin) IsPositive() bool {
   192  	return coin.Amount.IsPositive()
   193  }
   194  
   195  // IsNegative returns true if the coin amount is negative and false otherwise.
   196  //
   197  // TODO: Remove once unsigned integers are used.
   198  func (coin DecCoin) IsNegative() bool {
   199  	return coin.Amount.Sign() == -1
   200  }
   201  
   202  // String implements the Stringer interface for DecCoin. It returns a
   203  // human-readable representation of a decimal coin.
   204  func (coin DecCoin) String() string {
   205  	amountStr := coin.Amount.String()
   206  	coinStr := make([]byte, len(amountStr)+len(coin.Denom))
   207  	copy(coinStr, amountStr)
   208  	copy(coinStr[len(amountStr):], coin.Denom)
   209  	return amino.BytesToStr(coinStr)
   210  }
   211  
   212  // IsValid returns true if the DecCoin has a non-negative amount and the denom is vaild.
   213  func (coin DecCoin) IsValid() bool {
   214  	if err := ValidateDenom(coin.Denom); err != nil {
   215  		return false
   216  	}
   217  	return !coin.IsNegative()
   218  }
   219  
   220  func (coin DecCoin) MarshalToAmino(cdc *amino.Codec) ([]byte, error) {
   221  	buf := bytes.NewBuffer(make([]byte, 0, coin.AminoSize(cdc)))
   222  	err := coin.MarshalAminoTo(cdc, buf)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	return buf.Bytes(), nil
   227  }
   228  
   229  func (coin DecCoin) MarshalAminoTo(cdc *amino.Codec, buf *bytes.Buffer) error {
   230  	// field 1
   231  	if coin.Denom != "" {
   232  		const pbKey = 1<<3 | 2
   233  		err := amino.EncodeStringWithKeyToBuffer(buf, coin.Denom, pbKey)
   234  		if err != nil {
   235  			return err
   236  		}
   237  	}
   238  	// field 2
   239  	{
   240  		const pbKey = 2<<3 | 2
   241  		data, err := coin.Amount.MarshalToAmino(cdc)
   242  		if err != nil {
   243  			return err
   244  		}
   245  		err = amino.EncodeByteSliceWithKeyToBuffer(buf, data, pbKey)
   246  		if err != nil {
   247  			return err
   248  		}
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  func (coin DecCoin) AminoSize(cdc *amino.Codec) int {
   255  	size := 0
   256  	if coin.Denom != "" {
   257  		size += 1 + amino.EncodedStringSize(coin.Denom)
   258  	}
   259  	coinSize := coin.Amount.AminoSize(cdc)
   260  	// coinSize must greater than 0 if coin.Amount.MarshalToAmino() is success
   261  	size += 1 + amino.UvarintSize(uint64(coinSize)) + coinSize
   262  	return size
   263  }
   264  
   265  // ----------------------------------------------------------------------------
   266  // Decimal Coins
   267  
   268  // DecCoins defines a slice of coins with decimal values
   269  type DecCoins []DecCoin
   270  
   271  // NewDecCoins constructs a new coin set with with decimal values
   272  // from DecCoins.
   273  func NewDecCoins(decCoins ...DecCoin) DecCoins {
   274  	// remove zeroes
   275  	newDecCoins := removeZeroDecCoins(DecCoins(decCoins))
   276  	if len(newDecCoins) == 0 {
   277  		return DecCoins{}
   278  	}
   279  
   280  	newDecCoins.Sort()
   281  
   282  	// detect duplicate Denoms
   283  	if dupIndex := findDup(newDecCoins); dupIndex != -1 {
   284  		panic(fmt.Errorf("find duplicate denom: %s", newDecCoins[dupIndex]))
   285  	}
   286  
   287  	if !newDecCoins.IsValid() {
   288  		panic(fmt.Errorf("invalid coin set: %s", newDecCoins))
   289  	}
   290  
   291  	return newDecCoins
   292  }
   293  
   294  // NewDecCoinsFromCoin constructs a new coin set with decimal values
   295  // from regular Coins.
   296  func NewDecCoinsFromCoins(coins ...Coin) DecCoins {
   297  	decCoins := make(DecCoins, len(coins))
   298  	newCoins := NewCoins(coins...)
   299  	for i, coin := range newCoins {
   300  		decCoins[i] = NewDecCoinFromCoin(coin)
   301  	}
   302  
   303  	return decCoins
   304  }
   305  
   306  // String implements the Stringer interface for DecCoins. It returns a
   307  // human-readable representation of decimal coins.
   308  func (coins DecCoins) String() string {
   309  	if len(coins) == 0 {
   310  		return ""
   311  	}
   312  	if len(coins) == 1 {
   313  		return coins[0].String()
   314  	}
   315  
   316  	out := ""
   317  	for _, coin := range coins {
   318  		out += fmt.Sprintf("%v,", coin.String())
   319  	}
   320  
   321  	return out[:len(out)-1]
   322  }
   323  
   324  // TruncateDecimal returns the coins with truncated decimals and returns the
   325  // change. Note, it will not return any zero-amount coins in either the truncated or
   326  // change coins.
   327  func (coins DecCoins) TruncateDecimal() (truncatedCoins Coins, changeCoins DecCoins) {
   328  	for _, coin := range coins {
   329  		truncated, change := coin.TruncateDecimal()
   330  		if !truncated.IsZero() {
   331  			truncatedCoins = truncatedCoins.Add(truncated)
   332  		}
   333  		if !change.IsZero() {
   334  			changeCoins = changeCoins.Add(change)
   335  		}
   336  	}
   337  
   338  	return truncatedCoins, changeCoins
   339  }
   340  
   341  // TruncateWithPrec returns the coins with truncated fix coins and returns the
   342  // change with prec. Note, it will not return any zero-amount coins in either the truncated or change coins.
   343  func (coins DecCoins) TruncateWithPrec(prec int64) (truncatedCoins Coins, changeCoins DecCoins) {
   344  	for _, coin := range coins {
   345  		truncated, change := coin.TruncateWithPrec(prec)
   346  		if !truncated.IsZero() {
   347  			truncatedCoins = truncatedCoins.Add(truncated)
   348  		}
   349  		if !change.IsZero() {
   350  			changeCoins = changeCoins.Add(change)
   351  		}
   352  	}
   353  
   354  	return truncatedCoins, changeCoins
   355  }
   356  
   357  // Add adds two sets of DecCoins.
   358  //
   359  // NOTE: Add operates under the invariant that coins are sorted by
   360  // denominations.
   361  //
   362  // CONTRACT: Add will never return Coins where one Coin has a non-positive
   363  // amount. In otherwords, IsValid will always return true.
   364  func (coins DecCoins) Add(coinsB ...DecCoin) DecCoins {
   365  	return coins.safeAdd(coinsB)
   366  }
   367  
   368  // safeAdd will perform addition of two DecCoins sets. If both coin sets are
   369  // empty, then an empty set is returned. If only a single set is empty, the
   370  // other set is returned. Otherwise, the coins are compared in order of their
   371  // denomination and addition only occurs when the denominations match, otherwise
   372  // the coin is simply added to the sum assuming it's not zero.
   373  func (coins DecCoins) safeAdd(coinsB DecCoins) DecCoins {
   374  	sum := ([]DecCoin)(nil)
   375  	indexA, indexB := 0, 0
   376  	lenA, lenB := len(coins), len(coinsB)
   377  
   378  	for {
   379  		if indexA == lenA {
   380  			if indexB == lenB {
   381  				// return nil coins if both sets are empty
   382  				return sum
   383  			}
   384  
   385  			// return set B (excluding zero coins) if set A is empty
   386  			return append(sum, removeZeroDecCoins(coinsB[indexB:])...)
   387  		} else if indexB == lenB {
   388  			// return set A (excluding zero coins) if set B is empty
   389  			return append(sum, removeZeroDecCoins(coins[indexA:])...)
   390  		}
   391  
   392  		coinA, coinB := coins[indexA], coinsB[indexB]
   393  
   394  		switch strings.Compare(coinA.Denom, coinB.Denom) {
   395  		case -1: // coin A denom < coin B denom
   396  			if !coinA.IsZero() {
   397  				sum = append(sum, coinA)
   398  			}
   399  
   400  			indexA++
   401  
   402  		case 0: // coin A denom == coin B denom
   403  			res := coinA.Add(coinB)
   404  			if !res.IsZero() {
   405  				sum = append(sum, res)
   406  			}
   407  
   408  			indexA++
   409  			indexB++
   410  
   411  		case 1: // coin A denom > coin B denom
   412  			if !coinB.IsZero() {
   413  				sum = append(sum, coinB)
   414  			}
   415  
   416  			indexB++
   417  		}
   418  	}
   419  }
   420  
   421  // negative returns a set of coins with all amount negative.
   422  func (coins DecCoins) negative() DecCoins {
   423  	res := make([]DecCoin, 0, len(coins))
   424  	for _, coin := range coins {
   425  		res = append(res, DecCoin{
   426  			Denom:  coin.Denom,
   427  			Amount: coin.Amount.Neg(),
   428  		})
   429  	}
   430  	return res
   431  }
   432  
   433  // Sub subtracts a set of DecCoins from another (adds the inverse).
   434  func (coins DecCoins) Sub(coinsB DecCoins) DecCoins {
   435  	diff, hasNeg := coins.SafeSub(coinsB)
   436  	if hasNeg {
   437  		panic("negative coin amount")
   438  	}
   439  
   440  	return diff
   441  }
   442  
   443  // SafeSub performs the same arithmetic as Sub but returns a boolean if any
   444  // negative coin amount was returned.
   445  func (coins DecCoins) SafeSub(coinsB DecCoins) (DecCoins, bool) {
   446  	diff := coins.safeAdd(coinsB.negative())
   447  	return diff, diff.IsAnyNegative()
   448  }
   449  
   450  // Intersect will return a new set of coins which contains the minimum DecCoin
   451  // for common denoms found in both `coins` and `coinsB`. For denoms not common
   452  // to both `coins` and `coinsB` the minimum is considered to be 0, thus they
   453  // are not added to the final set.In other words, trim any denom amount from
   454  // coin which exceeds that of coinB, such that (coin.Intersect(coinB)).IsLTE(coinB).
   455  func (coins DecCoins) Intersect(coinsB DecCoins) DecCoins {
   456  	res := make([]DecCoin, len(coins))
   457  	for i, coin := range coins {
   458  		minCoin := DecCoin{
   459  			Denom:  coin.Denom,
   460  			Amount: MinDec(coin.Amount, coinsB.AmountOf(coin.Denom)),
   461  		}
   462  		res[i] = minCoin
   463  	}
   464  	return removeZeroDecCoins(res)
   465  }
   466  
   467  // GetDenomByIndex returns the Denom to make the findDup generic
   468  func (coins DecCoins) GetDenomByIndex(i int) string {
   469  	return coins[i].Denom
   470  }
   471  
   472  // IsAnyNegative returns true if there is at least one coin whose amount
   473  // is negative; returns false otherwise. It returns false if the DecCoins set
   474  // is empty too.
   475  //
   476  // TODO: Remove once unsigned integers are used.
   477  func (coins DecCoins) IsAnyNegative() bool {
   478  	for _, coin := range coins {
   479  		if coin.IsNegative() {
   480  			return true
   481  		}
   482  	}
   483  
   484  	return false
   485  }
   486  
   487  // MulDec multiplies all the coins by a decimal.
   488  //
   489  // CONTRACT: No zero coins will be returned.
   490  func (coins DecCoins) MulDec(d Dec) DecCoins {
   491  	var res DecCoins
   492  	for _, coin := range coins {
   493  		product := DecCoin{
   494  			Denom:  coin.Denom,
   495  			Amount: coin.Amount.Mul(d),
   496  		}
   497  
   498  		if !product.IsZero() {
   499  			res = res.Add(product)
   500  		}
   501  	}
   502  
   503  	return res
   504  }
   505  
   506  // MulDecTruncate multiplies all the decimal coins by a decimal, truncating. It
   507  // panics if d is zero.
   508  //
   509  // CONTRACT: No zero coins will be returned.
   510  func (coins DecCoins) MulDecTruncate(d Dec) DecCoins {
   511  	var res DecCoins
   512  
   513  	for _, coin := range coins {
   514  		product := DecCoin{
   515  			Denom:  coin.Denom,
   516  			Amount: coin.Amount.MulTruncate(d),
   517  		}
   518  
   519  		if !product.IsZero() {
   520  			res = res.Add(product)
   521  		}
   522  	}
   523  
   524  	return res
   525  }
   526  
   527  // QuoDec divides all the decimal coins by a decimal. It panics if d is zero.
   528  //
   529  // CONTRACT: No zero coins will be returned.
   530  func (coins DecCoins) QuoDec(d Dec) DecCoins {
   531  	if d.IsZero() {
   532  		panic("invalid zero decimal")
   533  	}
   534  
   535  	var res DecCoins
   536  	for _, coin := range coins {
   537  		quotient := DecCoin{
   538  			Denom:  coin.Denom,
   539  			Amount: coin.Amount.Quo(d),
   540  		}
   541  
   542  		if !quotient.IsZero() {
   543  			res = res.Add(quotient)
   544  		}
   545  	}
   546  
   547  	return res
   548  }
   549  
   550  // QuoDecTruncate divides all the decimal coins by a decimal, truncating. It
   551  // panics if d is zero.
   552  //
   553  // CONTRACT: No zero coins will be returned.
   554  func (coins DecCoins) QuoDecTruncate(d Dec) DecCoins {
   555  	if d.IsZero() {
   556  		panic("invalid zero decimal")
   557  	}
   558  
   559  	var res DecCoins
   560  	for _, coin := range coins {
   561  		quotient := DecCoin{
   562  			Denom:  coin.Denom,
   563  			Amount: coin.Amount.QuoTruncate(d),
   564  		}
   565  
   566  		if !quotient.IsZero() {
   567  			res = res.Add(quotient)
   568  		}
   569  	}
   570  
   571  	return res
   572  }
   573  
   574  // Empty returns true if there are no coins and false otherwise.
   575  func (coins DecCoins) Empty() bool {
   576  	return len(coins) == 0
   577  }
   578  
   579  // AmountOf returns the amount of a denom from deccoins
   580  func (coins DecCoins) AmountOf(denom string) Dec {
   581  	mustValidateDenom(denom)
   582  
   583  	switch len(coins) {
   584  	case 0:
   585  		return ZeroDec()
   586  
   587  	case 1:
   588  		coin := coins[0]
   589  		if coin.Denom == denom {
   590  			return coin.Amount
   591  		}
   592  		return ZeroDec()
   593  
   594  	default:
   595  		midIdx := len(coins) / 2 // 2:1, 3:1, 4:2
   596  		coin := coins[midIdx]
   597  
   598  		switch {
   599  		case denom < coin.Denom:
   600  			return coins[:midIdx].AmountOf(denom)
   601  		case denom == coin.Denom:
   602  			return coin.Amount
   603  		default:
   604  			return coins[midIdx+1:].AmountOf(denom)
   605  		}
   606  	}
   607  }
   608  
   609  // IsEqual returns true if the two sets of DecCoins have the same value.
   610  func (coins DecCoins) IsEqual(coinsB DecCoins) bool {
   611  	if len(coins) != len(coinsB) {
   612  		return false
   613  	}
   614  
   615  	coins = coins.Sort()
   616  	coinsB = coinsB.Sort()
   617  
   618  	for i := 0; i < len(coins); i++ {
   619  		if !coins[i].IsEqual(coinsB[i]) {
   620  			return false
   621  		}
   622  	}
   623  
   624  	return true
   625  }
   626  
   627  // IsZero returns whether all coins are zero
   628  func (coins DecCoins) IsZero() bool {
   629  	for _, coin := range coins {
   630  		if !coin.Amount.IsZero() {
   631  			return false
   632  		}
   633  	}
   634  	return true
   635  }
   636  
   637  // IsValid asserts the DecCoins are sorted, have positive amount, and Denom
   638  // does not contain upper case characters.
   639  func (coins DecCoins) IsValid() bool {
   640  	switch len(coins) {
   641  	case 0:
   642  		return true
   643  
   644  	case 1:
   645  		if err := ValidateDenom(coins[0].Denom); err != nil {
   646  			return false
   647  		}
   648  		return coins[0].IsPositive()
   649  
   650  	default:
   651  		// check single coin case
   652  		if !(DecCoins{coins[0]}).IsValid() {
   653  			return false
   654  		}
   655  
   656  		lowDenom := coins[0].Denom
   657  		for _, coin := range coins[1:] {
   658  			if strings.ToLower(coin.Denom) != coin.Denom {
   659  				return false
   660  			}
   661  			if coin.Denom <= lowDenom {
   662  				return false
   663  			}
   664  			if !coin.IsPositive() {
   665  				return false
   666  			}
   667  
   668  			// we compare each coin against the last denom
   669  			lowDenom = coin.Denom
   670  		}
   671  
   672  		return true
   673  	}
   674  }
   675  
   676  // IsAllPositive returns true if there is at least one coin and all currencies
   677  // have a positive value.
   678  //
   679  // TODO: Remove once unsigned integers are used.
   680  func (coins DecCoins) IsAllPositive() bool {
   681  	if len(coins) == 0 {
   682  		return false
   683  	}
   684  
   685  	for _, coin := range coins {
   686  		if !coin.IsPositive() {
   687  			return false
   688  		}
   689  	}
   690  
   691  	return true
   692  }
   693  
   694  func removeZeroDecCoins(coins DecCoins) DecCoins {
   695  	for i := 0; i < len(coins); i++ {
   696  		if coins[i].IsZero() {
   697  			break
   698  		} else if i == len(coins)-1 {
   699  			return coins
   700  		}
   701  	}
   702  	var result []DecCoin
   703  	if len(coins) > 0 {
   704  		result = make([]DecCoin, 0, len(coins)-1)
   705  	}
   706  
   707  	for _, coin := range coins {
   708  		if !coin.IsZero() {
   709  			result = append(result, coin)
   710  		}
   711  	}
   712  	return result
   713  }
   714  
   715  //-----------------------------------------------------------------------------
   716  // Sorting
   717  
   718  var _ sort.Interface = Coins{}
   719  
   720  // nolint
   721  func (coins DecCoins) Len() int           { return len(coins) }
   722  func (coins DecCoins) Less(i, j int) bool { return coins[i].Denom < coins[j].Denom }
   723  func (coins DecCoins) Swap(i, j int)      { coins[i], coins[j] = coins[j], coins[i] }
   724  
   725  // Sort is a helper function to sort the set of decimal coins in-place.
   726  func (coins DecCoins) Sort() DecCoins {
   727  	sort.Sort(coins)
   728  	return coins
   729  }
   730  
   731  // ----------------------------------------------------------------------------
   732  // Parsing
   733  
   734  // ParseDecCoin parses a decimal coin from a string, returning an error if
   735  // invalid. An empty string is considered invalid.
   736  func ParseDecCoin(coinStr string) (coin DecCoin, err error) {
   737  	coinStr = strings.TrimSpace(coinStr)
   738  
   739  	matches := reDecCoin.FindStringSubmatch(coinStr)
   740  	if matches == nil {
   741  		if strings.Contains(coinStr, "ibc/") {
   742  			return IBCParseDecCoin(coinStr)
   743  		}
   744  		return DecCoin{}, fmt.Errorf("invalid decimal coin expression: %s", coinStr)
   745  	}
   746  
   747  	amountStr, denomStr := matches[1], matches[2]
   748  
   749  	amount, err := NewDecFromStr(amountStr)
   750  	if err != nil {
   751  		return DecCoin{}, errors.Wrap(err, fmt.Sprintf("failed to parse decimal coin amount: %s", amountStr))
   752  	}
   753  
   754  	if err := ValidateDenom(denomStr); err != nil {
   755  		return DecCoin{}, fmt.Errorf("invalid denom cannot contain upper case characters or spaces: %s", err)
   756  	}
   757  
   758  	return NewDecCoinFromDec(denomStr, amount), nil
   759  }
   760  
   761  // ParseDecCoins will parse out a list of decimal coins separated by commas.
   762  // If nothing is provided, it returns nil DecCoins. Returned decimal coins are
   763  // sorted.
   764  func ParseDecCoins(coinsStr string) (DecCoins, error) {
   765  	coinsStr = strings.TrimSpace(coinsStr)
   766  	if len(coinsStr) == 0 {
   767  		return nil, nil
   768  	}
   769  
   770  	coinStrs := strings.Split(coinsStr, ",")
   771  	coins := make(DecCoins, len(coinStrs))
   772  	for i, coinStr := range coinStrs {
   773  		coin, err := ParseDecCoin(coinStr)
   774  		if err != nil {
   775  			return nil, err
   776  		}
   777  
   778  		coins[i] = coin
   779  	}
   780  
   781  	// sort coins for determinism
   782  	coins.Sort()
   783  
   784  	// validate coins before returning
   785  	if !coins.IsValid() {
   786  		return nil, fmt.Errorf("parsed decimal coins are invalid: %#v", coins)
   787  	}
   788  
   789  	return coins, nil
   790  }