@@ -6,6 +6,10 @@ import (
6
6
"os"
7
7
"strconv"
8
8
"strings"
9
+ "time"
10
+
11
+ rpchelper "github.com/powerloom/go-rpc-helper"
12
+ "github.com/powerloom/go-rpc-helper/reporting"
9
13
10
14
"github.com/ethereum/go-ethereum/common"
11
15
)
@@ -18,6 +22,15 @@ type DataMarketMigrationEntry struct {
18
22
}
19
23
20
24
type Settings struct {
25
+ // RPC Helper Configuration
26
+ RPCNodes []string `json:"rpc_nodes"`
27
+ ArchiveRPCNodes []string `json:"archive_rpc_nodes"`
28
+ MaxRetries int `json:"max_retries"`
29
+ RetryDelayMs int `json:"retry_delay_ms"`
30
+ MaxRetryDelayS int `json:"max_retry_delay_s"`
31
+ RequestTimeoutS int `json:"request_timeout_s"`
32
+
33
+ // Legacy fields (keeping for backward compatibility during transition)
21
34
ClientUrl string
22
35
ContractAddress string
23
36
RedisHost string
@@ -53,17 +66,57 @@ type Settings struct {
53
66
}
54
67
55
68
func LoadConfig () {
69
+ // Parse RPC nodes from environment variable
70
+ rpcNodesStr := getEnv ("RPC_NODES" , "[]" )
71
+ var rpcNodes []string
72
+ err := json .Unmarshal ([]byte (rpcNodesStr ), & rpcNodes )
73
+ if err != nil {
74
+ log .Fatalf ("Failed to parse RPC_NODES environment variable: %v" , err )
75
+ }
76
+ if len (rpcNodes ) == 0 {
77
+ // Fallback to legacy PROST_RPC_URL for backward compatibility
78
+ legacyRPCURL := getEnv ("PROST_RPC_URL" , "" )
79
+ if legacyRPCURL != "" {
80
+ rpcNodes = []string {legacyRPCURL }
81
+ } else {
82
+ log .Fatalf ("RPC_NODES environment variable has an empty array and no PROST_RPC_URL fallback" )
83
+ }
84
+ }
85
+
86
+ // Clean quotes from RPC node URLs
87
+ for i , url := range rpcNodes {
88
+ rpcNodes [i ] = strings .Trim (url , "\" " )
89
+ }
90
+
91
+ // Parse archive RPC nodes from environment variable (optional)
92
+ archiveRPCNodesStr := getEnv ("ARCHIVE_RPC_NODES" , "[]" )
93
+ var archiveRPCNodes []string
94
+ err = json .Unmarshal ([]byte (archiveRPCNodesStr ), & archiveRPCNodes )
95
+ if err != nil {
96
+ log .Fatalf ("Failed to parse ARCHIVE_RPC_NODES environment variable: %v" , err )
97
+ }
98
+
99
+ // Clean quotes from archive RPC node URLs
100
+ for i , url := range archiveRPCNodes {
101
+ archiveRPCNodes [i ] = strings .Trim (url , "\" " )
102
+ }
103
+
56
104
dataMarketAddresses := getEnv ("DATA_MARKET_ADDRESSES" , "[]" )
57
105
dataMarketAddressesList := []string {}
58
106
59
- err : = json .Unmarshal ([]byte (dataMarketAddresses ), & dataMarketAddressesList )
107
+ err = json .Unmarshal ([]byte (dataMarketAddresses ), & dataMarketAddressesList )
60
108
if err != nil {
61
109
log .Fatalf ("Failed to parse DATA_MARKET_ADDRESSES environment variable: %v" , err )
62
110
}
63
111
if len (dataMarketAddressesList ) == 0 {
64
112
log .Fatalf ("DATA_MARKET_ADDRESSES environment variable has an empty array" )
65
113
}
66
114
115
+ // Clean quotes from data market addresses
116
+ for i , addr := range dataMarketAddressesList {
117
+ dataMarketAddressesList [i ] = strings .Trim (addr , "\" " )
118
+ }
119
+
67
120
periodicEligibleCountAlerts , periodicEligibleCountAlertsErr := strconv .ParseBool (getEnv ("PERIODIC_ELIGIBLE_COUNT_ALERTS" , "true" ))
68
121
if periodicEligibleCountAlertsErr != nil {
69
122
log .Fatalf ("Failed to parse PERIODIC_ELIGIBLE_COUNT_ALERTS environment variable: %v" , periodicEligibleCountAlertsErr )
@@ -93,8 +146,17 @@ func LoadConfig() {
93
146
}
94
147
95
148
config := Settings {
149
+ // RPC Helper Configuration
150
+ RPCNodes : rpcNodes ,
151
+ ArchiveRPCNodes : archiveRPCNodes ,
152
+ MaxRetries : getEnvInt ("RPC_MAX_RETRIES" , 3 ),
153
+ RetryDelayMs : getEnvInt ("RPC_RETRY_DELAY_MS" , 500 ),
154
+ MaxRetryDelayS : getEnvInt ("RPC_MAX_RETRY_DELAY_S" , 30 ),
155
+ RequestTimeoutS : getEnvInt ("RPC_REQUEST_TIMEOUT_S" , 30 ),
156
+
157
+ // Legacy configuration (keeping for backward compatibility)
96
158
ClientUrl : getEnv ("PROST_RPC_URL" , "" ),
97
- ContractAddress : getEnv ("PROTOCOL_STATE_CONTRACT" , "" ),
159
+ ContractAddress : strings . Trim ( getEnv ("PROTOCOL_STATE_CONTRACT" , "" ), " \ " " ),
98
160
RedisHost : getEnv ("REDIS_HOST" , "" ),
99
161
RedisPort : getEnv ("REDIS_PORT" , "" ),
100
162
RedisDB : getEnv ("REDIS_DB" , "" ),
@@ -224,3 +286,52 @@ func getEnv(key, defaultValue string) string {
224
286
}
225
287
return value
226
288
}
289
+
290
+ func getEnvInt (key string , defaultValue int ) int {
291
+ value := getEnv (key , "" )
292
+ if value == "" {
293
+ return defaultValue
294
+ }
295
+ intValue , err := strconv .Atoi (value )
296
+ if err != nil {
297
+ log .Fatalf ("Failed to parse %s environment variable: %v" , key , err )
298
+ }
299
+ return intValue
300
+ }
301
+
302
+ func (s * Settings ) ToRPCConfig () * rpchelper.RPCConfig {
303
+ config := & rpchelper.RPCConfig {
304
+ Nodes : func () []rpchelper.NodeConfig {
305
+ var nodes []rpchelper.NodeConfig
306
+ for _ , url := range s .RPCNodes {
307
+ nodes = append (nodes , rpchelper.NodeConfig {URL : url })
308
+ }
309
+ return nodes
310
+ }(),
311
+ ArchiveNodes : func () []rpchelper.NodeConfig {
312
+ var nodes []rpchelper.NodeConfig
313
+ for _ , url := range s .ArchiveRPCNodes {
314
+ nodes = append (nodes , rpchelper.NodeConfig {URL : url })
315
+ }
316
+ return nodes
317
+ }(),
318
+ MaxRetries : s .MaxRetries ,
319
+ RetryDelay : time .Duration (s .RetryDelayMs ) * time .Millisecond ,
320
+ MaxRetryDelay : time .Duration (s .MaxRetryDelayS ) * time .Second ,
321
+ RequestTimeout : time .Duration (s .RequestTimeoutS ) * time .Second ,
322
+ }
323
+
324
+ // Configure webhook if SlackReportingUrl is provided
325
+ if s .SlackReportingUrl != "" {
326
+ log .Printf ("Configuring webhook alerts with URL: %s" , s .SlackReportingUrl )
327
+ config .WebhookConfig = & reporting.WebhookConfig {
328
+ URL : s .SlackReportingUrl ,
329
+ Timeout : 30 * time .Second ,
330
+ Retries : 3 ,
331
+ }
332
+ } else {
333
+ log .Printf ("No webhook URL configured - SLACK_REPORTING_URL environment variable not set" )
334
+ }
335
+
336
+ return config
337
+ }
0 commit comments