Skip to content

Commit

Permalink
Merge pull request #3031 from dusk-network/feature-3017
Browse files Browse the repository at this point in the history
web-wallet: streamline number types in `Stake` component
  • Loading branch information
ascartabelli authored Nov 21, 2024
2 parents 50af9b7 + fa6ebbb commit 11f76b3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 78 deletions.
126 changes: 62 additions & 64 deletions web-wallet/src/lib/components/Stake/Stake.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
} from "@mdi/js";
import { DOCUMENTATION_LINKS, MESSAGES } from "$lib/constants";
import { areValidGasSettings, deductLuxFeeFrom } from "$lib/contracts";
import { areValidGasSettings } from "$lib/contracts";
import { duskToLux, luxToDusk } from "$lib/dusk/currency";
import { logo } from "$lib/dusk/icons";
Expand Down Expand Up @@ -47,45 +47,47 @@
/** @type {(amount: number) => string} */
export let formatter;
/** @type {GasStoreContent} */
export let gasLimits;
/** @type {ContractGasSettings} */
export let gasSettings;
/** @type {number} */
/** @type {boolean} */
export let hideStakingNotice;
/** @type {bigint} */
export let minAllowedStake;
/** @type {bigint} */
export let rewards;
/** @type {bigint} */
export let spendable;
/** @type {number} */
/** @type {bigint} */
export let staked;
/** @type {ContractStatus[]} */
export let statuses;
/** @type {boolean} */
export let hideStakingNotice;
/** @type {GasStoreContent} */
export let gasLimits;
/** @type {number} */
export let minAllowedStake;
/** @type {number} */
let stakeAmount = {
stake: minAllowedStake,
unstake: staked,
"withdraw-rewards": rewards,
}[flow];
/** @type {HTMLInputElement|null} */
let stakeInput;
/** @type {boolean} */
let activeStep = 0;
let { gasLimit, gasPrice } = gasSettings;
let hideStakingNoticeNextTime = false;
let isGasValid = false;
let { gasLimit, gasPrice } = gasSettings;
/**
* We are forced to keep `stakeAmount`
* as number if we want to use
* Svelte's binding.
*/
let stakeAmount = luxToDusk(
{
stake: minAllowedStake,
unstake: staked,
"withdraw-rewards": rewards,
}[flow]
);
/** @type {Record<StakeType, string>} */
const confirmLabels = {
Expand All @@ -101,6 +103,8 @@
"withdraw-rewards": "Withdraw Rewards",
};
const steps = getStepperSteps();
const dispatch = createEventDispatcher();
const resetOperation = () => dispatch("operationChange", "");
const suppressStakingNotice = () => dispatch("suppressStakingNotice");
Expand All @@ -117,37 +121,6 @@
}
};
onMount(() => {
if (flow === "stake") {
stakeAmount = Math.min(minStake, stakeAmount);
}
isGasValid = areValidGasSettings(gasPrice, gasLimit);
});
$: fee = gasLimit * gasPrice;
$: maxSpendable = deductLuxFeeFrom(luxToDusk(spendable), fee);
$: minStake =
maxSpendable > 0
? Math.min(minAllowedStake, maxSpendable)
: minAllowedStake;
$: isStakeAmountValid =
stakeAmount >= minStake && stakeAmount <= maxSpendable;
$: totalLuxFee = fee + duskToLux(stakeAmount);
$: isFeeWithinLimit = totalLuxFee <= spendable;
$: isNextButtonDisabled =
flow === "stake"
? !(isStakeAmountValid && isGasValid && isFeeWithinLimit)
: false;
function getWizardSteps() {
if (flow === "stake") {
return hideStakingNotice ? 3 : 4;
}
return 2;
}
function getStepperSteps() {
if (flow === "stake") {
return hideStakingNotice
Expand All @@ -163,6 +136,14 @@
return [{ label: "Overview" }, { label: "Done" }];
}
function getWizardSteps() {
if (flow === "stake") {
return hideStakingNotice ? 3 : 4;
}
return 2;
}
function setMaxAmount() {
if (!isGasValid) {
toast("error", "Please set valid gas settings first", mdiAlertOutline);
Expand All @@ -178,15 +159,32 @@
return;
}
if (stakeInput) {
stakeInput.value = maxSpendable.toString();
stakeAmount = luxToDusk(maxSpendable);
}
onMount(() => {
if (flow === "stake") {
stakeAmount = Math.min(luxToDusk(minStake), stakeAmount);
}
stakeAmount = maxSpendable;
}
isGasValid = areValidGasSettings(gasPrice, gasLimit);
});
const steps = getStepperSteps();
let activeStep = 0;
$: fee = gasLimit * gasPrice;
$: maxSpendable = spendable - fee;
$: minStake =
maxSpendable > 0n && minAllowedStake > maxSpendable
? maxSpendable
: minAllowedStake;
$: stakeAmountInLux = duskToLux(stakeAmount);
$: isStakeAmountValid =
stakeAmountInLux >= minStake && stakeAmountInLux <= maxSpendable;
$: totalLuxFee = fee + stakeAmountInLux;
$: isFeeWithinLimit = totalLuxFee <= spendable;
$: isNextButtonDisabled =
flow === "stake"
? !(isStakeAmountValid && isGasValid && isFeeWithinLimit)
: false;
</script>

<div class="operation">
Expand Down Expand Up @@ -281,8 +279,8 @@
className="operation__input-field"
bind:value={stakeAmount}
type="number"
min={minStake}
max={maxSpendable}
min={luxToDusk(minStake)}
max={luxToDusk(maxSpendable)}
required
step="0.000000001"
/>
Expand Down Expand Up @@ -367,7 +365,7 @@
errorMessage="Transaction failed"
onBeforeLeave={resetOperation}
operation={flow === "stake"
? execute(duskToLux(stakeAmount), gasPrice, gasLimit)
? execute(stakeAmountInLux, gasPrice, gasLimit)
: execute(gasPrice, gasLimit)}
pendingMessage="Processing transaction"
successMessage="Transaction created"
Expand Down
22 changes: 11 additions & 11 deletions web-wallet/src/lib/components/__tests__/Stake.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ describe("Stake", () => {
gasPrice: 1n,
},
hideStakingNotice: true,
minAllowedStake: 1234,
rewards: 345,
minAllowedStake: 1_234_000_000_000n,
rewards: 345_000_000_000n,
spendable: 10_000_000_000_000n,
staked: 278,
staked: 278_000_000_000n,
statuses: [
{
label: "Spendable",
Expand Down Expand Up @@ -112,7 +112,7 @@ describe("Stake", () => {

expect(nextButton).toBeEnabled();
expect(amountInput.getAttribute("min")).toBe(
baseProps.minAllowedStake.toString()
luxToDusk(baseProps.minAllowedStake).toString()
);
expect(amountInput.getAttribute("max")).toBe(maxSpendable.toString());
expect(container.firstChild).toMatchSnapshot();
Expand All @@ -138,7 +138,7 @@ describe("Stake", () => {
await fireInput(amountInput, 1000);
expect(nextButton).toBeDisabled();
expect(amountInput.getAttribute("min")).toBe(
baseProps.minAllowedStake.toString()
luxToDusk(baseProps.minAllowedStake).toString()
);
expect(amountInput.getAttribute("max")).toBe(
currentMaxSpendable.toString()
Expand Down Expand Up @@ -167,11 +167,11 @@ describe("Stake", () => {
const useMaxButton = getByRole("button", { name: "USE MAX" });
const amountInput = getByRole("spinbutton");

expect(amountInput).toHaveValue(baseProps.minAllowedStake);
expect(amountInput).toHaveValue(luxToDusk(baseProps.minAllowedStake));

await fireEvent.click(useMaxButton);

expect(amountInput).toHaveValue(baseProps.minAllowedStake);
expect(amountInput).toHaveValue(luxToDusk(baseProps.minAllowedStake));
});

it("should not change the default amount (1) in the textbox if the user clicks the related button and the gas settings are invalid", async () => {
Expand All @@ -188,11 +188,11 @@ describe("Stake", () => {
const useMaxButton = getByRole("button", { name: "USE MAX" });
const amountInput = getByRole("spinbutton");

expect(amountInput).toHaveValue(baseProps.minAllowedStake);
expect(amountInput).toHaveValue(luxToDusk(baseProps.minAllowedStake));

await fireEvent.click(useMaxButton);

expect(amountInput).toHaveValue(baseProps.minAllowedStake);
expect(amountInput).toHaveValue(luxToDusk(baseProps.minAllowedStake));
});

it("should disable the next button if the user enters an invalid amount", async () => {
Expand Down Expand Up @@ -232,7 +232,7 @@ describe("Stake", () => {
const { getByRole, getByText } = render(Stake, baseProps);
const amountInput = getByRole("spinbutton");

expect(amountInput).toHaveValue(baseProps.minAllowedStake);
expect(amountInput).toHaveValue(luxToDusk(baseProps.minAllowedStake));

await fireEvent.click(getByRole("button", { name: "Next" }));
await fireEvent.click(getByRole("button", { name: "Stake" }));
Expand All @@ -241,7 +241,7 @@ describe("Stake", () => {

expect(baseProps.execute).toHaveBeenCalledTimes(1);
expect(baseProps.execute).toHaveBeenCalledWith(
duskToLux(baseProps.minAllowedStake),
baseProps.minAllowedStake,
baseProps.gasSettings.gasPrice,
baseProps.gasSettings.gasLimit
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@
formatter={duskFormatter}
{gasLimits}
{gasSettings}
minAllowedStake={luxToDusk(minimumStake)}
minAllowedStake={minimumStake}
on:operationChange
on:suppressStakingNotice
rewards={luxToDusk(stakeInfo.reward)}
rewards={stakeInfo.reward}
spendable={balance.unshielded.value}
staked={stakeInfo.amount ? luxToDusk(stakeInfo.amount.total) : 0}
staked={stakeInfo.amount ? stakeInfo.amount.total : 0n}
{statuses}
{hideStakingNotice}
/>
Expand Down

0 comments on commit 11f76b3

Please sign in to comment.