1271d48e9f
Créer un portefeuille, en obtenir le .ngw, traverser le broker : ce n'est pas du ressort du polyfill. C'est un besoin commun au polyfill et à toute application NextGraph — et surtout, ça SURVIT à la migration, alors que le polyfill est fait pour disparaître. L'y laisser, c'était le faire mourir avec lui ou rendre le polyfill indéracinable. Le paquet n'importe rien du polyfill — vérifié mécaniquement — et déclare Playwright et @ng-org/web en pairs, le consommateur devant maîtriser les versions. Sa surface : attentes bornées, mesure, navigateur, profils, portefeuille, traversée du broker, rapport d'exécution, et reconnaissance des modes de panne connus. La preuve qu'il est utilisable de l'extérieur : le polyfill le CONSOMME, sans garder de copie. Restent chez lui les parcours, la barrière et les identités virtuelles, qui lui sont propres. Le verrou entre exécutions disparaît, remplacé par un profil par exécution. Il ne traitait qu'un symptôme — un répertoire partagé que la création de portefeuille effaçait. Avec un profil par exécution il n'y a plus rien à sérialiser, les exécutions concurrentes deviennent indépendantes, et la collision entre deux dépôts s'évanouit au lieu d'être exportée. Six exécutions : aucun répertoire ni Chromium orphelin. Et la connaissance descriptive est séparée du pilotage : URL, sélecteurs et inventaire ordonné des écrans sont des données, passées DANS la page pour la reconnaissance — donc un échec nomme le même écran que celui sur lequel on dispatchait. Un échec de navigateur est désormais nommé comme tel — « the actors browser STOPPED ANSWERING » — au lieu de sortir sous le nom de l'opération innocente qui se trouvait en vol.
62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
/**
|
|
* 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<Record<string, unknown> | null | undefined>;
|
|
wallet_get_file(name: string): Promise<Uint8Array | ArrayLike<number>>;
|
|
}
|
|
|
|
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<ExportedWallet> {
|
|
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 };
|
|
},
|
|
};
|