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 := © 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