Skip to content

Commit 38df4a0

Browse files
grunchclaude
andcommitted
fix(transport): make DM-listing/follow-up fetches transport-aware (Codex review)
Addresses the Codex P2 on PR #177: the range-order child-order follow-up fetched after a `release` (send_msg.rs) used `create_filter(DirectMessagesUser, …)`, whose DirectMessages branch hard-coded `Kind::GiftWrap`. On a v2 node the child `NewOrder` is a kind-14 event authored by Mostro, so it was never fetched and `print_commands_results` never ran. Fix: make `create_filter` transport-aware for the `DirectMessages*` kinds — `transport.event_kind()` plus an `author = mostro_pubkey` pin on v2 (new `mostro_pubkey` param threaded through its call sites + the integration test). This also makes the `get-dm` historical listing v2-aware, so the whole interactive path is fully v2 (spec note updated; the item is no longer deferred to Phase 3). cargo build/test/clippy --all-targets --all-features -D warnings/fmt all clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e846fd8 commit 38df4a0

4 files changed

Lines changed: 35 additions & 16 deletions

File tree

docs/TRANSPORT_V2_SPEC.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ Tests: `Transport::from_str` → `event_kind` mapping, and a
121121
`wrap_message_with(Nip44Direct) → unwrap_incoming` roundtrip (kind 14, author =
122122
trade key, message round-trips). Full suite green; clippy + fmt clean.
123123

124-
Known gap (deferred to Phase 3): the `get-dm` **historical listing** filter
125-
(`create_filter` for the `DirectMessages*` kinds) still hard-codes gift wrap,
126-
so listing past Mostro DMs on a v2 node returns nothing. The interactive
127-
request/response path (the one that exercises the daemon's anti-spam gate) is
128-
fully v2.
124+
- **Listing / follow-up fetches:** `create_filter` for the `DirectMessages*`
125+
kinds is transport-aware as well — it uses `transport.event_kind()` and pins
126+
`author = mostro_pubkey` on v2 (new `mostro_pubkey` param). This covers both
127+
the `get-dm` historical listing **and** the range-order child-order follow-up
128+
fetched after a `release` (which a v2 node delivers as a kind-14 event
129+
authored by Mostro), so the whole interactive path is fully v2.
129130

130131
Acceptance: against a `transport = "nip44"` daemon, run the CLI with
131132
`--transport nip44` and a full `new-order → take → add-invoice → fiat-sent →
@@ -141,9 +142,6 @@ gates.
141142
142143
### Phase 3 — Capability auto-detection + docs/UX — PENDING
143144

144-
- Make the `get-dm` historical-listing filter transport-aware
145-
(`create_filter` for the `DirectMessages*` kinds: kind 14 + `author =
146-
mostro_pubkey` on v2), closing the Phase 2 known gap.
147145
- Read the node's `protocol_versions` tag from its kind-`38385` info event
148146
(same fetch path as the existing `pow` probe) and, when `--transport` is not
149147
given, auto-select the matching transport — warning on a mismatch

src/cli/send_msg.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,13 @@ pub async fn execute_send_msg(
120120
// Get the correct keys for decoding the child order message
121121
let next_trade_key = User::get_trade_keys(&ctx.pool, *index as i64).await?;
122122
// Fake timestamp for giftwraps
123+
// Transport-aware so the v2 child-order event (kind 14,
124+
// authored by Mostro) is fetched too, not just gift wraps.
123125
let subscription = create_filter(
124126
ListKind::DirectMessagesUser,
125127
next_trade_key.public_key,
126128
None,
129+
ctx.mostro_pubkey,
127130
)?;
128131

129132
// Wait for potential new order message from Mostro

src/util/events.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub fn create_filter(
4242
list_kind: ListKind,
4343
pubkey: PublicKey,
4444
since: Option<&i64>,
45+
mostro_pubkey: PublicKey,
4546
) -> Result<Filter> {
4647
match list_kind {
4748
ListKind::Orders => create_seven_days_filter(
@@ -58,10 +59,20 @@ pub fn create_filter(
5859
),
5960
ListKind::DirectMessagesAdmin | ListKind::DirectMessagesUser => {
6061
let fake_timestamp = create_fake_timestamp()?;
61-
Ok(Filter::new()
62-
.kind(nostr_sdk::Kind::GiftWrap)
62+
// Mostro→user/admin DMs travel on the node's transport: gift wrap
63+
// (v1, kind 1059) or NIP-44 direct (v2, kind 14). On v2 the reply
64+
// is authored by Mostro's own key, so pin the author to keep it
65+
// distinct from NIP-17 peer chat that shares kind 14
66+
// (docs/TRANSPORT_V2_SPEC.md §2).
67+
let transport = crate::util::messaging::parse_transport_env()?;
68+
let mut filter = Filter::new()
69+
.kind(transport.event_kind())
6370
.pubkey(pubkey)
64-
.since(fake_timestamp))
71+
.since(fake_timestamp);
72+
if transport == Transport::Nip44Direct {
73+
filter = filter.author(mostro_pubkey);
74+
}
75+
Ok(filter)
6576
}
6677
ListKind::PrivateDirectMessagesUser => {
6778
let since = if let Some(mins) = since {
@@ -175,7 +186,7 @@ pub async fn fetch_events_list(
175186
) -> Result<Vec<Event>> {
176187
match list_kind {
177188
ListKind::Orders => {
178-
let filters = create_filter(list_kind, ctx.mostro_pubkey, None)?;
189+
let filters = create_filter(list_kind, ctx.mostro_pubkey, None, ctx.mostro_pubkey)?;
179190
let fetched_events = ctx
180191
.client
181192
.fetch_events(filters, FETCH_EVENTS_TIMEOUT)
@@ -187,7 +198,8 @@ pub async fn fetch_events_list(
187198
// Get admin keys
188199
let admin_keys = get_admin_keys(ctx)?;
189200
// Create filter
190-
let filters = create_filter(list_kind, admin_keys.public_key(), None)?;
201+
let filters =
202+
create_filter(list_kind, admin_keys.public_key(), None, ctx.mostro_pubkey)?;
191203
let fetched_events = ctx
192204
.client
193205
.fetch_events(filters, FETCH_EVENTS_TIMEOUT)
@@ -209,6 +221,7 @@ pub async fn fetch_events_list(
209221
ListKind::PrivateDirectMessagesUser,
210222
trade_key.public_key(),
211223
None,
224+
ctx.mostro_pubkey,
212225
)?;
213226
let fetched_user_messages = ctx
214227
.client
@@ -230,8 +243,12 @@ pub async fn fetch_events_list(
230243
let mut direct_messages: Vec<(Message, u64, PublicKey)> = Vec::new();
231244
for index in 1..=ctx.trade_index {
232245
let trade_key = User::get_trade_keys(&ctx.pool, index).await?;
233-
let filter =
234-
create_filter(ListKind::DirectMessagesUser, trade_key.public_key(), None)?;
246+
let filter = create_filter(
247+
ListKind::DirectMessagesUser,
248+
trade_key.public_key(),
249+
None,
250+
ctx.mostro_pubkey,
251+
)?;
235252
let fetched_user_messages = ctx
236253
.client
237254
.fetch_events(filter, FETCH_EVENTS_TIMEOUT)
@@ -248,7 +265,7 @@ pub async fn fetch_events_list(
248265
.collect())
249266
}
250267
ListKind::Disputes => {
251-
let filters = create_filter(list_kind, ctx.mostro_pubkey, None)?;
268+
let filters = create_filter(list_kind, ctx.mostro_pubkey, None, ctx.mostro_pubkey)?;
252269
let fetched_events = ctx
253270
.client
254271
.fetch_events(filters, FETCH_EVENTS_TIMEOUT)

tests/integration_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ async fn test_filter_creation_integration() {
6464
mostro_client::util::ListKind::Orders,
6565
ctx.mostro_pubkey,
6666
None,
67+
ctx.mostro_pubkey,
6768
)
6869
.unwrap();
6970

0 commit comments

Comments
 (0)