Skip to content

feat(order): show and enter BTC-pegged amounts right - #910

Merged
grunch merged 5 commits into
mainfrom
feat/btc-pegged-amounts
Oct 28, 2026
Merged

grunch merged 5 commits into
mainfrom
feat/btc-pegged-amounts

Conversation

@grunch

@grunch grunch commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Linked issue

Refs #907 (items 6–8). The issue closes with the last of its PRs. Merge order: #908 (rates), #909 (conversion), this one, then #911 (catalogue) and #912 (trade copy), which are stacked on it.

Type

feat

What changes and why

For BTC, LBTC and RBTC (protocol "Bitcoin on other networks", mostrod docs/PRICE_PROVIDERS.md §11.9) an order's fiat amount counts sats of the asset: fa = 100000 is 0.001 RBTC. Every screen read it as whole units, so an RBTC order showed as "100,000 RBTC", whichever client published it. This PR makes the amounts right before the codes become pickable (#911).

  • Shown in the asset unit, 8 decimals at most, next to the code: 0.001 RBTC. The "{amount} {code}" strings and their l10n stay as they are.
  • Entered in sats, which is what goes on the wire: the amount field takes whole numbers with a sats unit, the take-order range modal names sats, and the out-of-range message gives the sats bounds.
  • Cleared when the unit changes: switching between a fiat and one of these codes empties the amount fields instead of rereading 12.5 USD as 12 sats.
  • Figures that mean nothing at 1:1: a fixed-sats card shows the premium its two figures imply instead of a price per BTC; the bond's and the node card's fiat equivalents are omitted.

Affected flow

Dart only. lib/shared/utils/btc_pegged.dart (new) and:

  • Order book: the card (order_list_item.dart).
  • Take: the take hero (OrderCardFormats.amount) and the range modal (range_amount_modal.dart).
  • Create: the amount field (amount_section.dart), the preview and the range warning (add_order_screen.dart).
  • Trades: the list and the trade detail (formatFiatAmount in trades_list_rules.dart, which now takes the code).
  • Chat: the list item, the info panels and the trade state header (trade_state_header.dart).
  • Bond: the pay hero and the payout hero (bond_rules.dart).
  • Elsewhere: the invoice screen (invoice_widgets.dart), the bond-slashed notification detail (notification_model.dart) and the node card (node_selector_rules.dart).

Blast radius

  • Fiat: unchanged, except in two places:
    • The chat trade state header now formats like the info panel of the same chat, with the locale's separators (25,50 in es).
    • The trade card's amount is 19 sp instead of 21 in every currency (see Screenshots).
  • Wire, persistence and bindings: nothing changes. The amount on the wire is the same integer; it was already sats for these codes.
  • Notifications: they keep the stored keys; only how the amount is shown changes.
  • Before the catalogue PR: these codes reach the app only from orders other clients publish.

Platforms tested

None by hand (see Manual testing). flutter test on Linux.

Manual testing

Not run. I could not run the app against a Mostro node here.

Setup

App built from this branch and from #911, against a mostrod with the pegged provider quoting RBTC (MostroP2P/mostro#1091).

Steps

  1. As a maker, pick RBTC and type 100000.5. Expected: the field shows 100,000 with sats beside it, and the preview reads "… for 0.001 RBTC".
  2. Switch the currency to USD. Expected: the amount field is empty.
  3. As a taker, open the order in the book. Expected: the card reads 0.001 with the RBTC chip. (fails on main): 100,000.
  4. Regression: create a USD order for 25.5. Expected: as on main.

Not covered

iOS and Android devices; the catalogue entries come with #911.

Screenshots

Visible change: the amounts of these codes, the sats unit in the field, and the implied premium on a fixed card.

The design check reads every class a change touches, so this branch also puts three older values on the scales:

  • the trade card's amount goes from 21 to 19 sp (DS-TYP-4; §3.2 sets 19 for a headline figure in a list);
  • its gap to the code goes from 7 to 8 (DS-SPC-2);
  • the node card's metrics strip padding goes from 11 to 12 (DS-SPC-2).

The Update goldens workflow regenerated the goldens. Screenshots were not captured, because I could not run the app here; they are needed before merge. Design-guide rules touched: DS-TYP-4 and DS-SPC-2, none changed. The figures keep AppFonts.figures.

Automated tests

  • btc_pegged_test: the codes, and the asset-unit format in two locales.
  • trades_list_rules_test: formatFiatAmount for RBTC and an LBTC range.
  • order_card_formats_test: card amounts, and the implied premium.
  • order_item_display_amount_test: displayAmount.
  • amount_section_test:
    • sats are whole with a sats unit;
    • crossing fiat ↔ sats clears the amount;
    • fiat ↔ fiat keeps it;
    • a fiat keeps its decimals.
  • range_amount_modal_test: the modal names sats.
  • bond_rules_test: no fiat equivalent, and the payout hero amount in the asset unit.
  • node_selector_rules_test: no fiat equivalent for these codes.

Whole suite: every new test passes, and the 98 failures are the same files as on a clean main (goldens and release-script tests in this environment).

Checklist

  • cd rust && cargo fmt --check && cargo clippy -- -D warnings && cargo test pass locally: no Rust change.
  • dart format --set-exit-if-changed ., flutter analyze and flutter test pass locally: flutter analyze reports only the existing trades_screen.dart info. My local Flutter (3.47.8) formats differently from CI (3.41.9), so the changed lines keep the repository's style instead of reformatting whole files.
  • Changed rust/src/api/ or an .arb: no
  • New or changed user-facing text: no new strings; the existing satsUnitLabel is reused.
  • Changed an automation identifier: no
  • Protocol or transport change: no; it reads what docs: add bitcoin on other networks as currencies protocol#90 specifies.
  • Behaviour or contract change: no spec under specs/ states how amounts are shown
  • Commits are signed
  • I ran the Manual testing steps myself and can explain every line of this diff: I did not run them (see Manual testing).

AI assistance

Written with Claude Code from #907, with an independent review round (fixes in fix(order): clear the amount when its unit changes) and a design-check round (fix(design): put the classes this branch touches on the scales).

🤖 Generated with Claude Code

https://claude.ai/code/session_016wLvLzCu94YTaE15zLR2Cn

grunch and others added 2 commits October 28, 2026 12:40
For BTC, LBTC and RBTC (mostro docs/PRICE_PROVIDERS.md §11.9, protocol
"Bitcoin on other networks") an order's fiat amount counts sats of the
asset: fa = 100000 is 0.001 RBTC. Every screen read it as whole units,
so an RBTC order showed as "100,000 RBTC".

- btc_pegged.dart: isBtcPeggedCode and formatBtcPeggedAmount (the sats
  in the asset unit, 8 decimals at most).
- Shown in the asset unit next to the code, so "{amount} {code}" stays
  as it was: the order card, the take hero, formatFiatAmount (trade
  card, trade detail, chat list and info panels; it now takes the
  code), OrderItem.displayAmount (trade state header), the invoice
  screen, the bond-slashed notification and the create preview.
- Entered in sats, which is what goes on the wire: the amount field
  takes whole numbers with a "sats" unit for these codes, the take
  range modal names sats instead of the code, and the out-of-range
  message gives the sats bounds.
- Figures that mean nothing at 1:1 are replaced or dropped: a
  fixed-sats card shows the premium its two figures imply instead of a
  price per BTC, and the bond's and the node card's fiat equivalents
  are omitted.

Refs #907 (items 6-8)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wLvLzCu94YTaE15zLR2Cn
Review round on the BTC-pegged amounts:

- Switching the currency between a fiat and a BTC-pegged code changes
  the unit of the typed amount, whole units or sats, and the field kept
  the text: 12.5 USD became 12 sats of RBTC, and 100000 RBTC sats
  became 100,000 USD. AmountSection now clears the amount fields when
  the selected code crosses that boundary, whoever changed it. A switch
  between two fiats keeps the amount, as before.
- formatBondFiat, used by the bond payout hero, printed a BTC-pegged
  claim as "100,000 RBTC"; it now reads the sats in the asset unit.
- The chat's trade state header printed the amount without the locale
  and, for these codes, in 'en' only; it now uses formatFiatAmount, as
  the info panel of the same chat does.

Refs #907 (items 6-8)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wLvLzCu94YTaE15zLR2Cn
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Walkthrough

The change adds BTC-pegged currency detection and asset-unit formatting for BTC, LBTC, and RBTC. It applies these rules to amount entry, order and trade displays, bond calculations, notifications, and node metrics.

Changes

BTC-Pegged Amount Handling

Layer / File(s) Summary
Shared formatting and trade displays
lib/shared/utils/btc_pegged.dart, lib/features/trades/..., lib/features/chat/..., test/shared/utils/*, test/features/trades/...
Adds case-insensitive BTC-pegged code detection and locale-aware sat-to-asset formatting. Trade formatting now receives the currency code, and trade and chat displays use the updated formatter.
Amount entry and order previews
lib/features/order/screens/add_order_screen.dart, lib/features/order/widgets/amount_section.dart, lib/features/order/widgets/range_amount_modal.dart, test/features/order/widgets/*
BTC-pegged inputs use whole sats and show a sats unit. Switching between BTC-pegged and other currency categories clears entered amounts. Previews and range dialogs format BTC-pegged amounts and bounds in the appropriate units.
Home order amounts and premiums
lib/features/home/providers/home_order_providers.dart, lib/features/home/widgets/order_list_item.dart, test/features/home/*
Home order amounts and ranges use asset-unit formatting for BTC-pegged codes. Fixed-sats BTC-pegged orders can display an implied premium when the fiat amount is positive.
Bond, notification, and fiat-equivalent handling
lib/features/order/models/bond_rules.dart, lib/features/order/screens/pay_bond_invoice_screen.dart, lib/features/order/widgets/invoice_widgets.dart, lib/features/notifications/models/notification_model.dart, lib/features/settings/..., related tests
Bond and invoice amounts use BTC-pegged formatting. Bond and node calculations return no fiat equivalent for BTC-pegged codes. Bond-slashed notification details format parseable amounts in asset units.

Priority: Pending latest changes

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Possibly related issues

Possibly related PRs

  • MostroP2P/app#908: It changes BTC-pegged rate parsing, which is related to this change’s BTC-pegged market pricing and order previews.

Suggested reviewers: 21mill, forte11cuba

Merge Risk: Moderate · up to 614f0

Valid LBTC and RBTC market orders can be blocked. Validate BTC-pegged amounts against the node’s sats bounds before merging.

Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit counts the sats with care
BTC-sized numbers fill the air
LBTC and RBTC shine
Locale marks each decimal line
Whole-sat fields now show their place
The bunny hops through every case

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T18:40:42.504789Z f222396 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e682901d8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

grunch and others added 3 commits October 28, 2026 14:55
The design check reads every class a change touches, and the metrics
strip of the node card and the trade card's amount row predate the
scales (CI: DS-SPC-2 ×2, DS-TYP-4 ×1):

- the strip's vertical padding 11 → 12, as its horizontal one;
- the trade card's amount 21 → 19, the size of a headline figure in a
  list (§3.2), and its gap to the code 7 → 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wLvLzCu94YTaE15zLR2Cn
@grunch

grunch commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

@codex review

@grunch

grunch commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@grunch
grunch merged commit aac3518 into main Oct 28, 2026
5 checks passed
@grunch
grunch deleted the feat/btc-pegged-amounts branch October 28, 2026 18:40
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: f222396b1f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant