Skip to content

Commit d81f577

Browse files
committed
feat: replace toml
1 parent 405df15 commit d81f577

File tree

2 files changed

+115
-13
lines changed

2 files changed

+115
-13
lines changed

utils/toml.go

+93-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,99 @@
11
package utils
22

3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
)
9+
10+
// Utility function to clean the string by trimming spaces and removing ^M characters
11+
func cleanString(input string) string {
12+
return strings.TrimSpace(strings.ReplaceAll(input, "\r", ""))
13+
}
14+
15+
// UpdateTomlValue updates a TOML file based on the provided key and value.
16+
// The key can be a field in a section (e.g., "api.enable") or a top-level field (e.g., "minimum-gas-prices").
317
func UpdateTomlValue(filePath, key, value string) error {
4-
// TODO: Implement this function
18+
value = cleanString(value)
19+
// Open the TOML file for reading
20+
file, err := os.Open(filePath)
21+
if err != nil {
22+
return fmt.Errorf("error opening file: %w", err)
23+
}
24+
defer file.Close()
25+
26+
// Determine if the key has a section (e.g., "api.enable") or is a top-level field (e.g., "minimum-gas-prices")
27+
var section, field string
28+
parts := strings.SplitN(key, ".", 2)
29+
if len(parts) == 2 {
30+
section = parts[0] // e.g., "api"
31+
field = parts[1] // e.g., "enable"
32+
} else {
33+
field = key // e.g., "minimum-gas-prices"
34+
}
35+
36+
// Slice to store updated file lines
37+
var updatedLines []string
38+
var currentSection string
39+
inTargetSection := false
40+
41+
// Read the file line by line
42+
scanner := bufio.NewScanner(file)
43+
for scanner.Scan() {
44+
line := scanner.Text()
45+
trimmedLine := strings.TrimSpace(line)
46+
47+
// Check if the line is a section header (e.g., [api])
48+
if isSectionHeader(trimmedLine) {
49+
currentSection = getSectionName(trimmedLine)
50+
inTargetSection = (currentSection == section)
51+
}
52+
53+
// Modify the field if it's in the correct section or at the top-level
54+
if shouldModifyField(inTargetSection, currentSection, field, trimmedLine) {
55+
line = fmt.Sprintf(`%s = "%s"`, field, value)
56+
}
57+
58+
// Add the line to the updated content
59+
updatedLines = append(updatedLines, line)
60+
}
61+
62+
// Check for any scanner errors
63+
if err := scanner.Err(); err != nil {
64+
return fmt.Errorf("error reading file: %w", err)
65+
}
66+
67+
// Write the modified lines back to the file
68+
err = os.WriteFile(filePath, []byte(strings.Join(updatedLines, "\n")), 0644)
69+
if err != nil {
70+
return fmt.Errorf("error writing to file: %w", err)
71+
}
572

673
return nil
774
}
75+
76+
// isSectionHeader checks if a line is a section header (e.g., [api]).
77+
func isSectionHeader(line string) bool {
78+
return strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]")
79+
}
80+
81+
// getSectionName extracts the section name from a section header (e.g., [api] -> api).
82+
func getSectionName(header string) string {
83+
return strings.Trim(header, "[]")
84+
}
85+
86+
// shouldModifyField checks if the current line should be modified.
87+
func shouldModifyField(inTargetSection bool, currentSection, field, line string) bool {
88+
// If there is no section (top-level), and the line starts with the field, modify it
89+
if currentSection == "" && strings.HasPrefix(strings.TrimSpace(line), field) {
90+
return true
91+
}
92+
93+
// If we are in the target section and the line starts with the field, modify it
94+
if inTargetSection && strings.HasPrefix(strings.TrimSpace(line), field) {
95+
return true
96+
}
97+
98+
return false
99+
}

utils/validate.go

+22-12
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,21 @@ func ValidateMnemonic(mnemonic string) error {
147147
return nil
148148
}
149149

150-
// IsValidPeerOrSeed checks if each address in a comma-separated list is valid
151-
// It allows empty strings and returns an error with detailed reasons if any address is invalid
150+
// IsValidDNS checks if a given string is a valid DNS name
151+
func IsValidDNS(dns string) bool {
152+
// Regular expression for validating DNS names
153+
dnsRegex := `^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`
154+
re := regexp.MustCompile(dnsRegex)
155+
156+
// Validate DNS name
157+
return re.MatchString(dns)
158+
}
159+
160+
// IsValidPeerOrSeed checks if each address in a comma-separated list is valid.
161+
// It allows empty strings and returns an error with detailed reasons if any address is invalid.
162+
// It accepts both IP addresses and DNS names.
152163
func IsValidPeerOrSeed(addresses string) error {
153-
// Compile the regular expression once
164+
// Compile the regular expression for node ID
154165
nodeIDRegex, err := regexp.Compile(`^[a-f0-9]{40}$`)
155166
if err != nil {
156167
return fmt.Errorf("failed to compile nodeID regex: %v", err)
@@ -172,7 +183,7 @@ func IsValidPeerOrSeed(addresses string) error {
172183

173184
parts := strings.Split(address, "@")
174185
if len(parts) != 2 {
175-
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': must be in format nodeID@ip:port", address))
186+
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': must be in format nodeID@ip_or_dns:port", address))
176187
continue
177188
}
178189

@@ -185,16 +196,16 @@ func IsValidPeerOrSeed(addresses string) error {
185196
continue
186197
}
187198

188-
// Split address into IP and optional port
199+
// Split peer address into host (IP or DNS) and port
189200
host, port, err := net.SplitHostPort(peerAddr)
190201
if err != nil && !strings.Contains(err.Error(), "missing port in address") {
191-
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': invalid address (IP:Port format required)", address))
202+
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': invalid address (IP:Port or DNS:Port format required)", address))
192203
continue
193204
}
194205

195-
// Validate IP (host part)
196-
if net.ParseIP(host) == nil {
197-
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': invalid IP address", address))
206+
// Validate host (can be IP or DNS)
207+
if net.ParseIP(host) == nil && !IsValidDNS(host) {
208+
invalidAddresses = append(invalidAddresses, fmt.Sprintf("'%s': invalid IP or DNS name", address))
198209
continue
199210
}
200211

@@ -207,10 +218,9 @@ func IsValidPeerOrSeed(addresses string) error {
207218
}
208219
}
209220

210-
// TODO add in error that id need to bbe 40 chars
221+
// If there are any invalid addresses, return an error with detailed messages
211222
if len(invalidAddresses) > 0 {
212-
// Return an error with detailed messages
213-
return errors.New("invalid peer/seed addresses:" + strings.Join(invalidAddresses, ","))
223+
return errors.New("invalid peer/seed addresses: " + strings.Join(invalidAddresses, ", "))
214224
}
215225

216226
return nil

0 commit comments

Comments
 (0)