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

     1  // Copyright 2016, 2024 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   * Parts of this file were auto generated. Edit only those parts of
     6   * the code inside of 'EXISTING_CODE' tags.
     7   */
     8  
     9  package listPkg
    10  
    11  import (
    12  	// EXISTING_CODE
    13  	"encoding/json"
    14  	"io"
    15  	"net/http"
    16  	"net/url"
    17  	"strings"
    18  
    19  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/internal/globals"
    20  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    21  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/caps"
    22  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    23  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
    24  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc"
    25  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/validate"
    26  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk"
    27  	// EXISTING_CODE
    28  )
    29  
    30  // ListOptions provides all command options for the chifra list command.
    31  type ListOptions struct {
    32  	Addrs       []string              `json:"addrs,omitempty"`       // One or more addresses (0x...) to list
    33  	Count       bool                  `json:"count,omitempty"`       // Display only the count of records for each monitor
    34  	NoZero      bool                  `json:"noZero,omitempty"`      // For the --count option only, suppress the display of zero appearance accounts
    35  	Bounds      bool                  `json:"bounds,omitempty"`      // Report first and last block this address appears
    36  	Unripe      bool                  `json:"unripe,omitempty"`      // List transactions labeled unripe (i.e. less than 28 blocks old)
    37  	Silent      bool                  `json:"silent,omitempty"`      // Freshen the monitor only (no reporting)
    38  	FirstRecord uint64                `json:"firstRecord,omitempty"` // The first record to process
    39  	MaxRecords  uint64                `json:"maxRecords,omitempty"`  // The maximum number of records to process
    40  	Reversed    bool                  `json:"reversed,omitempty"`    // Produce results in reverse chronological order
    41  	Publisher   string                `json:"publisher,omitempty"`   // For some query options, the publisher of the index
    42  	FirstBlock  base.Blknum           `json:"firstBlock,omitempty"`  // First block to export (inclusive, ignored when freshening)
    43  	LastBlock   base.Blknum           `json:"lastBlock,omitempty"`   // Last block to export (inclusive, ignored when freshening)
    44  	Globals     globals.GlobalOptions `json:"globals,omitempty"`     // The global options
    45  	Conn        *rpc.Connection       `json:"conn,omitempty"`        // The connection to the RPC server
    46  	BadFlag     error                 `json:"badFlag,omitempty"`     // An error flag if needed
    47  	// EXISTING_CODE
    48  	PublisherAddr base.Address `json:"-"`
    49  	// EXISTING_CODE
    50  }
    51  
    52  var defaultListOptions = ListOptions{
    53  	MaxRecords: 250,
    54  	LastBlock:  base.NOPOSN,
    55  }
    56  
    57  // testLog is used only during testing to export the options for this test case.
    58  func (opts *ListOptions) testLog() {
    59  	logger.TestLog(len(opts.Addrs) > 0, "Addrs: ", opts.Addrs)
    60  	logger.TestLog(opts.Count, "Count: ", opts.Count)
    61  	logger.TestLog(opts.NoZero, "NoZero: ", opts.NoZero)
    62  	logger.TestLog(opts.Bounds, "Bounds: ", opts.Bounds)
    63  	logger.TestLog(opts.Unripe, "Unripe: ", opts.Unripe)
    64  	logger.TestLog(opts.Silent, "Silent: ", opts.Silent)
    65  	logger.TestLog(opts.FirstRecord != 0, "FirstRecord: ", opts.FirstRecord)
    66  	logger.TestLog(opts.MaxRecords != 250, "MaxRecords: ", opts.MaxRecords)
    67  	logger.TestLog(opts.Reversed, "Reversed: ", opts.Reversed)
    68  	logger.TestLog(len(opts.Publisher) > 0, "Publisher: ", opts.Publisher)
    69  	logger.TestLog(opts.FirstBlock != 0, "FirstBlock: ", opts.FirstBlock)
    70  	logger.TestLog(opts.LastBlock != base.NOPOSN && opts.LastBlock != 0, "LastBlock: ", opts.LastBlock)
    71  	opts.Conn.TestLog(opts.getCaches())
    72  	opts.Globals.TestLog()
    73  }
    74  
    75  // String implements the Stringer interface
    76  func (opts *ListOptions) String() string {
    77  	b, _ := json.MarshalIndent(opts, "", "  ")
    78  	return string(b)
    79  }
    80  
    81  // listFinishParseApi finishes the parsing for server invocations. Returns a new ListOptions.
    82  func listFinishParseApi(w http.ResponseWriter, r *http.Request) *ListOptions {
    83  	values := r.URL.Query()
    84  	if r.Header.Get("User-Agent") == "testRunner" {
    85  		values.Set("testRunner", "true")
    86  	}
    87  	return ListFinishParseInternal(w, values)
    88  }
    89  
    90  func ListFinishParseInternal(w io.Writer, values url.Values) *ListOptions {
    91  	copy := defaultListOptions
    92  	copy.Globals.Caps = getCaps()
    93  	opts := &copy
    94  	opts.MaxRecords = 250
    95  	opts.LastBlock = base.NOPOSN
    96  	for key, value := range values {
    97  		switch key {
    98  		case "addrs":
    99  			for _, val := range value {
   100  				s := strings.Split(val, " ") // may contain space separated items
   101  				opts.Addrs = append(opts.Addrs, s...)
   102  			}
   103  		case "count":
   104  			opts.Count = true
   105  		case "noZero":
   106  			opts.NoZero = true
   107  		case "bounds":
   108  			opts.Bounds = true
   109  		case "unripe":
   110  			opts.Unripe = true
   111  		case "silent":
   112  			opts.Silent = true
   113  		case "firstRecord":
   114  			opts.FirstRecord = base.MustParseUint64(value[0])
   115  		case "maxRecords":
   116  			opts.MaxRecords = base.MustParseUint64(value[0])
   117  		case "reversed":
   118  			opts.Reversed = true
   119  		case "publisher":
   120  			opts.Publisher = value[0]
   121  		case "firstBlock":
   122  			opts.FirstBlock = base.MustParseBlknum(value[0])
   123  		case "lastBlock":
   124  			opts.LastBlock = base.MustParseBlknum(value[0])
   125  		default:
   126  			if !copy.Globals.Caps.HasKey(key) {
   127  				err := validate.Usage("Invalid key ({0}) in {1} route.", key, "list")
   128  				if opts.BadFlag == nil || opts.BadFlag.Error() > err.Error() {
   129  					opts.BadFlag = err
   130  				}
   131  			}
   132  		}
   133  	}
   134  	opts.Conn = opts.Globals.FinishParseApi(w, values, opts.getCaches())
   135  	opts.Publisher, _ = opts.Conn.GetEnsAddress(config.GetPublisher(opts.Publisher))
   136  	opts.PublisherAddr = base.HexToAddress(opts.Publisher)
   137  
   138  	// EXISTING_CODE
   139  	// EXISTING_CODE
   140  	opts.Addrs, _ = opts.Conn.GetEnsAddresses(opts.Addrs)
   141  
   142  	return opts
   143  }
   144  
   145  // listFinishParse finishes the parsing for command line invocations. Returns a new ListOptions.
   146  func listFinishParse(args []string) *ListOptions {
   147  	// remove duplicates from args if any (not needed in api mode because the server does it).
   148  	dedup := map[string]int{}
   149  	if len(args) > 0 {
   150  		tmp := []string{}
   151  		for _, arg := range args {
   152  			if value := dedup[arg]; value == 0 {
   153  				tmp = append(tmp, arg)
   154  			}
   155  			dedup[arg]++
   156  		}
   157  		args = tmp
   158  	}
   159  
   160  	defFmt := "txt"
   161  	opts := GetOptions()
   162  	opts.Conn = opts.Globals.FinishParse(args, opts.getCaches())
   163  	opts.Publisher, _ = opts.Conn.GetEnsAddress(config.GetPublisher(opts.Publisher))
   164  	opts.PublisherAddr = base.HexToAddress(opts.Publisher)
   165  
   166  	// EXISTING_CODE
   167  	for _, arg := range args {
   168  		if base.IsValidAddress(arg) {
   169  			opts.Addrs = append(opts.Addrs, arg)
   170  		}
   171  	}
   172  	// EXISTING_CODE
   173  	opts.Addrs, _ = opts.Conn.GetEnsAddresses(opts.Addrs)
   174  	if len(opts.Globals.Format) == 0 || opts.Globals.Format == "none" {
   175  		opts.Globals.Format = defFmt
   176  	}
   177  
   178  	return opts
   179  }
   180  
   181  func GetOptions() *ListOptions {
   182  	// EXISTING_CODE
   183  	// EXISTING_CODE
   184  	return &defaultListOptions
   185  }
   186  
   187  func getCaps() caps.Capability {
   188  	var capabilities caps.Capability // capabilities for chifra list
   189  	capabilities = capabilities.Add(caps.Default)
   190  	capabilities = capabilities.Add(caps.Names)
   191  	// EXISTING_CODE
   192  	// EXISTING_CODE
   193  	return capabilities
   194  }
   195  
   196  func ResetOptions(testMode bool) {
   197  	// We want to keep writer between command file calls
   198  	w := GetOptions().Globals.Writer
   199  	opts := ListOptions{}
   200  	globals.SetDefaults(&opts.Globals)
   201  	opts.Globals.TestMode = testMode
   202  	opts.Globals.Writer = w
   203  	opts.Globals.Caps = getCaps()
   204  	opts.MaxRecords = 250
   205  	opts.LastBlock = base.NOPOSN
   206  	defaultListOptions = opts
   207  }
   208  
   209  func (opts *ListOptions) getCaches() (caches map[walk.CacheType]bool) {
   210  	// EXISTING_CODE
   211  	// EXISTING_CODE
   212  	return
   213  }
   214  
   215  // EXISTING_CODE
   216  // EXISTING_CODE