Skip to content

Commit 5e01601

Browse files
committed
refactor some wallet code
1 parent 3878d89 commit 5e01601

File tree

6 files changed

+242
-284
lines changed

6 files changed

+242
-284
lines changed

ndk-mobile/src/providers/session/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ const NDKSessionProvider = ({ children, ...opts }: PropsWithChildren<NDKSessionP
148148
if (opts.wallet) filters[0].kinds!.push(NDKKind.CashuWallet);
149149
if (opts.kinds) filters[0].kinds!.push(...opts.kinds.keys());
150150

151-
if (opts.settingsStore) {
151+
if (opts.settingsStore && !ndk.wallet) {
152152
loadWallet(ndk, opts.settingsStore, (wallet) => setActiveWallet(wallet, false));
153153
}
154154

ndk-wallet/src/nutzap-monitor/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export class NDKNutzapMonitor extends EventEmitter<{
204204

205205
if (!wallet) throw new Error("wallet not found for nutzap");
206206
privkey = wallet.privkey;
207-
207+
208208
const _wallet = await wallet.walletForMint(mint);
209209
if (!_wallet) throw new Error("unable to load wallet for mint " + mint);
210210
const proofsWeHave = wallet.proofsForMint(mint);
@@ -222,6 +222,7 @@ export class NDKNutzapMonitor extends EventEmitter<{
222222
// save new proofs in wallet
223223
wallet.saveProofs(res, mint, { nutzap, amount: receivedAmount });
224224
} catch (e: any) {
225+
console.log("failed to redeem nutzap", nutzap.id, e.message);
225226
this.emit("failed", nutzap, e.message);
226227
}
227228
} catch (e: any) {

ndk-wallet/src/wallets/cashu/pay.ts

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import type { NDKCashuWallet } from "./wallet";
33
import createDebug from "debug";
44
import type { CashuPaymentInfo, LnPaymentInfo, NDKZapDetails } from "@nostr-dev-kit/ndk";
55
import type { NutPayment } from "./pay/nut.js";
6-
import { createTokenForPayment } from "./pay/nut.js";
76
import { payLn } from "./pay/ln.js";
87
import { decode as decodeBolt11 } from "light-bolt11-decoder";
98

10-
function correctP2pk(p2pk?: string) {
9+
export function correctP2pk(p2pk?: string) {
1110
if (p2pk) {
1211
if (p2pk.length === 64) p2pk = `02${p2pk}`;
1312
}
@@ -18,64 +17,64 @@ function correctP2pk(p2pk?: string) {
1817
/**
1918
* Uses cashu balance to make a payment, whether a cashu swap or a lightning
2019
*/
21-
export class NDKCashuPay {
22-
public wallet: NDKCashuWallet;
23-
public info: NDKZapDetails<LnPaymentInfo | CashuPaymentInfo>;
24-
public type: "ln" | "nut" = "ln";
25-
public debug = createDebug("ndk-wallet:cashu:pay");
26-
public unit: string = "sat";
20+
// export class NDKCashuPay {
21+
// public wallet: NDKCashuWallet;
22+
// public info: NDKZapDetails<LnPaymentInfo | CashuPaymentInfo>;
23+
// public type: "ln" | "nut" = "ln";
24+
// public debug = createDebug("ndk-wallet:cashu:pay");
25+
// public unit: string = "sat";
2726

28-
constructor(wallet: NDKCashuWallet, info: NDKZapDetails<LnPaymentInfo | CashuPaymentInfo>) {
29-
this.wallet = wallet;
27+
// constructor(wallet: NDKCashuWallet, info: NDKZapDetails<LnPaymentInfo | CashuPaymentInfo>) {
28+
// this.wallet = wallet;
3029

31-
if ((info as LnPaymentInfo).pr) {
32-
this.type = "ln";
33-
this.info = info as NDKZapDetails<LnPaymentInfo>;
34-
} else {
35-
this.type = "nut";
36-
this.info = info as NDKZapDetails<CashuPaymentInfo>;
37-
if (this.info.unit.startsWith("msat")) {
38-
this.info.unit = "sat";
39-
this.info.amount = this.info.amount / 1000;
40-
this.info.p2pk = correctP2pk(this.info.p2pk);
41-
}
30+
// if ((info as LnPaymentInfo).pr) {
31+
// this.type = "ln";
32+
// this.info = info as NDKZapDetails<LnPaymentInfo>;
33+
// } else {
34+
// this.type = "nut";
35+
// this.info = info as NDKZapDetails<CashuPaymentInfo>;
36+
// if (this.info.unit.startsWith("msat")) {
37+
// this.info.unit = "sat";
38+
// this.info.amount = this.info.amount / 1000;
39+
// this.info.p2pk = correctP2pk(this.info.p2pk);
40+
// }
4241

43-
this.debug("nut payment %o", this.info);
44-
}
45-
}
42+
// this.debug("nut payment %o", this.info);
43+
// }
44+
// }
4645

47-
public getAmount() {
48-
if (this.type === "ln") {
49-
const bolt11 = (this.info as LnPaymentInfo).pr;
50-
const { sections } = decodeBolt11(bolt11);
51-
for (const section of sections) {
52-
if (section.name === "amount") {
53-
const { value } = section;
54-
return Number(value);
55-
}
56-
}
57-
// stab
58-
return 1;
59-
} else {
60-
return (this.info as NutPayment).amount;
61-
}
62-
}
46+
// public getAmount() {
47+
// if (this.type === "ln") {
48+
// const bolt11 = (this.info as LnPaymentInfo).pr;
49+
// const { sections } = decodeBolt11(bolt11);
50+
// for (const section of sections) {
51+
// if (section.name === "amount") {
52+
// const { value } = section;
53+
// return Number(value);
54+
// }
55+
// }
56+
// // stab
57+
// return 1;
58+
// } else {
59+
// return (this.info as NutPayment).amount;
60+
// }
61+
// }
6362

64-
/**
65-
*
66-
* @param description A description of what this payment is for to be added to the wallet history
67-
* @param nutzap If this payment is a nutzap, this is the nutzap to be added to the wallet history
68-
* @returns
69-
*/
70-
public async pay(payment: NDKZapDetails<LnPaymentInfo | NutPayment>) {
71-
if (this.type === "ln") {
72-
return this.payLn(payment as NDKZapDetails<LnPaymentInfo>)
73-
} else {
74-
return this.payNut(payment as NDKZapDetails<NutPayment>);
75-
}
76-
}
63+
// /**
64+
// *
65+
// * @param description A description of what this payment is for to be added to the wallet history
66+
// * @param nutzap If this payment is a nutzap, this is the nutzap to be added to the wallet history
67+
// * @returns
68+
// */
69+
// public async pay(payment: NDKZapDetails<LnPaymentInfo | NutPayment>) {
70+
// if (this.type === "ln") {
71+
// return this.payLn(payment as NDKZapDetails<LnPaymentInfo>)
72+
// } else {
73+
// return this.payNut(payment as NDKZapDetails<NutPayment>);
74+
// }
75+
// }
7776

78-
public payNut = createTokenForPayment.bind(this);
77+
// public payNut = createTokenForPayment.bind(this);
7978

80-
public payLn = payLn.bind(this);
81-
}
79+
// public payLn = payLn.bind(this);
80+
// }

ndk-wallet/src/wallets/cashu/pay/ln.ts

Lines changed: 46 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,30 @@
1-
import { CashuWallet, CashuMint, Proof, MeltQuoteState } from "@cashu/cashu-ts";
1+
import { CashuWallet, CashuMint, Proof, MeltQuoteState, SendResponse } from "@cashu/cashu-ts";
22
import { NDKEvent, NDKTag, NDKUser, NDKZapDetails, type LnPaymentInfo } from "@nostr-dev-kit/ndk";
3-
import type { NDKCashuPay } from "../pay";
43
import { rollOverProofs, type TokenSelection } from "../proofs";
54
import type { MintUrl } from "../mint/utils";
65
import { NDKCashuWallet } from "../wallet";
76
import { NDKWalletChange } from "../history";
87

9-
export async function payLn(
10-
this: NDKCashuPay,
11-
payment: NDKZapDetails<LnPaymentInfo>,
12-
useMint?: MintUrl,
13-
): Promise<string | undefined> {
14-
this.debug("payLn %o", this.info);
15-
16-
const mintBalances = this.wallet.mintBalances;
17-
const amount = this.getAmount() / 1000; // convert msat to sat
18-
const data = this.info as LnPaymentInfo;
19-
if (!data.pr) throw new Error("missing pr");
20-
21-
return new Promise<string>((resolve, reject) => {
22-
const eligibleMints = getEligibleMints(mintBalances, amount, useMint, this.debug);
23-
24-
if (eligibleMints.length === 0) {
25-
handleInsufficientBalance(amount, data.pr, this.wallet, this.debug, reject);
26-
return;
27-
}
28-
29-
attemptPaymentWithEligibleMints(
30-
eligibleMints,
31-
data.pr,
32-
amount,
33-
this.wallet,
34-
payment,
35-
this.debug,
36-
resolve,
37-
reject
38-
);
39-
});
40-
}
41-
42-
function getEligibleMints(
43-
mintBalances: Record<string, number>,
44-
amount: number,
45-
useMint: MintUrl | undefined,
46-
debug: NDKCashuPay["debug"]
47-
): string[] {
48-
return Object.entries(mintBalances)
49-
.filter(([mint, balance]) => {
50-
if (useMint && mint !== useMint) return false;
51-
if (balance < amount) {
52-
debug("mint %s has insufficient balance %d", mint, balance, amount);
53-
return false;
54-
}
55-
return true;
56-
})
57-
.map(([mint]) => mint);
58-
}
8+
type LNPaymentResult = SendResponse & { preimage: string, change: Proof[], mint: MintUrl };
599

60-
function handleInsufficientBalance(
10+
export async function payLn(
11+
wallet: NDKCashuWallet,
6112
amount: number,
6213
pr: string,
63-
wallet: NDKCashuPay["wallet"],
64-
debug: NDKCashuPay["debug"],
65-
reject: (reason: string) => void
66-
): void {
67-
wallet.emit("insufficient_balance", { amount, pr });
68-
debug("no mint with sufficient balance found");
69-
reject("no mint with sufficient balance found");
70-
}
71-
72-
async function attemptPaymentWithEligibleMints(
73-
eligibleMints: string[],
74-
pr: string,
75-
amount: number,
76-
wallet: NDKCashuPay["wallet"],
77-
payment: NDKZapDetails<LnPaymentInfo>,
78-
debug: NDKCashuPay["debug"],
79-
resolve: (value: string) => void,
80-
reject: (reason: string, errors: Record<string, string>) => void
81-
): Promise<void> {
82-
const errors: Record<string, string> = {};
14+
): Promise<LNPaymentResult | undefined | null> {
15+
const eligibleMints = wallet.getMintsWithBalance(amount);
16+
console.log("eligible mints", eligibleMints, {amount});
8317

8418
for (const mint of eligibleMints) {
8519
try {
86-
const result = await executePayment(mint, pr, amount, wallet, payment, debug);
20+
const result = await executePayment(mint, pr, amount, wallet);
8721
if (result) {
88-
resolve(result);
89-
return;
22+
return result;
9023
}
9124
} catch (error: any) {
92-
debug("Failed to execute payment for mint %s: %s", mint, error);
93-
errors[mint] = error.message;
25+
console.log("Failed to execute payment for mint %s: %s", mint, error);
9426
}
9527
}
96-
97-
reject("Failed to pay with any mint", errors);
9828
}
9929

10030
/**
@@ -120,9 +50,8 @@ async function executePayment(
12050
pr: string,
12151
amount: number,
12252
wallet: NDKCashuWallet,
123-
payment: NDKZapDetails<LnPaymentInfo>,
124-
debug: NDKCashuPay["debug"]
125-
): Promise<string | undefined | null> {
53+
): Promise<LNPaymentResult | undefined | null> {
54+
console.log("executing payment from mint", mint);
12655
const _wallet = await wallet.walletForMint(mint);
12756
if (!_wallet) throw new Error("unable to load wallet for mint " + mint);
12857
const mintProofs = wallet.proofsForMint(mint);
@@ -135,10 +64,10 @@ async function executePayment(
13564
const meltQuote = await _wallet.createMeltQuote(pr);
13665
const amountToSend = meltQuote.amount + meltQuote.fee_reserve;
13766

138-
const res = _wallet.selectProofsToSend(mintProofs, amountToSend);
67+
const proofs = _wallet.selectProofsToSend(mintProofs, amountToSend);
13968

140-
const meltResult = await _wallet.meltProofs(meltQuote, mintProofs);
141-
debug("Melt result: %o", meltResult);
69+
const meltResult = await _wallet.meltProofs(meltQuote, proofs.send);
70+
console.log("Melt result: %o", meltResult);
14271

14372
const fee = calculateFee(amount, mintProofs, meltResult.change);
14473

@@ -151,59 +80,46 @@ async function executePayment(
15180

15281
// generate history event
15382
if (meltResult.quote.state === MeltQuoteState.PAID && meltResult.quote.payment_preimage) {
154-
debug("Payment successful");
155-
const { destroyedTokens, createdToken } = await rollOverProofs(
156-
{
157-
usedProofs: mintProofs,
158-
movedProofs: [
159-
...meltResult.keep,
160-
...meltResult.change
161-
],
162-
usedTokens: mintProofs,
163-
mint,
164-
},
165-
[],
166-
mint,
167-
wallet
168-
);
169-
const historyEvent = new NDKWalletChange(wallet.ndk);
170-
historyEvent.destroyedTokens = destroyedTokens;
171-
if (createdToken) historyEvent.createdTokens = [createdToken];
172-
if (wallet.event) historyEvent.tag(wallet.event);
173-
historyEvent.direction = 'out';
174-
historyEvent.description = payment.paymentDescription;
83+
console.log("Payment successful");
84+
85+
// const historyEvent = new NDKWalletChange(wallet.ndk);
86+
// historyEvent.destroyedTokens = sendProofs;
87+
// historyEvent.createdTokens = meltResult.change;
88+
// if (wallet.event) historyEvent.tag(wallet.event);
89+
// historyEvent.direction = 'out';
90+
// historyEvent.description = payment.paymentDescription;
17591

176-
if (payment.target) {
177-
let tag: NDKTag | undefined;
92+
// if (payment.target) {
93+
// let tag: NDKTag | undefined;
17894

179-
if (payment.target instanceof NDKEvent) {
180-
tag = payment.target.tagReference();
181-
} else if (payment.target instanceof NDKUser && !payment.recipientPubkey) {
182-
tag = ['p', payment.target.pubkey];
183-
}
184-
185-
if (tag) {
186-
console.log("adding tag", tag);
187-
historyEvent.tags.push(tag);
188-
}
189-
}
95+
// if (payment.target instanceof NDKEvent) {
96+
// tag = payment.target.tagReference();
97+
// } else if (payment.target instanceof NDKUser && !payment.recipientPubkey) {
98+
// tag = ['p', payment.target.pubkey];
99+
// }
100+
101+
// if (tag) {
102+
// console.log("adding tag", tag);
103+
// historyEvent.tags.push(tag);
104+
// }
105+
// }
190106

191-
if (payment.recipientPubkey) {
192-
historyEvent.tags.push(['p', payment.recipientPubkey]);
193-
}
107+
// if (payment.recipientPubkey) {
108+
// historyEvent.tags.push(['p', payment.recipientPubkey]);
109+
// }
194110

195-
historyEvent.tags.push(['preimage', meltResult.quote.payment_preimage]);
196-
historyEvent.amount = meltResult.quote.amount;
197-
historyEvent.fee = fee;
198-
historyEvent.publish(wallet.relaySet);
111+
// historyEvent.tags.push(['preimage', meltResult.quote.payment_preimage]);
112+
// historyEvent.amount = meltResult.quote.amount;
113+
// historyEvent.fee = fee;
114+
// historyEvent.publish(wallet.relaySet);
199115

200-
return meltResult.quote.payment_preimage;
116+
return { preimage: meltResult.quote.payment_preimage, change: meltResult.change, ...proofs, mint };
201117
}
202118

203-
return meltResult.quote.payment_preimage;
119+
return null;
204120
} catch (e) {
205121
if (e instanceof Error) {
206-
debug("Failed to pay with mint %s", e.message);
122+
console.log("Failed to pay with mint %s", e.message);
207123
// if (e.message.match(/already spent/i)) {
208124
// debug("Proofs already spent, rolling over");
209125
// rollOverProofs(selection, [], selection.mint, wallet);

0 commit comments

Comments
 (0)