Summary
Add support for optional buyer-selected payout to Bitcoin onchain using a pluggable swap provider.
This proposal is intentionally scoped to the Lightning -> onchain direction and uses Boltz for the MVP. The design must remain provider-agnostic so we can swap Boltz out later without changing the order flow.
Important: Silent Payments are not in scope for this implementation. They should be considered a future payout format and the design should leave room for them, but this issue only covers Lightning -> onchain via Boltz.
Problem
Today, if a buyer wants to end up with onchain BTC, the flow requires extra manual steps outside Mostro. That adds friction, increases the chance of user error, and makes the user experience less predictable.
We want Mostro to support a payout path where the buyer chooses how they want to receive sats, while keeping the core trade flow clean and non-custodial.
Goals
- Let the buyer choose their payout preference when creating or taking an order.
- Support Lightning -> onchain swaps in the MVP.
- Use Boltz as the first provider.
- Keep the provider interface generic so the provider can be replaced later.
- Make fees paid by the buyer.
- Make min/max limits configurable in
settings.toml.
- If the swap expires, Mostro must ask the buyer for new payout instructions.
Out of scope for this issue
- Silent Payments execution.
- Any provider-specific hardcoding that makes Boltz the only possible implementation.
- Automatic provider fallback / routing across multiple providers.
- Changing the existing core trade semantics beyond what is needed to support the new payout flow.
Future-proofing requirement
The data model and payout abstraction should be designed so that a future proposal can add payout formats such as Silent Payments without rewriting the whole flow.
Proposed implementation phases
To keep the review manageable, this should be split into small phases. The spec must come first.
Phase 0 — Technical spec / design doc
Create a short spec that defines:
- payout methods and their lifecycle
- state machine transitions
- provider interface
- persistence fields
- config keys in
settings.toml
- error / expiry / retry behavior
- what happens when the buyer needs to provide new instructions after expiry
- how the design remains compatible with future payout formats like Silent Payments
Exit criteria: spec reviewed and approved before implementation starts.
Phase 1 — Domain model and config plumbing
Implement the minimal data model changes:
- buyer payout preference on the order/trade model
- swap metadata persistence
- configurable min/max limits and provider selection in
settings.toml
- validation for the selected payout mode
Exit criteria: the system can store and validate payout preferences without executing a swap.
Phase 2 — Provider abstraction
Introduce a provider-agnostic interface for swap operations, for example:
- quote request
- swap creation
- status polling / updates
- expiry handling
- optional cancel / cleanup hooks
Exit criteria: the order flow talks to an interface, not directly to Boltz.
Phase 3 — Boltz MVP adapter
Implement the first concrete provider adapter using Boltz for Lightning -> onchain swaps:
- quote and swap creation
- status tracking
- fee calculation / display
- limits enforcement
- proper verification of returned data
Exit criteria: an end-to-end Boltz swap can be executed in the happy path.
Phase 4 — Order-flow integration and fallback handling
Wire the provider into the Mostro order lifecycle:
- create/take order with payout preference
- buyer pays the swap fee
- handle timeout / expiry
- if the swap expires, request new payout instructions from the buyer
- keep the order state machine consistent
Exit criteria: the trade flow handles success, expiry, and recovery without leaving the order in an inconsistent state.
Phase 5 — Tests, docs, and review cleanup
Add coverage and docs:
- unit tests for the provider abstraction and state machine
- integration tests for the Boltz path
- config examples and operator notes
- user-facing messaging for failure/expiry paths
Exit criteria: reviewable, documented, and regression-covered.
Technical notes
- Keep the provider contract narrow and explicit.
- Avoid Boltz-specific fields leaking into core domain objects.
- Prefer deterministic state transitions and persisted swap metadata.
- Ensure the code path can support a future Silent Payments proposal without redesigning the whole feature.
Open questions for the spec
- Should the buyer choose payout method when creating the order, taking the order, or both?
- Which states should be added to the order lifecycle?
- What exact data do we persist for quotes and swaps?
- How should the UI/API request a new payout instruction after expiry?
- Which parts belong in core Mostro vs provider adapter?
- What is the minimum surface area needed to support future payout formats like Silent Payments?
Summary
Add support for optional buyer-selected payout to Bitcoin onchain using a pluggable swap provider.
This proposal is intentionally scoped to the Lightning -> onchain direction and uses Boltz for the MVP. The design must remain provider-agnostic so we can swap Boltz out later without changing the order flow.
Problem
Today, if a buyer wants to end up with onchain BTC, the flow requires extra manual steps outside Mostro. That adds friction, increases the chance of user error, and makes the user experience less predictable.
We want Mostro to support a payout path where the buyer chooses how they want to receive sats, while keeping the core trade flow clean and non-custodial.
Goals
settings.toml.Out of scope for this issue
Future-proofing requirement
The data model and payout abstraction should be designed so that a future proposal can add payout formats such as Silent Payments without rewriting the whole flow.
Proposed implementation phases
To keep the review manageable, this should be split into small phases. The spec must come first.
Phase 0 — Technical spec / design doc
Create a short spec that defines:
settings.tomlExit criteria: spec reviewed and approved before implementation starts.
Phase 1 — Domain model and config plumbing
Implement the minimal data model changes:
settings.tomlExit criteria: the system can store and validate payout preferences without executing a swap.
Phase 2 — Provider abstraction
Introduce a provider-agnostic interface for swap operations, for example:
Exit criteria: the order flow talks to an interface, not directly to Boltz.
Phase 3 — Boltz MVP adapter
Implement the first concrete provider adapter using Boltz for Lightning -> onchain swaps:
Exit criteria: an end-to-end Boltz swap can be executed in the happy path.
Phase 4 — Order-flow integration and fallback handling
Wire the provider into the Mostro order lifecycle:
Exit criteria: the trade flow handles success, expiry, and recovery without leaving the order in an inconsistent state.
Phase 5 — Tests, docs, and review cleanup
Add coverage and docs:
Exit criteria: reviewable, documented, and regression-covered.
Technical notes
Open questions for the spec