commit 46c04272f416f13d5440481fd047d63aa962bcaa
parent cc1fda1d865c8be8e7807340ea9f53a037ea2e03
Author: triesap <tyson@radroots.org>
Date: Tue, 28 Apr 2026 13:56:34 +0000
cli: filter order events by order id
Diffstat:
| M | src/runtime/order.rs | | | 127 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
1 file changed, 119 insertions(+), 8 deletions(-)
diff --git a/src/runtime/order.rs b/src/runtime/order.rs
@@ -614,7 +614,7 @@ pub fn history(
}
};
let seller_pubkey = seller.record.public_identity.public_key_hex;
- let filter = order_request_filter(seller_pubkey.as_str())?;
+ let filter = order_request_filter(seller_pubkey.as_str(), order_id)?;
let receipt = fetch_events_from_relays(&config.relay.urls, filter)
.map_err(|error| RuntimeError::Network(error.to_string()))?;
@@ -702,14 +702,18 @@ fn order_history_from_receipt(
} = receipt;
let fetched_count = events.len();
let mut skipped_count = 0usize;
+ let mut decoded_count = 0usize;
let mut orders = Vec::new();
for event in events {
match order_history_entry_from_event(&event, seller_pubkey.as_str()) {
- Ok(entry) if order_id.is_none_or(|order_id| entry.id == order_id) => {
- orders.push(entry);
+ Ok(entry) => {
+ decoded_count += 1;
+ if order_id.is_none_or(|order_id| entry.id == order_id) {
+ orders.push(entry);
+ }
}
- Ok(_) | Err(_) => skipped_count += 1,
+ Err(_) => skipped_count += 1,
}
}
@@ -720,7 +724,6 @@ fn order_history_from_receipt(
.then_with(|| left.id.cmp(&right.id))
});
- let decoded_count = orders.len();
let reason = if orders.is_empty() {
Some(match order_id {
Some(order_id) => {
@@ -801,12 +804,20 @@ fn order_history_entry_from_event(
})
}
-fn order_request_filter(seller_pubkey: &str) -> Result<RadrootsNostrFilter, RuntimeError> {
+fn order_request_filter(
+ seller_pubkey: &str,
+ order_id: Option<&str>,
+) -> Result<RadrootsNostrFilter, RuntimeError> {
let filter = RadrootsNostrFilter::new()
.kind(radroots_nostr_kind(KIND_TRADE_ORDER_REQUEST as u16))
.limit(1_000);
- radroots_nostr_filter_tag(filter, "p", vec![seller_pubkey.to_owned()])
- .map_err(|error| RuntimeError::Config(format!("build order event filter: {error}")))
+ let filter = radroots_nostr_filter_tag(filter, "p", vec![seller_pubkey.to_owned()])
+ .map_err(|error| RuntimeError::Config(format!("build order event filter: {error}")))?;
+ if let Some(order_id) = order_id {
+ return radroots_nostr_filter_tag(filter, "d", vec![order_id.to_owned()])
+ .map_err(|error| RuntimeError::Config(format!("build order event filter: {error}")));
+ }
+ Ok(filter)
}
fn event_kind_u32(event: &RadrootsNostrEvent) -> u32 {
@@ -1687,7 +1698,9 @@ mod tests {
use super::{
ORDER_DRAFT_KIND, OrderDraft, OrderDraftDocument, OrderDraftItem, collect_issues,
inspect_document, next_order_id, order_history_entry_from_event,
+ order_history_from_receipt, order_request_filter,
};
+ use crate::runtime::direct_relay::DirectRelayFetchReceipt;
#[test]
fn generated_order_id_uses_stable_prefix() {
@@ -1798,4 +1811,102 @@ mod tests {
assert_eq!(entry.seller_pubkey.as_deref(), Some(seller_pubkey.as_str()));
assert_eq!(entry.item_count, Some(1));
}
+
+ #[test]
+ fn order_request_filter_includes_order_id_d_tag_when_provided() {
+ let filter = order_request_filter("a", Some("ord_AAAAAAAAAAAAAAAAAAAAAg"))
+ .expect("order request filter");
+ let value = serde_json::to_value(filter).expect("filter json");
+
+ assert_eq!(value["kinds"][0], 3422);
+ assert_eq!(value["#p"][0], "a");
+ assert_eq!(value["#d"][0], "ord_AAAAAAAAAAAAAAAAAAAAAg");
+ }
+
+ #[test]
+ fn order_history_counts_decoded_before_order_id_narrowing() {
+ let seller = RadrootsIdentity::generate();
+ let other_seller = RadrootsIdentity::generate();
+ let buyer = RadrootsIdentity::generate();
+ let seller_pubkey = seller.public_key_hex();
+ let other_seller_pubkey = other_seller.public_key_hex();
+ let buyer_pubkey = buyer.public_key_hex();
+ let first_order_id = "ord_AAAAAAAAAAAAAAAAAAAAAg";
+ let second_order_id = "ord_AAAAAAAAAAAAAAAAAAAAAw";
+ let first_listing_addr = format!("30402:{seller_pubkey}:AAAAAAAAAAAAAAAAAAAAAg");
+ let second_listing_addr = format!("30402:{seller_pubkey}:AAAAAAAAAAAAAAAAAAAAAw");
+ let other_listing_addr = format!("30402:{other_seller_pubkey}:AAAAAAAAAAAAAAAAAAAAAg");
+ let listing_event_id = "1".repeat(64);
+ let receipt = DirectRelayFetchReceipt {
+ target_relays: vec!["ws://relay.test".to_owned()],
+ connected_relays: vec!["ws://relay.test".to_owned()],
+ failed_relays: Vec::new(),
+ events: vec![
+ signed_order_request_event(
+ &buyer,
+ first_order_id,
+ first_listing_addr.as_str(),
+ buyer_pubkey.as_str(),
+ seller_pubkey.as_str(),
+ listing_event_id.as_str(),
+ ),
+ signed_order_request_event(
+ &buyer,
+ second_order_id,
+ second_listing_addr.as_str(),
+ buyer_pubkey.as_str(),
+ seller_pubkey.as_str(),
+ listing_event_id.as_str(),
+ ),
+ signed_order_request_event(
+ &buyer,
+ "ord_AAAAAAAAAAAAAAAAAAAABA",
+ other_listing_addr.as_str(),
+ buyer_pubkey.as_str(),
+ other_seller_pubkey.as_str(),
+ listing_event_id.as_str(),
+ ),
+ ],
+ };
+
+ let history = order_history_from_receipt(seller_pubkey, Some(first_order_id), receipt);
+
+ assert_eq!(history.fetched_count, 3);
+ assert_eq!(history.decoded_count, 2);
+ assert_eq!(history.skipped_count, 1);
+ assert_eq!(history.count, 1);
+ assert_eq!(history.orders[0].id, first_order_id);
+ }
+
+ fn signed_order_request_event(
+ buyer: &RadrootsIdentity,
+ order_id: &str,
+ listing_addr: &str,
+ buyer_pubkey: &str,
+ seller_pubkey: &str,
+ listing_event_id: &str,
+ ) -> radroots_nostr::prelude::RadrootsNostrEvent {
+ let payload = RadrootsTradeOrderRequested {
+ order_id: order_id.to_owned(),
+ listing_addr: listing_addr.to_owned(),
+ buyer_pubkey: buyer_pubkey.to_owned(),
+ seller_pubkey: seller_pubkey.to_owned(),
+ items: vec![RadrootsTradeOrderItem {
+ bin_id: "bin-1".to_owned(),
+ bin_count: 2,
+ }],
+ };
+ let parts = active_trade_order_request_event_build(
+ &RadrootsNostrEventPtr {
+ id: listing_event_id.to_owned(),
+ relays: None,
+ },
+ &payload,
+ )
+ .expect("order request parts");
+ radroots_nostr_build_event(parts.kind, parts.content, parts.tags)
+ .expect("nostr event builder")
+ .sign_with_keys(buyer.keys())
+ .expect("signed order request")
+ }
}