github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/blocks/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 blocksPkg
     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/validate"
    13  )
    14  
    15  func (opts *BlocksOptions) validateBlocks() error {
    16  	chain := opts.Globals.Chain
    17  
    18  	opts.testLog()
    19  
    20  	if opts.BadFlag != nil {
    21  		return opts.BadFlag
    22  	}
    23  
    24  	if !config.IsChainConfigured(chain) {
    25  		return validate.Usage("chain {0} is not properly configured.", chain)
    26  	}
    27  
    28  	for _, emitter := range opts.Emitter {
    29  		valid, err := base.IsValidAddressE(emitter)
    30  		if !valid {
    31  			return err
    32  		}
    33  	}
    34  
    35  	for _, topic := range opts.Topic {
    36  		valid, err := validate.IsValidTopicE(topic)
    37  		if !valid {
    38  			return err
    39  		}
    40  	}
    41  
    42  	if opts.tooMany() {
    43  		return validate.Usage("Please choose only a single mode (--uncles, --logs, --withdrawal, etc.)")
    44  	}
    45  
    46  	err := validate.ValidateIdentifiers(
    47  		chain,
    48  		opts.Blocks,
    49  		validate.ValidBlockIdWithRange,
    50  		1,
    51  		&opts.BlockIds,
    52  	)
    53  	if err != nil {
    54  		if invalidLiteral, ok := err.(*validate.InvalidIdentifierLiteralError); ok {
    55  			return invalidLiteral
    56  		}
    57  
    58  		if errors.Is(err, validate.ErrTooManyRanges) {
    59  			return validate.Usage("Specify only a single block range at a time.")
    60  		}
    61  
    62  		return err
    63  	}
    64  
    65  	if len(opts.Flow) > 0 {
    66  		if !opts.Uniq {
    67  			return validate.Usage("The {0} option is only available with the {1} option", "--flow", "--uniq")
    68  		}
    69  		err := validate.ValidateEnum("flow", opts.Flow, "[from|to|reward]")
    70  		if err != nil {
    71  			return err
    72  		}
    73  	}
    74  
    75  	if len(opts.Globals.File) > 0 {
    76  		// Do nothing
    77  	} else {
    78  		if len(opts.Blocks) == 0 {
    79  			return validate.Usage("Please supply at least one {0}.", "block identifier")
    80  		}
    81  		if !opts.Logs && (len(opts.Emitter) > 0 || len(opts.Topic) > 0) {
    82  			return validate.Usage("The {0} option are only available with the {1} option.", "--emitter and --topic", "--log")
    83  		}
    84  		if opts.Traces && opts.Hashes {
    85  			return validate.Usage("The {0} option is not available{1}.", "--traces", " with the --hashes option")
    86  		}
    87  		if !validate.HasArticulationKey(opts.Articulate) {
    88  			return validate.Usage("The {0} option requires an Etherscan API key.", "--articulate")
    89  		}
    90  		if opts.Articulate && !opts.Logs {
    91  			return validate.Usage("The {0} option is only available with the {1} option.", "--articulate", "--logs")
    92  		}
    93  		if opts.Uniq && !opts.Count {
    94  			if opts.Traces {
    95  				return validate.Usage("The {0} option is not available{1}.", "--traces", " with the --uniq option")
    96  			}
    97  			if opts.Uncles {
    98  				return validate.Usage("The {0} option is not available{1}.", "--uncles", " with the --uniq option")
    99  			}
   100  			if opts.Logs {
   101  				return validate.Usage("The {0} option is not available{1}.", "--logs", " with the --uniq option")
   102  			}
   103  		}
   104  
   105  		if opts.Traces {
   106  			err, ok := opts.Conn.IsNodeTracing()
   107  			if !ok {
   108  				return validate.Usage("{0} requires tracing, err: {1}", "chifra blocks --traces", err.Error())
   109  			}
   110  		}
   111  
   112  		if opts.Articulate {
   113  			if opts.Uncles {
   114  				return validate.Usage("The {0} option is not available{1}.", "--articulate", " with the --uncles option")
   115  			}
   116  		}
   117  
   118  		// We cannot cache uncles because they are identical to the cannonical blocks of the same number and would be incorrectly retreived.
   119  		if opts.Globals.Cache && opts.Uncles {
   120  			return validate.Usage("The {0} option is currently not available{1}.", "--cache", " with the --uncles option")
   121  		}
   122  		if opts.Globals.Decache && opts.Uncles {
   123  			return validate.Usage("The {0} option is currently not available{1}.", "--decache", " with the --uncles option")
   124  		}
   125  	}
   126  
   127  	return opts.Globals.Validate()
   128  }
   129  
   130  func (opts *BlocksOptions) tooMany() bool {
   131  	cnt := 0
   132  	if opts.Uncles {
   133  		cnt++
   134  	}
   135  	if opts.Traces {
   136  		cnt++
   137  	}
   138  	if opts.Uniq {
   139  		cnt++
   140  	}
   141  	if opts.Logs {
   142  		cnt++
   143  	}
   144  	if opts.Withdrawals {
   145  		cnt++
   146  	}
   147  	return !opts.Count && cnt > 1
   148  }