1212 * home org IDs) stripped, matching the convention from wallet-health.js.
1313 */
1414
15- import os from 'os' ;
16-
1715import _ from 'lodash' ;
1816
1917import { getConfig , getConfigV2 } from '../utils/config-loader.js' ;
@@ -248,24 +246,32 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
248246 const { OrganizationsV2 } = await import ( '../models/v2/index.js' ) ;
249247 const fullNodeModule = await import ( '../datalayer/fullNode.js' ) ;
250248
251- // Kick off every external call in parallel. None of these can throw.
252- const [
253- activeNetworkRes ,
254- walletSyncedRes ,
255- walletBalanceRes ,
256- walletConnectionsRes ,
257- walletHealthRes ,
258- fullNodeStateRes ,
259- fullNodeConnectionsRes ,
260- chiaConfigRes ,
261- datalayerAvailableRes ,
262- subscriptionsRes ,
263- homeOrgV1Res ,
264- homeOrgV2Res ,
265- systemInfoRes ,
266- chiaProcessesRes ,
267- chiaToolsRes ,
268- ] = await Promise . all ( [
249+ // Phase 1: fast local probes (process scan, system info, chia-tools).
250+ // We need the process scan result before deciding whether to probe the
251+ // full node RPC, so these run first.
252+ const [ chiaProcessesRes , systemInfoRes , chiaToolsRes ] = await Promise . all ( [
253+ settle ( 'scanChiaProcesses' , ( ) => scanChiaProcesses ( ) , DEFAULT_TIMEOUT_MS ) ,
254+ settle ( 'getSystemInfo' , ( ) => getSystemInfo ( ) , DEFAULT_TIMEOUT_MS ) ,
255+ settle ( 'probeChiaTools' , ( ) => probeChiaTools ( ) , DEFAULT_TIMEOUT_MS ) ,
256+ ] ) ;
257+
258+ const processesValue = chiaProcessesRes . ok
259+ ? chiaProcessesRes . value
260+ : { matches : [ ] , installPaths : [ ] , multipleVersionsDetected : false , error : chiaProcessesRes . error } ;
261+
262+ // If the scan succeeded and found processes, check for chia_full_node.
263+ // If the scan failed or is unsupported (Windows, minimal Docker image
264+ // without ps, /proc restrictions), we can't tell whether the full node
265+ // is running, so default to true and let the RPC timeout be the backstop.
266+ const scanReliable = chiaProcessesRes . ok && ! processesValue . note ;
267+ const fullNodeRunningLocally = scanReliable
268+ ? processesValue . matches . some ( ( m ) => / c h i a _ f u l l _ n o d e / i. test ( m . command ) )
269+ : true ;
270+
271+ // Phase 2: network RPCs in parallel. Full-node RPCs are skipped when the
272+ // process scan shows no local full node — the calls would just timeout or
273+ // ECONNREFUSED, wasting wall-clock for no diagnostic value.
274+ const rpcSettles = [
269275 settle ( 'wallet.getActiveNetwork' , ( ) => wallet . getActiveNetwork ( ) , DEFAULT_TIMEOUT_MS ) ,
270276 settle ( 'wallet.walletIsSynced' , ( ) => wallet . walletIsSynced ( ) , DEFAULT_TIMEOUT_MS ) ,
271277 settle ( 'wallet.getWalletBalance' , ( ) => wallet . getWalletBalance ( ) , DEFAULT_TIMEOUT_MS ) ,
@@ -275,12 +281,12 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
275281 ( ) => getWalletHealthResponse ( wallet , { readOnly : false } ) ,
276282 DEFAULT_TIMEOUT_MS ,
277283 ) ,
278- settle ( 'fullNode.getBlockchainState' , ( ) => fullNodeRpc . getBlockchainState ( ) , DEFAULT_TIMEOUT_MS ) ,
279- settle (
280- 'fullNode.getFullNodeConnections' ,
281- ( ) => fullNodeRpc . getFullNodeConnections ( ) ,
282- DEFAULT_TIMEOUT_MS ,
283- ) ,
284+ fullNodeRunningLocally
285+ ? settle ( 'fullNode.getBlockchainState' , ( ) => fullNodeRpc . getBlockchainState ( ) , DEFAULT_TIMEOUT_MS )
286+ : Promise . resolve ( { ok : false , error : 'full node not running locally' } ) ,
287+ fullNodeRunningLocally
288+ ? settle ( 'fullNode.getFullNodeConnections' , ( ) => fullNodeRpc . getFullNodeConnections ( ) , DEFAULT_TIMEOUT_MS )
289+ : Promise . resolve ( { ok : false , error : 'full node not running locally' } ) ,
284290 settle ( 'getChiaConfig' , ( ) => Promise . resolve ( fullNodeModule . getChiaConfig ( ) ) , 1000 ) ,
285291 settle ( 'persistance.dataLayerAvailable' , ( ) => persistance . dataLayerAvailable ( ) , DEFAULT_TIMEOUT_MS ) ,
286292 settle (
@@ -290,10 +296,22 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
290296 ) ,
291297 settle ( 'Organization.getHomeOrg' , ( ) => readHomeOrgId ( Organization ) , DEFAULT_TIMEOUT_MS ) ,
292298 settle ( 'OrganizationsV2.getHomeOrg' , ( ) => readHomeOrgId ( OrganizationsV2 ) , DEFAULT_TIMEOUT_MS ) ,
293- settle ( 'getSystemInfo' , ( ) => getSystemInfo ( ) , DEFAULT_TIMEOUT_MS ) ,
294- settle ( 'scanChiaProcesses' , ( ) => scanChiaProcesses ( ) , DEFAULT_TIMEOUT_MS ) ,
295- settle ( 'probeChiaTools' , ( ) => probeChiaTools ( ) , DEFAULT_TIMEOUT_MS ) ,
296- ] ) ;
299+ ] ;
300+
301+ const [
302+ activeNetworkRes ,
303+ walletSyncedRes ,
304+ walletBalanceRes ,
305+ walletConnectionsRes ,
306+ walletHealthRes ,
307+ fullNodeStateRes ,
308+ fullNodeConnectionsRes ,
309+ chiaConfigRes ,
310+ datalayerAvailableRes ,
311+ subscriptionsRes ,
312+ homeOrgV1Res ,
313+ homeOrgV2Res ,
314+ ] = await Promise . all ( rpcSettles ) ;
297315
298316 // walletReachable: derived from the get_network_info RPC return value, NOT
299317 // from settle().ok -- walletIsSynced and getWalletBalance both swallow
@@ -399,13 +417,17 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
399417
400418 // ---- Chia: full node ----------------------------------------------------
401419 const fullNodeSection = ( ( ) => {
420+ if ( ! fullNodeRunningLocally ) {
421+ return { runningLocally : false , reachable : false } ;
422+ }
402423 const base = fullNodeStateRes . ok
403424 ? fullNodeStateRes . value
404425 : { reachable : false , error : fullNodeStateRes . error } ;
405426 const connections = fullNodeConnectionsRes . ok
406427 ? fullNodeConnectionsRes . value
407428 : { reachable : false , error : fullNodeConnectionsRes . error } ;
408429 return {
430+ runningLocally : true ,
409431 ...base ,
410432 peerCount : connections . connections ? connections . connections . length : null ,
411433 connectionsError : connections . error || null ,
@@ -431,24 +453,16 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
431453 // ---- Chia: services / chia-tools / processes ---------------------------
432454 const servicesSection = {
433455 walletReachable,
434- fullNodeReachable : fullNodeStateRes . ok ? ! ! fullNodeStateRes . value ?. reachable : false ,
456+ fullNodeReachable : fullNodeRunningLocally && fullNodeStateRes . ok
457+ ? ! ! fullNodeStateRes . value ?. reachable
458+ : false ,
435459 datalayerReachable : datalayerAvailableRes . ok ? datalayerAvailableRes . value === true : false ,
436460 } ;
437461
438462 const chiaToolsSection = chiaToolsRes . ok
439463 ? chiaToolsRes . value
440464 : { installed : false , version : null , error : chiaToolsRes . error , note : 'probe failed' } ;
441465
442- const processesSection = chiaProcessesRes . ok
443- ? chiaProcessesRes . value
444- : {
445- supported : false ,
446- platform : os . platform ( ) ,
447- matches : [ ] ,
448- multipleVersionsDetected : false ,
449- error : chiaProcessesRes . error ,
450- } ;
451-
452466 // ---- System -------------------------------------------------------------
453467 const systemSection = systemInfoRes . ok
454468 ? systemInfoRes . value
@@ -459,18 +473,18 @@ export const getDiagnosticsResponse = async ({ readOnly = false } = {}) => {
459473 timestamp,
460474 readOnly : false ,
461475 cadt : cadtSection ,
476+ network : {
477+ chia : actualNetwork ,
478+ cadt : configuredNetwork ,
479+ matches : networkMatches ,
480+ } ,
462481 chia : {
463- network : {
464- actual : actualNetwork ,
465- configured : configuredNetwork ,
466- matches : networkMatches ,
467- } ,
468482 wallet : walletSection ,
469483 fullNode : fullNodeSection ,
470484 datalayer : datalayerSection ,
471485 services : servicesSection ,
472486 chiaTools : chiaToolsSection ,
473- processes : processesSection ,
487+ runningProcesses : processesValue ,
474488 } ,
475489 system : systemSection ,
476490 } ;
@@ -495,9 +509,9 @@ const buildReadOnlyResponse = async ({ timestamp, configV1, configV2, appConfig
495509 settle ( 'probeChiaTools' , ( ) => probeChiaTools ( ) , DEFAULT_TIMEOUT_MS ) ,
496510 ] ) ;
497511
498- const processesSection = chiaProcessesRes . ok
512+ const processesValue = chiaProcessesRes . ok
499513 ? chiaProcessesRes . value
500- : { supported : false , matches : [ ] , multipleVersionsDetected : false , error : chiaProcessesRes . error } ;
514+ : { matches : [ ] , installPaths : [ ] , multipleVersionsDetected : false , error : chiaProcessesRes . error } ;
501515 const chiaToolsSection = chiaToolsRes . ok
502516 ? chiaToolsRes . value
503517 : { installed : false , version : null , error : chiaToolsRes . error } ;
@@ -529,13 +543,11 @@ const buildReadOnlyResponse = async ({ timestamp, configV1, configV2, appConfig
529543 governanceBodyId : configV2 . GOVERNANCE ?. GOVERNANCE_BODY_ID || null ,
530544 } ,
531545 } ,
546+ network : { cadt : appConfig . CHIA_NETWORK || null } ,
532547 chia : {
533- network : { configured : appConfig . CHIA_NETWORK || null } ,
534548 chiaTools : { installed : chiaToolsSection . installed , version : chiaToolsSection . version } ,
535- processes : {
536- supported : processesSection . supported ,
537- platform : processesSection . platform || null ,
538- multipleVersionsDetected : processesSection . multipleVersionsDetected ,
549+ runningProcesses : {
550+ multipleVersionsDetected : processesValue . multipleVersionsDetected ,
539551 } ,
540552 } ,
541553 system : systemSection ,
0 commit comments