aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/(app)/+layout.server.js2
-rw-r--r--src/routes/(app)/[username]/dashboard/+page.svelte2
-rw-r--r--src/routes/(app)/[username]/generate/+page.svelte61
-rw-r--r--src/routes/(app)/[username]/generate/+server.js8
4 files changed, 72 insertions, 1 deletions
diff --git a/src/routes/(app)/+layout.server.js b/src/routes/(app)/+layout.server.js
index d968be70..88ca1539 100644
--- a/src/routes/(app)/+layout.server.js
+++ b/src/routes/(app)/+layout.server.js
@@ -11,6 +11,8 @@ export async function load({ cookies, locals, request, url, params }) {
let { user } = locals;
if (user) {
+ if (!user.pubkey && !url.pathname.includes('gen'))
+ throw redirect(307, `/${user.username}/generate`);
let account = user.accounts.find((a) => a.asset === btc && !a.pubkey);
if (account) {
let { id } = account;
diff --git a/src/routes/(app)/[username]/dashboard/+page.svelte b/src/routes/(app)/[username]/dashboard/+page.svelte
index c10518f5..0b49a870 100644
--- a/src/routes/(app)/[username]/dashboard/+page.svelte
+++ b/src/routes/(app)/[username]/dashboard/+page.svelte
@@ -3,7 +3,7 @@
import { f, s, post, failure, sat, sats } from '$lib/utils';
import { tick } from 'svelte';
import { Avatar, Icon } from '$comp';
- import { rate, selectedRate } from '$lib/store';
+ import { rate, password, selectedRate } from '$lib/store';
import { goto } from '$app/navigation';
import { t } from '$lib/translations';
diff --git a/src/routes/(app)/[username]/generate/+page.svelte b/src/routes/(app)/[username]/generate/+page.svelte
new file mode 100644
index 00000000..873e336f
--- /dev/null
+++ b/src/routes/(app)/[username]/generate/+page.svelte
@@ -0,0 +1,61 @@
+<script>
+ import { Buffer } from 'buffer';
+ import { onMount } from 'svelte';
+ import { BIP32Factory } from 'bip32';
+ import { bech32m } from 'bech32';
+ import { generateMnemonic, mnemonicToEntropy, mnemonicToSeedSync } from 'bip39';
+ import * as ecc from 'tiny-secp256k1';
+ import { post } from '$lib/utils';
+ import { goto } from '$app/navigation';
+
+ export let data;
+ let { user } = data;
+
+ const { encode, decode, fromWords, toWords } = bech32m;
+
+ const stretch = async (password, salt) =>
+ crypto.subtle.deriveKey(
+ {
+ name: 'PBKDF2',
+ salt,
+ iterations: 100000,
+ hash: 'SHA-256'
+ },
+ await crypto.subtle.importKey(
+ 'raw',
+ new TextEncoder().encode(password),
+ { name: 'PBKDF2' },
+ false,
+ ['deriveBits', 'deriveKey']
+ ),
+ { name: 'AES-GCM', length: 256 },
+ true,
+ ['encrypt', 'decrypt']
+ );
+
+ let mnemonic, key, password, seed, entropy, cipher, pubkey, salt, child;
+
+ onMount(async () => {
+ let bip32 = await BIP32Factory(ecc);
+ mnemonic = generateMnemonic();
+ seed = mnemonicToSeedSync(mnemonic);
+ entropy = mnemonicToEntropy(mnemonic);
+ key = bip32.fromSeed(seed);
+ child = key.derivePath("m/44'/1237'/0'/0/0");
+ salt = crypto.getRandomValues(new Uint8Array(16));
+
+ let bytes = new Uint8Array(
+ await crypto.subtle.encrypt(
+ { name: 'AES-GCM', iv: new Uint8Array(16) },
+ await stretch(password, salt),
+ Uint8Array.from(Buffer.from(entropy, 'hex'))
+ )
+ );
+
+ user.pubkey = Buffer.from(ecc.xOnlyPointFromPoint(child.publicKey)).toString('hex');
+ user.cipher = encode('encprv', toWords(bytes), 180);
+
+ await post(`/${user.username}/generate`, user);
+ goto(`/${user.username}/dashboard`);
+ });
+</script>
diff --git a/src/routes/(app)/[username]/generate/+server.js b/src/routes/(app)/[username]/generate/+server.js
new file mode 100644
index 00000000..c63ab5a6
--- /dev/null
+++ b/src/routes/(app)/[username]/generate/+server.js
@@ -0,0 +1,8 @@
+import { auth, post } from '$lib/utils';
+import { json } from '@sveltejs/kit';
+
+export async function POST({ cookies, request }) {
+ let body = await request.json();
+ let user = await post(`/user`, body, auth(cookies));
+ return json(user);
+}