github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/tokens/validate.go (about)

     1  // Copyright 2021 The TrueBlocks Authors. All rights reserved.
     2  // Use of this source code is governed by a license that can
     3  // be found in the LICENSE file.
     4  
     5  package tokensPkg
     6  
     7  import (
     8  	"errors"
     9  
    10  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    12  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc"
    13  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/validate"
    14  )
    15  
    16  func (opts *TokensOptions) validateTokens() error {
    17  	chain := opts.Globals.Chain
    18  
    19  	opts.testLog()
    20  
    21  	if opts.BadFlag != nil {
    22  		return opts.BadFlag
    23  	}
    24  
    25  	if !config.IsChainConfigured(chain) {
    26  		return validate.Usage("chain {0} is not properly configured.", chain)
    27  	}
    28  
    29  	err := validate.ValidateEnumSlice("--parts", opts.Parts, "[name|symbol|decimals|totalSupply|version|some|all]")
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	if opts.Changes {
    35  		return validate.Usage("The {0} option is not yet implemented.", "--changes")
    36  	}
    37  
    38  	if len(opts.Addrs) == 0 {
    39  		return validate.Usage("You must specify at least two address")
    40  
    41  	} else {
    42  		if opts.ByAcct {
    43  			if len(opts.Addrs) < 2 {
    44  				return validate.Usage("You must specify at least two addresses")
    45  			}
    46  
    47  			// all but the last is assumed to be a token
    48  			for _, addr := range opts.Addrs[:len(opts.Addrs)-1] {
    49  				err := opts.Conn.IsContractAtLatest(base.HexToAddress(addr))
    50  				if err != nil {
    51  					if errors.Is(err, rpc.ErrNotAContract) {
    52  						return validate.Usage("The value {0} is not a token contract.", addr)
    53  					}
    54  					return err
    55  				}
    56  			}
    57  		} else {
    58  			// the first is assumed to be a smart contract, the rest can be either non-existant, another smart contract or an EOA
    59  			addr := opts.Addrs[0]
    60  			err := opts.Conn.IsContractAtLatest(base.HexToAddress(addr))
    61  			if err != nil {
    62  				if errors.Is(err, rpc.ErrNotAContract) {
    63  					return validate.Usage("The value {0} is not a token contract.", addr)
    64  				}
    65  				return err
    66  			}
    67  		}
    68  	}
    69  
    70  	err = validate.ValidateAddresses(opts.Addrs)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	// Blocks are optional, but if they are present, they must be valid
    76  	if len(opts.Blocks) > 0 {
    77  		bounds, err := validate.ValidateIdentifiersWithBounds(
    78  			chain,
    79  			opts.Blocks,
    80  			validate.ValidBlockIdWithRangeAndDate,
    81  			1,
    82  			&opts.BlockIds,
    83  		)
    84  
    85  		if err != nil {
    86  			if invalidLiteral, ok := err.(*validate.InvalidIdentifierLiteralError); ok {
    87  				return invalidLiteral
    88  			}
    89  
    90  			if errors.Is(err, validate.ErrTooManyRanges) {
    91  				return validate.Usage("Specify only a single block range at a time.")
    92  			}
    93  
    94  			return err
    95  		}
    96  
    97  		latest := opts.Conn.GetLatestBlockNumber()
    98  		if bounds.First < (latest-250) && !opts.Conn.IsNodeArchive() {
    99  			return validate.Usage("The {0} requires {1}.", "query for historical state", "an archive node")
   100  		}
   101  	}
   102  
   103  	return opts.Globals.Validate()
   104  }