Background
mostrod changed its range-order behavior with MostroP2P/mostro#873 ("fix: never abort release after settle when child-order setup fails").
Before the fix, a Release without a NextTrade payload on a range order with a remainder aborted mid-flow after the escrow settle — a funds-loss bug for the buyer. After the fix, mostrod instead:
- Settles the hold invoice and pays the buyer (correct), and
- Silently ends the range: no child order is created, no
NewOrder message is sent, and the maker is never notified that the range terminated — only a server-side warn log records it.
The same applies on the buy side: a FiatSent without NextTrade from a buyer-maker stores no next_trade_pubkey, so the range ends at release time.
The daemon cannot distinguish "user intentionally ended the range" from "client did not attach NextTrade". The client has all the information: it knows min, max, the taken fiat_amount, whether a remainder exists (max - fiat_amount >= min), and whether it attached a NextTrade payload. The app is therefore the right place to set the user's expectations.
Why this matters for this app specifically
release() and fiat_sent() in rust/src/mostro/actions.rs are built via simple_action(...), which always sends payload: None — there is no NextTrade support yet (see also the known child-order session gap in .specify/v1-reference/SESSION_AND_KEY_MANAGEMENT.md). This means every range-order release from the v2 app currently terminates the range at that slice, with no signal to the user. Until full child-order support lands, a clear notification is the only mitigation.
What the app should do
When the user's release (sell maker) or fiat-sent (buy maker) is the terminal slice of their range — either because:
- no remainder is possible (
max - fiat_amount < min, or the remainder is zero), i.e. the range is naturally consumed; or
- a remainder exists but the message will carry no
NextTrade payload (currently always the case),
…the app should tell the user that this trade completes the range order and the remaining amount will not be relisted. For example:
- a confirmation note in the release / fiat-sent flow ("This is the last order of your range — the range closes after this trade"), and/or
- a post-completion state in "My Trades" marking the range as completed/exhausted, instead of leaving the parent order looking active.
When NextTrade / child-order support is implemented later, the same computation (remainder >= min) decides whether to attach the payload, so the UI logic built here carries over.
References
- Daemon behavior change: MostroP2P/mostro#873
- Payload-less actions:
rust/src/mostro/actions.rs (release, fiat_sent, simple_action)
- Child-order session gap (planned work):
.specify/v1-reference/SESSION_AND_KEY_MANAGEMENT.md — "Child Order Session Management After Release"
Background
mostrod changed its range-order behavior with MostroP2P/mostro#873 ("fix: never abort release after settle when child-order setup fails").
Before the fix, a
Releasewithout aNextTradepayload on a range order with a remainder aborted mid-flow after the escrow settle — a funds-loss bug for the buyer. After the fix, mostrod instead:NewOrdermessage is sent, and the maker is never notified that the range terminated — only a server-sidewarnlog records it.The same applies on the buy side: a
FiatSentwithoutNextTradefrom a buyer-maker stores nonext_trade_pubkey, so the range ends at release time.The daemon cannot distinguish "user intentionally ended the range" from "client did not attach NextTrade". The client has all the information: it knows
min,max, the takenfiat_amount, whether a remainder exists (max - fiat_amount >= min), and whether it attached aNextTradepayload. The app is therefore the right place to set the user's expectations.Why this matters for this app specifically
release()andfiat_sent()inrust/src/mostro/actions.rsare built viasimple_action(...), which always sendspayload: None— there is noNextTradesupport yet (see also the known child-order session gap in.specify/v1-reference/SESSION_AND_KEY_MANAGEMENT.md). This means every range-order release from the v2 app currently terminates the range at that slice, with no signal to the user. Until full child-order support lands, a clear notification is the only mitigation.What the app should do
When the user's
release(sell maker) orfiat-sent(buy maker) is the terminal slice of their range — either because:max - fiat_amount < min, or the remainder is zero), i.e. the range is naturally consumed; orNextTradepayload (currently always the case),…the app should tell the user that this trade completes the range order and the remaining amount will not be relisted. For example:
When
NextTrade/ child-order support is implemented later, the same computation (remainder >= min) decides whether to attach the payload, so the UI logic built here carries over.References
rust/src/mostro/actions.rs(release,fiat_sent,simple_action).specify/v1-reference/SESSION_AND_KEY_MANAGEMENT.md— "Child Order Session Management After Release"