Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(frontend): svelte v5 #3929

Draft
wants to merge 36 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a88a26a
build(frontend): svelte v5
peterpeterparker Dec 11, 2024
8f1bbb5
build: use temporary local gix-cmp
peterpeterparker Dec 11, 2024
ee8d55e
fix: no span in option
peterpeterparker Dec 11, 2024
b7152b1
fix(frontend): button authenticate animation selector
peterpeterparker Dec 11, 2024
82fd385
fix(frontend): self-closing HTML tags for non-void elements are ambig…
peterpeterparker Dec 11, 2024
80fd104
chore: fmt
peterpeterparker Dec 11, 2024
8d914d3
feat: adapt cmp type
peterpeterparker Dec 11, 2024
969d174
feat(frontend): listener templating
peterpeterparker Dec 11, 2024
35c85c4
feat: reintroduce slot
peterpeterparker Dec 11, 2024
e4083b4
feat: convert steps type
peterpeterparker Dec 11, 2024
62f2c26
feat: use Component
peterpeterparker Dec 11, 2024
34501a9
feat: use Component
peterpeterparker Dec 11, 2024
2847e9b
fix: listener map types
peterpeterparker Dec 11, 2024
9ebae9f
feat: use const
peterpeterparker Dec 11, 2024
e6e7aa8
feat: use typeof
peterpeterparker Dec 11, 2024
ccb0314
feat: cmp type
peterpeterparker Dec 11, 2024
85d9b03
chore: merge main
peterpeterparker Dec 11, 2024
9ce190a
Merge branch 'main' into build/svelte-v5
peterpeterparker Dec 11, 2024
2c48f9f
build: fix audit
peterpeterparker Dec 12, 2024
7e8a12f
Merge remote-tracking branch 'origin/build/svelte-v5' into build/svel…
peterpeterparker Dec 12, 2024
2730438
fix: eslint for transaction ui
peterpeterparker Dec 12, 2024
7fb4bbf
chore: merge main
peterpeterparker Dec 16, 2024
84e0732
chore: redo
peterpeterparker Dec 16, 2024
d38dc44
build: cleanup and redo svelte v5
peterpeterparker Dec 16, 2024
df02668
Merge branch 'main' into build/svelte-v5
peterpeterparker Dec 16, 2024
f697a2c
chore: more resize observer for tests
peterpeterparker Dec 16, 2024
6d84eac
test(frontend): adapt
peterpeterparker Dec 16, 2024
ec2474e
test: adapt
peterpeterparker Dec 16, 2024
f549ddd
test: mock animate
peterpeterparker Dec 16, 2024
e22bf22
test: props
peterpeterparker Dec 16, 2024
8429434
test: props
peterpeterparker Dec 16, 2024
c5151c7
test: adapt
peterpeterparker Dec 16, 2024
dee6e9d
test: adapt props
peterpeterparker Dec 16, 2024
6f8a1d2
test: state props
peterpeterparker Dec 16, 2024
b943f47
feat: imperative query param for network guard
peterpeterparker Dec 16, 2024
a8b5c9b
chore: latest gix-cmp
peterpeterparker Dec 17, 2024
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
Binary file added dfinity-gix-components-5.0.0.tgz
Binary file not shown.
629 changes: 275 additions & 354 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@dfinity/candid": "^2.1.2",
"@dfinity/ckbtc": "^3.1.0",
"@dfinity/cketh": "^3.3.1",
"@dfinity/gix-components": "^4.8.0-next-2024-11-04",
"@dfinity/gix-components": "file:dfinity-gix-components-5.0.0.tgz",
"@dfinity/ic-management": "^5.2.1",
"@dfinity/ledger-icp": "^2.6.0",
"@dfinity/ledger-icrc": "^2.6.0",
Expand All @@ -79,15 +79,16 @@
"@playwright/test": "^1.49.0",
"@rollup/plugin-inject": "^5.0.5",
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@sveltejs/kit": "^2.11.1",
"@sveltejs/vite-plugin-svelte": "^4.0.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/svelte": "^5.2.6",
"@types/dom-view-transitions": "^1.0.5",
"@types/node": "^20.14.9",
"@vitest/coverage-v8": "^2.1.8",
"autoprefixer": "^10.4.20",
"dotenv": "^16.4.7",
"eslint-plugin-svelte": "^2.46.1",
"fake-indexeddb": "^6.0.0",
"jimp": "^1.6.0",
"jsdom": "^25.0.1",
Expand All @@ -99,7 +100,7 @@
"prettier-plugin-svelte": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"sass": "^1.81.0",
"svelte": "^4.2.19",
"svelte": "^5.14.0",
"svelte-check": "^4.1.1",
"tailwindcss": "^3.4.15",
"tslib": "^2.8.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { nonNullish } from '@dfinity/utils';
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import { slide } from 'svelte/transition';
import { ICP_TOKEN } from '$env/tokens/tokens.icp.env';
import Info from '$icp/components/info/Info.svelte';
Expand Down Expand Up @@ -37,7 +37,7 @@
let ckEthereum: boolean;
$: ckEthereum = $tokenCkEthLedger || $tokenCkErc20Ledger;

let additionalListener: ComponentType;
let additionalListener: Component;
$: additionalListener = $tokenCkBtcLedger
? IcTransactionsBtcListeners
: ckEthereum
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/lib/components/hero/HeroSignIn.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import ButtonAuthenticateWithLicense from '$lib/components/auth/ButtonAuthenticateWithLicense.svelte';
import IconScanFace from '$lib/components/icons/lucide/IconScanFace.svelte';
import IconShieldCheck from '$lib/components/icons/lucide/IconShieldCheck.svelte';
import IconWallet from '$lib/components/icons/lucide/IconWallet.svelte';
import { i18n } from '$lib/stores/i18n.store';

let infoList: { label: string; icon: ComponentType }[];
let infoList: { label: string; icon: Component }[];
$: infoList = [
{
label: $i18n.auth.text.asset_types,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
<script lang="ts">
import { WizardModal, type WizardStep, type WizardSteps } from '@dfinity/gix-components';
import { nonNullish } from '@dfinity/utils';
import type { ComponentType } from 'svelte';
import IcReceiveInfoCkBTC from '$icp/components/receive/IcReceiveInfoCkBTC.svelte';
import IcReceiveInfoICP from '$icp/components/receive/IcReceiveInfoICP.svelte';
import IcReceiveInfoIcrc from '$icp/components/receive/IcReceiveInfoIcrc.svelte';
import ReceiveAddressQRCode from '$lib/components/receive/ReceiveAddressQRCode.svelte';
import ReceiveAddresses from '$lib/components/receive/ReceiveAddresses.svelte';
import ReceiveTitle from '$lib/components/receive/ReceiveTitle.svelte';
import { RECEIVE_TOKENS_MODAL } from '$lib/constants/test-ids.constants';
import { i18n } from '$lib/stores/i18n.store';
import type { ReceiveQRCode } from '$lib/types/receive';
import type { Token } from '$lib/types/token';

export let infoCmp: ComponentType;
export let infoCmp:
| typeof ReceiveAddresses
| typeof IcReceiveInfoCkBTC
| typeof IcReceiveInfoICP
| typeof IcReceiveInfoIcrc;

const steps: WizardSteps = [
{
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/lib/components/signer/SignerAlert.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import IconCheck from '$lib/components/icons/IconCheck.svelte';
import IconClose from '$lib/components/icons/IconClose.svelte';

export let alertType: 'ok' | 'error';

let icon: ComponentType;
let icon: Component;
$: icon = alertType === 'error' ? IconClose : IconCheck;
</script>

Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/lib/components/tokens/TokenLogo.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import NetworkLogo from '$lib/components/networks/NetworkLogo.svelte';
import Logo from '$lib/components/ui/Logo.svelte';
import { i18n } from '$lib/stores/i18n.store';
Expand All @@ -12,7 +12,7 @@
export let badge:
| { type: 'network'; blackAndWhite?: boolean }
| { type: 'tokenCount'; count: number }
| { type: 'icon'; icon: ComponentType; ariaLabel: string }
| { type: 'icon'; icon: Component; ariaLabel: string }
| undefined = undefined;
export let logoSize: LogoSize = 'lg';
export let ring = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { nonNullish } from '@dfinity/utils';
import { BigNumber } from '@ethersproject/bignumber';
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import TokenLogo from '$lib/components/tokens/TokenLogo.svelte';
import TransactionStatusComponent from '$lib/components/transactions/TransactionStatus.svelte';
import Amount from '$lib/components/ui/Amount.svelte';
Expand All @@ -20,7 +20,7 @@
export let token: Token;
export let iconType: 'token' | 'transaction' = 'transaction';

let icon: ComponentType;
let icon: Component;
$: icon = mapTransactionIcon({ type, status });

let iconWithOpacity: boolean;
Expand Down
8 changes: 5 additions & 3 deletions src/frontend/src/lib/components/ui/InProgress.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script lang="ts">
import { ProgressSteps as ProgressStepsCmp, type ProgressStep } from '@dfinity/gix-components';
import type { ComponentType } from 'svelte';
import StaticSteps from '$lib/components/ui/StaticSteps.svelte';
import type { ProgressSteps } from '$lib/types/progress-steps';
import type { StaticStep } from '$lib/types/steps';
Expand All @@ -9,10 +8,13 @@
export let steps: [ProgressStep | StaticStep, ...(ProgressStep | StaticStep)[]];
export let type: 'progress' | 'static' = 'progress';

let cmp: ComponentType;
let cmp: typeof StaticSteps | typeof ProgressStepsCmp;
$: cmp = type === 'static' ? StaticSteps : ProgressStepsCmp;

let dynamicSteps: [ProgressStep | StaticStep, ...(ProgressStep | StaticStep)[]] = [...steps];
let dynamicSteps: [ProgressStep, ...ProgressStep[]] = [
// TODO: have a look if there is a better solution than casting
...(steps as [ProgressStep, ...ProgressStep[]])
];

const updateSteps = () => {
const progressIndex = dynamicSteps.findIndex(({ step }) => step === progressStep);
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/lib/components/ui/RoundedIcon.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';

export let icon: ComponentType;
export let icon: Component;
export let opacity = false;
</script>

Expand Down
5 changes: 3 additions & 2 deletions src/frontend/src/lib/types/listener.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import BitcoinListener from '$btc/components/core/BitcoinListener.svelte';
import EthListener from '$eth/components/core/EthListener.svelte';
import type { Token } from '$lib/types/token';
import type { ComponentType } from 'svelte';

export interface WalletWorker {
start: () => void;
Expand All @@ -11,5 +12,5 @@ export type InitWalletWorkerFn = (params: { token: Token }) => Promise<WalletWor

export interface TokenToListener {
token: Token;
listener: ComponentType;
listener: typeof BitcoinListener | typeof EthListener;
}
4 changes: 2 additions & 2 deletions src/frontend/src/lib/utils/transaction.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
} from '$lib/types/transaction';
import { formatSecondsToNormalizedDate } from '$lib/utils/format.utils';
import { isNullish, nonNullish } from '@dfinity/utils';
import type { ComponentType } from 'svelte';
import type { Component } from 'svelte';
import { get } from 'svelte/store';

export const mapTransactionIcon = ({
Expand All @@ -26,7 +26,7 @@ export const mapTransactionIcon = ({
}: {
type: TransactionType;
status: TransactionStatus;
}): ComponentType => {
}): Component => {
const isConversionFrom = type === 'withdraw' || type === 'mint';

const isConversionTo = type === 'deposit' || type === 'burn' || type === 'approve';
Expand Down
12 changes: 8 additions & 4 deletions src/frontend/src/routes/(app)/transactions/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
<script lang="ts">
import { isNullish } from '@dfinity/utils';
import { isNullish, notEmptyString } from '@dfinity/utils';
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import Transactions from '$lib/components/transactions/Transactions.svelte';
import { routeNetwork } from '$lib/derived/nav.derived';
import { NETWORK_PARAM } from '$lib/constants/routes.constants';
import { networks } from '$lib/derived/networks.derived';

onMount(async () => {
// We imperatively load the network parameters because the Svelte $page store might still be initialized as undefined at this point.
const urlParams = new URLSearchParams(window.location.search);
const routeNetwork = urlParams.get(NETWORK_PARAM);

// We need to know the network on which the transactions should be loaded.
// While we can guess the network for ICP, we cannot do the same for ICRC tokens as they are loaded asynchronously.
// Therefore, we cannot automatically select the network if it is not provided when the component mounts, and we cannot wait indefinitely.
// That's why, if no network is provided, we route to the root.
if (isNullish($routeNetwork)) {
if (isNullish(routeNetwork) || !notEmptyString(routeNetwork)) {
await goto('/');
}

const unknownNetwork =
$networks.find(({ id }) => id.description === $routeNetwork) === undefined;
$networks.find(({ id }) => id.description === routeNetwork) === undefined;

if (unknownNetwork) {
await goto('/');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,63 @@ describe('BtcConvertFeeTotal', () => {
});

it('should not update totalFee if only default fee is available', () => {
const { component } = render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store })
const props = $state({
totalFee: undefined
});
expect(component.$$.ctx[component.$$.props['totalFee']]).toBeUndefined();

render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store }),
props
});

expect(props.totalFee).toBeUndefined();
});

it('should not update totalFee if only default and utxos fees are available', () => {
const props = $state({
totalFee: undefined
});

store.setUtxosFee({ utxosFee: mockUtxosFee });
const { component } = render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store })

render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store }),
props
});
expect(component.$$.ctx[component.$$.props['totalFee']]).toBeUndefined();

expect(props.totalFee).toBeUndefined();
});

it('should not update totalFee if only default and ckBTC minter fees are available', () => {
const props = $state({
totalFee: undefined
});

const tokenId = setupCkBTCStores();
const { component } = render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store, destinationTokenId: tokenId })

render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store, destinationTokenId: tokenId }),
props
});
expect(component.$$.ctx[component.$$.props['totalFee']]).toBeUndefined();

expect(props.totalFee).toBeUndefined();
});

it('should calculate totalFee correctly if all fees are available', () => {
const props = $state({
totalFee: undefined
});

store.setUtxosFee({ utxosFee: mockUtxosFee });

const tokenId = setupCkBTCStores();
const { component } = render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store, destinationTokenId: tokenId })

render(BtcConvertFeeTotal, {
context: mockContext({ utxosFeeStore: store, destinationTokenId: tokenId }),
props
});
expect(component.$$.ctx[component.$$.props['totalFee']]).toBe(

expect(props.totalFee).toBe(
BTC_CONVERT_FEE + mockCkBtcMinterInfo.kyt_fee + mockUtxosFee.feeSatoshis
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,47 @@ describe('ConvertAmountDestination', () => {
});

it('should calculate receiveAmount correctly', () => {
const { component } = render(ConvertAmountDestination, {
props,
const testProps = $state({
...props,
receiveAmount: undefined
});

render(ConvertAmountDestination, {
props: testProps,
context: mockContext
});

expect(component.$$.ctx[component.$$.props['receiveAmount']]).toBe(receiveAmount);
expect(testProps.receiveAmount).toBe(receiveAmount);
});

it('should calculate receiveAmount correctly if sendAmount is not provided', () => {
const { sendAmount: _, ...newProps } = props;
const { component } = render(ConvertAmountDestination, {
props: newProps,

const testProps = $state({
...newProps,
receiveAmount: undefined
});

render(ConvertAmountDestination, {
props: testProps,
context: mockContext
});

expect(component.$$.ctx[component.$$.props['receiveAmount']]).toBeUndefined();
expect(testProps.receiveAmount).toBeUndefined();
});

it('should calculate receiveAmount correctly if insufficientFunds is true', () => {
const { component } = render(ConvertAmountDestination, {
props: { ...props, insufficientFunds: true },
const testProps = $state({
...props,
insufficientFunds: true,
receiveAmount: undefined
});

render(ConvertAmountDestination, {
props: testProps,
context: mockContext
});

expect(component.$$.ctx[component.$$.props['receiveAmount']]).toBeUndefined();
expect(testProps.receiveAmount).toBeUndefined();
});
});
Loading
Loading