diff options
| author | Adam Soltys <[email protected]> | 2025-11-26 21:44:55 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-11 15:33:08 -0800 |
| commit | 3aab57df2063d913bd16b953187ced242421f66a (patch) | |
| tree | 9f8fcb8d266e00e1112af106d1480e9fc08e8b04 /src | |
| parent | 68e7fe9655f94efc573f3aab7acf60d03c4162a0 (diff) | |
| download | coinos-ui-3aab57df2063d913bd16b953187ced242421f66a.tar.gz coinos-ui-3aab57df2063d913bd16b953187ced242421f66a.zip | |
ark stuff
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Account.svelte | 86 | ||||
| -rw-r--r-- | src/components/InvoiceActions.svelte | 32 | ||||
| -rw-r--r-- | src/lib/ark.ts | 97 | ||||
| -rw-r--r-- | src/lib/parse.ts | 4 | ||||
| -rw-r--r-- | src/routes/(app)/+layout.svelte | 14 | ||||
| -rw-r--r-- | src/routes/(app)/account/ark/+page.svelte | 228 | ||||
| -rw-r--r-- | src/routes/(app)/account/bitcoin/+page.svelte | 34 | ||||
| -rw-r--r-- | src/routes/(app)/account/savings/+page.svelte | 49 | ||||
| -rw-r--r-- | src/routes/(app)/ark/+page.server.ts | 11 | ||||
| -rw-r--r-- | src/routes/(app)/ark/+page.svelte | 113 | ||||
| -rw-r--r-- | src/routes/(app)/invoice/[id]/+layout.server.ts | 1 | ||||
| -rw-r--r-- | src/routes/(app)/send/ark/[address]/+page.svelte | 3 |
12 files changed, 395 insertions, 277 deletions
diff --git a/src/components/Account.svelte b/src/components/Account.svelte index 744821a3..d37101ee 100644 --- a/src/components/Account.svelte +++ b/src/components/Account.svelte @@ -1,20 +1,61 @@ <script> + import { hex } from "@scure/base"; + import WalletPass from "$comp/WalletPass.svelte"; import { run } from "svelte/legacy"; - + import { onMount } from "svelte"; import { goto } from "$app/navigation"; import Icon from "$comp/Icon.svelte"; import Balance from "$comp/Balance.svelte"; import { t } from "$lib/translations"; + import { decrypt } from "nostr-tools/nip49"; + import { arkkey } from "$lib/ark"; let { user, rate, account, last } = $props(); - let { name, seed, balance, id } = $derived(account); + let { + name, + seed, + balance, + id, + type: accountType, + arkAddress, + } = $derived(account); + + let arkBalance = $state(0); + let arkLoading = $state(false); + let passwordPrompt = $state(false); + let password = $state(); + let pendingUrl = $state(); + let cancel = $state(() => { + passwordPrompt = false; + pendingUrl = undefined; + }); + + let setAccount = (event, url) => { + event.preventDefault(); + document.cookie = `aid=${id}; path=/; max-age=86400`; + if (isArk) { + pendingUrl = url; + if ($arkkey) goto(pendingUrl); + else passwordPrompt = true; + } else { + $arkkey = undefined; + goto(url); + } + }; - let setAccount = () => (document.cookie = `aid=${id}; path=/; max-age=86400`); - let go = () => { - setAccount(); - goto("/payments"); + let submitPassword = () => { + $arkkey = hex.encode(decrypt(seed, password)); + passwordPrompt = false; + if (pendingUrl) { + goto(pendingUrl); + pendingUrl = undefined; + } }; - let type = $derived(seed ? "Savings" : "Cash"); + + let displayType = $derived( + accountType === "ark" ? "Ark" : seed ? "Savings" : "Cash", + ); + let isArk = $derived(accountType === "ark"); </script> <div @@ -43,7 +84,11 @@ </div> <div class="flex justify-center w-full text-xl gap-2"> - <a href={"/invoice"} class="contents" onclick={setAccount}> + <a + href={"/invoice"} + class="contents" + onclick={(e) => setAccount(e, "/invoice")} + > <button class="btn !w-auto flex-grow"> <iconify-icon noobserver @@ -55,7 +100,26 @@ </button> </a> - <a href={`/send`} class="contents grow" onclick={setAccount}> + <a + href={"/payments"} + class="contents" + onclick={(e) => setAccount(e, "/payments")} + > + <button class="btn !w-auto flex-grow"> + <iconify-icon + noobserver + icon="ph:clock-bold" + width="32" + flip="horizontal" + ></iconify-icon> + </button> + </a> + + <a + href={`/send`} + class="contents grow" + onclick={(e) => setAccount(e, "/send")} + > <button type="button" class="btn !w-auto flex-grow"> <iconify-icon noobserver icon="ph:paper-plane-right-bold" width="32" ></iconify-icon> @@ -64,3 +128,7 @@ </a> </div> </div> + +{#if passwordPrompt} + <WalletPass bind:password bind:cancel submit={submitPassword} /> +{/if} diff --git a/src/components/InvoiceActions.svelte b/src/components/InvoiceActions.svelte index 08f9920d..b6005217 100644 --- a/src/components/InvoiceActions.svelte +++ b/src/components/InvoiceActions.svelte @@ -19,7 +19,7 @@ toggleMemo, } = $props(); - let { aid, address_type, type } = $derived(invoice); + let { aid, account, address_type, type } = $derived(invoice); </script> <div class="text-secondary space-y-2 text-xl pt-2"> @@ -133,7 +133,9 @@ </div> <div class="my-auto text-lg">Lightning</div> </button> - {:else} + {/if} + + {#if account?.type === types.ark} <button class="btn flex-nowrap !w-auto grow" class:bg-base-300={type === types.ark} @@ -148,22 +150,26 @@ class="bg-black rounded-full w-8 h-8 items-center justify-center flex" > <div class="m-auto"> - <img src="/images/ark.png" class="w-8 h-8 rounded-full object-cover" alt="Bitcoin" /> + <img + src="/images/ark.png" + class="w-8 h-8 rounded-full object-cover" + alt="Bitcoin" + /> </div> </div> <div class="my-auto text-lg">Ark</div> </button> + {:else} + <button + class="btn flex-nowrap !w-auto grow" + class:bg-base-300={type === types.bitcoin} + class:text-secondary={type === types.bitcoin} + onclick={() => setType(types.bitcoin)} + > + <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" /> + <div class="my-auto text-lg">Bitcoin</div> + </button> {/if} - - <button - class="btn flex-nowrap !w-auto grow" - class:bg-base-300={type === types.bitcoin} - class:text-secondary={type === types.bitcoin} - onclick={() => setType(types.bitcoin)} - > - <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" /> - <div class="my-auto text-lg">Bitcoin</div> - </button> </div> {#if aid === user.id} diff --git a/src/lib/ark.ts b/src/lib/ark.ts index 7649a6bf..487898ae 100644 --- a/src/lib/ark.ts +++ b/src/lib/ark.ts @@ -1,54 +1,13 @@ import { persistLocal } from "$lib/store"; -import { get } from "svelte/store"; import { SingleKey, Wallet } from "@arkade-os/sdk"; -import { bytesToHex, randomBytes } from "@noble/hashes/utils"; -import { nip19 } from "nostr-tools"; -import { hex } from "@scure/base"; +import { get } from "svelte/store"; export const arkServerUrl = "http://localhost:7070"; export const arkkey = persistLocal("arkkey", ""); -export const generateKey = (): string => { - const privateKey = bytesToHex(randomBytes(32)); - arkkey.set(privateKey); - return privateKey; -}; - -export const getKey = (): string => { - let key = get(arkkey); - if (!key) { - key = generateKey(); - } - return key; -}; - -export const hasKey = (): boolean => { - return !!get(arkkey); -}; - -export const clearKey = (): void => { - arkkey.set(""); -}; - -export const keyToNsec = (key?: string): string => { - const k = key || getKey(); - return nip19.nsecEncode(hex.decode(k)); -}; - -export const nsecToKey = (nsec: string): string => { - const { type, data } = nip19.decode(nsec); - if (type !== "nsec") throw new Error("Invalid nsec format"); - return bytesToHex(data); -}; - -export const restoreFromNsec = (nsec: string): string => { - const key = nsecToKey(nsec); - arkkey.set(key); - return key; -}; - export const getWallet = async () => { - const key = getKey(); + const key = get(arkkey); + if (!key) return; const identity = SingleKey.fromHex(key); return Wallet.create({ @@ -62,55 +21,7 @@ export const getAddress = async (): Promise<string> => { return wallet.getAddress(); }; -export const getBalance = async (): Promise<{ available: number; pending: number }> => { +export const getBalance = async (): Promise<{ available: number }> => { const wallet = await getWallet(); return wallet.getBalance(); }; - -export const syncArkAddress = async ( - currentAddress: string | undefined, - updateFn: (arkAddress: string) => Promise<void> -): Promise<string> => { - const address = await getAddress(); - if (address !== currentAddress) { - await updateFn(address); - } - return address; -}; - -export const sendArk = async (address: string, amount: number): Promise<string> => { - const wallet = await getWallet(); - const vtxos = await wallet.getVtxos(); - - // Sort by expiry (spend oldest first) - const sorted = vtxos.sort( - (a, b) => (a.virtualStatus.batchExpiry ?? 0) - (b.virtualStatus.batchExpiry ?? 0) - ); - - // Select inputs - const inputs = []; - let selectedAmount = 0; - for (const vtxo of sorted) { - if (selectedAmount >= amount) break; - inputs.push(vtxo); - selectedAmount += vtxo.value; - } - - if (selectedAmount < amount) { - throw new Error(`Insufficient funds: have ${selectedAmount}, need ${amount}`); - } - - // Build outputs - const outputs: { address: string; amount: bigint }[] = [ - { address, amount: BigInt(amount) } - ]; - - // Add change output if needed - const change = selectedAmount - amount; - if (change > 0) { - const changeAddress = await wallet.getAddress(); - outputs.push({ address: changeAddress, amount: BigInt(change) }); - } - - return wallet.settle({ inputs, outputs }); -}; diff --git a/src/lib/parse.ts b/src/lib/parse.ts index c69032d1..bbcab429 100644 --- a/src/lib/parse.ts +++ b/src/lib/parse.ts @@ -11,7 +11,9 @@ export default async (s, host, cookies) => { let invoice; let user; - if (t.startsWith("ark")) redirect(307, `/send/ark/${t}`); + if (t.startsWith("ark") || t.startsWith("tark")) + redirect(307, `/send/ark/${t}`); + if (t.startsWith("http")) redirect(307, t); if (t.startsWith(host)) redirect(307, `http://${t}`); diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index ed76e103..6624fff8 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -76,19 +76,7 @@ if (user) { const wallet = await getWallet(); - wallet.notifyIncomingFunds(handleArkPayment); - - // Sync ARK address with backend if changed - const arkAddress = await getAddress(); - if (arkAddress !== user.arkAddress) { - try { - console.log("SYNCING", arkAddress); - await post("/post/user", { arkAddress }); - user.arkAddress = arkAddress; - } catch (e) { - console.error("Failed to sync ARK address:", e); - } - } + if (wallet) wallet.notifyIncomingFunds(handleArkPayment); } // if (window.NDEFReader) { diff --git a/src/routes/(app)/account/ark/+page.svelte b/src/routes/(app)/account/ark/+page.svelte new file mode 100644 index 00000000..ff313664 --- /dev/null +++ b/src/routes/(app)/account/ark/+page.svelte @@ -0,0 +1,228 @@ +<script lang="ts"> + import { preventDefault } from "svelte/legacy"; + import { tick, onMount } from "svelte"; + import { t } from "$lib/translations"; + import Spinner from "$comp/Spinner.svelte"; + import { encrypt } from "nostr-tools/nip49"; + import { bytesToHex, randomBytes } from "@noble/hashes/utils"; + import { nip19 } from "nostr-tools"; + import { hex } from "@scure/base"; + import { focus, fail, post, copy } from "$lib/utils"; + import { goto } from "$app/navigation"; + import { SingleKey, Wallet } from "@arkade-os/sdk"; + import { arkServerUrl } from "$lib/ark"; + + let { data } = $props(); + let { user } = data; + + let privateKey = $state(""); + let arkAddress = $state(""); + let nsec = $state(""); + let showNsec = $state(false); + let confirmed = $state(false); + let submitting = $state(false); + + let password = $state(""); + let confirm = $state(""); + let revealPassword = $state(false); + let revealConfirm = $state(false); + + let name = "Ark Vault"; + let type = "ark"; + + onMount(() => { + generateKey(); + }); + + let generateKey = async () => { + privateKey = bytesToHex(randomBytes(32)); + nsec = nip19.nsecEncode(hex.decode(privateKey)); + showNsec = false; + confirmed = false; + + // Derive the ARK address from the private key + const identity = SingleKey.fromHex(privateKey); + const wallet = await Wallet.create({ identity, arkServerUrl }); + arkAddress = await wallet.getAddress(); + }; + + let revealNsec = () => { + showNsec = true; + }; + + let confirmBackup = () => { + confirmed = true; + }; + + let submit = async () => { + if (!confirmed) { + fail("Please backup your key first"); + return; + } + + if (!password || password !== confirm) { + fail($t("accounts.passwordMismatch")); + return; + } + + submitting = true; + await tick(); + + try { + // Encrypt the private key using NIP-49 + let seed = await encrypt(hex.decode(privateKey), password); + + await post("/account", { name, seed, type, arkAddress }); + goto(`/${user.username}`); + } catch (e) { + console.log(e); + fail(e.message); + } + + submitting = false; + }; +</script> + +<div class="space-y-5"> + <div class="flex items-center justify-center gap-2"> + <iconify-icon noobserver icon="ph:vault-bold" width="32"></iconify-icon> + <h1 class="text-3xl font-semibold">Create Ark Wallet</h1> + </div> + + <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5"> + {#if !confirmed} + <div class="space-y-4"> + <p class="text-secondary"> + Your Ark wallet is secured by a private key. Back it up now - you won't be able to see it again without your password. + </p> + + {#if showNsec} + <div class="space-y-2"> + <div class="text-sm text-secondary">Your backup key (nsec)</div> + <div + class="text-sm break-all bg-warning/20 p-4 rounded-lg cursor-pointer border border-warning font-mono" + onclick={() => copy(nsec)} + > + {nsec} + </div> + <div class="text-sm text-warning"> + Click to copy. Store this somewhere safe - anyone with this key can spend your funds. + </div> + </div> + + <div class="flex gap-2"> + <button type="button" class="btn flex-grow" onclick={generateKey}> + <iconify-icon noobserver icon="ph:dice-three-bold" width="24"></iconify-icon> + Regenerate + </button> + <button type="button" class="btn btn-accent flex-grow" onclick={confirmBackup}> + <iconify-icon noobserver icon="ph:check-bold" width="24"></iconify-icon> + I've backed it up + </button> + </div> + {:else} + <button type="button" class="btn btn-warning w-full" onclick={revealNsec}> + <iconify-icon noobserver icon="ph:eye-bold" width="24"></iconify-icon> + Reveal backup key + </button> + {/if} + </div> + {:else} + <form onsubmit={preventDefault(submit)} class="space-y-5"> + <p class="text-secondary"> + Set a password to encrypt your key. You'll need this password to send funds. + </p> + + <label + for="password" + class="input flex items-center justify-center gap-2 w-full" + > + {#if revealPassword} + <input + name="password" + type="text" + required + bind:value={password} + autocapitalize="none" + class="clean" + placeholder="Password" + /> + {:else} + <input + use:focus + name="password" + type="password" + placeholder="Password" + required + bind:value={password} + autocapitalize="none" + class="clean" + /> + {/if} + + <iconify-icon + noobserver + class="cursor-pointer ml-auto" + onclick={() => (revealPassword = !revealPassword)} + icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"} + width="32" + ></iconify-icon> + </label> + + <label + for="confirm" + class="input flex items-center justify-center gap-2 w-full" + > + {#if revealConfirm} + <input + name="confirm" + type="text" + placeholder="Confirm password" + required + bind:value={confirm} + autocapitalize="none" + class="clean" + /> + {:else} + <input + type="password" + placeholder="Confirm password" + required + bind:value={confirm} + autocapitalize="none" + class="clean" + /> + {/if} + <iconify-icon + noobserver + class="cursor-pointer ml-auto" + onclick={() => (revealConfirm = !revealConfirm)} + icon={revealConfirm ? "ph:eye-bold" : "ph:eye-slash-bold"} + width="32" + ></iconify-icon> + </label> + + <div class="flex gap-2"> + <button + type="button" + class="btn !w-auto grow" + onclick={() => (confirmed = false)} + > + Back + </button> + <button + disabled={submitting} + type="submit" + class="btn btn-accent !w-auto grow" + > + {#if submitting} + <Spinner /> + {:else} + Create Wallet + {/if} + </button> + </div> + </form> + {/if} + </div> +</div> diff --git a/src/routes/(app)/account/bitcoin/+page.svelte b/src/routes/(app)/account/bitcoin/+page.svelte new file mode 100644 index 00000000..d45ff8c6 --- /dev/null +++ b/src/routes/(app)/account/bitcoin/+page.svelte @@ -0,0 +1,34 @@ +<script> + import { t } from "$lib/translations"; +</script> + +<div class="space-y-5"> + <h1 class="text-center text-3xl font-semibold"> + {$t("accounts.accountSetup")} + </h1> + + <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5"> + <a href="/account/seed" class="block"> + <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> + <figure class="w-20 flex items-center justify-center"> + <iconify-icon noobserver icon="ph:file-plus-bold" width="64"></iconify-icon> + </figure> + <div> + <div class="text-xl">{$t("accounts.create")}</div> + <div class="text-secondary">{$t("accounts.generateSeed")}</div> + </div> + </div> + </a> + <a href="/account/import" class="block"> + <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> + <figure class="w-20 flex items-center justify-center"> + <iconify-icon noobserver icon="ph:folder-open-bold" width="64"></iconify-icon> + </figure> + <div> + <div class="text-xl">{$t("accounts.import")}</div> + <div class="text-secondary">{$t("accounts.importSeed")}</div> + </div> + </div> + </a> + </div> +</div> diff --git a/src/routes/(app)/account/savings/+page.svelte b/src/routes/(app)/account/savings/+page.svelte index 22d550b4..a474ad52 100644 --- a/src/routes/(app)/account/savings/+page.svelte +++ b/src/routes/(app)/account/savings/+page.svelte @@ -1,37 +1,40 @@ <script> import { t } from "$lib/translations"; - import Icon from "$comp/Icon.svelte"; </script> <div class="space-y-5"> <h1 class="text-center text-3xl font-semibold"> - {$t("accounts.accountSetup")} + Choose wallet type </h1> - <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-2"> - <div class="space-y-5"> - <a href="/account/seed" class="block"> - <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> - <figure class="w-20"> - <iconify-icon noobserver icon="ph:file-plus-bold" width="64"></iconify-icon> - </figure> - <div> - <div class="text-xl">{$t("accounts.create")}</div> - <div class="text-secondary">{$t("accounts.generateSeed")}</div> + <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5"> + <a href="/account/bitcoin" class="block"> + <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> + <figure class="w-20 flex items-center justify-center"> + <iconify-icon noobserver icon="ph:coins-bold" width="64"></iconify-icon> + </figure> + <div> + <div class="text-xl">Bitcoin (On-chain)</div> + <div class="text-secondary"> + Standard Bitcoin wallet secured by a 12-word seed phrase. + Full control over your UTXOs. </div> </div> - </a> - <a href="/account/import" class="block"> - <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> - <figure class="w-20"> - <iconify-icon noobserver icon="ph:folder-open-bold" width="64"></iconify-icon> - </figure> - <div> - <div class="text-xl">{$t("accounts.import")}</div> - <div class="text-secondary">{$t("accounts.importSeed")}</div> + </div> + </a> + <a href="/account/ark" class="block"> + <div class="card card-side shadow shadow-base-300 p-8 hover:bg-base-200"> + <figure class="w-20 flex items-center justify-center"> + <iconify-icon noobserver icon="ph:vault-bold" width="64"></iconify-icon> + </figure> + <div> + <div class="text-xl">Ark (Off-chain)</div> + <div class="text-secondary"> + Fast, private transactions using virtual UTXOs. + Lower fees with instant settlement. </div> </div> - </a> - </div> + </div> + </a> </div> </div> diff --git a/src/routes/(app)/ark/+page.server.ts b/src/routes/(app)/ark/+page.server.ts deleted file mode 100644 index bac0a02a..00000000 --- a/src/routes/(app)/ark/+page.server.ts +++ /dev/null @@ -1,11 +0,0 @@ -import getRates from "$lib/rates"; - -export async function load({ depends, parent }) { - depends("app:payments"); - depends("app:items"); - - const { user } = await parent(); - - const rates = await getRates(); - return { rate: rates[user.currency] }; -} diff --git a/src/routes/(app)/ark/+page.svelte b/src/routes/(app)/ark/+page.svelte deleted file mode 100644 index 3089d887..00000000 --- a/src/routes/(app)/ark/+page.svelte +++ /dev/null @@ -1,113 +0,0 @@ -<script> - import { onMount } from "svelte"; - import { getBalance, getAddress, keyToNsec } from "$lib/ark"; - import Amount from "$comp/Amount.svelte"; - import { s, copy } from "$lib/utils"; - import { t } from "$lib/translations"; - - let { data } = $props(); - let { user, rate } = $derived(data); - - let loading = $state(true); - let balance = $state({ available: 0, pending: 0 }); - let address = $state(""); - let showNsec = $state(false); - let nsec = $state(""); - - onMount(async () => { - await refresh(); - }); - - let refresh = async () => { - loading = true; - try { - [balance, address] = await Promise.all([getBalance(), getAddress()]); - } catch (e) { - console.error("Failed to load ARK wallet:", e); - } - loading = false; - }; - - let revealNsec = () => { - nsec = keyToNsec(); - showNsec = true; - }; - - let copyNsec = () => { - copy(nsec); - }; -</script> - -<div class="space-y-5"> - <div class="flex items-center justify-center gap-2"> - <iconify-icon noobserver icon="ph:vault-bold" width="32"></iconify-icon> - <h1 class="text-3xl font-semibold">Ark Wallet</h1> - </div> - - <div class="container w-full mx-auto px-4 max-w-xl space-y-5"> - {#if loading} - <div class="flex justify-center py-8"> - <div class="loading loading-spinner loading-lg"></div> - </div> - {:else} - <div class="text-center space-y-2"> - <Amount - amount={balance.available} - {rate} - currency={user?.currency || "USD"} - /> - {#if balance.pending > 0} - <div class="text-sm text-warning"> - +{s(balance.pending)} pending - </div> - {/if} - </div> - - <div class="flex gap-2 justify-center w-full text-xl"> - <a href="/invoice" class="btn flex-grow"> - <iconify-icon noobserver icon="ph:hand-coins-bold" width="24" flip="horizontal"></iconify-icon> - Receive - </a> - <a href="/send" class="btn flex-grow"> - <iconify-icon noobserver icon="ph:paper-plane-right-bold" width="24"></iconify-icon> - Send - </a> - </div> - - <button class="btn btn-ghost btn-sm w-full" onclick={refresh}> - <iconify-icon noobserver icon="ph:arrows-clockwise-bold" width="20"></iconify-icon> - Refresh - </button> - - <div class="divider"></div> - - <div class="space-y-2"> - <div class="text-sm text-secondary">Your ARK Address</div> - <div - class="text-xs break-all bg-base-200 p-3 rounded-lg cursor-pointer hover:bg-base-300" - onclick={() => copy(address)} - > - {address} - </div> - </div> - - <div class="space-y-2"> - <div class="text-sm text-secondary">Backup Key</div> - {#if showNsec} - <div - class="text-xs break-all bg-warning/20 p-3 rounded-lg cursor-pointer border border-warning" - onclick={copyNsec} - > - {nsec} - </div> - <div class="text-xs text-warning">⚠️ Keep this secret! Anyone with this key can spend your funds.</div> - {:else} - <button class="btn btn-warning btn-sm" onclick={revealNsec}> - <iconify-icon noobserver icon="ph:eye-bold" width="20"></iconify-icon> - Reveal nsec - </button> - {/if} - </div> - {/if} - </div> -</div> diff --git a/src/routes/(app)/invoice/[id]/+layout.server.ts b/src/routes/(app)/invoice/[id]/+layout.server.ts index a18dad4e..ab41dddc 100644 --- a/src/routes/(app)/invoice/[id]/+layout.server.ts +++ b/src/routes/(app)/invoice/[id]/+layout.server.ts @@ -11,7 +11,6 @@ export async function load({ cookies, depends, params, url, parent }) { if (id) { invoice = await get(`/invoice/${id}`); - console.log("INV", invoice); const options = !!url.searchParams.get("options"); let { amount, pending, received } = invoice; amount = parseInt(amount); diff --git a/src/routes/(app)/send/ark/[address]/+page.svelte b/src/routes/(app)/send/ark/[address]/+page.svelte index 6ff6ed58..4f355ec1 100644 --- a/src/routes/(app)/send/ark/[address]/+page.svelte +++ b/src/routes/(app)/send/ark/[address]/+page.svelte @@ -6,6 +6,7 @@ import { page } from "$app/stores"; import { rate } from "$lib/store"; import { loc, fail, s } from "$lib/utils"; + import { getWallet } from "$lib/ark"; let { data } = $props(); @@ -31,6 +32,8 @@ }; let send = async () => { + console.log("SENDING", a); + let wallet = await getWallet(); const txid = await wallet.sendBitcoin({ address, amount, |
