clean code, and use newly created PortalBtcWallet library
This commit is contained in:
parent
9825c53c1c
commit
45dfe1a1c7
22 changed files with 503 additions and 1087 deletions
|
@ -4,23 +4,19 @@ import {
|
|||
generateSecretKey,
|
||||
getPublicKey,
|
||||
nip04,
|
||||
nip19,
|
||||
SimplePool,
|
||||
verifyEvent,
|
||||
} from "nostr-tools";
|
||||
import type { Event as NostrEvent } from "nostr-tools";
|
||||
import { derived, get, type Writable, writable } from "svelte/store";
|
||||
import { derived, get } from "svelte/store";
|
||||
import { browser } from "$app/environment";
|
||||
import { getBreezSDK, refreshBalances } from "$lib/breez.svelte";
|
||||
import type { BindingLiquidSdk } from "@breeztech/breez-sdk-liquid/web";
|
||||
import {
|
||||
bytesToHex,
|
||||
hexToBytes,
|
||||
type MetaEntry,
|
||||
persistentDbWritable,
|
||||
} from "./utils";
|
||||
import { cashuDB, cashuState, getNpub } from "./cashu.svelte";
|
||||
import { send } from "./payments";
|
||||
} from "$lib";
|
||||
import { walletState } from "$lib/wallet.svelte";
|
||||
|
||||
interface PaidInvoice {
|
||||
paymentHash: string;
|
||||
|
@ -81,8 +77,7 @@ interface JsonRpcReq {
|
|||
| "get_balance"
|
||||
| "list_transactions"
|
||||
| "get_info"
|
||||
| "make_invoice"
|
||||
| "lookup_invoice";
|
||||
| "make_invoice";
|
||||
params: Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
@ -161,7 +156,6 @@ async function connect(): Promise<void> {
|
|||
if (!maybePriv) throw new Error("NWC privkey missing");
|
||||
const privkey = maybePriv;
|
||||
const pubkey = getPublicKey(hexToBytes(privkey));
|
||||
const breezSDK = await getBreezSDK();
|
||||
|
||||
pool = new SimplePool();
|
||||
sub = pool.subscribeMany(relays, [
|
||||
|
@ -171,7 +165,7 @@ async function connect(): Promise<void> {
|
|||
},
|
||||
], {
|
||||
onevent: async (evt: NostrEvent) => {
|
||||
await handleEvent(evt, privkey, pubkey, relays, breezSDK);
|
||||
await handleEvent(evt, privkey, pubkey, relays);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -181,7 +175,6 @@ async function handleEvent(
|
|||
privkey: string,
|
||||
ourPubkey: string,
|
||||
relays: string[],
|
||||
breezSDK: BindingLiquidSdk,
|
||||
): Promise<void> {
|
||||
try {
|
||||
if (!verifyEvent(evt)) return;
|
||||
|
@ -231,6 +224,8 @@ async function handleEvent(
|
|||
async function processRpc(
|
||||
req: JsonRpcReq,
|
||||
): Promise<unknown> {
|
||||
const currentWalletState = get(walletState);
|
||||
if (!currentWalletState.open) throw new Error("Wallet not open");
|
||||
console.log("processRpc", req);
|
||||
switch (req.method) {
|
||||
case "pay_invoice": {
|
||||
|
@ -239,102 +234,51 @@ async function processRpc(
|
|||
throw { code: "INTERNAL", message: "missing_invoice" };
|
||||
}
|
||||
|
||||
const breezSDK = await getBreezSDK();
|
||||
const parsed = await breezSDK.parse(destination);
|
||||
|
||||
if (parsed.type !== "bolt11") {
|
||||
throw { code: "INTERNAL", message: "not a bolt11 invoice" };
|
||||
}
|
||||
const paymentHash = (parsed as any).invoice.paymentHash;
|
||||
|
||||
const existing = await nwcDB.paidInvoices.get(paymentHash);
|
||||
if (existing) {
|
||||
throw { code: "OTHER", message: "invoice already paid" };
|
||||
if (await nwcDB.paidInvoices.get(destination)) {
|
||||
throw { code: "OTHER", message: "invoice_already_paid" };
|
||||
}
|
||||
|
||||
const sender = send(destination, 0, parsed);
|
||||
let res = await sender.next();
|
||||
while (!res.done) {
|
||||
const sender = currentWalletState.wallet.pay(destination, 0);
|
||||
let res;
|
||||
try {
|
||||
res = await sender.next();
|
||||
while (!res.done) {
|
||||
res = await sender.next();
|
||||
}
|
||||
} catch (err) {
|
||||
throw { code: "PAYMENT_FAILED", message: (err as Error).message };
|
||||
}
|
||||
|
||||
if (res.value.error) {
|
||||
throw { code: "PAYMENT_FAILED", message: res.value.error };
|
||||
}
|
||||
await nwcDB.paidInvoices.put({
|
||||
paymentHash: destination,
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
}).catch((err) => {
|
||||
console.error("Failed to save paid invoice", err);
|
||||
});
|
||||
|
||||
if (res.value.paymentHash) {
|
||||
await nwcDB.paidInvoices.put({
|
||||
paymentHash: res.value.paymentHash,
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
});
|
||||
}
|
||||
|
||||
await refreshBalances();
|
||||
return {
|
||||
preimage: res.value.preimage,
|
||||
paymentHash: res.value.paymentHash,
|
||||
};
|
||||
return {};
|
||||
// TODO: check if it works without the preimage and paymentHash
|
||||
// return {
|
||||
// preimage: res.value.preimage,
|
||||
// paymentHash: res.value.paymentHash,
|
||||
// };
|
||||
}
|
||||
case "get_balance": {
|
||||
const breezSDK = await getBreezSDK();
|
||||
const info = await breezSDK.getInfo();
|
||||
return {
|
||||
balance: info.walletInfo.balanceSat * 1000 + get(cashuState).balance *
|
||||
1000,
|
||||
balance: currentWalletState.balance * 1000,
|
||||
};
|
||||
}
|
||||
case "list_transactions": {
|
||||
const from_timestamp =
|
||||
(req.params?.from_timestamp as number | undefined) ?? 0;
|
||||
const to_timestamp = (req.params?.to_timestamp as number | undefined) ??
|
||||
undefined;
|
||||
const limit = (req.params?.limit as number | undefined) ?? 20;
|
||||
const offset = (req.params?.offset as number | undefined) ?? undefined;
|
||||
const offset = (req.params?.offset as number | undefined) ?? 0;
|
||||
|
||||
const breezSDK = await getBreezSDK();
|
||||
const liquidPayments = (await breezSDK.listPayments({
|
||||
fromTimestamp: from_timestamp,
|
||||
toTimestamp: to_timestamp,
|
||||
const transactions = await currentWalletState.wallet.listPayments(
|
||||
limit,
|
||||
offset,
|
||||
})) as any[];
|
||||
|
||||
const cashuTxns = await cashuDB.txns.toArray();
|
||||
|
||||
const allTxns = [
|
||||
...liquidPayments.map((p) => ({
|
||||
type: p.paymentType,
|
||||
invoice: p.bolt11,
|
||||
description: p.description,
|
||||
payment_hash: p.paymentHash,
|
||||
preimage: p.paymentPreimage,
|
||||
amount: p.amountSat * 1000,
|
||||
fees_paid: p.feesSat * 1000,
|
||||
created_at: Math.floor(p.paymentTime / 1000),
|
||||
settled_at: p.status === "complete"
|
||||
? Math.floor(p.paymentTime / 1000)
|
||||
: undefined,
|
||||
})),
|
||||
...cashuTxns.map((p) => ({
|
||||
type: p.paymentType,
|
||||
invoice: "",
|
||||
description: "Cashu",
|
||||
payment_hash: p.txId,
|
||||
preimage: "",
|
||||
amount: p.amountSat * 1000,
|
||||
fees_paid: 0,
|
||||
created_at: p.timestamp,
|
||||
settled_at: p.timestamp,
|
||||
})),
|
||||
].sort((a, b) => b.created_at - a.created_at);
|
||||
|
||||
return {
|
||||
transactions: allTxns,
|
||||
};
|
||||
);
|
||||
return { transactions };
|
||||
}
|
||||
case "get_info": {
|
||||
const breezSDK = await getBreezSDK();
|
||||
const info = await breezSDK.getInfo();
|
||||
const privkey = get(nwcPrivkey);
|
||||
if (!privkey) throw new Error("missing_privkey");
|
||||
|
||||
|
@ -349,7 +293,6 @@ async function processRpc(
|
|||
"list_transactions",
|
||||
"get_info",
|
||||
"make_invoice",
|
||||
"lookup_invoice",
|
||||
],
|
||||
notifications: [],
|
||||
};
|
||||
|
@ -361,7 +304,9 @@ async function processRpc(
|
|||
throw { code: "INTERNAL", message: "missing_amount" };
|
||||
}
|
||||
|
||||
const npub = await getNpub();
|
||||
const npub = currentWalletState.wallet.npub;
|
||||
if (!npub) throw new Error("Wallet not open");
|
||||
|
||||
const res = await fetch(
|
||||
`/.well-known/lnurl-pay/callback/${npub}?amount=${amountMsat}`,
|
||||
);
|
||||
|
@ -385,35 +330,6 @@ async function processRpc(
|
|||
invoice,
|
||||
};
|
||||
}
|
||||
case "lookup_invoice": {
|
||||
const paymentHash = req.params?.payment_hash as string | undefined;
|
||||
|
||||
if (!paymentHash) {
|
||||
throw { code: "INTERNAL", message: "missing_payment_hash" };
|
||||
}
|
||||
|
||||
const breezSDK = await getBreezSDK();
|
||||
const payments = (await breezSDK.listPayments({})) as any[];
|
||||
const payment = payments.find((p) => p.paymentHash === paymentHash);
|
||||
|
||||
if (!payment) {
|
||||
throw { code: "NOT_FOUND", message: "invoice_not_found" };
|
||||
}
|
||||
|
||||
return {
|
||||
type: payment.paymentType,
|
||||
invoice: payment.bolt11,
|
||||
description: payment.description,
|
||||
payment_hash: payment.paymentHash,
|
||||
preimage: payment.paymentPreimage,
|
||||
amount: payment.amountSat * 1000,
|
||||
fees_paid: payment.feesSat * 1000,
|
||||
created_at: Math.floor(payment.paymentTime / 1000),
|
||||
settled_at: payment.status === "complete"
|
||||
? Math.floor(payment.paymentTime / 1000)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw { code: "NOT_IMPLEMENTED", message: "unknown_method" };
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue