From 813e29f28bc4dc9d442f4be69485f30106309849 Mon Sep 17 00:00:00 2001 From: Kieran Hall Date: Fri, 23 Aug 2024 17:41:17 +0200 Subject: [PATCH] web-wallet: Add allocation page Resolves #2106 --- web-wallet/CHANGELOG.md | 2 + web-wallet/README.md | 2 +- .../src/__mocks__/mockedOperationsStore.js | 5 + .../(app) => }/__mocks__/mockedWalletStore.js | 4 +- .../lib/components/Allocate/Allocate.svelte | 413 ++++++++++++++++++ .../src/lib/components/GasFee/GasFee.svelte | 10 +- .../lib/components/__tests__/GasFee.spec.js | 7 +- .../__snapshots__/GasFee.spec.js.snap | 24 +- .../__snapshots__/GasSettings.spec.js.snap | 48 +- .../__tests__/__snapshots__/Send.spec.js.snap | 48 +- .../__snapshots__/Stake.spec.js.snap | 48 +- web-wallet/src/lib/components/index.js | 1 + .../AllocateContract/AllocateContract.svelte | 31 ++ .../TransferContract/TransferContract.svelte | 9 +- web-wallet/src/lib/containers/index.js | 3 +- .../contracts/__tests__/executeSend.spec.js | 58 +++ .../__tests__/updateOperation.spec.js | 11 + .../src/lib/contracts/contract-descriptors.js | 15 + web-wallet/src/lib/contracts/executeSend.js | 10 + web-wallet/src/lib/contracts/index.js | 2 + .../src/lib/contracts/updateOperation.js | 11 + .../lib/stores/__tests__/walletStore.spec.js | 2 +- web-wallet/src/lib/stores/operationsStore.js | 9 +- web-wallet/src/lib/stores/stores.d.ts | 4 + .../src/routes/(app)/dashboard/+page.svelte | 34 +- .../__tests__/__snapshots__/page.spec.js.snap | 60 +++ .../(app)/dashboard/__tests__/layout.spec.js | 2 +- .../(app)/dashboard/__tests__/page.spec.js | 2 +- .../(app)/dashboard/allocate/+page.svelte | 21 + .../__tests__/__snapshots__/page.spec.js.snap | 291 ++++++++++++ .../dashboard/allocate/__tests__/page.spec.js | 44 ++ .../(app)/dashboard/staking/+page.svelte | 38 +- .../__tests__/__snapshots__/page.spec.js.snap | 93 ++++ .../dashboard/staking/__tests__/page.spec.js | 17 + .../(app)/dashboard/transfer/+page.svelte | 35 +- .../__tests__/__snapshots__/page.spec.js.snap | 161 +++++++ .../dashboard/transfer/__tests__/page.spec.js | 15 + .../(app)/settings/__tests__/page.spec.js | 2 +- .../style/app-components/horizontal-rules.css | 15 + web-wallet/src/style/dusk/language.css | 18 +- web-wallet/src/style/main.css | 4 + web-wallet/vite.config.js | 4 +- 42 files changed, 1512 insertions(+), 121 deletions(-) create mode 100644 web-wallet/src/__mocks__/mockedOperationsStore.js rename web-wallet/src/{routes/(app) => }/__mocks__/mockedWalletStore.js (79%) create mode 100644 web-wallet/src/lib/components/Allocate/Allocate.svelte create mode 100644 web-wallet/src/lib/containers/AllocateContract/AllocateContract.svelte create mode 100644 web-wallet/src/lib/contracts/__tests__/executeSend.spec.js create mode 100644 web-wallet/src/lib/contracts/__tests__/updateOperation.spec.js create mode 100644 web-wallet/src/lib/contracts/executeSend.js create mode 100644 web-wallet/src/lib/contracts/updateOperation.js create mode 100644 web-wallet/src/routes/(app)/dashboard/allocate/+page.svelte create mode 100644 web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap create mode 100644 web-wallet/src/routes/(app)/dashboard/allocate/__tests__/page.spec.js create mode 100644 web-wallet/src/routes/(app)/dashboard/staking/__tests__/__snapshots__/page.spec.js.snap create mode 100644 web-wallet/src/routes/(app)/dashboard/staking/__tests__/page.spec.js create mode 100644 web-wallet/src/routes/(app)/dashboard/transfer/__tests__/__snapshots__/page.spec.js.snap create mode 100644 web-wallet/src/routes/(app)/dashboard/transfer/__tests__/page.spec.js diff --git a/web-wallet/CHANGELOG.md b/web-wallet/CHANGELOG.md index 6481471c8a..d706b92ea4 100644 --- a/web-wallet/CHANGELOG.md +++ b/web-wallet/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added gas settings validation on Unstake / Widthdraw Rewards flows [#2000] +- Added allocation (shield/unshield) page and UI [#2196] ### Changed @@ -18,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update Transactions list design [#1922] - Update Buttons to match the design system [#1606] - Update `Stepper` component to new design [#2071] +- Update dashboard to use routes instead of `Tabs` for navigation pattern [#2075] ### Fixed diff --git a/web-wallet/README.md b/web-wallet/README.md index ec583725a2..fd86c74669 100644 --- a/web-wallet/README.md +++ b/web-wallet/README.md @@ -33,6 +33,7 @@ N.B. the current `0.1.2` version of the library has no option to pick the networ ``` # can be empty string, must start with a slash otherwise, must not end with a slash VITE_BASE_PATH="" +VITE_CONTRACT_ALLOCATE_DISABLED=true VITE_CONTRACT_STAKE_DISABLED=false VITE_CONTRACT_TRANSFER_DISABLED=false VITE_CURRENT_NODE=${VITE_LOCAL_NODE} @@ -51,7 +52,6 @@ VITE_TESTNET_NODE="https://nodes.dusk.network/" VITE_TESTNET_PROVER_NODE="https://provers.dusk.network/" VITE_TRANSFER_CONTRACT="0100000000000000000000000000000000000000000000000000000000000000" VITE_GET_QUOTE_API_ENDPOINT="https://api.dusk.network/v1/quote" -VITE_MOONLIGHT_DISABLED=true ``` To run a local node different steps are needed, so please read the [related section](#running-a-local-rusk-node). diff --git a/web-wallet/src/__mocks__/mockedOperationsStore.js b/web-wallet/src/__mocks__/mockedOperationsStore.js new file mode 100644 index 0000000000..a28d7e379c --- /dev/null +++ b/web-wallet/src/__mocks__/mockedOperationsStore.js @@ -0,0 +1,5 @@ +import { mockReadableStore } from "$lib/dusk/test-helpers"; + +const content = { currentOperation: "something" }; + +export default mockReadableStore(content); diff --git a/web-wallet/src/routes/(app)/__mocks__/mockedWalletStore.js b/web-wallet/src/__mocks__/mockedWalletStore.js similarity index 79% rename from web-wallet/src/routes/(app)/__mocks__/mockedWalletStore.js rename to web-wallet/src/__mocks__/mockedWalletStore.js index 3d2c378327..bd2c41e7bd 100644 --- a/web-wallet/src/routes/(app)/__mocks__/mockedWalletStore.js +++ b/web-wallet/src/__mocks__/mockedWalletStore.js @@ -14,4 +14,6 @@ const content = { isSyncing: false, }; -export default mockReadableStore(content); +const mockedWalletStore = mockReadableStore(content); + +export default mockedWalletStore; diff --git a/web-wallet/src/lib/components/Allocate/Allocate.svelte b/web-wallet/src/lib/components/Allocate/Allocate.svelte new file mode 100644 index 0000000000..e7714c5d07 --- /dev/null +++ b/web-wallet/src/lib/components/Allocate/Allocate.svelte @@ -0,0 +1,413 @@ + + + + +
+ + +
+

+ Edit the value to change the allocation of your Dusk between your + shielded or public account. +

+ +
+
Shielded
+ +
+ + {middleEllipsis( + shieldedAddress, + calculateAdaptiveCharCount(screenWidth, 320, 640, 5, 20) + )} +
+ +
+ { + unshieldedAmount = +( + shieldedBalance + + unshieldedBalance - + shieldedAmount + ).toFixed(9); + }} + /> + +
+ +
+ +
Unshielded
+ +
+ + {middleEllipsis( + unshieldedAddress, + calculateAdaptiveCharCount(screenWidth, 320, 640, 5, 20) + )} +
+ +
+ { + shieldedAmount = +( + unshieldedBalance + + shieldedBalance - + unshieldedAmount + ).toFixed(9); + }} + /> + +
+
+ + { + isGasValid = areValidGasSettings( + event.detail.price, + event.detail.limit + ); + + if (isGasValid) { + gasPrice = event.detail.price; + gasLimit = event.detail.limit; + } + }} + /> +
+
+ +
+ +
+
+ + Amount: +
+
+ + {isFromUnshielded + ? `${formatter(luxToDusk(duskToLux(unshieldedBalance) - duskToLux(unshieldedAmount)))} DUSK` + : `${formatter(luxToDusk(duskToLux(shieldedBalance) - duskToLux(shieldedAmount)))} DUSK`} + + +
+
+
+
+ + From +
+
+ + {isFromUnshielded ? unshieldedAddress : shieldedAddress} + +
+
+
+
+ + To +
+
+ + {isFromShielded ? unshieldedAddress : shieldedAddress} + +
+
+ +
+
+ + + + {#if hash} + + {/if} + + + +
+
+ + diff --git a/web-wallet/src/lib/components/GasFee/GasFee.svelte b/web-wallet/src/lib/components/GasFee/GasFee.svelte index 205cb44020..020b3f8fdf 100644 --- a/web-wallet/src/lib/components/GasFee/GasFee.svelte +++ b/web-wallet/src/lib/components/GasFee/GasFee.svelte @@ -7,9 +7,9 @@
- Max Gas Fee: + Fee:
- {fee} +
max {fee}
span:first-of-type { + font-weight: initial; + } } } diff --git a/web-wallet/src/lib/components/__tests__/GasFee.spec.js b/web-wallet/src/lib/components/__tests__/GasFee.spec.js index 311396e2dd..34b993001c 100644 --- a/web-wallet/src/lib/components/__tests__/GasFee.spec.js +++ b/web-wallet/src/lib/components/__tests__/GasFee.spec.js @@ -21,9 +21,10 @@ describe("GasFee", () => { }; const { container } = render(GasFee, baseProps); - expect(container.querySelector(".gas-fee__amount-value")?.innerHTML).toBe( - fee - ); + expect( + container.querySelector(".gas-fee__amount-value span:nth-child(2)") + ?.innerHTML + ).toBe(fee); expect(container.firstChild).toMatchSnapshot(); }); diff --git a/web-wallet/src/lib/components/__tests__/__snapshots__/GasFee.spec.js.snap b/web-wallet/src/lib/components/__tests__/__snapshots__/GasFee.spec.js.snap index 3e98c31e82..6f8d22f8ed 100644 --- a/web-wallet/src/lib/components/__tests__/__snapshots__/GasFee.spec.js.snap +++ b/web-wallet/src/lib/components/__tests__/__snapshots__/GasFee.spec.js.snap @@ -2,20 +2,30 @@ exports[`GasFee > renders the GasFee component 1`] = `
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
renders the GasSettings component closed 1`] = ` class="gas-settings__edit svelte-1daay07" >
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
renders the GasSettings component opened 1`] = ` class="gas-settings__edit svelte-1daay07" >
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
Amount step > should render the Send component Amount step 1`] = class="gas-settings__edit svelte-1daay07" >
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
Review step > should render the Send component Review step 1`] =
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
should render the Stake component 1`] = ` class="gas-settings__edit svelte-1daay07" >
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
should render the review step of the Stake component 1`] = `
- Max Gas Fee: + Fee:
- - 0.020000000 - + + max + + + + 0.020000000 + +
+ + + + diff --git a/web-wallet/src/lib/containers/TransferContract/TransferContract.svelte b/web-wallet/src/lib/containers/TransferContract/TransferContract.svelte index 2458419151..496fb0001a 100644 --- a/web-wallet/src/lib/containers/TransferContract/TransferContract.svelte +++ b/web-wallet/src/lib/containers/TransferContract/TransferContract.svelte @@ -11,9 +11,8 @@ setKey, when, } from "lamb"; - + import { executeSend } from "$lib/contracts"; import { createCurrencyFormatter } from "$lib/dusk/currency"; - import { getLastTransactionHash } from "$lib/transactions"; import { gasStore, operationsStore, @@ -30,12 +29,6 @@ /** @type {ContractDescriptor} */ export let descriptor; - /** @type {(to: string, amount: number, gasPrice:number, gasLimit:number) => Promise} */ - const executeSend = (to, amount, gasPrice, gasLimit) => - walletStore - .transfer(to, amount, gasPrice, gasLimit) - .then(getLastTransactionHash); - const collectSettings = collect([ pick(["gasLimit", "gasPrice"]), getKey("language"), diff --git a/web-wallet/src/lib/containers/index.js b/web-wallet/src/lib/containers/index.js index 2387cdbe37..0c1394e722 100644 --- a/web-wallet/src/lib/containers/index.js +++ b/web-wallet/src/lib/containers/index.js @@ -1,3 +1,4 @@ +export { default as AllocateContract } from "./AllocateContract/AllocateContract.svelte"; +export { default as MigrateContract } from "./MigrateContract/MigrateContract.svelte"; export { default as StakeContract } from "./StakeContract/StakeContract.svelte"; export { default as TransferContract } from "./TransferContract/TransferContract.svelte"; -export { default as MigrateContract } from "./MigrateContract/MigrateContract.svelte"; diff --git a/web-wallet/src/lib/contracts/__tests__/executeSend.spec.js b/web-wallet/src/lib/contracts/__tests__/executeSend.spec.js new file mode 100644 index 0000000000..f6588c1f6b --- /dev/null +++ b/web-wallet/src/lib/contracts/__tests__/executeSend.spec.js @@ -0,0 +1,58 @@ +import { afterAll, afterEach, describe, expect, it, vi } from "vitest"; +import { walletStore } from "$lib/stores"; +import { getLastTransactionHash } from "$lib/transactions"; +import { executeSend } from ".."; + +vi.mock("$lib/stores", async (importOriginal) => { + /** @type {typeof import("$lib/stores")} */ + const original = await importOriginal(); + + return { + ...original, + walletStore: { + ...original.walletStore, + transfer: vi.fn().mockResolvedValue(undefined), + }, + }; +}); + +vi.mock("$lib/transactions", async (importOriginal) => { + /** @type {typeof import("$lib/transactions")} */ + const original = await importOriginal(); + + return { + ...original, + getLastTransactionHash: vi.fn(() => ""), + }; +}); + +afterEach(() => { + vi.mocked(walletStore.transfer).mockClear(); + vi.mocked(getLastTransactionHash).mockClear(); +}); + +afterAll(() => { + vi.doUnmock("$lib/stores/walletStore"); + vi.doUnmock("$lib/transactions"); +}); + +describe("executeSend", () => { + it("should call the walletStore transfer method", async () => { + const args = ["abc", 1000, 1, 2]; + // @ts-ignore + await executeSend(...args); + + expect(walletStore.transfer).toHaveBeenCalledTimes(1); + expect(walletStore.transfer).toHaveBeenCalledWith(...args); + expect(getLastTransactionHash).toHaveBeenCalledTimes(1); + }); + + it("should not call the getLastTransactionHash function when an error is emitted from the transfer function", async () => { + const err = new Error("some error"); + + vi.mocked(walletStore.transfer).mockRejectedValueOnce(err); + + await expect(executeSend("abc", 1000, 1, 2)).rejects.toBe(err); + expect(getLastTransactionHash).not.toHaveBeenCalled(); + }); +}); diff --git a/web-wallet/src/lib/contracts/__tests__/updateOperation.spec.js b/web-wallet/src/lib/contracts/__tests__/updateOperation.spec.js new file mode 100644 index 0000000000..cf461c3eb3 --- /dev/null +++ b/web-wallet/src/lib/contracts/__tests__/updateOperation.spec.js @@ -0,0 +1,11 @@ +import { describe, expect, it } from "vitest"; +import { updateOperation } from ".."; +import { get } from "svelte/store"; +import { operationsStore } from "$lib/stores"; + +describe("updateOperation", () => { + it("should set the current operation in the operationStore", () => { + updateOperation("some operation"); + expect(get(operationsStore).currentOperation).toBe("some operation"); + }); +}); diff --git a/web-wallet/src/lib/contracts/contract-descriptors.js b/web-wallet/src/lib/contracts/contract-descriptors.js index 50afc04304..49d4f75f96 100644 --- a/web-wallet/src/lib/contracts/contract-descriptors.js +++ b/web-wallet/src/lib/contracts/contract-descriptors.js @@ -54,4 +54,19 @@ export default [ }, ], }, + { + disabled: + import.meta.env.VITE_CONTRACT_ALLOCATE_DISABLED && + import.meta.env.VITE_CONTRACT_ALLOCATE_DISABLED === "true", + id: "allocate", + label: "Shield / Unshield", + operations: [ + { + disabled: false, + id: "send", + label: "send", + primary: true, + }, + ], + }, ]; diff --git a/web-wallet/src/lib/contracts/executeSend.js b/web-wallet/src/lib/contracts/executeSend.js new file mode 100644 index 0000000000..6bc3e4cc63 --- /dev/null +++ b/web-wallet/src/lib/contracts/executeSend.js @@ -0,0 +1,10 @@ +import { getLastTransactionHash } from "$lib/transactions"; +import { walletStore } from "$lib/stores"; + +/** @type {(to: string, amount: number, gasPrice:number, gasLimit:number) => Promise} */ +const executeSend = (to, amount, gasPrice, gasLimit) => + walletStore + .transfer(to, amount, gasPrice, gasLimit) + .then(getLastTransactionHash); + +export default executeSend; diff --git a/web-wallet/src/lib/contracts/index.js b/web-wallet/src/lib/contracts/index.js index e71743ccff..bb1d1ea387 100644 --- a/web-wallet/src/lib/contracts/index.js +++ b/web-wallet/src/lib/contracts/index.js @@ -1,3 +1,5 @@ export { default as contractDescriptors } from "./contract-descriptors"; export { default as deductLuxFeeFrom } from "./deductLuxFeeFrom"; +export { default as executeSend } from "./executeSend"; export { default as areValidGasSettings } from "./areValidGasSettings"; +export { default as updateOperation } from "./updateOperation"; diff --git a/web-wallet/src/lib/contracts/updateOperation.js b/web-wallet/src/lib/contracts/updateOperation.js new file mode 100644 index 0000000000..a3ebdfe992 --- /dev/null +++ b/web-wallet/src/lib/contracts/updateOperation.js @@ -0,0 +1,11 @@ +import { operationsStore } from "$lib/stores"; + +/** @param {string} id */ +function updateOperation(id) { + operationsStore.update((store) => ({ + ...store, + currentOperation: id, + })); +} + +export default updateOperation; diff --git a/web-wallet/src/lib/stores/__tests__/walletStore.spec.js b/web-wallet/src/lib/stores/__tests__/walletStore.spec.js index 2381c601ad..467f28910c 100644 --- a/web-wallet/src/lib/stores/__tests__/walletStore.spec.js +++ b/web-wallet/src/lib/stores/__tests__/walletStore.spec.js @@ -500,7 +500,7 @@ describe("walletStore", async () => { walletStore.reset(); }); - it("should return a rejected promise with the operation error if an operation fails and try a sync afterwards nonetheless", async () => { + it("should return a rejected promise with the operation error if an operation fails and try a sync afterwards", async () => { await walletStore.init(wallet); await vi.advanceTimersToNextTimerAsync(); diff --git a/web-wallet/src/lib/stores/operationsStore.js b/web-wallet/src/lib/stores/operationsStore.js index b0fa02b8ce..b6c5615f5b 100644 --- a/web-wallet/src/lib/stores/operationsStore.js +++ b/web-wallet/src/lib/stores/operationsStore.js @@ -1,6 +1,9 @@ import { writable } from "svelte/store"; -/** @type {import("svelte/store").Writable<{ currentOperation: string }>} */ -const count = writable({ currentOperation: "" }); +/** @type OperationsStoreContent */ +const initialState = { currentOperation: "" }; -export default count; +/** @type OperationsStore */ +const store = writable(initialState); + +export default store; diff --git a/web-wallet/src/lib/stores/stores.d.ts b/web-wallet/src/lib/stores/stores.d.ts index 6a9d10678b..4f9abe431b 100644 --- a/web-wallet/src/lib/stores/stores.d.ts +++ b/web-wallet/src/lib/stores/stores.d.ts @@ -31,6 +31,10 @@ type TransactionsStoreContent = { transactions: Transaction[] }; type TransactionsStore = Readable; +type OperationsStoreContent = { currentOperation: string }; + +type OperationsStore = Writable; + type WalletStoreContent = { balance: { maximum: number; diff --git a/web-wallet/src/routes/(app)/dashboard/+page.svelte b/web-wallet/src/routes/(app)/dashboard/+page.svelte index 440bca589a..e7dc871644 100644 --- a/web-wallet/src/routes/(app)/dashboard/+page.svelte +++ b/web-wallet/src/routes/(app)/dashboard/+page.svelte @@ -2,7 +2,12 @@ + +{#if !!import.meta.env.VITE_CONTRACT_ALLOCATE_DISABLED} + + updateOperation(detail)} + /> + +{/if} diff --git a/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap new file mode 100644 index 0000000000..12335431b5 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap @@ -0,0 +1,291 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Allocate > should render the allocation page 1`] = ` +
+
+
+
+ + + + + +

+ Shield / Unshield +

+
+
+
+ +
+
+
+ + +
+

+ Edit the value to change the allocation of your Dusk between your + shielded or public account. +

+ +
+
+ Shielded +
+ +
+ + + + + + +
+ +
+ + + + + + + +
+ +
+ +
+ Unshielded +
+ +
+ + + + + + +
+ +
+ + + + + + + +
+
+ +
+
+
+ + Fee: + + +
+
+ + max + + + + 0.020000000 + +
+ + + + + +
+
+
+ +
+
+ +
+
+ +
+ + + + + + + + Back + + + + + + + +
+ + + + + + +
+
+
+ +
+`; diff --git a/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/page.spec.js b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/page.spec.js new file mode 100644 index 0000000000..b78431b634 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/page.spec.js @@ -0,0 +1,44 @@ +import { afterAll, afterEach, describe, expect, it, vi } from "vitest"; +import { get } from "svelte/store"; +import { cleanup, render } from "@testing-library/svelte"; +import { operationsStore } from "$lib/stores"; +import Allocation from "../+page.svelte"; + +vi.mock("$lib/stores", async (importOriginal) => { + /** @type {typeof import("$lib/stores")} */ + const original = await importOriginal(); + + return { + ...original, + operationsStore: { + ...original.operationsStore, + }, + }; +}); + +vi.useFakeTimers(); + +describe("Allocate", () => { + afterEach(cleanup); + afterAll(() => { + vi.doUnmock("$lib/stores"); + }); + + it("should render the allocation page", async () => { + const { container } = render(Allocation); + + await vi.advanceTimersToNextTimerAsync(); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it("should set the current operation to an empty string when destroyed", async () => { + const { component } = render(Allocation); + + component.$destroy(); + + expect(get(operationsStore)).toStrictEqual({ + currentOperation: "", + }); + }); +}); diff --git a/web-wallet/src/routes/(app)/dashboard/staking/+page.svelte b/web-wallet/src/routes/(app)/dashboard/staking/+page.svelte index fec550b8b0..49d20d3081 100644 --- a/web-wallet/src/routes/(app)/dashboard/staking/+page.svelte +++ b/web-wallet/src/routes/(app)/dashboard/staking/+page.svelte @@ -5,16 +5,8 @@ import { mdiDatabaseOutline } from "@mdi/js"; import { StakeContract } from "$lib/containers"; import { IconHeadingCard } from "$lib/containers/Cards"; - import { contractDescriptors } from "$lib/contracts"; - import { operationsStore, settingsStore } from "$lib/stores"; - - /** @param {string} id */ - function updateOperation(id) { - operationsStore.update((store) => ({ - ...store, - currentOperation: id, - })); - } + import { contractDescriptors, updateOperation } from "$lib/contracts"; + import { settingsStore } from "$lib/stores"; /** * @param {keyof SettingsStoreContent} property @@ -32,15 +24,17 @@ }); - - updateOperation(detail)} - on:suppressStakingNotice={() => updateSetting("hideStakingNotice", true)} - /> - +{#if !!import.meta.env.VITE_CONTRACT_STAKE_DISABLED} + + updateOperation(detail)} + on:suppressStakingNotice={() => updateSetting("hideStakingNotice", true)} + /> + +{/if} diff --git a/web-wallet/src/routes/(app)/dashboard/staking/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(app)/dashboard/staking/__tests__/__snapshots__/page.spec.js.snap new file mode 100644 index 0000000000..e3b506e309 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/staking/__tests__/__snapshots__/page.spec.js.snap @@ -0,0 +1,93 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Staking > should render the staking page 1`] = ` +
+
+
+
+ + + + + +

+ Staking +

+
+
+
+ +
+
+
+ + Failed to retrieve stake info + + +
+          			
+          No wallet instance to sync
+          
+		
+        
+
+ + + + + + + + + + + Back + + + + +
+ +
+ +
+`; diff --git a/web-wallet/src/routes/(app)/dashboard/staking/__tests__/page.spec.js b/web-wallet/src/routes/(app)/dashboard/staking/__tests__/page.spec.js new file mode 100644 index 0000000000..1d09dd3bb8 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/staking/__tests__/page.spec.js @@ -0,0 +1,17 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { cleanup, render } from "@testing-library/svelte"; +import Staking from "../+page.svelte"; + +vi.useFakeTimers(); + +describe("Staking", () => { + afterEach(cleanup); + + it("should render the staking page", async () => { + const { container } = render(Staking); + + await vi.advanceTimersToNextTimerAsync(); // Wait until the stakeInfo promise has resolved + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/web-wallet/src/routes/(app)/dashboard/transfer/+page.svelte b/web-wallet/src/routes/(app)/dashboard/transfer/+page.svelte index 72a175d315..294176a919 100644 --- a/web-wallet/src/routes/(app)/dashboard/transfer/+page.svelte +++ b/web-wallet/src/routes/(app)/dashboard/transfer/+page.svelte @@ -4,31 +4,24 @@ import { onDestroy } from "svelte"; import { TransferContract } from "$lib/containers"; import { IconHeadingCard } from "$lib/containers/Cards"; - import { contractDescriptors } from "$lib/contracts"; - import { operationsStore } from "$lib/stores"; + import { contractDescriptors, updateOperation } from "$lib/contracts"; import { mdiSwapVertical } from "@mdi/js"; - /** @param {string} id */ - function updateOperation(id) { - operationsStore.update((store) => ({ - ...store, - currentOperation: id, - })); - } - onDestroy(() => { updateOperation(""); }); - - updateOperation(detail)} - /> - +{#if !!import.meta.env.VITE_CONTRACT_TRANSFER_DISABLED} + + updateOperation(detail)} + /> + +{/if} diff --git a/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/__snapshots__/page.spec.js.snap new file mode 100644 index 0000000000..8e7202d565 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/__snapshots__/page.spec.js.snap @@ -0,0 +1,161 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Transfer > should render the transfer page 1`] = ` +
+
+
+
+ + + + + +

+ Transfer +

+
+
+
+ +
+
+
+ Spendable + +
+
+ + 0.000000000 + + + + + + + +
+
+ + +
  • + +
  • +
  • + +
  • + +
  • + + + + + + + + Back + + + + +
  • +
    + +
    + +
    +`; diff --git a/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/page.spec.js b/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/page.spec.js new file mode 100644 index 0000000000..ae84243208 --- /dev/null +++ b/web-wallet/src/routes/(app)/dashboard/transfer/__tests__/page.spec.js @@ -0,0 +1,15 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { cleanup, render } from "@testing-library/svelte"; +import Transfer from "../+page.svelte"; + +vi.useFakeTimers(); + +describe("Transfer", () => { + afterEach(cleanup); + + it("should render the transfer page", async () => { + const { container } = render(Transfer); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js b/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js index dacf27d0bd..d6c16fbb16 100644 --- a/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js +++ b/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js @@ -9,7 +9,7 @@ import { } from "vitest"; import { act, cleanup, fireEvent, render } from "@testing-library/svelte"; -import mockedWalletStore from "../../__mocks__/mockedWalletStore"; +import mockedWalletStore from "../../../../__mocks__/mockedWalletStore"; import * as navigation from "$lib/navigation"; import { settingsStore, walletStore } from "$lib/stores"; import loginInfoStorage from "$lib/services/loginInfoStorage"; diff --git a/web-wallet/src/style/app-components/horizontal-rules.css b/web-wallet/src/style/app-components/horizontal-rules.css index 4d516c47f2..8c803e6383 100644 --- a/web-wallet/src/style/app-components/horizontal-rules.css +++ b/web-wallet/src/style/app-components/horizontal-rules.css @@ -1,5 +1,20 @@ hr { + text-align: center; + overflow: visible; border: none; border-top: 1px solid var(--divider-color-primary); width: 100%; + height: 1px; + padding: 0; +} + +hr.glyph:after { + display: inline-block; + position: relative; + top: -1.1em; + font-size: 1em; + border: solid thin var(--divider-border-color); + border-radius: 2em; + padding: 0.5em 1.25em; + background-color: var(--divider-background-color); } diff --git a/web-wallet/src/style/dusk/language.css b/web-wallet/src/style/dusk/language.css index b26b9e0452..74aff3f4d6 100644 --- a/web-wallet/src/style/dusk/language.css +++ b/web-wallet/src/style/dusk/language.css @@ -109,9 +109,15 @@ --checkbox-control-border-color: var(--smokey-black); --checkbox-control-checked-bg-color: var(--smokey-black); + /* Fieldset */ + --fieldset-background-color: var(--light-grey); + --fieldset-border-radius: 1.5em; + /* Dividers */ - --divider-color-primary: var(--taupe-grey); + --divider-color-primary: var(--smokey-black); + --divider-background-color: var(--light-gray); + --divider-border-color: var(--smokey-black); /* Home animation */ @@ -152,6 +158,16 @@ --checkbox-control-border-color: var(--light-grey); --checkbox-control-checked-bg-color: var(--light-grey); + /* Fieldset */ + + --fieldset-background-color: var(--smokey-black); + + /* Dividers */ + + --divider-color-primary: var(--magnolia); + --divider-background-color: var(--smokey-black); + --divider-border-color: var(--magnolia); + /* Home animation */ --home-grid-color: var(--smokey-black); diff --git a/web-wallet/src/style/main.css b/web-wallet/src/style/main.css index 3e99a04f9c..345fc9def8 100644 --- a/web-wallet/src/style/main.css +++ b/web-wallet/src/style/main.css @@ -92,6 +92,10 @@ svg { fill: currentColor; } +fieldset { + border: none; +} + #outer-container { background-color: var(--background-color); width: 60%; diff --git a/web-wallet/vite.config.js b/web-wallet/vite.config.js index 64861c573a..7029f9f94c 100644 --- a/web-wallet/vite.config.js +++ b/web-wallet/vite.config.js @@ -48,6 +48,7 @@ export default defineConfig(({ mode }) => { TESTNET_NODE: env.VITE_TESTNET_NODE, TESTNET_PROVER_NODE: env.VITE_TESTNET_PROVER_NODE, TRANSFER_CONTRACT: env.VITE_TRANSFER_CONTRACT, + VITE_CONTRACT_ALLOCATE_DISABLED: env.VITE_CONTRACT_ALLOCATE_DISABLED, VITE_CONTRACT_STAKE_DISABLED: env.VITE_CONTRACT_STAKE_DISABLED, VITE_CONTRACT_TRANSFER_DISABLED: env.VITE_CONTRACT_TRANSFER_DISABLED, VITE_GAS_LIMIT_DEFAULT: env.VITE_GAS_LIMIT_DEFAULT, @@ -58,8 +59,6 @@ export default defineConfig(({ mode }) => { VITE_GAS_PRICE_UPPER: env.VITE_GAS_PRICE_UPPER, VITE_GET_QUOTE_API_ENDPOINT: env.VITE_GET_QUOTE_API_ENDPOINT, VITE_MINIMUM_ALLOWED_STAKE: env.VITE_MINIMUM_ALLOWED_STAKE, - VITE_STAKING_ENABLED: env.VITE_STAKING_ENABLED, - VITE_TRANSFER_ENABLED: env.VITE_TRANSFER_ENABLED, }, }, plugins: @@ -98,6 +97,7 @@ export default defineConfig(({ mode }) => { "0200000000000000000000000000000000000000000000000000000000000000", TRANSFER_CONTRACT: "0100000000000000000000000000000000000000000000000000000000000000", + VITE_CONTRACT_ALLOCATE_DISABLED: "false", VITE_CONTRACT_STAKE_DISABLED: "false", VITE_CONTRACT_TRANSFER_DISABLED: "false", VITE_GAS_LIMIT_DEFAULT: "20000000",