Skip to content

feat: new currency input#2320

Merged
rolznz merged 13 commits into
masterfrom
codex/currency-input-receive
May 27, 2026
Merged

feat: new currency input#2320
rolznz merged 13 commits into
masterfrom
codex/currency-input-receive

Conversation

@stackingsaunter
Copy link
Copy Markdown
Member

@stackingsaunter stackingsaunter commented May 8, 2026

Summary

Part of #2319.

Fixes #2379

Adds a reusable CurrencyInputField composed from the existing shadcn Field and InputGroup primitives, then adopts it in receive flows. The field supports bitcoin/sats display, fiat entry through the configured currency, opposite-currency preview, and context rows.

Scope

  • Add CurrencyInputField
  • Replace amount input in Lightning invoice creation
  • Replace amount input in receive-from-on-chain flow
  • Show Receive limit context from existing balance data

Validation

  • yarn tsc:compile
  • yarn lint before splitting the PR stack

Summary by CodeRabbit

Release Notes

  • New Features

    • Added currency input field with bitcoin/fiat conversion support, enabling seamless amount entry in BTC, sats, or fiat with mode toggling across receive, send, and swap flows.
  • Improvements

    • Refined UI consistency across invoice, on-chain, Lightning, and auto-swap screens with enhanced currency input fields and real-time balance context display.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Warning

Review limit reached

@rolznz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 5 minutes and 31 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a390c3f8-0262-47c7-b239-65511ed27b22

📥 Commits

Reviewing files that changed from the base of the PR and between dc54aba and 086441d.

📒 Files selected for processing (1)
  • frontend/src/components/CurrencyInputField.tsx
📝 Walkthrough

Walkthrough

This PR introduces CurrencyInputField, a new reusable component for satoshi/fiat amount entry with denomination switching, then replaces manual numeric inputs across receive, send, and swap wallet flows with this component, consolidating currency formatting and entry logic.

Changes

Currency Input Component & Wallet Integration

Layer / File(s) Summary
CurrencyInputField component: helpers, logic, and render
frontend/src/components/CurrencyInputField.tsx
New CurrencyInputField component with Intl-based currency formatting, bitcoin denomination handling (sats/BTC), mode toggling (bitcoin/fiat entry), state management, and conversion handlers that route user edits through onValueSatChange while supporting context rows and validation wiring.
Receive flow integration
frontend/src/screens/wallet/receive/ReceiveInvoice.tsx, frontend/src/screens/wallet/receive/ReceiveOnchain.tsx
Replaces numeric amount inputs with CurrencyInputField in invoice and on-chain receive flows, wiring satoshi state, setting receiver-capacity bounds, and conditionally showing receive limits via context rows.
Send flow integration
frontend/src/screens/wallet/send/LnurlPay.tsx, frontend/src/screens/wallet/send/Onchain.tsx, frontend/src/screens/wallet/send/ZeroAmount.tsx
Replaces manual numeric amount inputs with CurrencyInputField across lightning LNURL, on-chain, and zero-amount send flows; each screen configured with spendable balance bounds and contextual balance/limit rows.
Swap flow integration
frontend/src/screens/wallet/swap/AutoSwap.tsx, frontend/src/screens/wallet/swap/index.tsx, frontend/src/components/AnchorReserveAlert.tsx
Replaces numeric swap inputs with CurrencyInputField in auto-swap and main swap screens; simplifies on-chain spendable calculation by removing useChannels dependency; wraps AnchorReserveAlert description in <p> element; adds AnchorReserveAlert to internal swap-in flow with dynamic bounds wiring.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • getAlby/hub#2379: The CurrencyInputField integration across receive flows provides a robust foundation for handling receive capacity logic with proper balance derivation, supporting future fixes to phoenixd backend balance reporting.

Possibly related PRs

  • getAlby/hub#2268: Refactoring of ReceiveOnchain.tsx to replace amount input logic with the new CurrencyInputField component.

Suggested reviewers

  • rolznz
  • reneaaron

Poem

🐰 A field for coins in every mode,
From sats to fiat, back and forth it flowed,
Through swaps and sends and receives so bright,
One component now makes the inputs right! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR introduces a CurrencyInputField component for receive flows but does not implement the core fixes for #2379: neither does phoenixd's GetBalances populate TotalReceivable* fields, nor does the frontend include a fallback to swapInfo.maxAmountSat when totalReceivableSat is 0. Implement the backend fix (phoenixd GetBalances should compute TotalReceivable*) or the frontend fallback (use swapInfo.maxAmountSat when totalReceivableSat is 0) to resolve the core issue described in #2379.
Out of Scope Changes check ⚠️ Warning The PR includes extensive refactoring of send and swap flows with CurrencyInputField beyond the stated objective of 'receive flows', introducing changes to LnurlPay, Onchain send, ZeroAmount, AutoSwap, and swap index screens. Either expand the PR title and objectives to accurately reflect the broader scope (send, swap, and receive flows), or split these changes into a separate PR to maintain focused scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: new currency input' is partially related to the changeset—it refers to the new CurrencyInputField component, which is a real and significant part of the change. However, it is overly broad and does not convey that the primary change is adopting this component across multiple send, receive, and swap flows throughout the codebase. The title captures the component creation but omits the broader scope of the refactoring effort.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/currency-input-receive

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

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

Comment thread frontend/src/screens/wallet/receive/ReceiveOnchain.tsx Outdated
@rolznz
Copy link
Copy Markdown
Member

rolznz commented May 20, 2026

Minor issue: weird highlighting on the input
image

The receive limit has a cursor hover (it does nothing when clicked though) from a UX perspective I'm confused because it looks the same as the amount input.

I tried pasting 0.1 into the input, I think it only supports sats right now, not toggling to BTC. Didn't you plan to add this toggle there?

@rolznz
Copy link
Copy Markdown
Member

rolznz commented May 20, 2026

image

when sats (rather than BIP-177) is selected, there is no unit (I know it complicates things that we support both 🤔 )

@stackingsaunter
Copy link
Copy Markdown
Member Author

image when sats (rather than BIP-177) is selected, there is no unit (I know it complicates things that we support both 🤔 )

This is on purpose as it looked strange with "sats" at the beginning, but we could add it

stackingsaunter and others added 9 commits May 27, 2026 21:37
* feat: use currency input in send flows

* feat: use currency input in swap flows (#2322)

* feat: use currency input in swap flows

* feat: add BTC denomination toggle to currency input (#2367)

* feat: add BTC denomination toggle to currency input

* fix: auto switch decimal bitcoin input to BTC

* chore: address feedback on currency input field (#2371)

* chore: address feedback on currency input field

* feat: make currency input units clickable

* fix: separate currency and unit click targets

* fix: remove persistent unit toggle highlight

* fix: tighten currency input unit spacing

* fix: make alternate bitcoin amount clickable

* fix: align context amount unit spacing

---------

Co-authored-by: saunter <68239231+stackingsaunter@users.noreply.github.com>

---------

Co-authored-by: Roland <33993199+rolznz@users.noreply.github.com>

---------

Co-authored-by: Roland <33993199+rolznz@users.noreply.github.com>

---------

Co-authored-by: Roland <33993199+rolznz@users.noreply.github.com>
Copy link
Copy Markdown
Member

@rolznz rolznz left a comment

Choose a reason for hiding this comment

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

tACK

@rolznz rolznz marked this pull request as ready for review May 27, 2026 15:42
@rolznz
Copy link
Copy Markdown
Member

rolznz commented May 27, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

✅ Actions performed

Full review triggered.

@rolznz rolznz changed the title feat: add currency input to receive flows feat: new currency input May 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/CurrencyInputField.tsx`:
- Around line 381-386: The code currently forces 2 decimal places for fiat
output by using .toFixed(2); change this to derive the decimal precision from
the active fiat currency instead of hardcoding 2: determine the number of
fraction digits (e.g., via a helper like getCurrencyDecimals(selectedCurrency)
or Intl.NumberFormat(selectedCurrency).resolvedOptions().maximumFractionDigits)
and use that value in place of 2 when formatting the converted amount in the
function that returns ((amountSat / SATS_PER_BTC) * rate).toFixed(...), with a
sensible fallback (e.g., 2) if the currency information is unavailable.
- Around line 451-454: In CurrencyInputField.tsx remove the Tailwind !important
modifier from the InputGroupAddon class (the className value on the
InputGroupAddon element) and replace it by composing normal utilities or wrapper
classes — e.g., remove "!mr-0" and use an equivalent combination such as "mr-0"
applied via a parent wrapper or add a specific component-level class (e.g.,
"addon-no-margin") and define the margin rule in the component's
stylesheet/JS-in-CSS so the addon styling is enforced without using !important;
update any tests or snapshots that depend on the previous rendering.

In `@frontend/src/screens/wallet/receive/ReceiveOnchain.tsx`:
- Around line 135-146: The maxSat calculation uses
balances.lightning.totalReceivableSat directly, which when 0 blocks valid
receives; update the logic in the maxSat expression (the ternary handling
swapFrom, hasChannelManagement, swapInfo.maxAmountSat,
balances.lightning.totalReceivableSat) to treat a zero or falsy
totalReceivableSat as "unknown" by falling back to swapInfo.maxAmountSat (for
bitcoin) or undefined (for non-bitcoin) — i.e., compute an effectiveReceivable =
balances.lightning.totalReceivableSat > 0 ?
balances.lightning.totalReceivableSat * 0.99 : undefined and then use
Math.min(swapInfo.maxAmountSat, effectiveReceivable) when appropriate so valid
amounts aren’t blocked; apply the same change to the similar block using the
same identifiers.

In `@frontend/src/screens/wallet/swap/index.tsx`:
- Around line 198-206: The maxSat calculation currently applies the receivable
cap even when balances.lightning.totalReceivableSat is zero, which can force
maxSat to 0; update the logic in the maxSat computation (the expression using
hasChannelManagement, balances.lightning.totalReceivableSat * 0.99,
swapInfo.maxAmountSat, isInternalSwap, and spendableOnchainBalance) to only
include the receivable bound when balances.lightning.totalReceivableSat > 0
(e.g., conditionally push balances.lightning.totalReceivableSat * 0.99 into the
Math.min arguments only if it is positive), and apply the same change to the
analogous block around lines 219-226 so missing/unreported receivable capacity
does not zero out the limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4bba7373-449c-4c1d-9926-280fff58c721

📥 Commits

Reviewing files that changed from the base of the PR and between 9f8da1a and dc54aba.

📒 Files selected for processing (9)
  • frontend/src/components/AnchorReserveAlert.tsx
  • frontend/src/components/CurrencyInputField.tsx
  • frontend/src/screens/wallet/receive/ReceiveInvoice.tsx
  • frontend/src/screens/wallet/receive/ReceiveOnchain.tsx
  • frontend/src/screens/wallet/send/LnurlPay.tsx
  • frontend/src/screens/wallet/send/Onchain.tsx
  • frontend/src/screens/wallet/send/ZeroAmount.tsx
  • frontend/src/screens/wallet/swap/AutoSwap.tsx
  • frontend/src/screens/wallet/swap/index.tsx

Comment thread frontend/src/components/CurrencyInputField.tsx
Comment thread frontend/src/components/CurrencyInputField.tsx
Comment thread frontend/src/screens/wallet/receive/ReceiveOnchain.tsx
Comment thread frontend/src/screens/wallet/swap/index.tsx
@rolznz rolznz merged commit efee2b8 into master May 27, 2026
12 checks passed
@rolznz rolznz deleted the codex/currency-input-receive branch May 27, 2026 16:11
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.

Receive from On-chain max amount is 0 with phoenixd backend (missing TotalReceivable in GetBalances)

2 participants