@nostr-dev-kit/ndk-wallet
Version:
109 lines (90 loc) • 3.85 kB
text/typescript
import type { Proof } from "@cashu/cashu-ts";
import type NDK from "@nostr-dev-kit/ndk";
import {
type CashuPaymentInfo,
type LnPaymentInfo,
NDKCashuWalletTx,
type NDKNutzap,
type NDKPaymentConfirmationLN,
type NDKRelaySet,
NDKUser,
proofsTotalBalance,
} from "@nostr-dev-kit/ndk";
import { getBolt11Amount, getBolt11Description } from "../../../utils/ln";
import type { MintUrl } from "../mint/utils";
import type { TokenCreationResult } from "../pay/nut";
import type { WalletOperation } from "./effect";
import type { PaymentWithOptionalZapInfo } from "./payment";
import type { UpdateStateResult } from "./state/update";
/**
* Creates a tx event for outgoing payment, this means we are spending cashu proofs.
*
* Nutzaps are only here to indicate that we have redeemed nutzaps and spent them into a non-NIP-60 wallet,
* like when redeeming nutzaps into an NWC wallet.
*/
export async function createOutTxEvent(
ndk: NDK,
paymentRequest: PaymentWithOptionalZapInfo<LnPaymentInfo | CashuPaymentInfo>,
paymentResult: WalletOperation<NDKPaymentConfirmationLN | TokenCreationResult>,
relaySet?: NDKRelaySet,
{ nutzaps }: { nutzaps?: NDKNutzap[] } = {},
): Promise<NDKCashuWalletTx> {
let description: string | undefined = paymentRequest.paymentDescription;
let amount: number | undefined;
if ((paymentRequest as LnPaymentInfo).pr) {
amount = getBolt11Amount((paymentRequest as LnPaymentInfo).pr);
description ??= getBolt11Description((paymentRequest as LnPaymentInfo).pr);
if (amount) amount /= 1000; // convert to sats
} else {
amount = paymentRequest.amount;
}
if (!amount) {
console.error("BUG: Unable to find amount for paymentRequest", paymentRequest);
}
const txEvent = new NDKCashuWalletTx(ndk);
txEvent.direction = "out";
txEvent.amount = amount ?? 0;
txEvent.mint = paymentResult.mint;
txEvent.description = description;
if (paymentResult.fee) txEvent.fee = paymentResult.fee;
if (paymentRequest.target) {
// tag the target if there is one
txEvent.tags.push(paymentRequest.target.tagReference());
if (!(paymentRequest.target instanceof NDKUser)) {
txEvent.tags.push(["p", paymentRequest.target.pubkey]);
}
}
if (nutzaps) {
txEvent.description ??= "nutzap redeem";
for (const nutzap of nutzaps) txEvent.addRedeemedNutzap(nutzap);
}
if (paymentResult.stateUpdate?.created) txEvent.createdTokens = [paymentResult.stateUpdate.created];
if (paymentResult.stateUpdate?.deleted) txEvent.destroyedTokenIds = paymentResult.stateUpdate.deleted;
if (paymentResult.stateUpdate?.reserved) txEvent.reservedTokens = [paymentResult.stateUpdate.reserved];
await txEvent.sign();
txEvent.publish(relaySet);
return txEvent;
}
export async function createInTxEvent(
ndk: NDK,
proofs: Proof[],
mint: MintUrl,
updateStateResult: UpdateStateResult,
{ nutzaps, fee, description }: { nutzaps?: NDKNutzap[]; fee?: number; description?: string },
relaySet?: NDKRelaySet,
): Promise<NDKCashuWalletTx> {
const txEvent = new NDKCashuWalletTx(ndk);
const amount = proofsTotalBalance(proofs);
txEvent.direction = "in";
txEvent.amount = amount;
txEvent.mint = mint;
txEvent.description = description;
if (updateStateResult.created) txEvent.createdTokens = [updateStateResult.created];
if (updateStateResult.deleted) txEvent.destroyedTokenIds = updateStateResult.deleted;
if (updateStateResult.reserved) txEvent.reservedTokens = [updateStateResult.reserved];
if (nutzaps) for (const nutzap of nutzaps) txEvent.addRedeemedNutzap(nutzap);
if (fee) txEvent.fee = fee;
await txEvent.sign();
txEvent.publish(relaySet);
return txEvent;
}