Initial Commit
This commit is contained in:
commit
2d858727b0
10 changed files with 1128 additions and 0 deletions
107
cashu.ts
Normal file
107
cashu.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
import { CashuMint, type Proof } from "@cashu/cashu-ts";
|
||||
import { CashuWallet } from "@cashu/cashu-ts";
|
||||
import NpubCash from "./npubCash";
|
||||
import type { CashuStore, CashuTxn } from "./paymentStatus";
|
||||
import PortalBtcWallet from ".";
|
||||
|
||||
export default class PortalBtcWalletCashu {
|
||||
private npubCash: NpubCash;
|
||||
private cashuTxns: CashuTxn[] = [];
|
||||
private proofs: Proof[] = [];
|
||||
private onBalanceUpdated: (() => void) | null = null;
|
||||
|
||||
get txns() {
|
||||
return this.cashuTxns;
|
||||
}
|
||||
|
||||
get cashuWallet() {
|
||||
const mint = new CashuMint(PortalBtcWallet.MINT_URL);
|
||||
return new CashuWallet(mint);
|
||||
}
|
||||
|
||||
get balance() {
|
||||
return this.proofs.reduce((sum, p) => sum + p.amount, 0);
|
||||
}
|
||||
|
||||
constructor(
|
||||
mnemonic: string,
|
||||
private cashuStore: CashuStore,
|
||||
) {
|
||||
this.npubCash = new NpubCash(mnemonic);
|
||||
}
|
||||
|
||||
async init(onBalanceUpdated: () => void) {
|
||||
this.cashuTxns = await this.cashuStore.getTxns();
|
||||
this.proofs = await this.cashuStore.getProofs();
|
||||
this.onBalanceUpdated = onBalanceUpdated;
|
||||
}
|
||||
|
||||
async redeemCashuQuotes() {
|
||||
const attempt = this.npubCash.tryRedeemUnredeemedCashuQuotes(
|
||||
await this.cashuStore.getLastRedeemedCashuQuoteTimestamp(),
|
||||
);
|
||||
for await (const quote of attempt) {
|
||||
this.cashuTxns.push({
|
||||
txId: `cashu-quote-${quote.quoteId}`,
|
||||
paymentType: "receive",
|
||||
amountSat: quote.amountSat,
|
||||
timestamp: quote.timestamp,
|
||||
status: "complete",
|
||||
});
|
||||
}
|
||||
const proofs = await attempt.next();
|
||||
if (!proofs.done || typeof proofs.value === "undefined") return [];
|
||||
this.proofs.push(...proofs.value);
|
||||
await this.persistState();
|
||||
this.onBalanceUpdated?.();
|
||||
return proofs.value;
|
||||
}
|
||||
|
||||
async persistState() {
|
||||
await this.cashuStore.persistProofs(this.proofs);
|
||||
await this.cashuStore.persistTxns(this.cashuTxns);
|
||||
await this.cashuStore.persistLastRedeemedCashuQuoteTimestamp(
|
||||
this.cashuTxns[this.cashuTxns.length - 1]?.timestamp ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
async meltProofsToPayInvoice(invoice: string) {
|
||||
const meltQuote = await this.cashuWallet.createMeltQuote(invoice);
|
||||
const amountToMelt = meltQuote.amount + meltQuote.fee_reserve;
|
||||
const { keep, send } = await this.cashuWallet.send(
|
||||
amountToMelt,
|
||||
this.proofs,
|
||||
{
|
||||
includeFees: true,
|
||||
},
|
||||
);
|
||||
const { change } = await this.cashuWallet.meltProofs(meltQuote, send);
|
||||
this.proofs = [...keep, ...change];
|
||||
this.cashuTxns.push({
|
||||
txId: `cashu-send-${Date.now()}`,
|
||||
paymentType: "send",
|
||||
amountSat: amountToMelt,
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
status: "complete",
|
||||
});
|
||||
await this.persistState();
|
||||
this.onBalanceUpdated?.();
|
||||
}
|
||||
|
||||
async redeemToken(token: string): Promise<void> {
|
||||
if (!token.trim()) throw new Error("Token is empty");
|
||||
|
||||
const received = await this.cashuWallet.receive(token.trim());
|
||||
this.proofs.push(...received);
|
||||
const amountReceived = received.reduce((sum, p) => sum + p.amount, 0);
|
||||
this.cashuTxns.push({
|
||||
txId: `cashu-receive-${Date.now()}`,
|
||||
paymentType: "receive",
|
||||
amountSat: amountReceived,
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
status: "complete",
|
||||
});
|
||||
await this.persistState();
|
||||
this.onBalanceUpdated?.();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue