// Copyright (C) 2026 Whiterun LLC, // This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later. // A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html import { describe, it, expect } from "vitest"; import { encodeHdPublicKey } from "@bitauth/libauth"; import type { PathXpub } from "@wizardconnect/core"; import { DappConnectionManager } from "./dapp-connection-manager.js"; // Build a valid xpub string from a deterministic test node. // Uses the secp256k1 generator point (a known valid public key). function makeTestXpub(): string { const node = { chainCode: new Uint8Array(32).fill(0xbb), // secp256k1 generator point (compressed) — always valid publicKey: Uint8Array.from( "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" .match(/.{2}/g)! .map((h) => parseInt(h, 16)), ), childIndex: 0, depth: 3, parentFingerprint: new Uint8Array(4), }; const result = encodeHdPublicKey({ node, network: "mainnet" }); if (typeof result === "string") throw new Error("Failed to encode test xpub: " + result); return result.hdPublicKey; } describe("DappConnectionManager", () => { describe("getSessionPaths", () => { it("returns empty array before wallet_ready", () => { const mgr = new DappConnectionManager(); expect(mgr.getSessionPaths()).toEqual([]); }); }); describe("restoreSessionPaths", () => { it("restores xpubs so getPubkey works", () => { const mgr = new DappConnectionManager(); const xpub = makeTestXpub(); const paths: PathXpub[] = [{ name: "receive", xpub }]; mgr.restoreSessionPaths(paths); expect(mgr.hasPath(0)).toBe(true); const pk = mgr.getPubkey(0, 0n); expect(pk).toBeInstanceOf(Uint8Array); expect(pk!.length).toBe(33); }); it("makes paths available via getSessionPaths", () => { const mgr = new DappConnectionManager(); const xpub = makeTestXpub(); const paths: PathXpub[] = [ { name: "receive", xpub }, { name: "change", xpub }, ]; mgr.restoreSessionPaths(paths); const stored = mgr.getSessionPaths(); expect(stored).toHaveLength(2); expect(stored[0].name).toBe("receive"); expect(stored[1].name).toBe("change"); }); it("returns a copy, not a reference", () => { const mgr = new DappConnectionManager(); const xpub = makeTestXpub(); mgr.restoreSessionPaths([{ name: "receive", xpub }]); const paths = mgr.getSessionPaths(); paths.push({ name: "change", xpub }); expect(mgr.getSessionPaths()).toHaveLength(1); }); it("throws on invalid xpub strings", () => { const mgr = new DappConnectionManager(); const paths: PathXpub[] = [{ name: "receive", xpub: "not-a-valid-xpub" }]; expect(() => mgr.restoreSessionPaths(paths)).toThrow("Invalid xpub"); }); it("can derive multiple child indices after restore", () => { const mgr = new DappConnectionManager(); const xpub = makeTestXpub(); mgr.restoreSessionPaths([{ name: "receive", xpub }]); for (const idx of [0n, 1n, 5n, 10n]) { const pk = mgr.getPubkey(0, idx); expect(pk, `index ${idx}`).toBeInstanceOf(Uint8Array); expect(pk!.length, `index ${idx}`).toBe(33); } }); it("does not affect paths not in the restore set", () => { const mgr = new DappConnectionManager(); const xpub = makeTestXpub(); mgr.restoreSessionPaths([{ name: "receive", xpub }]); expect(mgr.hasPath(0)).toBe(true); // receive = 0 expect(mgr.hasPath(1)).toBe(false); // change = 1 }); }); });