Skip to content

Improve Fee UX: Bidirectional Fee/Rate Input & Better Rebalance Button#447

Open
Legend101Zz wants to merge 15 commits into
caravan-bitcoin:mainfrom
Legend101Zz:feat/fees-based-change-in-tx
Open

Improve Fee UX: Bidirectional Fee/Rate Input & Better Rebalance Button#447
Legend101Zz wants to merge 15 commits into
caravan-bitcoin:mainfrom
Legend101Zz:feat/fees-based-change-in-tx

Conversation

@Legend101Zz

Copy link
Copy Markdown
Contributor

Problem

Users reported two major UX issues when building transactions:

  1. No way to specify exact fee amounts: Users could only set a fee rate and had to use trial-and-error, repeatedly adjusting the rate (4 → 5 → 4.5 → 4.6 sats/vB) until they achieved the desired total fee. This was frustrating when trying to pay exactly X satoshis in fees.

  2. Unintuitive rebalance button: The output amount rebalance feature used a small gray +/- icon button that users found difficult to discover and unclear in its purpose.

  3. Auto-spend mode limitations: In wallet auto-spend mode, the fee amount field was completely hidden, preventing any fee customization beyond the rate.

Changes Made

Screenshot 2026-01-13 at 20 39 03

Testing

Manual Testing Checklist:

  • Fee Rate → Fee Amount sync

    • Enter fee rate with inputs selected → fee amount updates
    • Enter fee rate without inputs → fee amount stays "0.0000"
    • Change fee rate → fee amount recalculates
  • Fee Amount → Fee Rate sync

    • Enter fee amount with inputs selected → rate updates
    • Enter fee amount without inputs → rate stays same
    • Helper text shows "Effective rate: X sats/vB"
  • Rebalance button

    • Button is visible and prominent (blue, labeled "Rebalance")
    • Shows correct action ("Increase to..." or "Decrease to...")
    • Clicking button adjusts output amount correctly
    • Only appears when balance error exists and is fixable
  • Auto-spend mode

    • Fee amount field is visible
    • Can enter exact fee amount
    • Auto coin selection uses exact fee when specified
    • Error shown if specified fee is too low
    • Effective fee rate updates correctly
  • Edge cases

    • Empty fee amount → graceful handling
    • Zero fee rate → no errors
    • Very large fees → validation works
    • Add/remove outputs → fee recalculates correctly

Test Transactions:

  1. Script Explorer (manual mode)
  2. Wallet spend (auto-spend mode)
  3. Multi-output transactions
  4. Transactions requiring change

Related Issues

Fixes #443


@changeset-bot

changeset-bot Bot commented Jan 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a61f963

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
caravan-coordinator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jan 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
caravan-coordinator Ready Ready Preview, Comment May 24, 2026 6:38pm

Request Review

@Legend101Zz

Copy link
Copy Markdown
Contributor Author

@bucko13 let me know if we want to make the fees field editable in auto mode too , not a big change , just wanted to confirm once :)

@Legend101Zz Legend101Zz requested a review from bucko13 January 13, 2026 15:53
Comment thread apps/coordinator/src/components/ScriptExplorer/OutputsForm.jsx Outdated

@bucko13 bucko13 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

a couple of console.logs to cleanup. will validate functionality as well.

Comment thread apps/coordinator/src/components/ScriptExplorer/OutputsForm.jsx Outdated
@bucko13

bucko13 commented Jan 21, 2026

Copy link
Copy Markdown
Contributor

The UX still feels a little funny to me and I wonder if maybe there are some regressions. First, to be clear, this is just in the manual mode right?

Screenshot 2026-01-21 at 4 34 26 PM

Second, there's some weird state management thing going on. When i clicked back and forth on the manual toggle. I got stuck with this error that inputs must be positive. Toggling the input on and off fixed that.

Screenshot 2026-01-21 at 4 35 38 PM

Lastly the "rebalance" is missing now for the change. Note in the second screenshot below when I add a second output for change the grey + shows up, but I don't see that in the new version for some reason.
Screenshot 2026-01-21 at 4 36 53 PM

Screenshot 2026-01-21 at 4 37 26 PM

Last thought: I wonder if fees should be in sats. The fee rate is of course in sats and I feel like thinking in sats for fees is a little more intuitive. It's certainly easier to type in with the number field.

@Legend101Zz

Copy link
Copy Markdown
Contributor Author

@bucko13 sorry for the huge delay on this , finally I have fixed all the issues and also I decided not have the fees edit field on auto mode as it was getting far to complicated and logic was being fragile and inaccurate to calculate the fees before hand without knowing the inputs , can you check the UI , I am happy to iterate as we are taking time so any new fresh and better UX would be very nice

Screenshot 2026-03-17 at 22 59 19

@Legend101Zz

Copy link
Copy Markdown
Contributor Author

@bucko13 @tomunchained how do these look ?
Screenshot 2026-03-17 at 23 10 48

Screenshot 2026-03-17 at 23 10 30

@bucko13

bucko13 commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

@bucko13

bucko13 commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Ah, i think this is a legitimate e2e failure!

    1 failed
      [mutate-wallet] › e2e/tests/mutate/transaction-flow.spec.ts:84:3 › Transaction Creation and Signing › manual coin selection: create, sign, broadcast 

)
rate = "0";
setFeeRate(rate);
setFeeRate(rate === "" ? "0" : rate); // Reducer handles fee calculation and validation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can also do:

Math.round(num * 100) / 100

@bucko13 bucko13 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

couple small questions/comments. Need to fix e2e as well. I'll test functionally next but the screenshots look good

let feeRateString = action.value;

// Limit to 2 decimal places
if (feeRateString && feeRateString.includes(".")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same

Math.round((num + Number.EPSILON) * 100) / 100

(or similar)

@bucko13

bucko13 commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

UX Feedback:

I don't love that the up arrow increments by a hundredth of a sat/vbyte when doing the up arrow. that's a very small unit of change that I don't think has much value

Screenshot 2026-03-17 at 4 48 10 PM

It looks like the fee rate is not updating with the fee amount

Screenshot 2026-03-17 at 4 51 43 PM Screenshot 2026-03-17 at 4 51 58 PM Screenshot 2026-03-17 at 4 52 09 PM

Got some weird UI juping around when I added a change. There was a

Screenshot 2026-03-17 at 4 53 14 PM

And this was funky too. When i changed the fee amount, rebalance was only available on the recipient output, rather than the change one which is where I would expect it
Screenshot 2026-03-17 at 4 53 38 PM

@Legend101Zz

Copy link
Copy Markdown
Contributor Author

Ah, i think this is a legitimate e2e failure!

    1 failed
      [mutate-wallet] › e2e/tests/mutate/transaction-flow.spec.ts:84:3 › Transaction Creation and Signing › manual coin selection: create, sign, broadcast 

I yes I suspected that as I made changes to the transcation creation flow so would need to make changes to selectors in the Page model in. e2e , glad it's working fine :)

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been inactive for 30 days and has been marked as stale. It will be closed in 7 days if no further activity occurs. To keep this PR open, add the "long-lived" label or comment on it.

@github-actions github-actions Bot added the stale label Apr 21, 2026
Address Buck's review feedback: only show the Rebalance button on the
change output (or on recipients when no change output is set), and use
Math.round((n + Number.EPSILON) * 100) / 100 for fee-rate rounding so
floating-point artifacts don't leak into the input.
Buck noted ↑/↓ on the fee rate input bumping by 0.01 sat/vB has no
practical value. Switch the step to 1 (manual decimal entry still works,
reducer still rounds to 2 places).

Also fix the row jumping when a change output is added: the rebalance
column (xs=2) plus delete column (xs=1) was overflowing past 12, causing
the row to wrap. Address column shrunk to xs=6 and both action slots are
now always rendered (empty when inactive) so columns stay stable. Helper
text under the Rebalance button is clipped with an ellipsis instead of
wrapping to a second line.
Buck reported the fee rate field staying stale while editing the fee
amount. updateFee was guarded by !feeError, so any non-fatal validation
hiccup (intermediate typing, fee-too-high) suppressed the back-calc and
left the rate showing the previous value.

Drop the !feeError guard. As long as inputs are known and feeSats > 0,
recompute the rate from the typed fee. Use the same EPSILON-based
rounding as updateFeeRate so display values stay consistent.
The IconButton wrapping AddCircle was replaced by a labelled Button, so
locating it via the auto-generated AddCircleIcon test id is brittle and
only matches the "Increase" variant. Tag the button with
data-testid="rebalance-button" and have the manual-coin-selection flow
look it up directly.
…c runs

bitcoinsToSatoshis returns a string, not a BigNumber. updateFee was
storing that string in feeSats and then guarding the back-calculation
with BigNumber.isBigNumber(feeSats), which always returned false. The
fee field updated, but feeRate silently stayed at its previous value —
the symptom Buck and the maintainer both saw in the form and Preview
modal.

Wrap the result in new BigNumber(...) so the guards behave like numbers
and the back-calc actually fires.

Add a regression test that mirrors the reported scenario (1 input of
6.25 BTC, two outputs, fee=0.001 BTC) and asserts the rate climbs well
above the previous value of 1 sat/vB.
…nge-in-tx

# Conflicts:
#	apps/coordinator/e2e/tests/03-transaction_flow.spec.ts
@Legend101Zz Legend101Zz force-pushed the feat/fees-based-change-in-tx branch from bf1b0f3 to c2a983a Compare April 27, 2026 18:19
@Legend101Zz

Copy link
Copy Markdown
Contributor Author

UX Feedback:

I don't love that the up arrow increments by a hundredth of a sat/vbyte when doing the up arrow. that's a very small unit of change that I don't think has much value

Screenshot 2026-03-17 at 4 48 10 PM It looks like the fee rate is not updating with the fee amount

Screenshot 2026-03-17 at 4 51 43 PM Screenshot 2026-03-17 at 4 51 58 PM Screenshot 2026-03-17 at 4 52 09 PM
Got some weird UI juping around when I added a change. There was a

Screenshot 2026-03-17 at 4 53 14 PM And this was funky too. When i changed the fee amount, rebalance was only available on the recipient output, rather than the change one which is where I would expect it Screenshot 2026-03-17 at 4 53 38 PM

Thank you for all the testing ... I have resolved all these bugs and flaky behaviour on my end , can you please test it out again :)

@bucko13

bucko13 commented May 19, 2026

Copy link
Copy Markdown
Contributor

Sorry for the delay. I will give this one more review ASAP. could you help cleanup the e2e as well when you get a chance?

@Legend101Zz

Copy link
Copy Markdown
Contributor Author

Sorry for the delay. I will give this one more review ASAP. could you help cleanup the e2e as well when you get a chance?

yes sure let me fix that :)

@bucko13

bucko13 commented May 26, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-05-26 at 11 01 11 AM

Thanks for fixing the tests! Still running into some issues unfortunately. notice that the "Outputs + Fees" section only reflects the total outputs (output + change) but the fee doesn't get included. If this is meant to just reflect total output, then we can rename the field otherwise need to update the calcuation.

Otherwise the feature is working nicely! (Also caravan-x which i used to test :) )
Screenshot 2026-05-26 at 11 03 59 AM

@tomunchained

Copy link
Copy Markdown

When I try to test via vercel "view deployment," I'm seeing no sign of the new feature. I load in a wallet, try to build a withdrawal transaction, and there's only the ability to adjust the fee rate without the absolute fee as shown in the screenshots. I asked another user to try it and he had the same experience. @bucko13 what are we doing wrong?

@bucko13

bucko13 commented May 29, 2026

Copy link
Copy Markdown
Contributor

@tomunchained what do you see in the bottom right hand corner for the version? And the URL? https://caravan-coordinator-denrj7idh-unchained.vercel.app/#/wallet

Screenshot 2026-05-29 at 11 10 44 AM

@jpcummins

Copy link
Copy Markdown
Contributor

Here's what I see:

image

@bucko13

bucko13 commented May 29, 2026

Copy link
Copy Markdown
Contributor

@tomunchained @jpcummins this is only exposed in manual coin selection mode. it's a little unintuitive (I ran into the same confusion in an earlier review) but that's because bitcoin fees are kind of unintuitive. In auto mode, the coin selection happens based on how much you're sending and your target fee rate. You can't know the absolute fee until your coins have been selected. You could probably design a UX where a user puts in a target, the coins are selected and then adjustments are made, but it adds a lot more complexity. and also from a usability point of view, you don't know how much you should even be paying until you know the size of the transaction (which is dependent on the inputs selected).

With manual mode, you know both the inputs and outputs at any given time. This makes setting the fee by rate or absolute number trivial.

Screenshot 2026-05-29 at 11 43 14 AM Screenshot 2026-05-29 at 11 43 25 AM

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

This pull request has been inactive for 30 days and has been marked as stale. It will be closed in 7 days if no further activity occurs. To keep this PR open, add the "long-lived" label or comment on it.

@github-actions github-actions Bot added the stale label Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Alternative way of choosing fees when building transactions

4 participants