@@ -186,9 +186,74 @@ def _stack_runtime_profile_kwargs(
186186 "intentkit_host" : str (profile .get ("intentkit_host" , "127.0.0.1" )),
187187 "intentkit_port" : int (profile .get ("intentkit_port" , 38000 )),
188188 "intentkit_api_port" : int (profile .get ("intentkit_api_port" , 38080 )),
189+ "shielded_relayer_enabled" : bool (
190+ profile .get ("shielded_relayer_enabled" )
191+ ),
192+ "shielded_relayer_host" : str (
193+ profile .get ("shielded_relayer_host" , "127.0.0.1" )
194+ ),
195+ "shielded_relayer_port" : int (
196+ profile .get ("shielded_relayer_port" , 38180 )
197+ ),
189198 }
190199
191200
201+ def _network_shielded_relayer_endpoints (
202+ network : dict [str , object ] | None ,
203+ ) -> dict [str , object ]:
204+ relayers_raw = []
205+ if isinstance (network , dict ):
206+ list_value = network .get ("shielded_relayers" )
207+ if isinstance (list_value , list ):
208+ relayers_raw = [
209+ item for item in list_value if isinstance (item , dict )
210+ ]
211+ elif isinstance (network .get ("shielded_relayer" ), dict ):
212+ relayers_raw = [network ["shielded_relayer" ]]
213+ if not relayers_raw :
214+ return {}
215+ relayers = sorted (
216+ relayers_raw ,
217+ key = lambda item : (
218+ int (item .get ("priority" , 100 )),
219+ str (item .get ("id" , "" )),
220+ str (item .get ("base_url" , "" )),
221+ ),
222+ )
223+ catalog : list [dict [str , object ]] = []
224+ for relayer in relayers :
225+ base_url = relayer .get ("base_url" )
226+ if not isinstance (base_url , str ) or not base_url :
227+ continue
228+ normalized_base = base_url .rstrip ("/" )
229+ catalog .append (
230+ {
231+ "id" : relayer .get ("id" ),
232+ "base_url" : normalized_base ,
233+ "auth_scheme" : relayer .get ("auth_scheme" ),
234+ "public_info" : relayer .get ("public_info" ),
235+ "public_quote" : relayer .get ("public_quote" ),
236+ "public_job_lookup" : relayer .get ("public_job_lookup" ),
237+ "priority" : relayer .get ("priority" , 100 ),
238+ "submission_kinds" : relayer .get ("submission_kinds" , []),
239+ "endpoints" : {
240+ "shielded_relayer" : normalized_base ,
241+ "shielded_relayer_info" : f"{ normalized_base } /v1/info" ,
242+ "shielded_relayer_metrics" : f"{ normalized_base } /metrics" ,
243+ "shielded_relayer_quote" : f"{ normalized_base } /v1/quote" ,
244+ "shielded_relayer_jobs" : f"{ normalized_base } /v1/jobs" ,
245+ },
246+ }
247+ )
248+ if not catalog :
249+ return {}
250+ primary = catalog [0 ]
251+ endpoints = dict (primary ["endpoints" ])
252+ endpoints ["shielded_relayer_primary_id" ] = str (primary .get ("id" ) or "" )
253+ endpoints ["shielded_relayers" ] = catalog
254+ return endpoints
255+
256+
192257def _resolve_node_image_settings (
193258 * ,
194259 node_image_mode : str ,
@@ -889,6 +954,39 @@ def _handle_network_create(args: argparse.Namespace) -> int:
889954 if validator ["is_bootstrap" ]
890955 else 38080
891956 ),
957+ shielded_relayer_enabled = (
958+ _pick_template_value (
959+ None ,
960+ None
961+ if template is None
962+ else template .get ("shielded_relayer_enabled" ),
963+ False ,
964+ )
965+ if validator ["is_bootstrap" ]
966+ else False
967+ ),
968+ shielded_relayer_host = (
969+ _pick_template_value (
970+ None ,
971+ None
972+ if template is None
973+ else template .get ("shielded_relayer_host" ),
974+ "127.0.0.1" ,
975+ )
976+ if validator ["is_bootstrap" ]
977+ else "127.0.0.1"
978+ ),
979+ shielded_relayer_port = (
980+ _pick_template_value (
981+ None ,
982+ None
983+ if template is None
984+ else template .get ("shielded_relayer_port" ),
985+ 38180 ,
986+ )
987+ if validator ["is_bootstrap" ]
988+ else 38180
989+ ),
892990 )
893991 write_json (profile_path , profile .to_dict (), force = args .force )
894992 validator_result ["profile_path" ] = str (profile_path )
@@ -1216,6 +1314,21 @@ def _handle_network_join(args: argparse.Namespace) -> int:
12161314 None if template is None else template .get ("intentkit_api_port" ),
12171315 38080 ,
12181316 ),
1317+ shielded_relayer_enabled = _pick_template_value (
1318+ None ,
1319+ None if template is None else template .get ("shielded_relayer_enabled" ),
1320+ False ,
1321+ ),
1322+ shielded_relayer_host = _pick_template_value (
1323+ None ,
1324+ None if template is None else template .get ("shielded_relayer_host" ),
1325+ "127.0.0.1" ,
1326+ ),
1327+ shielded_relayer_port = _pick_template_value (
1328+ None ,
1329+ None if template is None else template .get ("shielded_relayer_port" ),
1330+ 38180 ,
1331+ ),
12191332 )
12201333 target = args .output or base_dir / "nodes" / f"{ args .name } .json"
12211334 if not target .is_absolute ():
@@ -2170,6 +2283,7 @@ def _fallback_node_endpoints(
21702283 * ,
21712284 rpc_status_url : str ,
21722285 profile : NodeProfile ,
2286+ network : dict [str , object ] | None = None ,
21732287) -> dict [str , str ]:
21742288 base_url = _rpc_base_url (rpc_status_url )
21752289 endpoints = {
@@ -2209,6 +2323,20 @@ def _fallback_node_endpoints(
22092323 endpoints ["intentkit" ] = frontend_url
22102324 endpoints ["intentkit_api" ] = api_url
22112325 endpoints ["intentkit_api_health" ] = f"{ api_url } /health"
2326+ if bool (profile .get ("shielded_relayer_enabled" )):
2327+ relayer_host = _display_endpoint_host (
2328+ str (profile .get ("shielded_relayer_host" , "127.0.0.1" ))
2329+ )
2330+ relayer_port = int (profile .get ("shielded_relayer_port" , 38180 ))
2331+ relayer_url = f"http://{ relayer_host } :{ relayer_port } "
2332+ endpoints ["shielded_relayer" ] = relayer_url
2333+ endpoints ["shielded_relayer_health" ] = f"{ relayer_url } /health"
2334+ endpoints ["shielded_relayer_info" ] = f"{ relayer_url } /v1/info"
2335+ endpoints ["shielded_relayer_metrics" ] = f"{ relayer_url } /metrics"
2336+ endpoints ["shielded_relayer_quote" ] = f"{ relayer_url } /v1/quote"
2337+ endpoints ["shielded_relayer_jobs" ] = f"{ relayer_url } /v1/jobs"
2338+ else :
2339+ endpoints .update (_network_shielded_relayer_endpoints (network ))
22122340 return endpoints
22132341
22142342
@@ -2237,6 +2365,9 @@ def _collect_node_endpoints(args: argparse.Namespace) -> dict[str, object]:
22372365 "dashboard_enabled" : bool (profile .get ("dashboard_enabled" )),
22382366 "monitoring_enabled" : bool (profile .get ("monitoring_enabled" )),
22392367 "intentkit_enabled" : bool (profile .get ("intentkit_enabled" )),
2368+ "shielded_relayer_enabled" : bool (
2369+ profile .get ("shielded_relayer_enabled" )
2370+ ),
22402371 "intentkit_network_id" : profile .get ("intentkit_network_id" ),
22412372 }
22422373 if stack_dir is not None :
@@ -2259,6 +2390,7 @@ def _collect_node_endpoints(args: argparse.Namespace) -> dict[str, object]:
22592390 payload ["endpoints" ] = _fallback_node_endpoints (
22602391 rpc_status_url = rpc_status_url ,
22612392 profile = profile ,
2393+ network = network ,
22622394 )
22632395 return payload
22642396
@@ -2301,6 +2433,9 @@ def _summarize_node_status(result: dict[str, object]) -> dict[str, object]:
23012433 "intentkit_enabled" : bool (
23022434 result .get ("profile" , {}).get ("intentkit_enabled" )
23032435 ),
2436+ "shielded_relayer_enabled" : bool (
2437+ result .get ("profile" , {}).get ("shielded_relayer_enabled" )
2438+ ),
23042439 "backend_running" : result .get ("backend_running" ),
23052440 "rpc_reachable" : result .get ("rpc_reachable" ),
23062441 "rpc_height" : sync_info .get ("latest_block_height" ),
@@ -2365,6 +2500,13 @@ def _summarize_node_status(result: dict[str, object]) -> dict[str, object]:
23652500 summary ["intentkit_api_reachable" ] = backend_status .get (
23662501 "intentkit_api_reachable"
23672502 )
2503+ if summary ["shielded_relayer_enabled" ]:
2504+ summary ["shielded_relayer_running" ] = backend_status .get (
2505+ "shielded_relayer_running"
2506+ )
2507+ summary ["shielded_relayer_reachable" ] = backend_status .get (
2508+ "shielded_relayer_reachable"
2509+ )
23682510 return summary
23692511
23702512
0 commit comments