From cd10e9f2ce5d84cf24d8f559aad3880ea513d277 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Mon, 6 Nov 2023 15:00:07 +0100 Subject: [PATCH] Add download page --- package.json | 1 + pnpm-lock.yaml | 16 ++++++ src/lib/helpers/index.ts | 1 - src/lib/queries/app-queries.ts | 20 +++++++ src/lib/queries/index.ts | 2 + src/lib/queries/query-keys.ts | 1 + .../{helpers => services}/generate-keys.ts | 2 +- src/lib/services/index.ts | 1 + src/lib/types/password.ts | 6 +++ src/routes/+layout.svelte | 8 ++- src/routes/setup/+layout.svelte | 10 ++-- src/routes/setup/download/+page.svelte | 50 +++++++++++++++++ src/routes/setup/generate-keys/+page.svelte | 53 +++++++++---------- static/img/check.svg | 4 ++ svelte.config.js | 4 +- 15 files changed, 142 insertions(+), 37 deletions(-) create mode 100644 src/lib/queries/app-queries.ts create mode 100644 src/lib/queries/index.ts create mode 100644 src/lib/queries/query-keys.ts rename src/lib/{helpers => services}/generate-keys.ts (93%) create mode 100644 src/lib/services/index.ts create mode 100644 src/routes/setup/download/+page.svelte create mode 100644 static/img/check.svg diff --git a/package.json b/package.json index c80da6e..a75bf91 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "type": "module", "dependencies": { + "@tanstack/svelte-query": "^5.4.3", "clsx": "^2.0.0", "file-saver": "^2.0.5", "hcSeedBundle": "git+https://github.com/mrruby/hcSeedBundle", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d012cbb..5bfdfd7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@tanstack/svelte-query': + specifier: ^5.4.3 + version: 5.4.3(svelte@4.2.0) clsx: specifier: ^2.0.0 version: 2.0.0 @@ -475,6 +478,19 @@ packages: - supports-color dev: true + /@tanstack/query-core@5.4.3: + resolution: {integrity: sha512-fnI9ORjcuLGm1sNrKatKIosRQUpuqcD4SV7RqRSVmj8JSicX2aoMyKryHEBpVQvf6N4PaBVgBxQomjsbsGPssQ==} + dev: false + + /@tanstack/svelte-query@5.4.3(svelte@4.2.0): + resolution: {integrity: sha512-mVUTuGkWCvr6PE/CgA75jZtbAtI5WCYrU4DV/WshNOod3H88ynlx2EC8x8PfQGTREl0NUHZwDUxeXIA7RDNfug==} + peerDependencies: + svelte: '>=3 <5' + dependencies: + '@tanstack/query-core': 5.4.3 + svelte: 4.2.0 + dev: false + /@types/cookie@0.5.1: resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==} dev: true diff --git a/src/lib/helpers/index.ts b/src/lib/helpers/index.ts index e9146c3..701e505 100644 --- a/src/lib/helpers/index.ts +++ b/src/lib/helpers/index.ts @@ -1,2 +1 @@ export * from './navigation'; -export * from './generate-keys'; diff --git a/src/lib/queries/app-queries.ts b/src/lib/queries/app-queries.ts new file mode 100644 index 0000000..922e4d6 --- /dev/null +++ b/src/lib/queries/app-queries.ts @@ -0,0 +1,20 @@ +import { createMutation, useQueryClient, createQuery } from '@tanstack/svelte-query'; +import { generateKeys } from '$lib/services'; +import type { GeneratedKeys } from '$types'; +import { queryKey } from './query-keys'; + +export function useGeneratedKeys() { + const queryClient = useQueryClient(); + + const generateKeysMutation = createMutation({ + mutationFn: (passphrase: string) => generateKeys(passphrase), + onSuccess: (data) => { + queryClient.setQueryData([queryKey], data); + } + }); + + const generatedKeysQuery = createQuery({ + queryKey: [queryKey] + }); + return { generateKeysMutation, generatedKeysQuery }; +} diff --git a/src/lib/queries/index.ts b/src/lib/queries/index.ts new file mode 100644 index 0000000..f6fa3e5 --- /dev/null +++ b/src/lib/queries/index.ts @@ -0,0 +1,2 @@ +export * from './app-queries'; +export * from './query-keys'; diff --git a/src/lib/queries/query-keys.ts b/src/lib/queries/query-keys.ts new file mode 100644 index 0000000..1a4594e --- /dev/null +++ b/src/lib/queries/query-keys.ts @@ -0,0 +1 @@ +export const queryKey = 'generatedKeys'; diff --git a/src/lib/helpers/generate-keys.ts b/src/lib/services/generate-keys.ts similarity index 93% rename from src/lib/helpers/generate-keys.ts rename to src/lib/services/generate-keys.ts index 4520892..28b97d0 100644 --- a/src/lib/helpers/generate-keys.ts +++ b/src/lib/services/generate-keys.ts @@ -1,7 +1,7 @@ // @ts-nocheck import * as hcSeedBundle from 'hcSeedBundle'; -export async function generateKeys(passphrase: string) { +export async function generateKeys(passphrase: string): Promise { await hcSeedBundle.seedBundleReady; const master = hcSeedBundle.UnlockedSeedBundle.newRandom({ diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts new file mode 100644 index 0000000..bfd61b7 --- /dev/null +++ b/src/lib/services/index.ts @@ -0,0 +1 @@ +export * from './generate-keys'; diff --git a/src/lib/types/password.ts b/src/lib/types/password.ts index fd468f9..6c2a3fd 100644 --- a/src/lib/types/password.ts +++ b/src/lib/types/password.ts @@ -1 +1,7 @@ export type SetPassphrase = 'set' | 'confirm'; + +export type GeneratedKeys = { + master: Uint8Array; + device: Uint8Array; + revocation: Uint8Array; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 2e511e0..5392c2a 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,5 +1,11 @@ - + + + diff --git a/src/routes/setup/+layout.svelte b/src/routes/setup/+layout.svelte index 5a9a4f3..9942811 100644 --- a/src/routes/setup/+layout.svelte +++ b/src/routes/setup/+layout.svelte @@ -3,17 +3,19 @@ import { setContext } from 'svelte'; import { passphrase, passphraseStore } from '$stores'; - function dismissExtensionWindow() { - window.history.back(); - } + const dismissExtensionWindow = () => window.history.back(); setContext(passphrase, passphraseStore); + + $: allowGoBack = !( + $page.url.pathname.includes('start') || $page.url.pathname.includes('download') + );
- {#if !$page.url.pathname.includes('start')} + {#if allowGoBack} + import { getContext, onMount } from 'svelte'; + import { passphrase } from '$stores'; + import JSZip from 'jszip'; + import fileSaver from 'file-saver'; + import type { Writable } from 'svelte/store'; + import { goto } from '$app/navigation'; + import Button from '$components/Button.svelte'; + import { useGeneratedKeys } from '$queries'; + import Title from '$components/Title.svelte'; + import AppParagraph from '$components/AppParagraph.svelte'; + + const passphraseStore = getContext>(passphrase); + + const { generatedKeysQuery } = useGeneratedKeys(); + + onMount(() => { + if ($passphraseStore === '') { + goto('/setup/start'); + } + }); + + async function download(): Promise { + const { saveAs } = fileSaver; + const files = [ + { name: 'master.txt', data: new TextDecoder().decode($generatedKeysQuery.data?.master) }, + { name: 'device.txt', data: new TextDecoder().decode($generatedKeysQuery.data?.device) }, + { + name: 'revocation.txt', + data: new TextDecoder().decode($generatedKeysQuery.data?.revocation) + } + ]; + const zip = new JSZip(); + files.forEach((file) => zip.file(file.name, file.data)); + const content = await zip.generateAsync({ type: 'blob' }); + + saveAs(content, 'keys.zip'); + } + + +check + +Save Seed Files and Keys + + +Padlock +