/** * The page that fetches a wallet's bytes — bundled and served by `exportWalletFile`. * * ── Why a page has to do this at all ───────────────────────────────────────── * A wallet's bytes exist only inside the broker iframe: `wallet_get_file()` is an RPC to the * wallet the broker holds, so nothing in Node can produce one. This page is the smallest thing * that can ask — it opens a NextGraph session the way any application does, and exposes one * function. * * It talks to `@ng-org/web` and to nothing else, deliberately: the machinery around it must * stay usable by an application that has never heard of any particular compatibility layer. * `init(callback, true, [])` is the shape an application writes; the broker (which loaded this * page in its iframe) drives the connection and calls back with the session. */ import { ng, init } from "@ng-org/web"; /** What crosses back to Node: base64, because a `Uint8Array` does not survive `evaluate`. */ export interface ExportedWallet { readonly walletName: string; readonly b64: string; readonly len: number; } /** * The two calls this page needs, named. A narrow local shape rather than the SDK's own types: * the wallet functions are not in its published surface at this version, and asserting the two * signatures we actually use says more than widening everything. */ interface WalletFunctions { get_wallets(): Promise | null | undefined>; wallet_get_file(name: string): Promise>; } const wallet = ng as unknown as WalletFunctions; const state: { status: string } = { status: "connecting" }; void (async () => { try { await init(() => { state.status = "connected"; }, true, []); } catch (e) { state.status = `error: ${e instanceof Error ? e.message : String(e)}`; } })(); (globalThis as unknown as { __ngWalletExport: unknown }).__ngWalletExport = { status: (): string => state.status, async file(): Promise { const wallets = await wallet.get_wallets(); const walletName = Object.keys(wallets ?? {})[0]; if (walletName === undefined) throw new Error("no wallet is open in this session"); const file = await wallet.wallet_get_file(walletName); const bytes = file instanceof Uint8Array ? file : new Uint8Array(Array.from(file)); let binary = ""; for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!); return { walletName, b64: btoa(binary), len: bytes.length }; }, };