From 3aab57df2063d913bd16b953187ced242421f66a Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 26 Nov 2025 21:44:55 -0800 Subject: ark stuff --- src/components/Account.svelte | 86 ++++++++- src/components/InvoiceActions.svelte | 32 ++-- src/lib/ark.ts | 97 +--------- src/lib/parse.ts | 4 +- src/routes/(app)/+layout.svelte | 14 +- src/routes/(app)/account/ark/+page.svelte | 228 +++++++++++++++++++++++ src/routes/(app)/account/bitcoin/+page.svelte | 34 ++++ src/routes/(app)/account/savings/+page.svelte | 49 ++--- src/routes/(app)/ark/+page.server.ts | 11 -- src/routes/(app)/ark/+page.svelte | 113 ----------- src/routes/(app)/invoice/[id]/+layout.server.ts | 1 - src/routes/(app)/send/ark/[address]/+page.svelte | 3 + 12 files changed, 395 insertions(+), 277 deletions(-) create mode 100644 src/routes/(app)/account/ark/+page.svelte create mode 100644 src/routes/(app)/account/bitcoin/+page.svelte delete mode 100644 src/routes/(app)/ark/+page.server.ts delete mode 100644 src/routes/(app)/ark/+page.svelte (limited to 'src') 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 @@
+ +{#if passwordPrompt} + +{/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);
@@ -133,7 +133,9 @@
Lightning
- {:else} + {/if} + + {#if account?.type === types.ark} + {:else} + {/if} - - {#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 => { 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 -): Promise => { - const address = await getAddress(); - if (address !== currentAddress) { - await updateFn(address); - } - return address; -}; - -export const sendArk = async (address: string, amount: number): Promise => { - 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 @@ + + +
+
+ +

Create Ark Wallet

+
+ +
+ {#if !confirmed} +
+

+ 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. +

+ + {#if showNsec} +
+
Your backup key (nsec)
+
copy(nsec)} + > + {nsec} +
+
+ Click to copy. Store this somewhere safe - anyone with this key can spend your funds. +
+
+ +
+ + +
+ {:else} + + {/if} +
+ {:else} +
+

+ Set a password to encrypt your key. You'll need this password to send funds. +

+ + + + + +
+ + +
+
+ {/if} +
+
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 @@ + + + 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 @@

- {$t("accounts.accountSetup")} + Choose wallet type

-
-
- -
-
- -
-
-
{$t("accounts.create")}
-
{$t("accounts.generateSeed")}
+
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 @@ - - -
-
- -

Ark Wallet

-
- -
- {#if loading} -
-
-
- {:else} -
- - {#if balance.pending > 0} -
- +{s(balance.pending)} pending -
- {/if} -
- - - - - -
- -
-
Your ARK Address
-
copy(address)} - > - {address} -
-
- -
-
Backup Key
- {#if showNsec} -
- {nsec} -
-
⚠️ Keep this secret! Anyone with this key can spend your funds.
- {:else} - - {/if} -
- {/if} -
-
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, -- cgit v1.2.3