mtp/example-usage/web-client/src/main.ts
Alex Emmet 8194fff3b6 [WIP]
2026-06-25 16:46:27 +02:00

119 lines
3 KiB
TypeScript

import init, {
WasmClient,
ConnectionConfig,
ConnectionState,
WasmEd25519Signer,
ed25519_generate,
keyring_from_ed25519,
build_demo_message,
} from "mtp-wasm";
const STATUS = document.getElementById("status")!;
const STORAGE_KEY = "mtp-web-client-keys";
function log(msg: string, cls = "") {
const line = document.createElement("div");
line.textContent = msg;
if (cls) line.className = cls;
STATUS.appendChild(line);
}
function saveKeys(clientId: bigint, keyringBytes: Uint8Array) {
const data = {
clientId: clientId.toString(),
keyring: Array.from(keyringBytes),
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}
function loadKeys(): { clientId: bigint; keyringBytes: Uint8Array } | null {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return null;
const data = JSON.parse(raw);
return {
clientId: BigInt(data.clientId),
keyringBytes: new Uint8Array(data.keyring),
};
}
async function initWasm() {
log("Loading WASM module...");
await init();
log(`WASM loaded. WebTransport supported: ${WasmClient.is_supported()}`);
}
function createClient(): WasmClient {
return new WasmClient(
(state: number) =>
log(`[state] ${ConnectionState[state] ?? state}`, "state"),
(data: Uint8Array) => {
const decoder = new TextDecoder();
log(
`[message] ${data.length} bytes: ${decoder.decode(data)}`,
"received",
);
},
(err: any) => log(`[error] ${err}`, "error"),
);
}
function generateKeyringBytes(): Uint8Array {
const gen = ed25519_generate();
const sk = gen.secretKey as Uint8Array;
const pk = gen.publicKey as Uint8Array;
gen.signer.free();
return keyring_from_ed25519(sk, pk);
}
async function run() {
await initWasm();
if (!WasmClient.is_supported()) {
log("WebTransport is not supported in this browser.", "error");
return;
}
const serverUrl = "https://127.0.0.1:8080";
const saved = loadKeys();
const client = createClient();
const config = new ConnectionConfig(serverUrl);
let clientId: bigint;
let keyringBytes: Uint8Array;
if (saved) {
log(`Found saved client keys (ID: ${saved.clientId})`);
const hostPk = new Uint8Array(0);
clientId = await client.auth_connect(
config,
hostPk,
saved.keyringBytes,
saved.clientId,
);
log(`Authenticated as client ${clientId}`);
keyringBytes = saved.keyringBytes;
} else {
log("No saved keys: registering new client...");
const hostPk = new Uint8Array(0);
keyringBytes = generateKeyringBytes();
clientId = await client.auth_register(config, hostPk, keyringBytes);
log(`Registered with ID: ${clientId}`);
saveKeys(clientId, keyringBytes);
log("Saved client keys to localStorage");
}
config.free();
log("\nSending demo message...");
const frame = build_demo_message(clientId, keyringBytes);
await client.send(frame);
log(`Sent ${frame.length} bytes`);
log("\nClient running. Waiting for incoming messages...");
}
run().catch((e) => {
log(`Fatal error: ${e}`, "error");
console.error(e);
});