diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Account.svelte | 3 | ||||
| -rw-r--r-- | src/components/Mnemonic.svelte | 14 | ||||
| -rw-r--r-- | src/components/WalletPass.svelte | 6 | ||||
| -rw-r--r-- | src/lib/parse.ts | 4 | ||||
| -rw-r--r-- | src/locales/en.json | 8 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/+page.svelte | 12 | ||||
| -rw-r--r-- | src/routes/(app)/account/[id]/+page.svelte | 19 | ||||
| -rw-r--r-- | src/routes/(app)/account/pass/+page.svelte | 29 | ||||
| -rw-r--r-- | src/routes/(app)/account/seed/+page.svelte | 26 | ||||
| -rw-r--r-- | src/routes/(app)/payment/[id]/+page.svelte | 17 | ||||
| -rw-r--r-- | src/routes/(app)/send/bitcoin/[address]/+layout.server.ts | 12 | ||||
| -rw-r--r-- | src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte | 20 |
12 files changed, 113 insertions, 57 deletions
diff --git a/src/components/Account.svelte b/src/components/Account.svelte index 4bfdc4ac..8f72119e 100644 --- a/src/components/Account.svelte +++ b/src/components/Account.svelte @@ -10,7 +10,8 @@ $: refresh(account); let refresh = (a) => ({ seed, balance, id } = a); - let setAccount = () => (document.cookie = `aid=${id}; path=/; max-age=86400`); + let setAccount = () => + (document.cookie = `aid=${id}; path=/; max-age=86400`); </script> <a href={`/payments`} class="block" on:click={setAccount}> diff --git a/src/components/Mnemonic.svelte b/src/components/Mnemonic.svelte new file mode 100644 index 00000000..5e834aed --- /dev/null +++ b/src/components/Mnemonic.svelte @@ -0,0 +1,14 @@ +<script> + export let mnemonic; +</script> + +<div + class="text-lg border p-4 rounded-2xl text-secondary grid grid-cols-3 gap-2 justify-center" +> + {#each mnemonic.split(" ") as w, i} + <div> + <span class="select-none text-sm text-black">{i + 1}.</span> + <span>{@html w === "-" ? "—" : w}</span> + </div> + {/each} +</div> diff --git a/src/components/WalletPass.svelte b/src/components/WalletPass.svelte index 7793ecc5..69b95107 100644 --- a/src/components/WalletPass.svelte +++ b/src/components/WalletPass.svelte @@ -46,10 +46,10 @@ <Icon icon={revealPassword ? "eye" : "eye-off"} /> </button> </div> - <div class="w-full flex"> + <div class="w-full flex justify-center gap-2"> <button type="button" - class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto" + class="border-2 bg-primary rounded-2xl font-semibold mx-auto py-5 px-6 hover:opacity-80 mx-auto grow" on:click={cancel} on:keydown={cancel} > @@ -57,7 +57,7 @@ </button> <button type="submit" - class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto" + class="rounded-2xl font-semibold mx-auto py-5 px-6 hover:opacity-80 mx-auto grow bg-black text-white" > <div class="my-auto">Submit</div> </button> diff --git a/src/lib/parse.ts b/src/lib/parse.ts index 781c7087..0ab3e809 100644 --- a/src/lib/parse.ts +++ b/src/lib/parse.ts @@ -10,7 +10,7 @@ export default async (t, host) => { if (t.startsWith("http")) redirect(307, t); if (t.startsWith(host)) redirect(307, `http://${t}`); - let amount, id, user; + let amount, user; t = t.trim(); t.toLowerCase().startsWith("bitcoin:") && @@ -37,7 +37,7 @@ export default async (t, host) => { if (t.toLowerCase().startsWith("ln")) { try { - ({ id } = await get(`/invoice/${t}`)); + await get(`/invoice/${t}`); } catch (e) { redirect(307, `/send/lightning/${t}`); } diff --git a/src/locales/en.json b/src/locales/en.json index 78ef8de1..f65841d3 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,5 +1,13 @@ { "accounts": { + "back": "Back", + "next": "Next", + "seedPhrase": "Seed phrase", + "save": "Save", + "copy": "Copy", + "revealMnemonic": "Reveal seed phrase", + "regenerate": "Regenerate", + "deleteAccount": "Delete account", "addAccount": "Add account", "create": "Create", "import": "Import", diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte index 2c2ff9a8..0d85fc56 100644 --- a/src/routes/(app)/[username]/(profile)/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/+page.svelte @@ -28,14 +28,6 @@ <div class="space-y-2"> {#if user?.id === subject.id} - {#if !user.balance} - <div class="mb-8"> - <p class="text-secondary text-lg"> - {$t("user.welcome")} - </p> - </div> - {/if} - {#each accounts as account} <Account {user} {rate} {account} /> {/each} @@ -47,7 +39,9 @@ > <div class="mx-auto flex gap-2"> <Icon icon="plus" style="w-8 mx-auto invert" /> - <div class="my-auto text-xl whitespace-nowrap">{$t("accounts.addAccount")}</div> + <div class="my-auto text-xl whitespace-nowrap"> + {$t("accounts.addAccount")} + </div> </div> </button> </a> diff --git a/src/routes/(app)/account/[id]/+page.svelte b/src/routes/(app)/account/[id]/+page.svelte index 3dcd99b8..06494dd8 100644 --- a/src/routes/(app)/account/[id]/+page.svelte +++ b/src/routes/(app)/account/[id]/+page.svelte @@ -1,4 +1,5 @@ <script> + import Mnemonic from "$comp/Mnemonic.svelte"; import WalletPass from "$comp/WalletPass.svelte"; import { goto } from "$app/navigation"; import { copy, fail, focus, post } from "$lib/utils"; @@ -46,28 +47,28 @@ <div class="space-y-2"> <button type="submit" - class="rounded-2xl border py-3 font-bold mx-auto bg-black text-white px-4 w-full" - >Submit</button + class="rounded-2xl border py-5 font-bold mx-auto bg-black text-white px-6 w-full" + >{$t("accounts.save")}</button > {#if mnemonic} - <div class="p-8">{mnemonic}</div> + <Mnemonic {mnemonic} /> <button on:click={() => copy(mnemonic)} type="button" - class="flex gap-2 rounded-2xl border py-3 font-bold mx-auto px-4 w-full justify-center" + class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > <Icon icon="copy" style="w-8 my-auto" /> - <div class="my-auto">Copy</div></button + <div class="my-auto">{$t("accounts.copy")}</div></button > {:else if seed} <button on:click={toggle} type="button" - class="flex gap-2 rounded-2xl border py-3 font-bold mx-auto px-4 w-full justify-center bg-primary" + class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > <Icon icon="eye" style="w-8 my-auto" /> - <div class="my-auto">Reveal mnemonic</div></button + <div class="my-auto">{$t("accounts.revealMnemonic")}</div></button > {/if} @@ -75,10 +76,10 @@ <button on:click={del} type="button" - class="flex gap-2 rounded-2xl border py-3 font-bold mx-auto px-4 w-full justify-center bg-primary" + class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > <Icon icon="trash" style="w-8 my-auto" /> - <div class="my-auto"><span class="text-red-600">Delete</span> account</div></button + <div class="my-auto">{$t("accounts.deleteAccount")}</div></button > {/if} </div> diff --git a/src/routes/(app)/account/pass/+page.svelte b/src/routes/(app)/account/pass/+page.svelte index 2ce8b168..36992a98 100644 --- a/src/routes/(app)/account/pass/+page.svelte +++ b/src/routes/(app)/account/pass/+page.svelte @@ -44,8 +44,6 @@ let child = master.derive("m/84'/0'/0'"); let pubkey = child.publicExtendedKey; let fingerprint = child.fingerprint.toString(16).padStart(8, "0"); - - let receiving = child.deriveChild(0); await post("/api/accounts", { fingerprint, pubkey, name, seed, type }); goto(`/${user.username}`); } catch (e) { @@ -59,7 +57,9 @@ <div class="space-y-5"> <div> - <h1 class="text-center text-3xl font-semibold">{$t("accounts.accountPassword")}</h1> + <h1 class="text-center text-3xl font-semibold"> + {$t("accounts.accountPassword")} + </h1> </div> <form @@ -67,7 +67,7 @@ class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5" > <p class="text-secondary mb-1"> - {$t("accounts.passwordWarning")} + {$t("accounts.passwordWarning")} </p> <div class="relative"> @@ -129,10 +129,21 @@ </button> </div> - <button - class="bg-black text-white w-full px-5 py-6 text-xl rounded-2xl font-bold" - > - Submit - </button> + <div class="flex gap-2"> + <a href={`/account/seed`} class="contents"> + <button + type="button" + class="bg-primary w-full px-5 py-6 text-xl rounded-2xl font-bold" + > + {$t("accounts.back")} + </button> + </a> + <button + type="submit" + class="bg-black text-white w-full px-5 py-6 text-xl rounded-2xl font-bold" + > + {$t("accounts.next")} + </button> + </div> </form> </div> diff --git a/src/routes/(app)/account/seed/+page.svelte b/src/routes/(app)/account/seed/+page.svelte index e922d6be..4e55534b 100644 --- a/src/routes/(app)/account/seed/+page.svelte +++ b/src/routes/(app)/account/seed/+page.svelte @@ -1,4 +1,5 @@ <script> + import Mnemonic from "$comp/Mnemonic.svelte"; import { browser } from "$app/environment"; import { tick, onMount } from "svelte"; import { copy } from "$lib/utils"; @@ -13,7 +14,7 @@ onMount(async () => { if (!browser) return; - await generate(); + if (!$mnemonic) await generate(); }); let generate = async () => { @@ -22,20 +23,13 @@ </script> <div class="space-y-5"> - <h1 class="text-center text-3xl font-semibold">Seed phrase</h1> + <h1 class="text-center text-3xl font-semibold"> + {$t("accounts.seedPhrase")} + </h1> <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5"> {#if $mnemonic} - <div - class="text-lg border p-4 rounded-2xl text-secondary grid grid-cols-3 gap-2 justify-center" - > - {#each $mnemonic.split(" ") as w, i} - <div> - <span class="select-none text-sm text-black">{i + 1}.</span> - <span>{@html w === "-" ? "—" : w}</span> - </div> - {/each} - </div> + <Mnemonic mnemonic={$mnemonic} /> {/if} <div> @@ -45,7 +39,7 @@ on:click={generate} > <Icon icon="random" style="w-8 my-auto" /> - <div class="my-auto">Regenerate</div> + <div class="my-auto">{$t("accounts.regenerate")}</div> </button> <button @@ -64,9 +58,9 @@ <a href={`/account/savings`} class="contents"> <button type="button" - class="bg-black text-white w-full px-5 py-6 text-xl rounded-2xl font-bold" + class="bg-primary w-full px-5 py-6 text-xl rounded-2xl font-bold" > - Back + {$t("accounts.back")} </button> </a> <a href={`/account/pass`} class="contents"> @@ -74,7 +68,7 @@ type="button" class="bg-black text-white w-full px-5 py-6 text-xl rounded-2xl font-bold" > - Next + {$t("accounts.next")} </button> </a> </div> diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index 9a278049..481d0242 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -34,6 +34,7 @@ rate, type, ref, + path, tip, ourfee, fee, @@ -57,6 +58,7 @@ rate, type, ref, + path, tip, ourfee, fee, @@ -225,6 +227,21 @@ </div> {/if} + {#if path} + <div> + <span class="text-lg text-secondary">Path</span> + <div class="flex"> + <div>{path}</div> + <button + class="flex font-bold hover:opacity-80 mb-auto my-auto" + on:click={() => copy(path)} + > + <Icon icon="copy" style="ml-2 w-12 my-auto" /> + </button> + </div> + </div> + {/if} + <div class="flex gap-2"> {#if user.admin} <button diff --git a/src/routes/(app)/send/bitcoin/[address]/+layout.server.ts b/src/routes/(app)/send/bitcoin/[address]/+layout.server.ts new file mode 100644 index 00000000..6c22f5f1 --- /dev/null +++ b/src/routes/(app)/send/bitcoin/[address]/+layout.server.ts @@ -0,0 +1,12 @@ +import { auth, get } from "$lib/utils"; +import { redirect } from "@sveltejs/kit"; + +export async function load({ cookies, params }) { + let aid = cookies.get("aid"); + let { address } = params; + let { balance } = await get(`/account/${aid}`, auth(cookies)); + let invoice = await get(`/invoice/${address}`); + let recipient = await get(`/user/${invoice.uid}`); + if (invoice.aid === invoice.uid) redirect(307, `/send/${recipient.username}`); + return { balance }; +} diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte index 4da2e04c..ba87436f 100644 --- a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte +++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte @@ -5,6 +5,7 @@ import Toggle from "$comp/Toggle.svelte"; import Icon from "$comp/Icon.svelte"; import Spinner from "$comp/Spinner.svelte"; + import WalletPass from "$comp/WalletPass.svelte"; import { page } from "$app/stores"; import { fiat as toFiat, @@ -21,6 +22,7 @@ import { applyAction } from "$app/forms"; import { hex as hexUtil } from "@scure/base"; import * as btc from "@scure/btc-signer"; + import { hash160 } from "@scure/btc-signer/utils"; import { decrypt } from "nostr-tools/nip49"; import { HDKey } from "@scure/bip32"; import { entropyToMnemonic, mnemonicToSeed } from "@scure/bip39"; @@ -51,22 +53,24 @@ let signTx = async () => { let entropy = await decrypt(account.seed, password); let mnemonic = entropyToMnemonic(entropy, wordlist); - let seed = await mnemonicToSeed(mnemonic); + let seed = await mnemonicToSeed(mnemonic, password); let master = HDKey.fromMasterSeed(seed, network); let child = master.derive("m/84'/0'/0'"); let tx = btc.Transaction.fromRaw(decode(hex)); for (let [i, input] of tx.inputs.entries()) { - let { nonWitnessUtxo, path } = inputs[i]; - tx.updateInput(i, { nonWitnessUtxo }); + let { witnessUtxo, path } = inputs[i]; + witnessUtxo.amount = BigInt(witnessUtxo.amount); + witnessUtxo.script = decode(witnessUtxo.script); let key = child.derive(path); - let { privateKey, publicKey } = key; - let address = btc.getAddress("wpkh", privateKey, network); - tx.signIdx(privateKey, i); + tx.updateInput(i, { witnessUtxo }); + tx.signIdx(key.privateKey, i); } + tx.finalize(); hex = tx.hex; + console.log("HEX", hex); signed = true; await tick(); submit.click(); @@ -182,7 +186,7 @@ <input name="pin" value={$pin} type="hidden" /> <input name="hex" value={hex} type="hidden" /> <input name="rate" value={$rate} type="hidden" /> - <input name="account" value={account.id} type="hidden" /> + <input name="aid" value={account.id} type="hidden" /> <input name="signed" value={signed} type="hidden" /> <div class="flex justify-center gap-2"> @@ -205,7 +209,7 @@ </div> {#if passwordPrompt} - <WalletPass bind:password bind:cancel /> + <WalletPass bind:password bind:cancel submit={signTx} /> {/if} <style> |
