@nostr-dev-kit/ndk-wallet
Version:
109 lines (91 loc) • 4.28 kB
text/typescript
import { NDKCashuToken } from "@nostr-dev-kit/ndk";
import NDK from "@nostr-dev-kit/ndk";
import { mockProof } from "@nostr-dev-kit/ndk/test";
import { beforeEach, describe, expect, it } from "vitest";
import type { WalletProofChange, WalletState } from ".";
import { NDKCashuWallet } from "..";
import { calculateNewState } from "./update";
const ndk = new NDK();
describe("calculateNewState", () => {
const wallet = new NDKCashuWallet(ndk);
let walletState: WalletState;
let stateChange: WalletProofChange;
beforeEach(() => {
walletState = wallet.state;
stateChange = {
store: [],
destroy: [],
reserve: [],
mint: "mintId",
};
});
it("should handle empty state change", () => {
const result = calculateNewState(walletState, stateChange);
expect(result).toEqual({
deletedTokenIds: new Set(),
deletedProofs: new Set(),
reserveProofs: [],
saveProofs: [],
});
});
it("should handle storing new proofs", () => {
const newProof = mockProof("proof1", 100);
stateChange.store = [newProof];
const result = calculateNewState(walletState, stateChange);
expect(result.saveProofs).toContain(newProof);
expect(result.deletedTokenIds.size).toBe(0);
});
it("should handle destroying proofs and affected tokens", () => {
const existingTokenId = "token1";
const existingProof = mockProof("proof1", 100);
const existingToken = new NDKCashuToken(ndk);
existingToken.mint = "mint";
existingToken.proofs = [existingProof];
existingToken.id = existingTokenId;
walletState.addToken(existingToken);
stateChange.destroy = [existingProof];
const result = calculateNewState(walletState, stateChange);
expect(result.deletedTokenIds).toContain(existingTokenId);
expect(result.deletedProofs).toContain(existingProof.C);
expect(result.saveProofs).not.toContain(existingProof);
});
it("should handle moving unused proofs from a deleted token to a new token", () => {
const existingTokenId = "token1";
const usedProof = mockProof("proof1", 100);
const unusedProof = mockProof("proof2", 100);
const existingToken = new NDKCashuToken(ndk);
existingToken.mint = "mint";
existingToken.id = existingTokenId;
existingToken.proofs = [usedProof, unusedProof];
walletState.addToken(existingToken);
stateChange.destroy = [usedProof];
const result = calculateNewState(walletState, stateChange);
expect(result.deletedTokenIds).toContain(existingTokenId);
expect(result.saveProofs).toContainEqual(unusedProof);
expect(result.saveProofs).not.toContain(usedProof);
});
it("should handle destroying multiple proofs from multiple tokens, moving unused proofs from multiple tokens", () => {
const tokens = [new NDKCashuToken(ndk), new NDKCashuToken(ndk)];
tokens.forEach((token, index) => {
token.mint = "mint";
token.id = `token${index}`;
token.proofs = [mockProof(`proof-${index}-1`, 100), mockProof(`proof-${index}-2`, 100)];
walletState.addToken(token);
});
stateChange.store = [];
stateChange.destroy = [tokens[0].proofs[0], tokens[1].proofs[0]];
const result = calculateNewState(walletState, stateChange);
expect(result.deletedTokenIds).toContain(tokens[0].id);
expect(result.deletedTokenIds).toContain(tokens[1].id);
expect(result.saveProofs).toContain(tokens[0].proofs[1]);
expect(result.saveProofs).toContain(tokens[1].proofs[1]);
expect(result.saveProofs).not.toContain(tokens[0].proofs[0]);
expect(result.saveProofs).not.toContain(tokens[1].proofs[0]);
});
it("should throw an error when reserve is used", () => {
stateChange.reserve = [mockProof("proof3", 300)];
expect(() => calculateNewState(walletState, stateChange)).not.toThrow();
// Note: The updateInternalState function throws an error on reserve,
// but calculateNewState does not handle reserve directly.
});
});