|
| 1 | +# Pay bond invoice |
| 2 | + |
| 3 | +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. |
| 4 | + |
| 5 | +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. |
| 6 | + |
| 7 | +## Direction and trigger |
| 8 | + |
| 9 | +- **Direction:** Mostro → user (the taker). |
| 10 | +- **Trigger:** Sent immediately after a successful `take-buy` / `take-sell` when the operator has bonds enabled. |
| 11 | +- **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. |
| 12 | + |
| 13 | +## Mostro message to the taker |
| 14 | + |
| 15 | +The rumor's content has the same shape as `pay-invoice`; only the action discriminator differs: |
| 16 | + |
| 17 | +```json |
| 18 | +[ |
| 19 | + { |
| 20 | + "order": { |
| 21 | + "version": 1, |
| 22 | + "id": "<Order Id>", |
| 23 | + "action": "pay-bond-invoice", |
| 24 | + "payload": { |
| 25 | + "payment_request": [ |
| 26 | + { |
| 27 | + "id": "<Order Id>", |
| 28 | + "kind": "sell", |
| 29 | + "status": "waiting-taker-bond", |
| 30 | + "amount": 7851, |
| 31 | + "fiat_code": "VES", |
| 32 | + "fiat_amount": 100, |
| 33 | + "payment_method": "face to face", |
| 34 | + "premium": 1, |
| 35 | + "created_at": 1698937797 |
| 36 | + }, |
| 37 | + "lnbcrt780n1pj59wmepp5..." |
| 38 | + ] |
| 39 | + } |
| 40 | + } |
| 41 | + }, |
| 42 | + null |
| 43 | +] |
| 44 | +``` |
| 45 | + |
| 46 | +> 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`. |
| 47 | +
|
| 48 | +## Expected client behaviour |
| 49 | + |
| 50 | +- 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`. |
| 51 | +- Pay it. The HTLC enters `Accepted` state — the sats are locked in the taker's wallet, not captured. |
| 52 | +- 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. |
| 53 | + |
| 54 | +## Follow-up flow |
| 55 | + |
| 56 | +Once the bond HTLC is `Accepted`, Mostro proceeds with the normal trade flow: |
| 57 | + |
| 58 | +- **Sell order taken (taker = buyer):** order status moves to `waiting-buyer-invoice`; the taker next receives `add-invoice` to provide a payout invoice. |
| 59 | +- **Buy order taken (taker = seller):** order status moves to `waiting-payment`; the taker next receives `pay-invoice` for the **trade hold invoice**. |
| 60 | + |
| 61 | +> **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. |
| 62 | +
|
| 63 | +## Daemon status `waiting-taker-bond` (DM payloads only) |
| 64 | + |
| 65 | +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`. |
| 66 | + |
| 67 | +Internal transitions (visible only in DM payload echoes): |
| 68 | + |
| 69 | +- From `pending` → `waiting-taker-bond`, after a successful `take-buy` / `take-sell` when bonds are enabled. |
| 70 | +- From `waiting-taker-bond` → `waiting-payment` (buy order taken) or → `waiting-buyer-invoice` (sell order taken), once the bond HTLC is `Accepted`. |
| 71 | +- 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. |
| 72 | + |
| 73 | +## Failure modes |
| 74 | + |
| 75 | +- 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. |
| 76 | +- The user pays the bond and then cancels before trade completion → the bond HTLC is cancelled and the funds return to the taker. |
| 77 | +- 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. |
| 78 | + |
| 79 | +## Backwards compatibility |
| 80 | + |
| 81 | +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: |
| 82 | + |
| 83 | +- Recognise the action explicitly and surface it to the user. |
| 84 | +- 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. |
| 85 | + |
| 86 | +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). |
0 commit comments