119 lines
3 KiB
TypeScript
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);
|
|
});
|