Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/famous-forks-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"caravan-coordinator": patch

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.

nit: This should be a minor bump since it's a new feature and does change how rebalance looks.

---

Feat: add func to edit fees in manual mode
4 changes: 2 additions & 2 deletions apps/coordinator/e2e/pages/SendTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ export class SendTab {
}

async addChangeOutput() {
await this.page.getByTestId("AddIcon").click();
await this.page.getByRole("button", { name: "Add output" }).click();
await this.page
.getByLabel("Set to wallet change address")
.getByRole("button")
.click();
await this.page.getByTestId("AddCircleIcon").click();
await this.page.getByTestId("rebalance-button").click();
}

async previewTransaction() {
Expand Down
92 changes: 66 additions & 26 deletions apps/coordinator/src/components/ScriptExplorer/OutputEntry.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
InputAdornment,
FormHelperText,
Typography,
Box,
Button,
} from "@mui/material";
import AccountBalanceWalletOutlinedIcon from "@mui/icons-material/AccountBalanceWallet";
import { Delete, AddCircle, RemoveCircle } from "@mui/icons-material";
Expand Down Expand Up @@ -133,12 +135,14 @@ class OutputEntry extends React.Component {
}
const newAmount = this.autoBalancedAmount();
if (
!BigNumber.isBigNumber(newAmount) ||
newAmount.isNaN() ||
validateOutputAmount(bitcoinsToSatoshis(newAmount), inputsTotalSats) !==
""
""
) {
return true;
}
return amountError === "" && newAmount === new BigNumber(amount);
return amountError === "" && newAmount.isEqualTo(new BigNumber(amount));
};

isBalanceable = () => !this.isNotBalanceable();
Expand All @@ -152,15 +156,17 @@ class OutputEntry extends React.Component {
const { number, fee, inputsTotalSats, outputs } = this.props;
const outputTotalSats = outputs
.filter((output, i) => i !== number - 1)
.map((output) => output.amountSats)
.map((output) => new BigNumber(output.amountSats || 0))
.reduce(
(accumulator, currentValue) => accumulator.plus(currentValue),
new BigNumber(0),
);
const feeSats = bitcoinsToSatoshis(new BigNumber(fee));
return satoshisToBitcoins(
const result = satoshisToBitcoins(
inputsTotalSats.minus(outputTotalSats.plus(feeSats)),
);
// Guarantee we always return a BigNumber so .toFixed() never crashes
return BigNumber.isBigNumber(result) ? result : new BigNumber(result || 0);
};

balanceAction = () => {
Expand Down Expand Up @@ -210,10 +216,18 @@ class OutputEntry extends React.Component {
} = this.props;

const gridSpacing = isWallet ? 10 : 1;
// Only show the rebalance button on the change output when one is set,
// not on recipient outputs.
const isChangeOutput =
changeOutputIndex > 0 && number === changeOutputIndex;
const showRebalance =
this.displayBalanceAction() &&
this.balanceAction() !== null &&
(changeOutputIndex === 0 || isChangeOutput);

return (
<Grid container spacing={gridSpacing}>
<Grid item xs={7}>
<Grid container spacing={gridSpacing} alignItems="flex-start">
<Grid item xs={6}>
<TextField
fullWidth
placeholder="Address"
Expand Down Expand Up @@ -266,35 +280,61 @@ class OutputEntry extends React.Component {
}}
/>
</Grid>
{this.displayBalanceAction() && (
<Grid item xs={1}>
<Tooltip
title={`${this.balanceAction()} to ${this.autoBalancedAmount().toString()}`}
placement="top"
>
<small>
<IconButton onClick={this.handleBalance}>
{this.balanceAction() === "Increase" ? (
<Grid item xs={2} sx={{ minHeight: 64 }}>
{showRebalance && (
<Box>
<Button
data-testid="rebalance-button"

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.

nit: data-testid props aren't great because they will render into an attribute on the html element.

variant="outlined"
color="primary"
size="small"
onClick={this.handleBalance}
startIcon={
this.balanceAction() === "Increase" ? (
<AddCircle />
) : (
<RemoveCircle />
)}
</IconButton>
</small>
</Tooltip>
</Grid>
)}
)
}
sx={{
textTransform: "none",
fontSize: "0.75rem",
whiteSpace: "nowrap",
minWidth: "auto",
}}
>
Rebalance
</Button>
<Typography
variant="caption"
color="textSecondary"
noWrap
sx={{
display: "block",
mt: 0.5,
fontSize: "0.65rem",
overflow: "hidden",
textOverflow: "ellipsis",
}}
title={`${this.balanceAction()} to ${this.autoBalancedAmount().toFixed(8)} BTC`}
>
{this.balanceAction()} to {this.autoBalancedAmount().toFixed(8)}{" "}
BTC
</Typography>
</Box>
)}
</Grid>

{!finalizedOutputs &&
outputs.length > (changeOutputIndex > 0 && autoSpend ? 2 : 1) && (
<Grid item xs={1}>
<Grid item xs={1}>
{!finalizedOutputs &&
outputs.length > (changeOutputIndex > 0 && autoSpend ? 2 : 1) && (
<Tooltip title="Remove Output" placement="top">
<IconButton onClick={this.handleDelete}>
<Delete />
</IconButton>
</Tooltip>
</Grid>
)}
)}
</Grid>
</Grid>
);
}
Expand Down
Loading
Loading