-
Notifications
You must be signed in to change notification settings - Fork 7
docs: document pay-bond-invoice action and waiting-taker-bond status #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Pay bond invoice | ||
|
|
||
| When the receiving Mostro node has the anti-abuse bond feature enabled, takers must lock a small Lightning hold invoice as a security deposit before the trade flow proceeds. Mostro asks for this payment with the `pay-bond-invoice` action. | ||
|
|
||
| The bond is **independent from the trade escrow**: it is a second hold invoice with its own payment hash, and it is **released on every normal exit path** — completion, cancel before timeout, or dispute resolution where the solver does not direct otherwise. Bonds are typically around **1% of the trade amount** (with an operator-configured floor), much smaller than the trade hold invoice that may follow. | ||
|
|
||
| ## Direction and trigger | ||
|
|
||
| - **Direction:** Mostro → user (the taker). | ||
| - **Trigger:** Sent immediately after a successful `take-buy` / `take-sell` when the operator has bonds enabled. | ||
| - **Order status:** The published NIP-33 order event keeps the `s` tag at `pending` while the bond is outstanding (per NIP-69's four-bucket model — see [Peer-to-peer Order events. NIP-69](./order_event.md)). The DM payload's embedded `SmallOrder` echo carries the daemon-internal status `waiting-taker-bond` so the recipient client can render the bond-payment phase distinctly, but external observers (other potential takers, order-book aggregators) continue to see the order as `pending` and may still attempt to take it. This is deliberate: a taker who never pays the bond cannot park the order off the book. | ||
|
|
||
| ## Mostro message to the taker | ||
|
|
||
| The rumor's content has the same shape as `pay-invoice`; only the action discriminator differs: | ||
|
|
||
| ```json | ||
| [ | ||
| { | ||
| "order": { | ||
| "version": 1, | ||
| "id": "<Order Id>", | ||
| "action": "pay-bond-invoice", | ||
| "payload": { | ||
| "payment_request": [ | ||
| { | ||
| "id": "<Order Id>", | ||
| "kind": "sell", | ||
| "status": "waiting-taker-bond", | ||
| "amount": 7851, | ||
| "fiat_code": "VES", | ||
| "fiat_amount": 100, | ||
| "payment_method": "face to face", | ||
| "premium": 1, | ||
| "created_at": 1698937797 | ||
| }, | ||
| "lnbcrt780n1pj59wmepp5..." | ||
| ] | ||
| } | ||
| } | ||
| }, | ||
| null | ||
| ] | ||
| ``` | ||
|
|
||
| > Note: the `status` value `"waiting-taker-bond"` here is the daemon-internal state echoed in the DM payload. The corresponding NIP-33 addressable order event's `s` tag is still `pending`. | ||
|
|
||
| ## Expected client behaviour | ||
|
|
||
| - Decode the bolt11 and surface it to the user **explicitly as a bond**, not as the trade escrow. Do not reuse the same wording or UI step that you use for `pay-invoice`. | ||
| - Pay it. The HTLC enters `Accepted` state — the sats are locked in the taker's wallet, not captured. | ||
| - Do not collapse this into the same UI step as any subsequent `pay-invoice` on the same order. They are independent HTLCs (different payment hashes), and the user must explicitly approve each. | ||
|
|
||
| ## Follow-up flow | ||
|
|
||
| Once the bond HTLC is `Accepted`, Mostro proceeds with the normal trade flow: | ||
|
|
||
| - **Sell order taken (taker = buyer):** order status moves to `waiting-buyer-invoice`; the taker next receives `add-invoice` to provide a payout invoice. | ||
| - **Buy order taken (taker = seller):** order status moves to `waiting-payment`; the taker next receives `pay-invoice` for the **trade hold invoice**. | ||
|
|
||
| > **Important — buy order taken (seller-as-taker):** this is the only flow on which a single user pays **two hold invoices in sequence on the same order** — first the bond (`pay-bond-invoice`), then the trade escrow (`pay-invoice`). They arrive as distinct actions and must be presented to the user as separate steps. Do not auto-pay either, do not coalesce them, and make the distinction obvious in the UI; this is the most error-prone path for client developers. | ||
|
|
||
| ## Daemon status `waiting-taker-bond` (DM payloads only) | ||
|
|
||
| In addition to the NIP-69 wire status (`pending` while the bond is outstanding), Mostro tags the order's internal state as `waiting-taker-bond` so it can route subsequent messages correctly. Clients see this value in the `SmallOrder` echo embedded in `pay-bond-invoice` payloads and may use it to drive UI ("Waiting for bond payment"). It does **not** appear on the addressable NIP-33 order event — that one continues to advertise the order as `pending`. | ||
|
|
||
| Internal transitions (visible only in DM payload echoes): | ||
|
|
||
| - From `pending` → `waiting-taker-bond`, after a successful `take-buy` / `take-sell` when bonds are enabled. | ||
| - From `waiting-taker-bond` → `waiting-payment` (buy order taken) or → `waiting-buyer-invoice` (sell order taken), once the bond HTLC is `Accepted`. | ||
| - From `waiting-taker-bond` → `pending`, if the bond bolt11 is never paid and expires, or the taker cancels before locking. The published `s` tag was `pending` throughout — observers see only that the take attempt left no trace. | ||
|
|
||
| ## Failure modes | ||
|
|
||
| - The user never pays the bond bolt11 → the invoice expires; the order's NIP-33 status was `pending` throughout, so the rollback only undoes the daemon-internal take state. The order remains takeable. | ||
| - The user pays the bond and then cancels before trade completion → the bond HTLC is cancelled and the funds return to the taker. | ||
| - Slashing conditions (solver-directed dispute resolution, or timeout while in a waiting state) can settle the bond rather than release it. These paths are documented under [Admin Settle order](./admin_settle_order.md) and [Admin Cancel order](./admin_cancel_order.md), and in the Mostro daemon's anti-abuse bond specification. | ||
|
|
||
| ## Backwards compatibility | ||
|
|
||
| Clients running an older `mostro-core` version that does not yet know `pay-bond-invoice` will fail to deserialize the message and silently drop it; from the user's perspective the take stalls and eventually times out without surfacing a useful error. Operators are responsible for not enabling bonds in production until clients in the wild have adopted the `mostro-core` release that ships `Action::PayBondInvoice`. Clients should: | ||
|
|
||
| - Recognise the action explicitly and surface it to the user. | ||
| - If unable to handle it (e.g. an older build talking to a bond-enabled node), present a clear error rather than silently retrying the take. | ||
|
|
||
| The Mostro info event will gain bond-related tags so clients can detect bond-enabled nodes ahead of a take — see [Other events published by Mostro](./other_events.md#mostro-instance-status). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify
waiting-taker-bondas daemon-internal, not public wire status.Line 206 currently reads like
waiting-taker-bondis a regular order status. To avoid client parser mistakes, call it out explicitly as DM-payload/internal state (e.g.,SmallOrder.statusecho), while public NIP-69 stayspending.Suggested wording
📝 Committable suggestion
🤖 Prompt for AI Agents