|
54 | 54 | import java.util.function.Consumer; |
55 | 55 |
|
56 | 56 | import static java.util.Objects.requireNonNullElse; |
| 57 | +import static software.sava.services.core.config.PropertiesParser.getProperty; |
| 58 | +import static software.sava.services.core.config.PropertiesParser.propertyPrefix; |
57 | 59 | import static software.sava.services.solana.config.ChainItemFormatter.parseFormatter; |
58 | 60 | import static software.sava.services.solana.load_balance.LoadBalanceUtil.createRPCLoadBalancer; |
59 | 61 | import static systems.comodal.jsoniter.JsonIterator.fieldEquals; |
@@ -253,6 +255,172 @@ protected ConfigParser(final ExecutorService taskExecutor, final HttpClient http |
253 | 255 | this.httpClient = httpClient; |
254 | 256 | } |
255 | 257 |
|
| 258 | + protected void parseProperties(final String prefix, final Properties properties) { |
| 259 | + final var p = propertyPrefix(prefix); |
| 260 | + |
| 261 | + final var glamStateKeyStr = getProperty(properties, p, "glamStateKey"); |
| 262 | + if (glamStateKeyStr != null) { |
| 263 | + this.glamStateKey = PublicKey.fromBase58Encoded(glamStateKeyStr); |
| 264 | + } |
| 265 | + |
| 266 | + final var signingServicePrefix = p + "signingService."; |
| 267 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(signingServicePrefix))) { |
| 268 | + this.signingServiceConfig = SigningServiceConfig.parseConfig( |
| 269 | + taskExecutor, signingServicePrefix, DEFAULT_NETWORK_BACKOFF, properties |
| 270 | + ); |
| 271 | + } |
| 272 | + |
| 273 | + final var serviceBackoffPrefix = p + "serviceBackoff."; |
| 274 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(serviceBackoffPrefix))) { |
| 275 | + final var backoffConfig = BackoffConfig.parse(serviceBackoffPrefix, properties); |
| 276 | + this.serviceBackoff = backoffConfig.createBackoff(); |
| 277 | + } |
| 278 | + |
| 279 | + final var formatterPrefix = p + "formatter."; |
| 280 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(formatterPrefix))) { |
| 281 | + this.formatter = ChainItemFormatter.parseConfig(formatterPrefix, properties); |
| 282 | + } |
| 283 | + |
| 284 | + final var notificationHooksPrefix = p + "notificationHooks."; |
| 285 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(notificationHooksPrefix))) { |
| 286 | + final var webHookConfigs = WebHookConfig.parseConfigs( |
| 287 | + notificationHooksPrefix, |
| 288 | + properties, |
| 289 | + null, |
| 290 | + CapacityConfig.createSimpleConfig( |
| 291 | + Duration.ofSeconds(13), |
| 292 | + 2, |
| 293 | + Duration.ofSeconds(1) |
| 294 | + ), |
| 295 | + DEFAULT_NETWORK_BACKOFF |
| 296 | + ); |
| 297 | + this.notifyClient = createNotifyClient(webHookConfigs); |
| 298 | + } |
| 299 | + |
| 300 | + final var cacheDirectoryStr = getProperty(properties, p, "cacheDirectory"); |
| 301 | + if (cacheDirectoryStr != null) { |
| 302 | + this.cacheDirectory = Path.of(cacheDirectoryStr); |
| 303 | + } |
| 304 | + |
| 305 | + final var tableCachePrefix = p + "tableCache."; |
| 306 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(tableCachePrefix))) { |
| 307 | + this.tableCacheConfig = TableCacheConfig.parseConfig(tableCachePrefix, properties); |
| 308 | + } |
| 309 | + |
| 310 | + final var rpcCallWeightsPrefix = p + "rpcCallWeights."; |
| 311 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(rpcCallWeightsPrefix))) { |
| 312 | + this.callWeights = CallWeights.parseConfig(rpcCallWeightsPrefix, properties); |
| 313 | + } |
| 314 | + |
| 315 | + final var rpcPrefix = p + "rpc."; |
| 316 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(rpcPrefix))) { |
| 317 | + final var loadBalancerConfig = LoadBalancerConfig.parse( |
| 318 | + rpcPrefix, |
| 319 | + properties, |
| 320 | + CapacityConfig.createSimpleConfig( |
| 321 | + Duration.ofSeconds(13), |
| 322 | + 10, |
| 323 | + Duration.ofSeconds(1) |
| 324 | + ), |
| 325 | + DEFAULT_NETWORK_BACKOFF |
| 326 | + ); |
| 327 | + this.defaultRPCBackoff = loadBalancerConfig.defaultBackoff(); |
| 328 | + this.rpcClients = createRPCLoadBalancer(loadBalancerConfig, httpClient); |
| 329 | + } |
| 330 | + |
| 331 | + final var sendRPCPrefix = p + "sendRPC."; |
| 332 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(sendRPCPrefix))) { |
| 333 | + final var loadBalancerConfig = LoadBalancerConfig.parse( |
| 334 | + sendRPCPrefix, |
| 335 | + properties, |
| 336 | + CapacityConfig.createSimpleConfig( |
| 337 | + Duration.ofSeconds(5), |
| 338 | + 1, |
| 339 | + Duration.ofSeconds(1) |
| 340 | + ), |
| 341 | + defaultRPCBackoff |
| 342 | + ); |
| 343 | + this.sendClients = createRPCLoadBalancer(loadBalancerConfig, httpClient); |
| 344 | + } |
| 345 | + |
| 346 | + final var websocketPrefix = p + "websocket."; |
| 347 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(websocketPrefix))) { |
| 348 | + this.websocketConfig = RemoteResourceConfig.parseConfig(websocketPrefix, properties, null, DEFAULT_NETWORK_BACKOFF); |
| 349 | + } |
| 350 | + |
| 351 | + final var epochServicePrefix = p + "epochService."; |
| 352 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(epochServicePrefix))) { |
| 353 | + this.epochServiceConfig = EpochServiceConfig.parseConfig(epochServicePrefix, properties); |
| 354 | + } |
| 355 | + |
| 356 | + final var txMonitorPrefix = p + "txMonitor."; |
| 357 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(txMonitorPrefix))) { |
| 358 | + this.txMonitorConfig = TxMonitorConfig.parseConfig(txMonitorPrefix, properties); |
| 359 | + } |
| 360 | + |
| 361 | + final var accountFetcherPrefix = p + "accountFetcher."; |
| 362 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(accountFetcherPrefix))) { |
| 363 | + this.accountFetcherConfig = AccountFetcherConfig.parseConfig(accountFetcherPrefix, properties); |
| 364 | + } |
| 365 | + |
| 366 | + final var defensivePollingPrefix = p + "defensivePolling."; |
| 367 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(defensivePollingPrefix))) { |
| 368 | + this.defensivePollingConfig = DefensivePollingConfig.parseConfig(defensivePollingPrefix, properties); |
| 369 | + } |
| 370 | + |
| 371 | + final var heliusPrefix = p + "helius."; |
| 372 | + if (properties.stringPropertyNames().stream().anyMatch(k -> k.startsWith(heliusPrefix))) { |
| 373 | + final var heliusConfig = HeliusConfig.parse(heliusPrefix, properties); |
| 374 | + final var heliusClient = heliusConfig.createClient(httpClient); |
| 375 | + final var balancedItem = BalancedItem.createItem( |
| 376 | + new HeliusFeeProvider(heliusClient), |
| 377 | + heliusConfig.capacityMonitor(), |
| 378 | + requireNonNullElse(heliusConfig.backoff(), DEFAULT_NETWORK_BACKOFF) |
| 379 | + ); |
| 380 | + this.feeProviders = LoadBalancer.createBalancer(balancedItem); |
| 381 | + } |
| 382 | + |
| 383 | + final var maxSOLPriorityFeeStr = getProperty(properties, p, "maxSOLPriorityFee"); |
| 384 | + if (maxSOLPriorityFeeStr != null) { |
| 385 | + this.maxSOLPriorityFee = new BigDecimal(maxSOLPriorityFeeStr); |
| 386 | + } |
| 387 | + |
| 388 | + final var warnFeePayerBalanceStr = getProperty(properties, p, "warnFeePayerBalance"); |
| 389 | + if (warnFeePayerBalanceStr != null) { |
| 390 | + this.warnFeePayerBalance = new BigDecimal(warnFeePayerBalanceStr); |
| 391 | + } |
| 392 | + |
| 393 | + final var minFeePayerBalanceStr = getProperty(properties, p, "minFeePayerBalance"); |
| 394 | + if (minFeePayerBalanceStr != null) { |
| 395 | + this.minFeePayerBalance = new BigDecimal(minFeePayerBalanceStr); |
| 396 | + } |
| 397 | + |
| 398 | + final var minCheckStateDelayStr = getProperty(properties, p, "minCheckStateDelay"); |
| 399 | + if (minCheckStateDelayStr != null) { |
| 400 | + this.minCheckStateDelay = ServiceConfigUtil.parseDuration(minCheckStateDelayStr); |
| 401 | + } |
| 402 | + |
| 403 | + final var maxCheckStateDelayStr = getProperty(properties, p, "maxCheckStateDelay"); |
| 404 | + if (maxCheckStateDelayStr != null) { |
| 405 | + this.maxCheckStateDelay = ServiceConfigUtil.parseDuration(maxCheckStateDelayStr); |
| 406 | + } |
| 407 | + |
| 408 | + final var defaultCuBudgetMultiplierStr = getProperty(properties, p, "defaultCuBudgetMultiplier"); |
| 409 | + if (defaultCuBudgetMultiplierStr != null) { |
| 410 | + this.defaultCuBudgetMultiplier = Double.parseDouble(defaultCuBudgetMultiplierStr); |
| 411 | + } |
| 412 | + |
| 413 | + final var maxTransactionRetriesStr = getProperty(properties, p, "maxTransactionRetries"); |
| 414 | + if (maxTransactionRetriesStr != null) { |
| 415 | + this.maxTransactionRetries = Integer.parseInt(maxTransactionRetriesStr); |
| 416 | + } |
| 417 | + |
| 418 | + final var hikariPropertiesFilesStr = getProperty(properties, p, "hikariPropertiesFiles"); |
| 419 | + if (hikariPropertiesFilesStr != null) { |
| 420 | + this.hikariPropertiesFiles = List.of(hikariPropertiesFilesStr.split(",")); |
| 421 | + } |
| 422 | + } |
| 423 | + |
256 | 424 | private NotifyClient createNotifyClient(final List<WebHookConfig> webHookConfigs) { |
257 | 425 | final var webHookClients = webHookConfigs.stream() |
258 | 426 | .map(webHookConfig -> webHookConfig.createCaller(httpClient)) |
|
0 commit comments