commit 6da69db2f79f812657ce33b6b335aa06ecd0a85b
parent a43f499a5be5655176377b9cc174a83bc9b076fd
Author: triesap <tyson@radroots.org>
Date: Thu, 9 Jul 2026 21:55:22 +0000
transport: align CLI public target surfaces
- rename CLI publish and trade JSON transport fields to target-oriented endpoint and failure names
- consume SDK Nostr-scoped validation evidence names and current satisfaction policy variants
- expose target scope, label, and typed transport outcome metadata on failure views
- update terminal renderers and tests for target-oriented transport wording
Diffstat:
20 files changed, 659 insertions(+), 440 deletions(-)
diff --git a/src/ops/exec/farm.rs b/src/ops/exec/farm.rs
@@ -350,8 +350,8 @@ fn farm_private_location_set_result(
fn farm_publish_relay_unavailable(view: &FarmPublishView) -> bool {
view.state == "partial"
- || !view.profile.failed_relays.is_empty()
- || !view.farm.failed_relays.is_empty()
+ || !view.profile.failed_transport_targets.is_empty()
+ || !view.farm.failed_transport_targets.is_empty()
}
fn require_relay_target<P>(
diff --git a/src/ops/exec/listing.rs b/src/ops/exec/listing.rs
@@ -339,10 +339,10 @@ fn listing_relay_unavailable(view: &ListingMutationView) -> bool {
) && (view.reason.as_deref().is_some_and(|reason| {
reason.contains("configured Nostr relay")
|| reason.contains("Nostr transport connection failed")
- || reason.contains("SDK relay publish")
- }) || !view.target_relays.is_empty()
- || !view.connected_relays.is_empty()
- || !view.failed_relays.is_empty())
+ || reason.contains("SDK transport publish")
+ }) || !view.target_transport_endpoints.is_empty()
+ || !view.attempted_transport_endpoints.is_empty()
+ || !view.failed_transport_targets.is_empty())
}
fn listing_app_record_export_result<R>(
diff --git a/src/ops/exec/trade.rs b/src/ops/exec/trade.rs
@@ -28,7 +28,7 @@ use crate::view::runtime::{
OrderSubmitView,
};
-const TRADE_EVENT_WATCH_DEFERRED_REASON: &str = "relay-backed trade event watch is not implemented";
+const TRADE_EVENT_WATCH_DEFERRED_REASON: &str = "Nostr-backed trade event watch is not implemented";
pub struct TradeOperationService<'a> {
config: &'a RuntimeConfig,
@@ -502,7 +502,9 @@ where
.unwrap_or_else(|| format!("order decision finished with state `{}`", view.state));
if disposition == CommandDisposition::ExternalUnavailable {
let detail = order_decision_error_detail(view);
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -555,10 +557,10 @@ fn order_decision_error_detail(view: &OrderDecisionView) -> Value {
"seller_pubkey": &view.seller_pubkey,
"decision": &view.decision,
"dry_run": view.dry_run,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "acknowledged_relays": &view.acknowledged_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "accepted_transport_endpoints": &view.accepted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -595,7 +597,9 @@ where
.unwrap_or_else(|| format!("order cancel finished with state `{}`", view.state));
if disposition == CommandDisposition::ExternalUnavailable {
let detail = order_cancellation_error_detail(view);
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -641,10 +645,10 @@ fn order_cancellation_error_detail(view: &OrderCancellationView) -> Value {
"seller_pubkey": &view.seller_pubkey,
"cancellation_reason": &view.cancellation_reason,
"dry_run": view.dry_run,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "acknowledged_relays": &view.acknowledged_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "accepted_transport_endpoints": &view.accepted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -686,7 +690,9 @@ where
});
if disposition == CommandDisposition::ExternalUnavailable {
let detail = order_revision_proposal_error_detail(view);
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -735,10 +741,10 @@ fn order_revision_proposal_error_detail(view: &OrderRevisionProposalView) -> Val
"buyer_pubkey": &view.buyer_pubkey,
"seller_pubkey": &view.seller_pubkey,
"dry_run": view.dry_run,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "acknowledged_relays": &view.acknowledged_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "accepted_transport_endpoints": &view.accepted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -782,7 +788,9 @@ where
});
if disposition == CommandDisposition::ExternalUnavailable {
let detail = order_revision_decision_error_detail(view);
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -832,10 +840,10 @@ fn order_revision_decision_error_detail(view: &OrderRevisionDecisionView) -> Val
"buyer_pubkey": &view.buyer_pubkey,
"seller_pubkey": &view.seller_pubkey,
"dry_run": view.dry_run,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "acknowledged_relays": &view.acknowledged_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "accepted_transport_endpoints": &view.accepted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -862,7 +870,9 @@ where
.unwrap_or_else(|| format!("order status finished with state `{}`", view.state));
if disposition == CommandDisposition::ExternalUnavailable {
let detail = order_status_error_detail(view);
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -910,9 +920,9 @@ fn order_status_error_detail(view: &OrderStatusView) -> Value {
"lifecycle": &view.lifecycle,
"sdk_receipt": &view.sdk_receipt,
"reducer_issues": &view.reducer_issues,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -964,7 +974,9 @@ where
))
}
CommandDisposition::ExternalUnavailable => {
- if !view.failed_relays.is_empty() && view.connected_relays.is_empty() {
+ if !view.failed_transport_targets.is_empty()
+ && view.attempted_transport_endpoints.is_empty()
+ {
Err(OperationAdapterError::network_unavailable_with_detail(
operation_id,
message,
@@ -1108,10 +1120,10 @@ fn order_submit_error_detail(view: &OrderSubmitView) -> Value {
"event_kind": view.event_kind,
"dry_run": view.dry_run,
"deduplicated": view.deduplicated,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "acknowledged_relays": &view.acknowledged_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "accepted_transport_endpoints": &view.accepted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"idempotency_key": &view.idempotency_key,
"signer_mode": &view.signer_mode,
"issues": &view.issues,
@@ -1160,9 +1172,9 @@ fn order_event_list_error_detail(view: &crate::view::runtime::OrderEventListView
json!({
"state": &view.state,
"seller_pubkey": &view.seller_pubkey,
- "target_relays": &view.target_relays,
- "connected_relays": &view.connected_relays,
- "failed_relays": &view.failed_relays,
+ "target_transport_endpoints": &view.target_transport_endpoints,
+ "attempted_transport_endpoints": &view.attempted_transport_endpoints,
+ "failed_transport_targets": &view.failed_transport_targets,
"fetched_count": view.fetched_count,
"decoded_count": view.decoded_count,
"skipped_count": view.skipped_count,
@@ -1397,7 +1409,12 @@ mod tests {
assert_eq!(detail["state"], "unconfigured");
assert_eq!(detail["trade_id"], "ord_pending");
assert_eq!(detail["decision"], "accepted");
- assert!(detail["target_relays"].as_array().unwrap().is_empty());
+ assert!(
+ detail["target_transport_endpoints"]
+ .as_array()
+ .unwrap()
+ .is_empty()
+ );
}
#[test]
@@ -1868,10 +1885,10 @@ mod tests {
event_kind: Some(3423),
inventory: None,
dry_run: false,
- target_relays: vec!["ws://relay.test".to_owned()],
- connected_relays: vec!["ws://relay.test".to_owned()],
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: vec!["ws://relay.test".to_owned()],
+ attempted_transport_endpoints: vec!["ws://relay.test".to_owned()],
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 2,
decoded_count: 2,
skipped_count: 0,
diff --git a/src/out/terminal/renderer.rs b/src/out/terminal/renderer.rs
@@ -211,7 +211,7 @@ mod tests {
))
.with_field(TerminalField::new("Listing", "AAAAAAAAAAAAAAAAAAAAAg"))
.with_field(TerminalField::new("Transport", "nostr"))
- .with_field(TerminalField::new("Relays", "2 acknowledged · 0 failed"))
+ .with_field(TerminalField::new("Targets", "2 acknowledged · 0 failed"))
.with_field(TerminalField::new("Event", "9f3a…c12"))
.with_next(TerminalAction::command(
"radroots listing get AAAAAAAAAAAAAAAAAAAAAg",
@@ -219,7 +219,7 @@ mod tests {
assert_eq!(
render_terminal_document(&document, &TerminalRenderContext::default()),
- "✓ Listing published\n\n Listing AAAAAAAAAAAAAAAAAAAAAg\n Transport nostr\n Relays 2 acknowledged · 0 failed\n Event 9f3a…c12\n\nNext\n radroots listing get AAAAAAAAAAAAAAAAAAAAAg"
+ "✓ Listing published\n\n Listing AAAAAAAAAAAAAAAAAAAAAg\n Transport nostr\n Targets 2 acknowledged · 0 failed\n Event 9f3a…c12\n\nNext\n radroots listing get AAAAAAAAAAAAAAAAAAAAAg"
);
}
diff --git a/src/out/terminal/renderers/farm.rs b/src/out/terminal/renderers/farm.rs
@@ -172,14 +172,14 @@ fn farm_publish_document(envelope: &OutputEnvelope, result: &Value) -> TerminalD
common::push_path_field(&mut document, "Farm publish", result, &["farm", "state"]);
push_publish_component_fields(
&mut document,
- "Profile relays",
+ "Profile targets",
"Profile event",
result,
&["profile"],
);
push_publish_component_fields(
&mut document,
- "Farm relays",
+ "Farm targets",
"Farm event",
result,
&["farm"],
@@ -289,7 +289,7 @@ fn push_missing_section(document: &mut TerminalDocument, result: &Value) {
fn push_publish_component_fields(
document: &mut TerminalDocument,
- relay_label: &str,
+ target_label: &str,
event_label: &str,
result: &Value,
path: &[&str],
@@ -298,7 +298,7 @@ fn push_publish_component_fields(
return;
};
if let Some(summary) = relay_component_summary(component) {
- common::push_field(document, relay_label, summary);
+ common::push_field(document, target_label, summary);
}
common::push_path_field(document, event_label, component, &["event_id"]);
common::push_path_field(document, "Job", component, &["job_id"]);
@@ -324,7 +324,7 @@ fn push_publish_components_section(document: &mut TerminalDocument, result: &Val
vec![
TerminalTableColumn::new("Part", 4, 8),
TerminalTableColumn::new("State", 5, 16),
- TerminalTableColumn::new("Relays", 8, 28),
+ TerminalTableColumn::new("Targets", 8, 28),
],
rows,
"No publish components",
@@ -332,13 +332,13 @@ fn push_publish_components_section(document: &mut TerminalDocument, result: &Val
}
fn relay_component_summary(value: &Value) -> Option<String> {
- let acknowledged = common::array(value, &["acknowledged_relays"])
+ let acknowledged = common::array(value, &["accepted_transport_endpoints"])
.map(Vec::len)
.unwrap_or(0);
- let failed = common::array(value, &["failed_relays"])
+ let failed = common::array(value, &["failed_transport_targets"])
.map(Vec::len)
.unwrap_or(0);
- let target = common::array(value, &["target_relays"])
+ let target = common::array(value, &["target_transport_endpoints"])
.map(Vec::len)
.unwrap_or(0);
(acknowledged > 0 || failed > 0 || target > 0)
diff --git a/src/out/terminal/renderers/listing.rs b/src/out/terminal/renderers/listing.rs
@@ -277,12 +277,12 @@ fn push_issues_section(document: &mut TerminalDocument, result: &Value) {
fn push_relay_field(document: &mut TerminalDocument, result: &Value) {
if let Some(summary) = relay_field_summary(result) {
- common::push_field(document, "Relays", summary);
+ common::push_field(document, "Targets", summary);
}
}
fn relay_field_summary(result: &Value) -> Option<String> {
- let acknowledged = common::array(result, &["acknowledged_relays"])
+ let acknowledged = common::array(result, &["accepted_transport_endpoints"])
.map(Vec::len)
.or_else(|| {
common::number_path(result, &["publish", "acknowledged_count"])
@@ -293,7 +293,7 @@ fn relay_field_summary(result: &Value) -> Option<String> {
.and_then(|value| usize::try_from(value).ok())
})
.unwrap_or(0);
- let failed = common::array(result, &["failed_relays"])
+ let failed = common::array(result, &["failed_transport_targets"])
.map(Vec::len)
.or_else(|| {
common::number_path(result, &["publish", "failed_count"])
@@ -304,7 +304,7 @@ fn relay_field_summary(result: &Value) -> Option<String> {
.and_then(|value| usize::try_from(value).ok())
})
.unwrap_or(0);
- let target = common::array(result, &["target_relays"])
+ let target = common::array(result, &["target_transport_endpoints"])
.map(Vec::len)
.unwrap_or(0);
(acknowledged > 0 || failed > 0 || target > 0)
@@ -339,8 +339,8 @@ mod tests {
"state": "published",
"listing_id": "AAAAAAAAAAAAAAAAAAAAAg",
"source": "SDK listing publish · configured signer",
- "acknowledged_relays": ["wss://relay.example"],
- "failed_relays": [],
+ "accepted_transport_endpoints": ["wss://relay.example"],
+ "failed_transport_targets": [],
"event_id": "9f3ac129f3ac129f3ac129f3ac129f3ac129f3ac129f3ac129f3ac129f3ac12",
"actions": ["radroots listing get AAAAAAAAAAAAAAAAAAAAAg"]
}),
@@ -351,7 +351,7 @@ mod tests {
assert!(rendered.contains("✓ Listing published"));
assert!(rendered.contains("Listing"));
- assert!(rendered.contains("Relays"));
+ assert!(rendered.contains("Targets"));
assert!(rendered.contains("Event"));
assert!(!rendered.contains("Proof"));
assert!(!rendered.contains("verified"));
diff --git a/src/out/terminal/renderers/trade.rs b/src/out/terminal/renderers/trade.rs
@@ -466,19 +466,19 @@ fn push_trade_identity_fields(document: &mut TerminalDocument, result: &Value) {
}
fn push_relay_field(document: &mut TerminalDocument, result: &Value) {
- let acknowledged = array_len(result, &["acknowledged_relays"]);
- let connected = array_len(result, &["connected_relays"]);
- let failed = array_len(result, &["failed_relays"]);
+ let acknowledged = array_len(result, &["accepted_transport_endpoints"]);
+ let connected = array_len(result, &["attempted_transport_endpoints"]);
+ let failed = array_len(result, &["failed_transport_targets"]);
if acknowledged > 0 || failed > 0 {
common::push_field(
document,
- "Relays",
+ "Targets",
relay_summary(acknowledged, failed, "acknowledged"),
);
} else if connected > 0 || failed > 0 {
common::push_field(
document,
- "Relays",
+ "Targets",
relay_summary(connected, failed, "connected"),
);
}
@@ -694,7 +694,7 @@ mod tests {
json!({
"state": "not_implemented",
"trade_id": "trade_test",
- "reason": "relay-backed trade event watch is not implemented",
+ "reason": "Nostr-backed trade event watch is not implemented",
"actions": ["radroots trade status get trade_test"]
}),
);
diff --git a/src/out/terminal/renderers/validation.rs b/src/out/terminal/renderers/validation.rs
@@ -161,12 +161,12 @@ fn push_invalid_receipts_section(document: &mut TerminalDocument, result: &Value
}
fn push_relay_field(document: &mut TerminalDocument, result: &Value) {
- let connected = array_len(result, &["connected_relays"]);
- let failed = array_len(result, &["failed_relays"]);
+ let connected = array_len(result, &["attempted_transport_endpoints"]);
+ let failed = array_len(result, &["failed_transport_targets"]);
if connected > 0 || failed > 0 {
common::push_field(
document,
- "Relays",
+ "Targets",
relay_summary(connected, failed, "connected"),
);
}
diff --git a/src/runtime/farm.rs b/src/runtime/farm.rs
@@ -35,7 +35,7 @@ use crate::runtime::farm_config::{
use crate::runtime::local_events::append_local_work;
use crate::runtime::sdk::{
CliSdkAdapterError, CliSdkSession, sdk_nostr_relay_url_policy, sdk_target_policy,
- validate_configured_signer_for_actor,
+ sdk_transport_outcome_kind_label, validate_configured_signer_for_actor,
};
use crate::runtime::signer::ActorWriteBindingError;
use crate::view::runtime::{
@@ -43,7 +43,7 @@ use crate::view::runtime::{
FarmPrivateExactLocationView, FarmPrivateLocationCandidateView, FarmPrivateLocationView,
FarmPrivatePublicLocalityView, FarmPublicationView, FarmPublishComponentView,
FarmPublishEventView, FarmPublishView, FarmRebindView, FarmSelectionView, FarmSetView,
- FarmSetupView, FarmStatusView, RelayFailureView,
+ FarmSetupView, FarmStatusView, TransportTargetFailureView,
};
const FARM_CONFIG_SOURCE: &str = "farm config · local first";
@@ -998,10 +998,10 @@ fn preview_component(
rpc_method: rpc_method.to_owned(),
event_kind,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
job_id: None,
job_status: None,
signer_mode: None,
@@ -1107,7 +1107,7 @@ fn sdk_prepared_publish_view(
),
FarmPublishComponentView {
state: "not_submitted".to_owned(),
- reason: Some("dry run requested; SDK enqueue and relay push skipped".to_owned()),
+ reason: Some("dry run requested; SDK enqueue and transport push skipped".to_owned()),
signer_mode: Some(config.signer.backend.as_str().to_owned()),
event_id: Some(plan.expected_event_id.as_str().to_owned()),
event_addr: Some(plan.farm_addr.as_str().to_owned()),
@@ -1120,7 +1120,7 @@ fn sdk_prepared_publish_view(
None,
)
},
- Some("dry run requested; SDK enqueue and relay push skipped".to_owned()),
+ Some("dry run requested; SDK enqueue and transport push skipped".to_owned()),
vec!["radroots farm publish".to_owned()],
)
}
@@ -1154,16 +1154,18 @@ fn sdk_enqueued_publish_view(
FarmPublishComponentView {
state,
deduplicated: matches!(enqueue.state, SdkMutationState::AlreadyQueued),
- target_relays: push_event
- .map(sdk_push_target_relays)
+ target_transport_endpoints: push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone()),
- connected_relays: push_event
- .map(sdk_push_connected_relays)
+ attempted_transport_endpoints: push_event
+ .map(sdk_push_attempted_transport_endpoints)
.unwrap_or_default(),
- acknowledged_relays: push_event
- .map(sdk_push_acknowledged_relays)
+ accepted_transport_endpoints: push_event
+ .map(sdk_push_accepted_transport_endpoints)
+ .unwrap_or_default(),
+ failed_transport_targets: push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default(),
- failed_relays: push_event.map(sdk_push_failed_relays).unwrap_or_default(),
signer_mode: Some(config.signer.backend.as_str().to_owned()),
event_id: Some(enqueue.signed_event_id.as_str().to_owned()),
event_addr: Some(enqueue.farm_addr.as_str().to_owned()),
@@ -1211,13 +1213,15 @@ fn sdk_publish_reason(push_event: Option<&PushOutboxEventReceipt>) -> Option<Str
match push_event.map(|event| event.final_state) {
Some(PushOutboxEventState::Published) => None,
Some(PushOutboxEventState::PublishRetryable) => Some(
- "SDK relay publish did not reach accepted quorum; outbox event remains retryable"
+ "SDK transport publish did not reach accepted quorum; outbox event remains retryable"
.to_owned(),
),
Some(PushOutboxEventState::FailedTerminal) => {
- Some("SDK relay publish failed terminally".to_owned())
+ Some("SDK transport publish failed terminally".to_owned())
}
- Some(state) => Some(format!("SDK relay push left event in state `{state:?}`")),
+ Some(state) => Some(format!(
+ "SDK transport push left event in state `{state:?}`"
+ )),
None => Some(
"farm publish queued in SDK outbox; no ready SDK outbox event was pushed".to_owned(),
),
@@ -1234,7 +1238,7 @@ fn sdk_publish_actions(push_event: Option<&PushOutboxEventReceipt>) -> Vec<Strin
Vec::new()
}
-fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_target_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -1242,7 +1246,7 @@ fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_attempted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -1251,7 +1255,7 @@ fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_accepted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -1266,7 +1270,9 @@ fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureView> {
+fn sdk_push_failed_transport_targets(
+ event: &PushOutboxEventReceipt,
+) -> Vec<TransportTargetFailureView> {
event
.targets
.iter()
@@ -1277,8 +1283,14 @@ fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureVie
| PushOutboxTargetOutcomeKind::DuplicateAccepted
)
})
- .map(|target| RelayFailureView {
- relay: target.endpoint_uri.clone(),
+ .map(|target| TransportTargetFailureView {
+ transport_kind: target.transport_kind.clone(),
+ endpoint_uri: target.endpoint_uri.clone(),
+ target_scope: target.target_scope.clone(),
+ target_label: target.target_label.clone(),
+ transport_outcome_kind: target
+ .transport_outcome_kind
+ .map(sdk_transport_outcome_kind_label),
reason: target
.message
.clone()
diff --git a/src/runtime/listing.rs b/src/runtime/listing.rs
@@ -49,7 +49,7 @@ use crate::runtime::local_events::{
};
use crate::runtime::sdk::{
CliSdkAdapterError, CliSdkSession, sdk_nostr_relay_url_policy, sdk_target_policy,
- validate_configured_signer_for_actor,
+ sdk_transport_outcome_kind_label, validate_configured_signer_for_actor,
};
use crate::runtime::sync::{
RelayIngestScope, freshness_for_scope_from_executor, market_refresh, missing_freshness,
@@ -59,7 +59,7 @@ use crate::view::runtime::{
ListingAppRecordListView, ListingAppRecordSummaryView, ListingGetView, ListingListView,
ListingMutationEventView, ListingMutationView, ListingNewView, ListingRebindView,
ListingSummaryView, ListingValidateView, ListingValidationIssueView, MarketReadinessView,
- RelayFailureView,
+ TransportTargetFailureView,
};
const DRAFT_KIND: &str = "listing_draft_v1";
@@ -1869,10 +1869,10 @@ fn sdk_prepared_publish_view(
event_kind: KIND_LISTING,
dry_run: true,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
job_id: None,
job_status: None,
signer_mode: Some(config.signer.backend.as_str().to_owned()),
@@ -1880,7 +1880,7 @@ fn sdk_prepared_publish_view(
event_addr: Some(listing_addr),
idempotency_key: args.idempotency_key.clone(),
local_replica: None,
- reason: Some("dry run requested; SDK enqueue and relay push skipped".to_owned()),
+ reason: Some("dry run requested; SDK enqueue and transport push skipped".to_owned()),
job: None,
event: args.print_event.then_some(event),
actions: vec![format!("radroots listing publish {}", args.file.display())],
@@ -1900,16 +1900,18 @@ fn sdk_enqueued_publish_view(
.and_then(|receipt| sdk_push_event_for_listing(&enqueue, receipt));
let state = sdk_publish_state(args, push_event);
let reason = sdk_publish_reason(args, push_event);
- let target_relays = push_event
- .map(sdk_push_target_relays)
+ let target_transport_endpoints = push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
- let connected_relays = push_event
- .map(sdk_push_connected_relays)
+ let attempted_transport_endpoints = push_event
+ .map(sdk_push_attempted_transport_endpoints)
.unwrap_or_default();
- let acknowledged_relays = push_event
- .map(sdk_push_acknowledged_relays)
+ let accepted_transport_endpoints = push_event
+ .map(sdk_push_accepted_transport_endpoints)
+ .unwrap_or_default();
+ let failed_transport_targets = push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default();
- let failed_relays = push_event.map(sdk_push_failed_relays).unwrap_or_default();
let event_id = enqueue.signed_event_id.as_str().to_owned();
let listing_addr = enqueue.public_listing_addr.as_str().to_owned();
ListingMutationView {
@@ -1925,10 +1927,10 @@ fn sdk_enqueued_publish_view(
event_kind: KIND_LISTING,
dry_run: false,
deduplicated: matches!(enqueue.state, SdkMutationState::AlreadyQueued),
- target_relays,
- connected_relays,
- acknowledged_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ accepted_transport_endpoints,
+ failed_transport_targets,
job_id: None,
job_status: None,
signer_mode: Some(config.signer.backend.as_str().to_owned()),
@@ -1987,15 +1989,18 @@ fn sdk_publish_reason(
match push_event.map(|event| event.final_state) {
Some(PushOutboxEventState::Published) => None,
Some(PushOutboxEventState::PublishRetryable) => Some(
- "SDK relay publish did not reach accepted quorum; outbox event remains retryable"
+ "SDK transport publish did not reach accepted quorum; outbox event remains retryable"
.to_owned(),
),
Some(PushOutboxEventState::FailedTerminal) => {
- Some("SDK relay publish failed terminally".to_owned())
+ Some("SDK transport publish failed terminally".to_owned())
}
- Some(state) => Some(format!("SDK relay push left event in state `{state:?}`")),
+ Some(state) => Some(format!(
+ "SDK transport push left event in state `{state:?}`"
+ )),
None if args.offline => Some(
- "listing publish queued in SDK outbox; relay push skipped for offline mode".to_owned(),
+ "listing publish queued in SDK outbox; transport push skipped for offline mode"
+ .to_owned(),
),
None => Some(
"listing publish queued in SDK outbox; no ready SDK outbox event was pushed".to_owned(),
@@ -2018,7 +2023,7 @@ fn sdk_publish_actions(
Vec::new()
}
-fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_target_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -2026,7 +2031,7 @@ fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_attempted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -2035,7 +2040,7 @@ fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_accepted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -2050,7 +2055,9 @@ fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureView> {
+fn sdk_push_failed_transport_targets(
+ event: &PushOutboxEventReceipt,
+) -> Vec<TransportTargetFailureView> {
event
.targets
.iter()
@@ -2061,8 +2068,14 @@ fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureVie
| PushOutboxTargetOutcomeKind::DuplicateAccepted
)
})
- .map(|target| RelayFailureView {
- relay: target.endpoint_uri.clone(),
+ .map(|target| TransportTargetFailureView {
+ transport_kind: target.transport_kind.clone(),
+ endpoint_uri: target.endpoint_uri.clone(),
+ target_scope: target.target_scope.clone(),
+ target_label: target.target_label.clone(),
+ transport_outcome_kind: target
+ .transport_outcome_kind
+ .map(sdk_transport_outcome_kind_label),
reason: target
.message
.clone()
@@ -3142,15 +3155,15 @@ fn encode_base64url_no_pad(bytes: [u8; 16]) -> String {
mod tests {
use super::{
DRAFT_KIND, ListingDraftDocument, encode_base64url_no_pad, generate_d_tag,
- sdk_publish_actions, sdk_publish_reason, sdk_publish_state, sdk_push_acknowledged_relays,
- sdk_push_failed_relays,
+ sdk_publish_actions, sdk_publish_reason, sdk_publish_state,
+ sdk_push_accepted_transport_endpoints, sdk_push_failed_transport_targets,
};
use crate::cli::global::ListingMutationArgs;
use radroots_events::ids::RadrootsEventId;
use radroots_events_codec::d_tag::is_d_tag_base64url;
use radroots_sdk::{
PushOutboxEventReceipt, PushOutboxEventState, PushOutboxTargetOutcomeKind,
- PushOutboxTargetReceipt,
+ PushOutboxTargetReceipt, PushOutboxTransportOutcomeKind,
};
#[test]
@@ -3179,17 +3192,17 @@ mod tests {
assert!(sdk_publish_reason(&args, Some(&accepted)).is_none());
assert!(sdk_publish_actions(&args, Some(&accepted)).is_empty());
assert_eq!(
- sdk_push_acknowledged_relays(&accepted),
+ sdk_push_accepted_transport_endpoints(&accepted),
vec!["ws://127.0.0.1:19000".to_owned()]
);
- assert!(sdk_push_failed_relays(&accepted).is_empty());
+ assert!(sdk_push_failed_transport_targets(&accepted).is_empty());
let auth_required = sdk_push_event(
PushOutboxEventState::PublishRetryable,
PushOutboxTargetOutcomeKind::AuthRequired,
Some("auth required".to_owned()),
);
- let failed = sdk_push_failed_relays(&auth_required);
+ let failed = sdk_push_failed_transport_targets(&auth_required);
assert_eq!(
sdk_publish_state(&args, Some(&auth_required)),
@@ -3201,7 +3214,7 @@ mod tests {
.contains("accepted quorum")
);
assert_eq!(failed.len(), 1);
- assert_eq!(failed[0].relay, "ws://127.0.0.1:19000");
+ assert_eq!(failed[0].endpoint_uri, "ws://127.0.0.1:19000");
assert_eq!(failed[0].reason, "auth required");
assert_eq!(
sdk_publish_actions(&args, Some(&auth_required)),
@@ -3376,13 +3389,47 @@ mod tests {
targets: vec![PushOutboxTargetReceipt {
transport_kind: "nostr".to_owned(),
endpoint_uri: "ws://127.0.0.1:19000".to_owned(),
+ target_scope: None,
+ target_label: None,
outcome_kind,
+ transport_outcome_kind: test_transport_outcome_kind(outcome_kind),
attempted: true,
message,
}],
}
}
+ fn test_transport_outcome_kind(
+ kind: PushOutboxTargetOutcomeKind,
+ ) -> Option<PushOutboxTransportOutcomeKind> {
+ Some(match kind {
+ PushOutboxTargetOutcomeKind::Accepted => PushOutboxTransportOutcomeKind::Accepted,
+ PushOutboxTargetOutcomeKind::DuplicateAccepted => {
+ PushOutboxTransportOutcomeKind::DuplicateAccepted
+ }
+ PushOutboxTargetOutcomeKind::Timeout => PushOutboxTransportOutcomeKind::Timeout,
+ PushOutboxTargetOutcomeKind::ConnectionFailed => {
+ PushOutboxTransportOutcomeKind::ConnectionFailed
+ }
+ PushOutboxTargetOutcomeKind::AuthRequired
+ | PushOutboxTargetOutcomeKind::Blocked
+ | PushOutboxTargetOutcomeKind::RateLimited
+ | PushOutboxTargetOutcomeKind::Invalid
+ | PushOutboxTargetOutcomeKind::PowRequired
+ | PushOutboxTargetOutcomeKind::Restricted
+ | PushOutboxTargetOutcomeKind::Muted
+ | PushOutboxTargetOutcomeKind::Unsupported
+ | PushOutboxTargetOutcomeKind::PaymentRequired
+ | PushOutboxTargetOutcomeKind::Error
+ | PushOutboxTargetOutcomeKind::TargetUriRejected
+ | PushOutboxTargetOutcomeKind::SkippedAlreadyAccepted
+ | PushOutboxTargetOutcomeKind::DeferredUntilImplemented
+ | PushOutboxTargetOutcomeKind::PreviewUnavailable
+ | PushOutboxTargetOutcomeKind::Unknown => PushOutboxTransportOutcomeKind::Rejected,
+ _ => PushOutboxTransportOutcomeKind::Rejected,
+ })
+ }
+
fn listing_mutation_args(offline: bool) -> ListingMutationArgs {
ListingMutationArgs {
file: "listing.toml".into(),
diff --git a/src/runtime/order.rs b/src/runtime/order.rs
@@ -83,6 +83,7 @@ use crate::runtime::local_events::{
};
use crate::runtime::sdk::{
CliSdkAdapterError, CliSdkSession, fetch_relay_events_via_shared_transport,
+ sdk_transport_outcome_kind_label,
};
use crate::runtime::sync::{RelayIngestScope, relay_provenance_relays_for_scope};
use crate::view::runtime::{
@@ -90,7 +91,7 @@ use crate::view::runtime::{
OrderCancellationView, OrderDecisionView, OrderDraftItemView, OrderEventListEntryView,
OrderEventListView, OrderGetView, OrderIssueView, OrderListView, OrderNewView, OrderRebindView,
OrderRevisionDecisionView, OrderRevisionProposalView, OrderStatusView, OrderSubmitView,
- OrderSummaryView, OrderTradeLocatorView, RelayFailureView,
+ OrderSummaryView, OrderTradeLocatorView, TransportTargetFailureView,
};
use self::sdk_status::sdk_order_status_view;
@@ -103,7 +104,7 @@ const ORDER_DECISION_SOURCE: &str = "SDK trade decision · local key";
const ORDER_REVISION_PROPOSAL_SOURCE: &str = "SDK trade revision proposal · local key";
const ORDER_REVISION_DECISION_SOURCE: &str = "SDK trade revision decision · local key";
const ORDER_CANCELLATION_SOURCE: &str = "SDK trade cancellation · local key";
-const ORDER_EVENT_LIST_SOURCE: &str = "shared relay transport fetch · selected seller identity";
+const ORDER_EVENT_LIST_SOURCE: &str = "shared Nostr transport fetch · selected seller identity";
const ORDER_STATUS_SDK_SOURCE: &str = "SDK local trade projection";
const ORDER_EVENT_LIST_RELAY_ACTION: &str =
"radroots transport profile set --kind nostr --nostr-relay wss://relay.example.com";
@@ -165,7 +166,7 @@ fn trade_publish_mode(config: &RuntimeConfig) -> PublishMode {
fn trade_satisfaction_policy(mode: PublishMode) -> Result<SatisfactionPolicy, RuntimeError> {
Ok(match mode {
PublishMode::DryRun | PublishMode::EnqueueOnly => SatisfactionPolicy::NoWait,
- PublishMode::EnqueueAndPublish => SatisfactionPolicy::AtLeastOneTarget,
+ PublishMode::EnqueueAndPublish => SatisfactionPolicy::AnyAccepted,
_ => {
return Err(RuntimeError::Config(
"unsupported SDK publish mode for CLI trade workflow".to_owned(),
@@ -897,10 +898,10 @@ pub fn submit(
event_kind: None,
dry_run: config.output.dry_run,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: None,
reason: Some(reason),
@@ -933,10 +934,10 @@ pub fn submit(
event_kind: None,
dry_run: config.output.dry_run,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: None,
reason: Some(format!("trade draft `{}` was not found", args.key)),
@@ -980,10 +981,10 @@ pub fn submit(
event_kind: None,
dry_run: config.output.dry_run,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: None,
reason: Some("trade draft is not ready for submit".to_owned()),
@@ -1592,7 +1593,7 @@ fn sdk_trade_decision_outcome_view(
view.prev_event_id = Some(plan.request_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_DECISION);
- view.target_relays = config.transport.nostr_relay_urls.clone();
+ view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.reason = Some(format!(
"dry run requested; seller trade {} publication skipped",
args.decision.command()
@@ -1634,7 +1635,7 @@ fn sdk_trade_revision_outcome_view(
})
.collect();
view.economics = Some(revision.economics);
- view.target_relays = config.transport.nostr_relay_urls.clone();
+ view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.reason =
Some("dry run requested; seller revision proposal publication skipped".to_owned());
view.actions = vec![format!("radroots trade status get {}", status.order_id)];
@@ -1669,7 +1670,7 @@ fn sdk_trade_revision_decision_outcome_view(
view.prev_event_id = Some(plan.previous_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_REVISION_DECISION);
- view.target_relays = config.transport.nostr_relay_urls.clone();
+ view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.reason = Some(format!(
"dry run requested; buyer revision {} publication skipped",
args.decision.command()
@@ -1700,7 +1701,7 @@ fn sdk_trade_cancellation_outcome_view(
view.prev_event_id = Some(plan.previous_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_CANCELLATION);
- view.target_relays = config.transport.nostr_relay_urls.clone();
+ view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.reason =
Some("dry run requested; buyer trade cancellation publication skipped".to_owned());
view.actions = vec![format!("radroots trade status get {}", status.order_id)];
@@ -1789,7 +1790,7 @@ fn order_event_list_unconfigured(
seller_pubkey: Option<String>,
actor_context_source: &'static str,
reason: String,
- target_relays: Vec<String>,
+ target_transport_endpoints: Vec<String>,
actions: Vec<String>,
) -> OrderEventListView {
OrderEventListView {
@@ -1797,9 +1798,9 @@ fn order_event_list_unconfigured(
source: ORDER_EVENT_LIST_SOURCE.to_owned(),
actor_context_source: actor_context_source.to_owned(),
seller_pubkey,
- target_relays,
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints,
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
@@ -1814,22 +1815,22 @@ fn order_event_list_unavailable(
seller_pubkey: String,
actor_context_source: &'static str,
reason: String,
- target_relays: Vec<String>,
- failed_relays: Vec<RadrootsRelayFetchFailure>,
+ target_transport_endpoints: Vec<String>,
+ failed_transport_targets: Vec<RadrootsRelayFetchFailure>,
) -> OrderEventListView {
OrderEventListView {
state: "unavailable".to_owned(),
source: ORDER_EVENT_LIST_SOURCE.to_owned(),
actor_context_source: actor_context_source.to_owned(),
seller_pubkey: Some(seller_pubkey),
- target_relays,
- connected_relays: Vec::new(),
- failed_relays: relay_failures(failed_relays),
+ target_transport_endpoints,
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: relay_failures(failed_transport_targets),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
count: 0,
- reason: Some(format!("relay transport fetch failed: {reason}")),
+ reason: Some(format!("Nostr transport fetch failed: {reason}")),
orders: Vec::new(),
actions: Vec::new(),
}
@@ -1875,9 +1876,9 @@ fn order_event_list_from_receipt(
let reason = if orders.is_empty() {
Some(match order_id {
Some(order_id) => {
- format!("no relay-backed order request events matched `{order_id}`")
+ format!("no Nostr-backed order request events matched `{order_id}`")
}
- None => "no relay-backed order request events matched the selected seller".to_owned(),
+ None => "no Nostr-backed order request events matched the selected seller".to_owned(),
})
} else {
None
@@ -1888,9 +1889,9 @@ fn order_event_list_from_receipt(
source: ORDER_EVENT_LIST_SOURCE.to_owned(),
actor_context_source: actor_context_source.to_owned(),
seller_pubkey: Some(seller_pubkey),
- target_relays,
- connected_relays,
- failed_relays: relay_failures(failed_relays),
+ target_transport_endpoints: target_relays,
+ attempted_transport_endpoints: connected_relays,
+ failed_transport_targets: relay_failures(failed_relays),
fetched_count,
decoded_count,
skipped_count,
@@ -1924,10 +1925,10 @@ fn order_decision_base_view(
event_kind: None,
inventory: None,
dry_run,
- target_relays: config.transport.nostr_relay_urls.clone(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: config.transport.nostr_relay_urls.clone(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
@@ -1964,10 +1965,10 @@ fn order_revision_base_view(
economics: None,
inventory: None,
dry_run,
- target_relays: config.transport.nostr_relay_urls.clone(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: config.transport.nostr_relay_urls.clone(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
@@ -2005,10 +2006,10 @@ fn order_revision_decision_base_view(
economics: None,
inventory: None,
dry_run,
- target_relays: config.transport.nostr_relay_urls.clone(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: config.transport.nostr_relay_urls.clone(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
@@ -2042,10 +2043,10 @@ fn order_cancellation_base_view(
event_kind: None,
cancellation_reason: Some(args.reason.clone()),
dry_run,
- target_relays: config.transport.nostr_relay_urls.clone(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: config.transport.nostr_relay_urls.clone(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: 0,
skipped_count: 0,
@@ -2067,9 +2068,9 @@ fn apply_order_cancellation_status(view: &mut OrderCancellationView, status: &Or
view.decision_event_id = status.decision_event_id.clone();
view.root_event_id = status.request_event_id.clone();
view.prev_event_id = order_cancellation_prev_event_id(status);
- view.target_relays = status.target_relays.clone();
- view.connected_relays = status.connected_relays.clone();
- view.failed_relays = status.failed_relays.clone();
+ view.target_transport_endpoints = status.target_transport_endpoints.clone();
+ view.attempted_transport_endpoints = status.attempted_transport_endpoints.clone();
+ view.failed_transport_targets = status.failed_transport_targets.clone();
view.fetched_count = status.fetched_count;
view.decoded_count = status.decoded_count;
view.skipped_count = status.skipped_count;
@@ -2097,9 +2098,9 @@ fn apply_order_decision_status(view: &mut OrderDecisionView, status: &OrderStatu
view.listing_event_id = status.listing_event_id.clone();
view.root_event_id = status.request_event_id.clone();
view.prev_event_id = status.last_event_id.clone();
- view.target_relays = status.target_relays.clone();
- view.connected_relays = status.connected_relays.clone();
- view.failed_relays = status.failed_relays.clone();
+ view.target_transport_endpoints = status.target_transport_endpoints.clone();
+ view.attempted_transport_endpoints = status.attempted_transport_endpoints.clone();
+ view.failed_transport_targets = status.failed_transport_targets.clone();
view.fetched_count = status.fetched_count;
view.decoded_count = status.decoded_count;
view.skipped_count = status.skipped_count;
@@ -2119,9 +2120,9 @@ fn apply_order_revision_status(view: &mut OrderRevisionProposalView, status: &Or
view.prev_event_id = status.last_event_id.clone();
view.economics = status.economics.clone();
view.inventory = status.inventory.clone();
- view.target_relays = status.target_relays.clone();
- view.connected_relays = status.connected_relays.clone();
- view.failed_relays = status.failed_relays.clone();
+ view.target_transport_endpoints = status.target_transport_endpoints.clone();
+ view.attempted_transport_endpoints = status.attempted_transport_endpoints.clone();
+ view.failed_transport_targets = status.failed_transport_targets.clone();
view.fetched_count = status.fetched_count;
view.decoded_count = status.decoded_count;
view.skipped_count = status.skipped_count;
@@ -2144,9 +2145,9 @@ fn apply_order_revision_decision_status(
view.prev_event_id = status.last_event_id.clone();
view.economics = status.economics.clone();
view.inventory = status.inventory.clone();
- view.target_relays = status.target_relays.clone();
- view.connected_relays = status.connected_relays.clone();
- view.failed_relays = status.failed_relays.clone();
+ view.target_transport_endpoints = status.target_transport_endpoints.clone();
+ view.attempted_transport_endpoints = status.attempted_transport_endpoints.clone();
+ view.failed_transport_targets = status.failed_transport_targets.clone();
view.fetched_count = status.fetched_count;
view.decoded_count = status.decoded_count;
view.skipped_count = status.skipped_count;
@@ -2408,16 +2409,18 @@ fn sdk_enqueued_order_decision_view(
view.prev_event_id = Some(enqueue.request_event_id.to_string());
view.event_id = Some(enqueue.signed_event_id.as_str().to_owned());
view.event_kind = Some(KIND_ORDER_DECISION);
- view.target_relays = push_event
- .map(sdk_push_target_relays)
+ view.target_transport_endpoints = push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
- view.connected_relays = push_event
- .map(sdk_push_connected_relays)
+ view.attempted_transport_endpoints = push_event
+ .map(sdk_push_attempted_transport_endpoints)
+ .unwrap_or_default();
+ view.accepted_transport_endpoints = push_event
+ .map(sdk_push_accepted_transport_endpoints)
.unwrap_or_default();
- view.acknowledged_relays = push_event
- .map(sdk_push_acknowledged_relays)
+ view.failed_transport_targets = push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default();
- view.failed_relays = push_event.map(sdk_push_failed_relays).unwrap_or_default();
view.reason = sdk_order_decision_reason(&enqueue.workflow, push_event);
view.actions = sdk_order_decision_actions(push_event);
view
@@ -2453,17 +2456,17 @@ fn sdk_order_decision_reason(
match push_event.map(|event| event.final_state) {
Some(PushOutboxEventState::Published) => None,
Some(PushOutboxEventState::PublishRetryable) => Some(format!(
- "{}; SDK relay publish did not reach accepted quorum; outbox event remains retryable; {}",
+ "{}; SDK transport publish did not reach accepted quorum; outbox event remains retryable; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(PushOutboxEventState::FailedTerminal) => Some(format!(
- "{}; SDK relay publish failed terminally; {}",
+ "{}; SDK transport publish failed terminally; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(state) => Some(format!(
- "{}; SDK relay push left event in state `{state:?}`; {}",
+ "{}; SDK transport push left event in state `{state:?}`; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
@@ -2517,16 +2520,18 @@ fn sdk_enqueued_order_revision_view(
view.economics = Some(revision.economics);
view.event_id = Some(enqueue.signed_event_id.as_str().to_owned());
view.event_kind = Some(KIND_ORDER_REVISION_PROPOSAL);
- view.target_relays = push_event
- .map(sdk_push_target_relays)
+ view.target_transport_endpoints = push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
- view.connected_relays = push_event
- .map(sdk_push_connected_relays)
+ view.attempted_transport_endpoints = push_event
+ .map(sdk_push_attempted_transport_endpoints)
.unwrap_or_default();
- view.acknowledged_relays = push_event
- .map(sdk_push_acknowledged_relays)
+ view.accepted_transport_endpoints = push_event
+ .map(sdk_push_accepted_transport_endpoints)
+ .unwrap_or_default();
+ view.failed_transport_targets = push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default();
- view.failed_relays = push_event.map(sdk_push_failed_relays).unwrap_or_default();
view.reason =
sdk_order_lifecycle_reason("trade revision proposal", &enqueue.workflow, push_event);
view.actions = sdk_order_lifecycle_actions(push_event);
@@ -2560,16 +2565,18 @@ fn sdk_enqueued_order_revision_decision_view(
if args.decision == TradeRevisionDecisionArg::Accept {
view.agreement_event_id = Some(enqueue.signed_event_id.as_str().to_owned());
}
- view.target_relays = push_event
- .map(sdk_push_target_relays)
+ view.target_transport_endpoints = push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
- view.connected_relays = push_event
- .map(sdk_push_connected_relays)
+ view.attempted_transport_endpoints = push_event
+ .map(sdk_push_attempted_transport_endpoints)
+ .unwrap_or_default();
+ view.accepted_transport_endpoints = push_event
+ .map(sdk_push_accepted_transport_endpoints)
.unwrap_or_default();
- view.acknowledged_relays = push_event
- .map(sdk_push_acknowledged_relays)
+ view.failed_transport_targets = push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default();
- view.failed_relays = push_event.map(sdk_push_failed_relays).unwrap_or_default();
view.reason =
sdk_order_lifecycle_reason("trade revision decision", &enqueue.workflow, push_event);
view.actions = sdk_order_lifecycle_actions(push_event);
@@ -2597,16 +2604,18 @@ fn sdk_enqueued_order_cancellation_view(
view.prev_event_id = Some(enqueue.previous_event_id.to_string());
view.event_id = Some(enqueue.signed_event_id.as_str().to_owned());
view.event_kind = Some(KIND_ORDER_CANCELLATION);
- view.target_relays = push_event
- .map(sdk_push_target_relays)
+ view.target_transport_endpoints = push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
- view.connected_relays = push_event
- .map(sdk_push_connected_relays)
+ view.attempted_transport_endpoints = push_event
+ .map(sdk_push_attempted_transport_endpoints)
+ .unwrap_or_default();
+ view.accepted_transport_endpoints = push_event
+ .map(sdk_push_accepted_transport_endpoints)
.unwrap_or_default();
- view.acknowledged_relays = push_event
- .map(sdk_push_acknowledged_relays)
+ view.failed_transport_targets = push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default();
- view.failed_relays = push_event.map(sdk_push_failed_relays).unwrap_or_default();
view.reason = sdk_order_lifecycle_reason("trade cancellation", &enqueue.workflow, push_event);
view.actions = sdk_order_lifecycle_actions(push_event);
view
@@ -2641,17 +2650,17 @@ fn sdk_order_lifecycle_reason(
match push_event.map(|event| event.final_state) {
Some(PushOutboxEventState::Published) => None,
Some(PushOutboxEventState::PublishRetryable) => Some(format!(
- "{}; SDK relay publish for {workflow} did not reach accepted quorum; outbox event remains retryable; {}",
+ "{}; SDK transport publish for {workflow} did not reach accepted quorum; outbox event remains retryable; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(PushOutboxEventState::FailedTerminal) => Some(format!(
- "{}; SDK relay publish for {workflow} failed terminally; {}",
+ "{}; SDK transport publish for {workflow} failed terminally; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(state) => Some(format!(
- "{}; SDK relay push for {workflow} left event in state `{state:?}`; {}",
+ "{}; SDK transport push for {workflow} left event in state `{state:?}`; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
@@ -4642,10 +4651,10 @@ fn order_submit_app_signed_evidence_view(
event_kind: Some(KIND_ORDER_REQUEST),
dry_run: config.output.dry_run,
deduplicated: true,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: None,
reason: Some(
@@ -4678,10 +4687,10 @@ fn order_submit_app_signed_evidence_view(
event_kind: Some(KIND_ORDER_REQUEST),
dry_run: config.output.dry_run,
deduplicated: false,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: None,
reason: Some(
@@ -4758,7 +4767,7 @@ fn order_submit_dry_run_view(
loaded: &LoadedOrderDraft,
args: &TradeSubmitArgs,
plan: TradeSubmitPlan,
- target_relays: Vec<String>,
+ target_transport_endpoints: Vec<String>,
) -> OrderSubmitView {
OrderSubmitView {
state: "dry_run".to_owned(),
@@ -4786,13 +4795,13 @@ fn order_submit_dry_run_view(
event_kind: Some(KIND_ORDER_REQUEST),
dry_run: true,
deduplicated: false,
- target_relays,
- connected_relays: Vec::new(),
- acknowledged_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints,
+ attempted_transport_endpoints: Vec::new(),
+ accepted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: Some(config.signer.backend.as_str().to_owned()),
- reason: Some("dry run requested; SDK enqueue and relay push skipped".to_owned()),
+ reason: Some("dry run requested; SDK enqueue and transport push skipped".to_owned()),
job: None,
issues: Vec::new(),
actions: vec![format!(
@@ -4953,16 +4962,18 @@ fn sdk_enqueued_order_submit_view(
event_kind: Some(KIND_ORDER_REQUEST),
dry_run: false,
deduplicated: matches!(enqueue.state, SdkMutationState::AlreadyQueued),
- target_relays: push_event
- .map(sdk_push_target_relays)
+ target_transport_endpoints: push_event
+ .map(sdk_push_target_transport_endpoints)
.unwrap_or_else(|| config.transport.nostr_relay_urls.clone()),
- connected_relays: push_event
- .map(sdk_push_connected_relays)
+ attempted_transport_endpoints: push_event
+ .map(sdk_push_attempted_transport_endpoints)
+ .unwrap_or_default(),
+ accepted_transport_endpoints: push_event
+ .map(sdk_push_accepted_transport_endpoints)
.unwrap_or_default(),
- acknowledged_relays: push_event
- .map(sdk_push_acknowledged_relays)
+ failed_transport_targets: push_event
+ .map(sdk_push_failed_transport_targets)
.unwrap_or_default(),
- failed_relays: push_event.map(sdk_push_failed_relays).unwrap_or_default(),
idempotency_key: args.idempotency_key.clone(),
signer_mode: Some(config.signer.backend.as_str().to_owned()),
reason: sdk_order_submit_reason(&enqueue.workflow, push_event),
@@ -4999,17 +5010,17 @@ fn sdk_order_submit_reason(
match push_event.map(|event| event.final_state) {
Some(PushOutboxEventState::Published) => None,
Some(PushOutboxEventState::PublishRetryable) => Some(format!(
- "{}; SDK relay publish did not reach accepted quorum; outbox event remains retryable; {}",
+ "{}; SDK transport publish did not reach accepted quorum; outbox event remains retryable; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(PushOutboxEventState::FailedTerminal) => Some(format!(
- "{}; SDK relay publish failed terminally; {}",
+ "{}; SDK transport publish failed terminally; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
Some(state) => Some(format!(
- "{}; SDK relay push left event in state `{state:?}`; {}",
+ "{}; SDK transport push left event in state `{state:?}`; {}",
sdk_order_enqueue_summary(enqueue),
sdk_order_enqueue_retry_summary(enqueue)
)),
@@ -5031,7 +5042,7 @@ fn sdk_order_submit_actions(push_event: Option<&PushOutboxEventReceipt>) -> Vec<
Vec::new()
}
-fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_target_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -5039,7 +5050,7 @@ fn sdk_push_target_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_attempted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -5048,7 +5059,7 @@ fn sdk_push_connected_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
+fn sdk_push_accepted_transport_endpoints(event: &PushOutboxEventReceipt) -> Vec<String> {
event
.targets
.iter()
@@ -5063,7 +5074,9 @@ fn sdk_push_acknowledged_relays(event: &PushOutboxEventReceipt) -> Vec<String> {
.collect()
}
-fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureView> {
+fn sdk_push_failed_transport_targets(
+ event: &PushOutboxEventReceipt,
+) -> Vec<TransportTargetFailureView> {
event
.targets
.iter()
@@ -5074,8 +5087,14 @@ fn sdk_push_failed_relays(event: &PushOutboxEventReceipt) -> Vec<RelayFailureVie
| PushOutboxTargetOutcomeKind::DuplicateAccepted
)
})
- .map(|target| RelayFailureView {
- relay: target.endpoint_uri.clone(),
+ .map(|target| TransportTargetFailureView {
+ transport_kind: target.transport_kind.clone(),
+ endpoint_uri: target.endpoint_uri.clone(),
+ target_scope: target.target_scope.clone(),
+ target_label: target.target_label.clone(),
+ transport_outcome_kind: target
+ .transport_outcome_kind
+ .map(sdk_transport_outcome_kind_label),
reason: target
.message
.clone()
@@ -5243,22 +5262,26 @@ fn order_relay_fetch_error(error: RadrootsRelayTransportError) -> RuntimeError {
RuntimeError::Network(error.to_string())
}
-fn relay_fetch_failure_reason(failed_relays: &[RadrootsRelayFetchFailure]) -> String {
- if failed_relays.is_empty() {
+fn relay_fetch_failure_reason(failed_transport_targets: &[RadrootsRelayFetchFailure]) -> String {
+ if failed_transport_targets.is_empty() {
return "no relay acknowledged the fetch".to_owned();
}
- failed_relays
+ failed_transport_targets
.iter()
.map(|failure| format!("{}: {}", failure.relay_url, failure.reason))
.collect::<Vec<_>>()
.join("; ")
}
-fn relay_failures(failures: Vec<RadrootsRelayFetchFailure>) -> Vec<RelayFailureView> {
+fn relay_failures(failures: Vec<RadrootsRelayFetchFailure>) -> Vec<TransportTargetFailureView> {
failures
.into_iter()
- .map(|failure| RelayFailureView {
- relay: failure.relay_url,
+ .map(|failure| TransportTargetFailureView {
+ transport_kind: "nostr".to_owned(),
+ endpoint_uri: failure.relay_url,
+ target_scope: None,
+ target_label: None,
+ transport_outcome_kind: None,
reason: failure.reason,
})
.collect()
diff --git a/src/runtime/order/sdk_status.rs b/src/runtime/order/sdk_status.rs
@@ -58,9 +58,9 @@ pub(super) fn sdk_order_status_view(receipt: TradeStatusReceipt) -> OrderStatusV
sdk_receipt,
ambiguity_candidates,
reducer_issues,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
fetched_count: 0,
decoded_count: receipt.event_count,
skipped_count: 0,
diff --git a/src/runtime/sdk.rs b/src/runtime/sdk.rs
@@ -16,12 +16,13 @@ use radroots_nostr_connect::prelude::{
RadrootsNostrConnectClientTarget, RadrootsNostrConnectError, RadrootsNostrConnectUri,
};
use radroots_sdk::{
- HybridProfile, MeshScopeId, NostrProfile, NostrRelayUrlPolicy, ProxyProfile, RadrootsClient,
- RadrootsClientBuilder, RadrootsSdkError, RadrootsSdkLocalKeySigner,
- RadrootsSdkMycNip46RequestPolicy, RadrootsSdkMycNip46Signer, RadrootsSdkNip46Transport,
- RadrootsSdkNip46TransportFuture, RadrootsSdkSignerProvider, RadrootsSdkStorageConfig,
- ReticulumPreviewAgentEndpoint, ReticulumPreviewBehavior as SdkReticulumPreviewBehavior,
- ReticulumPreviewProfile, TargetPolicy, TransportProfile,
+ HybridProfile, MeshScopeId, NostrProfile, NostrRelayUrlPolicy, ProxyProfile,
+ PushOutboxTransportOutcomeKind, RadrootsClient, RadrootsClientBuilder, RadrootsSdkError,
+ RadrootsSdkLocalKeySigner, RadrootsSdkMycNip46RequestPolicy, RadrootsSdkMycNip46Signer,
+ RadrootsSdkNip46Transport, RadrootsSdkNip46TransportFuture, RadrootsSdkSignerProvider,
+ RadrootsSdkStorageConfig, ReticulumPreviewAgentEndpoint,
+ ReticulumPreviewBehavior as SdkReticulumPreviewBehavior, ReticulumPreviewProfile, TargetPolicy,
+ TradeValidationReceiptNostrRelayTransportOutcomeKind, TransportProfile,
};
use radroots_transport_nostr::{
RadrootsNostrClientFetchAdapter, RadrootsRelayFetchRequest, RadrootsRelayFetchedEventsReceipt,
@@ -51,6 +52,24 @@ pub enum CliSdkAdapterError {
Sdk(#[from] RadrootsSdkError),
}
+pub fn sdk_transport_outcome_kind_label(kind: PushOutboxTransportOutcomeKind) -> String {
+ sdk_enum_label(kind)
+}
+
+pub fn sdk_validation_transport_outcome_kind_label(
+ kind: TradeValidationReceiptNostrRelayTransportOutcomeKind,
+) -> String {
+ sdk_enum_label(kind)
+}
+
+fn sdk_enum_label<T: serde::Serialize>(value: T) -> String {
+ match serde_json::to_value(value) {
+ Ok(serde_json::Value::String(value)) => value,
+ Ok(value) => panic!("SDK enum serialized to non-string JSON value `{value}`"),
+ Err(error) => panic!("SDK enum serialization failed: {error}"),
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CliSdkConfig {
pub storage_root: PathBuf,
@@ -1160,7 +1179,7 @@ mod tests {
"ReplicaSql::new",
"SqliteExecutor::open(&config.local.replica_db_path)",
"outbox_idempotency_digest",
- "canonical_target_relays",
+ "canonical_target_transport_endpoints",
"radroots_sdk::protocol::order",
"build_order_request_draft",
"build_order_decision_draft",
diff --git a/src/runtime/sync.rs b/src/runtime/sync.rs
@@ -37,7 +37,7 @@ use crate::runtime::RuntimeError;
use crate::runtime::config::{RuntimeConfig, TransportProfileKind};
use crate::runtime::sdk::{
CliSdkAdapterError, CliSdkSession, fetch_relay_events_via_shared_transport,
- sdk_nostr_relay_url_policy,
+ sdk_nostr_relay_url_policy, sdk_transport_outcome_kind_label,
};
use crate::view::runtime::{
SyncActionView, SyncFreshnessView, SyncQueueView, SyncRunFreshnessView, SyncStatusView,
@@ -54,7 +54,7 @@ const SYNC_PULL_ACTION: &str = "radroots sync pull";
const SYNC_PUSH_ACTION: &str = "radroots sync push";
const SYNC_READY_ACTION: &str = "radroots market product search eggs";
const MARKET_READY_ACTION: &str = "radroots market product search eggs";
-const INGEST_SOURCE: &str = "shared relay transport fetch · local replica ingest";
+const INGEST_SOURCE: &str = "shared Nostr transport fetch · local replica ingest";
const RELAY_FETCH_LIMIT: usize = 1_000;
const RELAY_FETCH_MAX_PAGES: usize = 5;
const MARKET_FRESHNESS_STALE_AFTER_SECONDS: u64 = 15 * 60;
@@ -236,7 +236,7 @@ where
if config.output.dry_run {
let mut view = empty_action_from_snapshot(snapshot, "pull");
view.state = "ready".to_owned();
- view.reason = Some("dry run requested; relay fetch skipped".to_owned());
+ view.reason = Some("dry run requested; Nostr fetch skipped".to_owned());
view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.fetched_count = Some(0);
view.ingested_count = Some(0);
@@ -256,7 +256,7 @@ where
let target_transport_endpoints = receipt.target_relays;
let failed_transport_targets = relay_failures(receipt.failed_relays);
let reason = relay_failure_reason(&failed_transport_targets);
- let failure_reason = format!("relay transport fetch failed: {reason}");
+ let failure_reason = format!("Nostr transport fetch failed: {reason}");
let executor = SqliteExecutor::open(&config.local.replica_db_path)?;
migrations::run_all_up(&executor)?;
record_sync_run(
@@ -273,7 +273,7 @@ where
let mut view = empty_action_from_snapshot(snapshot, "pull");
view.state = "unavailable".to_owned();
view.reason = Some(failure_reason);
- view.reason_code = Some("relay_fetch_failed".to_owned());
+ view.reason_code = Some("nostr_fetch_failed".to_owned());
view.target_transport_endpoints = target_transport_endpoints;
view.failed_transport_targets = failed_transport_targets;
view.freshness = freshness_for_scope_from_executor(config, &executor, scope)?;
@@ -298,7 +298,7 @@ where
let mut view = empty_action_from_snapshot(snapshot, "pull");
view.state = "unavailable".to_owned();
view.reason = Some(failure_reason);
- view.reason_code = Some("relay_fetch_failed".to_owned());
+ view.reason_code = Some("nostr_fetch_failed".to_owned());
view.target_transport_endpoints = config.transport.nostr_relay_urls.clone();
view.freshness = freshness_for_scope_from_executor(config, &executor, scope)?;
return Ok(view);
@@ -588,6 +588,8 @@ fn sdk_transport_targets(receipt: &SyncStatusReceipt) -> Vec<SyncTransportTarget
transport_kind: target.transport_kind.clone(),
endpoint_uri: target.endpoint_uri.clone(),
endpoint_fingerprint: target.endpoint_fingerprint.clone(),
+ target_scope: target.target_scope.clone(),
+ target_label: target.target_label.clone(),
})
.collect()
}
@@ -834,6 +836,11 @@ fn sdk_push_failed_transport_targets(
.map(|target| TransportTargetFailureView {
transport_kind: target.transport_kind.clone(),
endpoint_uri: target.endpoint_uri.clone(),
+ target_scope: target.target_scope.clone(),
+ target_label: target.target_label.clone(),
+ transport_outcome_kind: target
+ .transport_outcome_kind
+ .map(sdk_transport_outcome_kind_label),
reason: target
.message
.clone()
@@ -935,6 +942,8 @@ fn sync_transport_target_view(
transport_kind: target.kind.canonical_label(),
endpoint_uri: target.uri.as_str().to_owned(),
endpoint_fingerprint: target.fingerprint.as_str().to_owned(),
+ target_scope: target.scope.as_ref().map(|scope| scope.as_str().to_owned()),
+ target_label: target.label.as_ref().map(|label| label.as_str().to_owned()),
})
}
@@ -1554,7 +1563,7 @@ fn relay_ingest_reason_code(
) -> Option<&'static str> {
ingest
.reason_code()
- .or_else(|| (!failed_transport_targets.is_empty()).then_some("relay_fetch_partial"))
+ .or_else(|| (!failed_transport_targets.is_empty()).then_some("nostr_fetch_partial"))
}
fn relay_ingest_reason(
@@ -1688,6 +1697,9 @@ fn relay_failures(failures: Vec<RadrootsRelayFetchFailure>) -> Vec<TransportTarg
.map(|failure| TransportTargetFailureView {
transport_kind: "nostr".to_owned(),
endpoint_uri: failure.relay_url,
+ target_scope: None,
+ target_label: None,
+ transport_outcome_kind: None,
reason: failure.reason,
})
.collect()
@@ -1781,9 +1793,9 @@ mod tests {
};
use radroots_sdk::{
PushOutboxEventReceipt, PushOutboxEventState, PushOutboxReceipt,
- PushOutboxTargetOutcomeKind, PushOutboxTargetReceipt, SyncEventStoreStatus,
- SyncOutboxStatus, SyncStatusReceipt, SyncStatusSource, SyncTransportProfileSummary,
- SyncTransportStatusSummary, SyncTransportTargetSummary,
+ PushOutboxTargetOutcomeKind, PushOutboxTargetReceipt, PushOutboxTransportOutcomeKind,
+ SyncEventStoreStatus, SyncOutboxStatus, SyncStatusReceipt, SyncStatusSource,
+ SyncTransportProfileSummary, SyncTransportStatusSummary, SyncTransportTargetSummary,
};
use radroots_secret_vault::RadrootsSecretBackend;
use radroots_transport::{
@@ -2087,11 +2099,15 @@ mod tests {
transport_kind: "nostr".to_owned(),
endpoint_uri: "wss://relay.example.com".to_owned(),
endpoint_fingerprint: "0".repeat(64),
+ target_scope: None,
+ target_label: None,
},
SyncTransportTargetSummary {
transport_kind: "reticulum".to_owned(),
endpoint_uri: RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI.to_owned(),
endpoint_fingerprint: "1".repeat(64),
+ target_scope: Some("local_preview".to_owned()),
+ target_label: None,
},
],
transport_statuses: vec![
@@ -2476,6 +2492,8 @@ mod tests {
transport_kind: "nostr".to_owned(),
endpoint_uri: (*relay).to_owned(),
endpoint_fingerprint: format!("test-fingerprint-{index}"),
+ target_scope: None,
+ target_label: None,
})
.collect(),
transport_statuses: vec![SyncTransportStatusSummary {
@@ -2525,6 +2543,8 @@ mod tests {
transport_kind: "reticulum".to_owned(),
endpoint_uri: RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI.to_owned(),
endpoint_fingerprint: "1".repeat(64),
+ target_scope: Some("local_preview".to_owned()),
+ target_label: None,
}],
transport_statuses: vec![SyncTransportStatusSummary {
transport: "reticulum".to_owned(),
@@ -2582,7 +2602,10 @@ mod tests {
targets: vec![PushOutboxTargetReceipt {
transport_kind: "nostr".to_owned(),
endpoint_uri: relay_url.to_owned(),
+ target_scope: None,
+ target_label: None,
outcome_kind,
+ transport_outcome_kind: test_transport_outcome_kind(outcome_kind),
attempted: true,
message,
}],
@@ -2606,13 +2629,51 @@ mod tests {
targets: vec![PushOutboxTargetReceipt {
transport_kind: "reticulum".to_owned(),
endpoint_uri: RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI.to_owned(),
+ target_scope: Some("local_preview".to_owned()),
+ target_label: None,
outcome_kind,
+ transport_outcome_kind: test_transport_outcome_kind(outcome_kind),
attempted: false,
message: Some(RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE.to_owned()),
}],
}
}
+ fn test_transport_outcome_kind(
+ kind: PushOutboxTargetOutcomeKind,
+ ) -> Option<PushOutboxTransportOutcomeKind> {
+ Some(match kind {
+ PushOutboxTargetOutcomeKind::Accepted => PushOutboxTransportOutcomeKind::Accepted,
+ PushOutboxTargetOutcomeKind::DuplicateAccepted => {
+ PushOutboxTransportOutcomeKind::DuplicateAccepted
+ }
+ PushOutboxTargetOutcomeKind::DeferredUntilImplemented => {
+ PushOutboxTransportOutcomeKind::DeferredUntilImplemented
+ }
+ PushOutboxTargetOutcomeKind::Timeout => PushOutboxTransportOutcomeKind::Timeout,
+ PushOutboxTargetOutcomeKind::ConnectionFailed => {
+ PushOutboxTransportOutcomeKind::ConnectionFailed
+ }
+ PushOutboxTargetOutcomeKind::PreviewUnavailable => {
+ PushOutboxTransportOutcomeKind::TransportUnavailable
+ }
+ PushOutboxTargetOutcomeKind::AuthRequired
+ | PushOutboxTargetOutcomeKind::Blocked
+ | PushOutboxTargetOutcomeKind::RateLimited
+ | PushOutboxTargetOutcomeKind::Invalid
+ | PushOutboxTargetOutcomeKind::PowRequired
+ | PushOutboxTargetOutcomeKind::Restricted
+ | PushOutboxTargetOutcomeKind::Muted
+ | PushOutboxTargetOutcomeKind::Unsupported
+ | PushOutboxTargetOutcomeKind::PaymentRequired
+ | PushOutboxTargetOutcomeKind::Error
+ | PushOutboxTargetOutcomeKind::TargetUriRejected
+ | PushOutboxTargetOutcomeKind::SkippedAlreadyAccepted
+ | PushOutboxTargetOutcomeKind::Unknown => PushOutboxTransportOutcomeKind::Rejected,
+ _ => PushOutboxTransportOutcomeKind::Rejected,
+ })
+ }
+
#[test]
fn sync_pull_ingests_relay_events_and_market_reads_without_daemon() {
let dir = tempdir().expect("tempdir");
@@ -2760,7 +2821,7 @@ mod tests {
);
assert_eq!(view.failed_transport_targets.len(), 1);
assert_eq!(view.failed_count, Some(1));
- assert_eq!(view.reason_code.as_deref(), Some("relay_fetch_partial"));
+ assert_eq!(view.reason_code.as_deref(), Some("nostr_fetch_partial"));
assert!(
view.reason
.as_deref()
diff --git a/src/runtime/transport.rs b/src/runtime/transport.rs
@@ -715,7 +715,9 @@ fn string_array_input(input: &OperationData, key: &str) -> Vec<String> {
mod tests {
use super::*;
use radroots_events::ids::RadrootsEventId;
- use radroots_sdk::{PushOutboxEventReceipt, PushOutboxTargetReceipt};
+ use radroots_sdk::{
+ PushOutboxEventReceipt, PushOutboxTargetReceipt, PushOutboxTransportOutcomeKind,
+ };
#[test]
fn transport_outbox_push_reports_reticulum_preview_without_attempts() {
@@ -767,7 +769,18 @@ mod tests {
targets: vec![PushOutboxTargetReceipt {
transport_kind: "reticulum".to_owned(),
endpoint_uri: RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI.to_owned(),
+ target_scope: Some("local_preview".to_owned()),
+ target_label: None,
outcome_kind,
+ transport_outcome_kind: Some(match outcome_kind {
+ PushOutboxTargetOutcomeKind::DeferredUntilImplemented => {
+ PushOutboxTransportOutcomeKind::DeferredUntilImplemented
+ }
+ PushOutboxTargetOutcomeKind::PreviewUnavailable => {
+ PushOutboxTransportOutcomeKind::TransportUnavailable
+ }
+ _ => PushOutboxTransportOutcomeKind::TransportUnavailable,
+ }),
attempted: false,
message: Some(RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE.to_owned()),
}],
diff --git a/src/runtime/validation_receipt.rs b/src/runtime/validation_receipt.rs
@@ -2,7 +2,7 @@ use radroots_sdk::{
RadrootsSdkError, TradeValidationReceiptEvent, TradeValidationReceiptInspectReceipt,
TradeValidationReceiptInspectRequest, TradeValidationReceiptInvalidCandidate,
TradeValidationReceiptListReceipt, TradeValidationReceiptListRequest,
- TradeValidationReceiptRelayOutcomeKind, TradeValidationReceiptRelayOutcomeReceipt,
+ TradeValidationReceiptNostrRelayOutcomeKind, TradeValidationReceiptNostrRelayOutcomeReceipt,
TradeValidationReceiptTags, TradeValidationReceiptVerifyRequest,
TradeValidationReceiptWorkerEvidence,
TradeValidationReceiptWorkerEvidenceSelection as SdkWorkerEvidenceSelection,
@@ -18,8 +18,10 @@ use serde::Serialize;
use serde_json::Value;
use crate::runtime::config::RuntimeConfig;
-use crate::runtime::sdk::{CliSdkAdapterError, CliSdkSession};
-use crate::view::runtime::{CommandDisposition, RelayFailureView};
+use crate::runtime::sdk::{
+ CliSdkAdapterError, CliSdkSession, sdk_validation_transport_outcome_kind_label,
+};
+use crate::view::runtime::{CommandDisposition, TransportTargetFailureView};
#[derive(Debug, Clone)]
pub struct ValidationReceiptEventArgs {
@@ -42,9 +44,9 @@ pub struct ValidationReceiptInspectionView {
pub receipt: Option<RadrootsTradeValidationReceipt>,
pub receipt_tags: Option<ValidationReceiptTagsView>,
pub event: Option<ValidationReceiptEventView>,
- pub target_relays: Vec<String>,
- pub connected_relays: Vec<String>,
- pub failed_relays: Vec<RelayFailureView>,
+ pub target_transport_endpoints: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
pub reason_code: Option<String>,
pub reason: Option<String>,
pub sdk_error: Option<Value>,
@@ -73,9 +75,9 @@ pub struct ValidationReceiptListView {
pub invalid_count: usize,
pub receipts: Vec<ValidationReceiptSummaryView>,
pub invalid_receipts: Vec<ValidationReceiptInvalidCandidateView>,
- pub target_relays: Vec<String>,
- pub connected_relays: Vec<String>,
- pub failed_relays: Vec<RelayFailureView>,
+ pub target_transport_endpoints: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
pub reason_code: Option<String>,
pub reason: Option<String>,
pub sdk_error: Option<Value>,
@@ -334,16 +336,19 @@ fn inspection_from_sdk_receipt(
intent: ValidationReceiptCommandIntent,
sdk_receipt: TradeValidationReceiptInspectReceipt,
) -> ValidationReceiptInspectionView {
- let target_relays = sdk_receipt.relay_targets;
- let connected_relays = connected_relays(&sdk_receipt.relay_evidence.relays);
- let failed_relays = sdk_relay_failures(&sdk_receipt.relay_evidence.relays);
- let reason_code = (!failed_relays.is_empty()).then_some("relay_fetch_partial".to_owned());
+ let target_transport_endpoints = sdk_receipt.nostr_relay_urls;
+ let attempted_transport_endpoints =
+ attempted_transport_endpoints(&sdk_receipt.nostr_evidence.nostr_relay_outcomes);
+ let failed_transport_targets =
+ sdk_relay_failures(&sdk_receipt.nostr_evidence.nostr_relay_outcomes);
+ let reason_code =
+ (!failed_transport_targets.is_empty()).then_some("nostr_fetch_partial".to_owned());
if let Some(invalid) = sdk_receipt.invalid_receipt {
return invalid_inspected_event_view(
invalid,
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
);
}
let Some(receipt) = sdk_receipt.receipt else {
@@ -357,9 +362,9 @@ fn inspection_from_sdk_receipt(
receipt: None,
receipt_tags: None,
event: None,
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code: Some("validation_receipt_not_found".to_owned()),
reason: Some(format!(
"validation receipt event `{receipt_event_id}` was not found on configured Nostr relays"
@@ -372,9 +377,9 @@ fn inspection_from_sdk_receipt(
receipt,
success_state,
intent,
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code,
)
}
@@ -383,9 +388,9 @@ fn inspected_event_view(
sdk_receipt: TradeValidationReceiptEvent,
success_state: &str,
intent: ValidationReceiptCommandIntent,
- target_relays: Vec<String>,
- connected_relays: Vec<String>,
- failed_relays: Vec<RelayFailureView>,
+ target_transport_endpoints: Vec<String>,
+ attempted_transport_endpoints: Vec<String>,
+ failed_transport_targets: Vec<TransportTargetFailureView>,
relay_reason_code: Option<String>,
) -> ValidationReceiptInspectionView {
let event_id = sdk_receipt.event.id.clone();
@@ -414,9 +419,9 @@ fn inspected_event_view(
receipt: Some(sdk_receipt.receipt),
receipt_tags: Some(tags_view(&sdk_receipt.tags)),
event: Some(event_view(sdk_receipt.event)),
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code: proof_verification.reason_code.clone(),
reason: proof_verification.reason.clone(),
sdk_error: None,
@@ -433,9 +438,9 @@ fn inspected_event_view(
receipt: Some(sdk_receipt.receipt),
receipt_tags: Some(tags_view(&sdk_receipt.tags)),
event: Some(event_view(sdk_receipt.event)),
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code: relay_reason_code,
reason: None,
sdk_error: None,
@@ -445,9 +450,9 @@ fn inspected_event_view(
fn invalid_inspected_event_view(
invalid: TradeValidationReceiptInvalidCandidate,
- target_relays: Vec<String>,
- connected_relays: Vec<String>,
- failed_relays: Vec<RelayFailureView>,
+ target_transport_endpoints: Vec<String>,
+ attempted_transport_endpoints: Vec<String>,
+ failed_transport_targets: Vec<TransportTargetFailureView>,
) -> ValidationReceiptInspectionView {
ValidationReceiptInspectionView {
state: "invalid".to_owned(),
@@ -459,9 +464,9 @@ fn invalid_inspected_event_view(
receipt: None,
receipt_tags: None,
event: Some(event_view(invalid.event)),
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code: Some(invalid.reason_code),
reason: Some(invalid.reason),
sdk_error: None,
@@ -472,9 +477,11 @@ fn invalid_inspected_event_view(
fn list_from_sdk_receipt(
sdk_receipt: TradeValidationReceiptListReceipt,
) -> ValidationReceiptListView {
- let target_relays = sdk_receipt.relay_targets;
- let connected_relays = connected_relays(&sdk_receipt.relay_evidence.relays);
- let failed_relays = sdk_relay_failures(&sdk_receipt.relay_evidence.relays);
+ let target_transport_endpoints = sdk_receipt.nostr_relay_urls;
+ let attempted_transport_endpoints =
+ attempted_transport_endpoints(&sdk_receipt.nostr_evidence.nostr_relay_outcomes);
+ let failed_transport_targets =
+ sdk_relay_failures(&sdk_receipt.nostr_evidence.nostr_relay_outcomes);
let mut invalid_receipts = sdk_receipt
.invalid_receipts
.into_iter()
@@ -522,8 +529,8 @@ fn list_from_sdk_receipt(
};
let reason_code = if invalid_count > 0 {
Some("validation_receipt_candidates_invalid".to_owned())
- } else if !failed_relays.is_empty() {
- Some("relay_fetch_partial".to_owned())
+ } else if !failed_transport_targets.is_empty() {
+ Some("nostr_fetch_partial".to_owned())
} else {
None
};
@@ -545,9 +552,9 @@ fn list_from_sdk_receipt(
invalid_count,
receipts,
invalid_receipts,
- target_relays,
- connected_relays,
- failed_relays,
+ target_transport_endpoints,
+ attempted_transport_endpoints,
+ failed_transport_targets,
reason_code,
reason,
sdk_error: None,
@@ -570,9 +577,9 @@ fn inspection_sdk_error_view(
receipt: None,
receipt_tags: None,
event: None,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
reason_code: Some(mapped.reason_code),
reason: Some(mapped.reason),
sdk_error: mapped.sdk_error,
@@ -590,9 +597,9 @@ fn list_sdk_error_view(order_id: &str, error: CliSdkAdapterError) -> ValidationR
invalid_count: 0,
receipts: Vec::new(),
invalid_receipts: Vec::new(),
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
reason_code: Some(mapped.reason_code),
reason: Some(mapped.reason),
sdk_error: mapped.sdk_error,
@@ -623,7 +630,7 @@ fn validation_receipt_sdk_error_parts(error: CliSdkAdapterError) -> ValidationRe
fn sdk_error_parts(error: RadrootsSdkError) -> ValidationReceiptSdkErrorParts {
let state = match error.code() {
- "empty_target_relays" => "unconfigured",
+ "empty_transport_targets" => "unconfigured",
_ => match error.class() {
radroots_sdk::RadrootsSdkErrorClass::Configuration
| radroots_sdk::RadrootsSdkErrorClass::Unsupported => "unconfigured",
@@ -636,7 +643,7 @@ fn sdk_error_parts(error: RadrootsSdkError) -> ValidationReceiptSdkErrorParts {
_ => "network_unavailable",
},
};
- let actions = if error.code() == "empty_target_relays" {
+ let actions = if error.code() == "empty_transport_targets" {
vec![
"radroots transport profile set --kind nostr --nostr-relay wss://relay.example.com"
.to_owned(),
@@ -668,9 +675,9 @@ fn invalid_inspection_view(
receipt: None,
receipt_tags: None,
event: None,
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
reason_code: Some(reason_code.to_owned()),
reason: Some(reason.into()),
sdk_error: None,
@@ -691,9 +698,9 @@ fn invalid_list_view(
invalid_count: 0,
receipts: Vec::new(),
invalid_receipts: Vec::new(),
- target_relays: Vec::new(),
- connected_relays: Vec::new(),
- failed_relays: Vec::new(),
+ target_transport_endpoints: Vec::new(),
+ attempted_transport_endpoints: Vec::new(),
+ failed_transport_targets: Vec::new(),
reason_code: Some(reason_code.to_owned()),
reason: Some(reason.into()),
sdk_error: None,
@@ -1222,22 +1229,30 @@ fn worker_evidence_view(
}
}
-fn connected_relays(relays: &[TradeValidationReceiptRelayOutcomeReceipt]) -> Vec<String> {
+fn attempted_transport_endpoints(
+ relays: &[TradeValidationReceiptNostrRelayOutcomeReceipt],
+) -> Vec<String> {
relays
.iter()
- .filter(|relay| relay.outcome_kind == TradeValidationReceiptRelayOutcomeKind::Eose)
- .map(|relay| relay.relay_url.clone())
+ .filter(|relay| relay.outcome_kind == TradeValidationReceiptNostrRelayOutcomeKind::Eose)
+ .map(|relay| relay.nostr_relay_url.clone())
.collect()
}
fn sdk_relay_failures(
- relays: &[TradeValidationReceiptRelayOutcomeReceipt],
-) -> Vec<RelayFailureView> {
+ relays: &[TradeValidationReceiptNostrRelayOutcomeReceipt],
+) -> Vec<TransportTargetFailureView> {
relays
.iter()
- .filter(|relay| relay.outcome_kind != TradeValidationReceiptRelayOutcomeKind::Eose)
- .map(|relay| RelayFailureView {
- relay: relay.relay_url.clone(),
+ .filter(|relay| relay.outcome_kind != TradeValidationReceiptNostrRelayOutcomeKind::Eose)
+ .map(|relay| TransportTargetFailureView {
+ transport_kind: "nostr".to_owned(),
+ endpoint_uri: relay.nostr_relay_url.clone(),
+ target_scope: None,
+ target_label: None,
+ transport_outcome_kind: relay
+ .transport_outcome_kind
+ .map(sdk_validation_transport_outcome_kind_label),
reason: relay
.message
.clone()
@@ -1246,11 +1261,11 @@ fn sdk_relay_failures(
.collect()
}
-fn sdk_relay_outcome_kind(kind: TradeValidationReceiptRelayOutcomeKind) -> &'static str {
+fn sdk_relay_outcome_kind(kind: TradeValidationReceiptNostrRelayOutcomeKind) -> &'static str {
match kind {
- TradeValidationReceiptRelayOutcomeKind::Eose => "eose",
- TradeValidationReceiptRelayOutcomeKind::Closed => "closed",
- TradeValidationReceiptRelayOutcomeKind::Notice => "notice",
+ TradeValidationReceiptNostrRelayOutcomeKind::Eose => "eose",
+ TradeValidationReceiptNostrRelayOutcomeKind::Closed => "closed",
+ TradeValidationReceiptNostrRelayOutcomeKind::Notice => "notice",
_ => "unknown",
}
}
diff --git a/src/view/runtime.rs b/src/view/runtime.rs
@@ -995,13 +995,13 @@ pub struct FarmPublishComponentView {
pub event_kind: u32,
pub deduplicated: bool,
#[serde(default)]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default)]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default)]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default)]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(skip_serializing_if = "Option::is_none")]
pub job_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -1064,12 +1064,6 @@ pub struct FarmPublishEventView {
}
#[derive(Debug, Clone, Serialize)]
-pub struct RelayFailureView {
- pub relay: String,
- pub reason: String,
-}
-
-#[derive(Debug, Clone, Serialize)]
pub struct FarmConfigSummaryView {
pub scope: String,
pub path: String,
@@ -1771,13 +1765,13 @@ pub struct OrderSubmitView {
#[serde(default)]
pub deduplicated: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(skip_serializing_if = "Option::is_none")]
pub idempotency_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -1879,13 +1873,13 @@ pub struct OrderDecisionView {
#[serde(default)]
pub dry_run: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -1947,13 +1941,13 @@ pub struct OrderCancellationView {
#[serde(default)]
pub dry_run: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -2023,13 +2017,13 @@ pub struct OrderRevisionProposalView {
#[serde(default)]
pub dry_run: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -2100,13 +2094,13 @@ pub struct OrderRevisionDecisionView {
#[serde(default)]
pub dry_run: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -2178,11 +2172,11 @@ pub struct OrderStatusView {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub reducer_issues: Vec<OrderIssueView>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -2364,11 +2358,11 @@ pub struct OrderEventListView {
#[serde(skip_serializing_if = "Option::is_none")]
pub seller_pubkey: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(default)]
pub fetched_count: usize,
#[serde(default)]
@@ -2919,13 +2913,13 @@ pub struct ListingMutationView {
#[serde(default)]
pub deduplicated: bool,
#[serde(default)]
- pub target_relays: Vec<String>,
+ pub target_transport_endpoints: Vec<String>,
#[serde(default)]
- pub connected_relays: Vec<String>,
+ pub attempted_transport_endpoints: Vec<String>,
#[serde(default)]
- pub acknowledged_relays: Vec<String>,
+ pub accepted_transport_endpoints: Vec<String>,
#[serde(default)]
- pub failed_relays: Vec<RelayFailureView>,
+ pub failed_transport_targets: Vec<TransportTargetFailureView>,
#[serde(skip_serializing_if = "Option::is_none")]
pub job_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -3551,6 +3545,10 @@ pub struct SyncTransportTargetView {
pub transport_kind: String,
pub endpoint_uri: String,
pub endpoint_fingerprint: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target_scope: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target_label: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
@@ -3570,6 +3568,12 @@ pub struct SyncTransportStatusView {
pub struct TransportTargetFailureView {
pub transport_kind: String,
pub endpoint_uri: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target_scope: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target_label: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub transport_outcome_kind: Option<String>,
pub reason: String,
}
diff --git a/tests/signer_runtime_modes.rs b/tests/signer_runtime_modes.rs
@@ -1447,7 +1447,7 @@ fn local_farm_publish_reports_sdk_push_failure_without_profile_publish() {
assert_eq!(value["errors"][0]["detail"]["class"], "network");
assert_contains(
&value["errors"][0]["message"],
- "SDK relay publish did not reach accepted quorum",
+ "SDK transport publish did not reach accepted quorum",
);
let detail = &value["errors"][0]["detail"];
assert_eq!(detail["source"], "SDK farm publish · configured signer");
@@ -1465,8 +1465,11 @@ fn local_farm_publish_reports_sdk_push_failure_without_profile_publish() {
assert_eq!(detail["profile"]["idempotency_key"], "farm_partial:profile");
assert_eq!(detail["farm"]["idempotency_key"], "farm_partial:farm");
assert_eq!(detail["actions"][0], "radroots sync push");
- assert_eq!(detail["farm"]["target_relays"][0], relay_url);
- assert_relay_url(&detail["farm"]["failed_relays"][0]["relay"], relay_url);
+ assert_eq!(detail["farm"]["target_transport_endpoints"][0], relay_url);
+ assert_relay_url(
+ &detail["farm"]["failed_transport_targets"][0]["endpoint_uri"],
+ relay_url,
+ );
assert_no_removed_command_reference(&value, &["farm", "publish"]);
assert_no_daemon_runtime_reference(&value, &["farm", "publish"]);
@@ -2167,18 +2170,18 @@ fn local_seller_publish_commands_attempt_configured_relay() {
assert_eq!(farm_value["errors"][0]["detail"]["class"], "network");
assert_contains(
&farm_value["errors"][0]["message"],
- "SDK relay publish did not reach accepted quorum",
+ "SDK transport publish did not reach accepted quorum",
);
assert_eq!(
farm_value["errors"][0]["detail"]["source"],
"SDK farm publish · configured signer"
);
assert_eq!(
- farm_value["errors"][0]["detail"]["farm"]["target_relays"][0],
+ farm_value["errors"][0]["detail"]["farm"]["target_transport_endpoints"][0],
relay
);
assert_eq!(
- farm_value["errors"][0]["detail"]["farm"]["failed_relays"][0]["relay"],
+ farm_value["errors"][0]["detail"]["farm"]["failed_transport_targets"][0]["endpoint_uri"],
relay
);
assert_no_removed_command_reference(&farm_value, &["farm", "publish"]);
@@ -2204,23 +2207,23 @@ fn local_seller_publish_commands_attempt_configured_relay() {
assert_eq!(publish_value["errors"][0]["detail"]["class"], "network");
assert_contains(
&publish_value["errors"][0]["message"],
- "SDK relay publish did not reach accepted quorum",
+ "SDK transport publish did not reach accepted quorum",
);
assert_no_removed_command_reference(&publish_value, &["listing", "publish"]);
assert_no_daemon_runtime_reference(&publish_value, &["listing", "publish"]);
assert_eq!(
- publish_value["errors"][0]["detail"]["target_relays"][0],
+ publish_value["errors"][0]["detail"]["target_transport_endpoints"][0],
relay
);
assert_eq!(
- publish_value["errors"][0]["detail"]["connected_relays"]
+ publish_value["errors"][0]["detail"]["attempted_transport_endpoints"]
.as_array()
.expect("connected relays")
.len(),
1
);
assert_eq!(
- publish_value["errors"][0]["detail"]["failed_relays"]
+ publish_value["errors"][0]["detail"]["failed_transport_targets"]
.as_array()
.expect("failed relays")
.len(),
@@ -2243,23 +2246,23 @@ fn local_seller_publish_commands_attempt_configured_relay() {
assert_eq!(archive_value["errors"][0]["detail"]["class"], "network");
assert_contains(
&archive_value["errors"][0]["message"],
- "SDK relay publish did not reach accepted quorum",
+ "SDK transport publish did not reach accepted quorum",
);
assert_no_removed_command_reference(&archive_value, &["listing", "archive"]);
assert_no_daemon_runtime_reference(&archive_value, &["listing", "archive"]);
assert_eq!(
- archive_value["errors"][0]["detail"]["target_relays"][0],
+ archive_value["errors"][0]["detail"]["target_transport_endpoints"][0],
relay
);
assert_eq!(
- archive_value["errors"][0]["detail"]["connected_relays"]
+ archive_value["errors"][0]["detail"]["attempted_transport_endpoints"]
.as_array()
.expect("connected relays")
.len(),
1
);
assert_eq!(
- archive_value["errors"][0]["detail"]["failed_relays"]
+ archive_value["errors"][0]["detail"]["failed_transport_targets"]
.as_array()
.expect("failed relays")
.len(),
@@ -2324,7 +2327,7 @@ fn local_seller_publish_commands_attempt_configured_relay() {
}
#[test]
-fn local_order_event_list_attempts_configured_shared_relay_transport() {
+fn local_order_event_list_attempts_configured_shared_nostr_transport() {
let sandbox = RadrootsCliSandbox::new();
sandbox.json_success(&["--format", "json", "account", "create"]);
let relay = "ws://127.0.0.1:9";
@@ -2333,25 +2336,28 @@ fn local_order_event_list_attempts_configured_shared_relay_transport() {
let (output, value) = sandbox.json_output(&["--format", "json", "trade", "event", "list"]);
assert!(!output.status.success());
- assert_relay_transport_fetch_failure(&value, "trade.event.list", &["trade", "event", "list"]);
+ assert_transport_fetch_failure(&value, "trade.event.list", &["trade", "event", "list"]);
assert_eq!(value["errors"][0]["detail"]["state"], "unavailable");
- assert_eq!(value["errors"][0]["detail"]["target_relays"][0], relay);
assert_eq!(
- value["errors"][0]["detail"]["connected_relays"]
+ value["errors"][0]["detail"]["target_transport_endpoints"][0],
+ relay
+ );
+ assert_eq!(
+ value["errors"][0]["detail"]["attempted_transport_endpoints"]
.as_array()
.expect("connected relays")
.len(),
0
);
assert_eq!(
- value["errors"][0]["detail"]["failed_relays"]
+ value["errors"][0]["detail"]["failed_transport_targets"]
.as_array()
.expect("failed relays")
.len(),
1
);
assert_contains(
- &value["errors"][0]["detail"]["failed_relays"][0]["relay"],
+ &value["errors"][0]["detail"]["failed_transport_targets"][0]["endpoint_uri"],
"127.0.0.1:9",
);
assert_eq!(value["errors"][0]["detail"]["fetched_count"], 0);
@@ -2662,11 +2668,7 @@ fn configure_myc_mode(sandbox: &RadrootsCliSandbox, executable: &Path) {
));
}
-fn assert_relay_transport_fetch_failure(
- value: &serde_json::Value,
- operation_id: &str,
- args: &[&str],
-) {
+fn assert_transport_fetch_failure(value: &serde_json::Value, operation_id: &str, args: &[&str]) {
assert_eq!(value["operation_id"], operation_id);
assert_eq!(value["result"], serde_json::Value::Null);
assert_eq!(value["errors"][0]["code"], "network_unavailable");
@@ -2674,7 +2676,7 @@ fn assert_relay_transport_fetch_failure(
assert_eq!(value["errors"][0]["detail"]["class"], "network");
assert_contains(
&value["errors"][0]["message"],
- "relay transport fetch failed",
+ "Nostr transport fetch failed",
);
assert_no_removed_command_reference(value, args);
assert_no_daemon_runtime_reference(value, args);
diff --git a/tests/support/mod.rs b/tests/support/mod.rs
@@ -341,9 +341,9 @@ pub fn seed_market_refresh_provenance(sandbox: &RadrootsCliSandbox, relay_urls:
id INTEGER PRIMARY KEY AUTOINCREMENT,
scope TEXT NOT NULL,
relay_set_fingerprint TEXT NOT NULL,
- target_relays_json TEXT NOT NULL,
- connected_relays_json TEXT NOT NULL,
- failed_relays_json TEXT NOT NULL,
+ target_transport_endpoints_json TEXT NOT NULL,
+ attempted_transport_endpoints_json TEXT NOT NULL,
+ failed_transport_targets_json TEXT NOT NULL,
started_at INTEGER NOT NULL,
completed_at INTEGER,
state TEXT NOT NULL,
@@ -368,9 +368,9 @@ pub fn seed_market_refresh_provenance(sandbox: &RadrootsCliSandbox, relay_urls:
"INSERT INTO radroots_cli_sync_run (
scope,
relay_set_fingerprint,
- target_relays_json,
- connected_relays_json,
- failed_relays_json,
+ target_transport_endpoints_json,
+ attempted_transport_endpoints_json,
+ failed_transport_targets_json,
started_at,
completed_at,
state,
diff --git a/tests/target_cli.rs b/tests/target_cli.rs
@@ -3156,7 +3156,7 @@ fn proxy_listing_publish_update_and_archive_dry_run_without_direct_publish_relay
);
assert_eq!(value["result"]["dry_run"], true);
assert_eq!(
- value["result"]["target_relays"]
+ value["result"]["target_transport_endpoints"]
.as_array()
.expect("relays")
.len(),
@@ -3164,7 +3164,7 @@ fn proxy_listing_publish_update_and_archive_dry_run_without_direct_publish_relay
);
assert_contains(
&value["result"]["reason"],
- "SDK enqueue and relay push skipped",
+ "SDK enqueue and transport push skipped",
);
}
}
@@ -3395,7 +3395,10 @@ relay_urls = ["{}"]
value["result"]["source"],
"SDK listing publish · configured signer"
);
- assert_eq!(value["result"]["target_relays"][0], relay_endpoint);
+ assert_eq!(
+ value["result"]["target_transport_endpoints"][0],
+ relay_endpoint
+ );
assert!(report.connection_count >= 1);
assert!(report.req_count >= 1);
assert_eq!(report.sign_request_count, 1);
@@ -3583,7 +3586,7 @@ fn listing_update_publish_attempts_direct_publish_with_approval() {
assert_eq!(value["errors"][0]["detail"]["class"], "network");
assert_contains(
&value["errors"][0]["message"],
- "SDK relay publish did not reach accepted quorum",
+ "SDK transport publish did not reach accepted quorum",
);
assert!(
!value["errors"][0]["message"]
@@ -4117,7 +4120,7 @@ fn quiet_terminal_failure_keeps_reason_and_suppresses_optional_body() {
let stderr = String::from_utf8(output.stderr).expect("utf8 stderr");
assert!(stderr.starts_with("✕ Command failed\n"));
- assert!(stderr.contains("Reason relay-backed trade event watch is not implemented"));
+ assert!(stderr.contains("Reason Nostr-backed trade event watch is not implemented"));
assert!(!stderr.contains("State not implemented"));
assert!(!stderr.contains("Next\n"));
assert!(serde_json::from_str::<Value>(&stderr).is_err());
@@ -4310,7 +4313,7 @@ fn terminal_failure_output_renders_structured_error_detail() {
let stderr = String::from_utf8(output.stderr).expect("utf8 stderr");
assert!(stderr.starts_with("✕ Command failed\n"));
- assert!(stderr.contains("Reason relay-backed trade event watch is not implemented"));
+ assert!(stderr.contains("Reason Nostr-backed trade event watch is not implemented"));
assert!(stderr.contains("State not implemented"));
assert!(stderr.contains("Next\n radroots trade status get ord_missing"));
assert!(serde_json::from_str::<Value>(&stderr).is_err());
@@ -4651,7 +4654,7 @@ fn offline_listing_publish_enqueues_sdk_outbox_without_direct_publish_push() {
publish["result"]["source"],
"SDK listing publish · configured signer"
);
- assert_eq!(publish["result"]["target_relays"][0], relay);
+ assert_eq!(publish["result"]["target_transport_endpoints"][0], relay);
assert_eq!(publish["result"]["actions"][0], "radroots sync push");
assert_eq!(
publish["result"]["event_id"]
@@ -6489,7 +6492,7 @@ fn order_app_records_list_export_get_and_submit_supported_app_order() {
assert_eq!(submit["result"]["state"], "dry_run");
assert_eq!(submit["result"]["source"], "SDK trade submit · local key");
assert_eq!(submit["result"]["event_kind"], 3422);
- assert!(submit["result"]["target_relays"].is_null());
+ assert!(submit["result"]["target_transport_endpoints"].is_null());
assert_eq!(
submit["result"]["event_id"]
.as_str()
@@ -7104,8 +7107,11 @@ fn farm_publish_uses_sdk_outbox_without_legacy_signed_event_records() {
assert_eq!(detail["profile"]["state"], "not_submitted");
assert_eq!(detail["profile"]["event_id"], serde_json::Value::Null);
assert_eq!(detail["farm"]["state"], "unavailable");
- assert_eq!(detail["farm"]["target_relays"][0], relay_url);
- assert_eq!(detail["farm"]["failed_relays"][0]["relay"], relay_url);
+ assert_eq!(detail["farm"]["target_transport_endpoints"][0], relay_url);
+ assert_eq!(
+ detail["farm"]["failed_transport_targets"][0]["endpoint_uri"],
+ relay_url
+ );
assert_eq!(
detail["farm"]["event_id"]
.as_str()
@@ -7173,11 +7179,11 @@ fn listing_publish_failure_uses_sdk_outbox_without_legacy_local_event_record() {
);
assert_eq!(publish["errors"][0]["detail"]["state"], "unavailable");
assert_eq!(
- publish["errors"][0]["detail"]["target_relays"][0],
+ publish["errors"][0]["detail"]["target_transport_endpoints"][0],
relay_url
);
assert_eq!(
- publish["errors"][0]["detail"]["failed_relays"][0]["relay"],
+ publish["errors"][0]["detail"]["failed_transport_targets"][0]["endpoint_uri"],
relay_url
);
assert_eq!(
@@ -8093,7 +8099,7 @@ fn buyer_target_flow_acceptance_uses_target_operations() {
assert_eq!(submit["result"]["source"], "SDK trade submit · local key");
assert_eq!(submit["result"]["event_kind"], 3422);
assert_eq!(
- submit["result"]["target_relays"][0],
+ submit["result"]["target_transport_endpoints"][0],
ORDERABLE_LISTING_RELAY
);
assert_eq!(
@@ -9290,7 +9296,7 @@ fn ready_order_submit_dry_run_validates_local_buyer_authority() {
assert_eq!(dry_run["result"]["source"], "SDK trade submit · local key");
assert_eq!(dry_run["result"]["event_kind"], 3422);
assert_eq!(
- dry_run["result"]["target_relays"][0],
+ dry_run["result"]["target_transport_endpoints"][0],
ORDERABLE_LISTING_RELAY
);
assert_no_daemon_runtime_reference(&dry_run, &["trade", "submit", "--dry-run"]);