From fa6ebbb3b1d0babe5006ee35d48bc15340521684 Mon Sep 17 00:00:00 2001 From: Andrea Scartabelli Date: Thu, 21 Nov 2024 08:05:41 +0100 Subject: [PATCH] web-wallet: streamline number types in `Stake` component - removed dead code about `stakeInput` Resolves #3017 --- .../src/lib/components/Stake/Stake.svelte | 126 +++++++++--------- .../lib/components/__tests__/Stake.spec.js | 22 +-- .../StakeContract/StakeContract.svelte | 6 +- 3 files changed, 76 insertions(+), 78 deletions(-) diff --git a/web-wallet/src/lib/components/Stake/Stake.svelte b/web-wallet/src/lib/components/Stake/Stake.svelte index 263046d3e..642737ad8 100644 --- a/web-wallet/src/lib/components/Stake/Stake.svelte +++ b/web-wallet/src/lib/components/Stake/Stake.svelte @@ -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"; @@ -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} */ const confirmLabels = { @@ -101,6 +103,8 @@ "withdraw-rewards": "Withdraw Rewards", }; + const steps = getStepperSteps(); + const dispatch = createEventDispatcher(); const resetOperation = () => dispatch("operationChange", ""); const suppressStakingNotice = () => dispatch("suppressStakingNotice"); @@ -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 @@ -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); @@ -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;
@@ -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" /> @@ -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" diff --git a/web-wallet/src/lib/components/__tests__/Stake.spec.js b/web-wallet/src/lib/components/__tests__/Stake.spec.js index d30ea3b77..6acf2a2e1 100644 --- a/web-wallet/src/lib/components/__tests__/Stake.spec.js +++ b/web-wallet/src/lib/components/__tests__/Stake.spec.js @@ -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", @@ -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(); @@ -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() @@ -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 () => { @@ -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 () => { @@ -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" })); @@ -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 ); diff --git a/web-wallet/src/lib/containers/StakeContract/StakeContract.svelte b/web-wallet/src/lib/containers/StakeContract/StakeContract.svelte index 99cbe3d2f..10d2312da 100644 --- a/web-wallet/src/lib/containers/StakeContract/StakeContract.svelte +++ b/web-wallet/src/lib/containers/StakeContract/StakeContract.svelte @@ -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} />