1234567891011121314import { Capacitor, registerPlugin } from "@capacitor/core";15import { generateKeyPair } from "@stablelib/x25519";1617interface SyncKeyPlugin {18 19202122 loadKeypair(): Promise<{ privateKeyHex: string; publicKeyHex: string }>;23 24 saveKeypair(keys: { privateKeyHex: string; publicKeyHex: string }): Promise<void>;25 26 clearKeypair(): Promise<void>;27}2829const SyncKey = registerPlugin<SyncKeyPlugin>("SyncKey");3031let cached: { privateKey: Uint8Array; publicKey: Uint8Array } | null = null;3233function bytesToHex(bytes: Uint8Array): string {34 return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");35}3637function hexToBytes(hex: string): Uint8Array {38 const out = new Uint8Array(hex.length / 2);39 for (let i = 0; i < hex.length; i += 2) {40 out[i / 2] = parseInt(hex.slice(i, i + 2), 16);41 }42 return out;43}4445export async function getAndroidSyncIdentity(): Promise<{46 privateKey: Uint8Array;47 publicKey: Uint8Array;48}> {49 if (cached) return cached;50 if (!Capacitor.isNativePlatform()) {51 throw new Error("Android sync identity requested on non-native platform");52 }5354 const stored = await SyncKey.loadKeypair();55 if (stored.privateKeyHex && stored.publicKeyHex) {56 cached = {57 privateKey: hexToBytes(stored.privateKeyHex),58 publicKey: hexToBytes(stored.publicKeyHex),59 };60 return cached;61 }6263 const pair = generateKeyPair();64 const privateKeyHex = bytesToHex(pair.secretKey);65 const publicKeyHex = bytesToHex(pair.publicKey);66 await SyncKey.saveKeypair({ privateKeyHex, publicKeyHex });67 cached = { privateKey: pair.secretKey, publicKey: pair.publicKey };68 return cached;69}7071727374757677export async function clearAndroidSyncIdentity(): Promise<void> {78 cached = null;79 if (!Capacitor.isNativePlatform()) return;80 try {81 await SyncKey.clearKeypair();82 } catch {83 84 }85}868788export function __resetForTests(): void {89 cached = null;90}