import Services from "../services/service"; import { getCorrectDOM } from "./html.utils"; import { addSubscription } from "./subscription.utils"; //Generate emojis list export function generateEmojiList(): string[] { const emojiRanges = [ [0x1f600, 0x1f64f], [0x1f300, 0x1f5ff], [0x1f680, 0x1f6ff], [0x1f700, 0x1f77f], ]; const emojiList: string[] = []; for (const range of emojiRanges) { const [start, end] = range; for (let i = start; i <= end && emojiList.length < 256; i++) { emojiList.push(String.fromCodePoint(i)); } if (emojiList.length >= 256) { break; } } return emojiList.slice(0, 256); } //Adress to emojis export async function addressToEmoji(text: string): Promise { //Adress to Hash const encoder = new TextEncoder(); const data = encoder.encode(text); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hash = new Uint8Array(hashBuffer); const bytes = hash.slice(-4); //Hash slice to emojis const emojiList = generateEmojiList(); const emojis = Array.from(bytes) .map((byte) => emojiList[byte]) .join(""); return emojis; } //Get emojis from other device async function emojisPairingRequest() { try { const container = getCorrectDOM("login-4nk-component") as HTMLElement; const urlParams: URLSearchParams = new URLSearchParams( window.location.search ); const sp_adress: string | null = urlParams.get("sp_address"); if (!sp_adress) { // console.error("No 'sp_adress' parameter found in the URL."); return; } const emojis = await addressToEmoji(sp_adress); const emojiDisplay = container?.querySelector(".pairing-request"); if (emojiDisplay) { emojiDisplay.textContent = "(Request from: " + emojis + ")"; } } catch (err) { console.error(err); } } // Display address emojis and other device emojis export async function displayEmojis(text: string) { try { const container = getCorrectDOM("login-4nk-component") as HTMLElement; const emojis = await addressToEmoji(text); const emojiDisplay = container?.querySelector(".emoji-display"); if (emojiDisplay) { emojiDisplay.textContent = emojis; } emojisPairingRequest(); initAddressInput(); } catch (err) { console.error(err); } } // Verify Other address export function initAddressInput() { const container = getCorrectDOM("login-4nk-component") as HTMLElement; const addressInput = container.querySelector( "#addressInput" ) as HTMLInputElement; const emojiDisplay = container.querySelector("#emoji-display-2"); const okButton = container.querySelector("#okButton") as HTMLButtonElement; const createButton = container.querySelector( "#createButton" ) as HTMLButtonElement; const actionButton = container.querySelector( "#actionButton" ) as HTMLButtonElement; addSubscription(addressInput, "input", async () => { let address = addressInput.value; // Vérifie si l'adresse est une URL try { const url = new URL(address); // Si c'est une URL valide, extraire le paramètre sp_address const urlParams = new URLSearchParams(url.search); const extractedAddress = urlParams.get("sp_address") || ""; // Prend sp_address ou une chaîne vide if (extractedAddress) { address = extractedAddress; addressInput.value = address; // Met à jour l'input pour afficher uniquement l'adresse extraite } } catch (e) { // Si ce n'est pas une URL valide, on garde l'adresse originale console.log("Ce n'est pas une URL valide, on garde l'adresse originale."); } if (address) { const emojis = await addressToEmoji(address); if (emojiDisplay) { emojiDisplay.textContent = emojis; } if (okButton) { okButton.style.display = "inline-block"; } } else { if (emojiDisplay) { emojiDisplay.textContent = ""; } if (okButton) { okButton.style.display = "none"; } } }); if (createButton) { addSubscription(createButton, "click", () => { onCreateButtonClick(); }); } } async function onCreateButtonClick() { try { await prepareAndSendPairingTx(); // Don't call confirmPairing immediately - it will be called when the pairing process is complete console.log("Pairing process initiated. Waiting for completion..."); } catch (e) { console.error(`onCreateButtonClick error: ${e}`); } } // Une constante est plus claire qu'une 'magic string' ("") const DEFAULT_PAIRING_PAYLOAD = ""; export async function prepareAndSendPairingTx(): Promise { const service = await Services.getInstance(); try { // 1. Création du processus d'appairage // const relayAddress = service.getAllRelays(); // <-- Cette variable n'était pas utilisée const createPairingProcessReturn = await service.createPairingProcess( DEFAULT_PAIRING_PAYLOAD, [] ); if (!createPairingProcessReturn.updated_process) { throw new Error("createPairingProcess returned an empty new process"); } // Utilisation du "destructuring" pour assigner les variables const { process_id: pairingId, current_process: process } = createPairingProcessReturn.updated_process; // Ajout d'une vérification pour éviter les erreurs si states est vide if (!process.states || process.states.length === 0) { throw new Error("Le processus reçu ne contient aucun état (state)"); } const stateId = process.states[0].state_id; // 2. Assurer les connexions await service.ensureConnections(process, stateId); // 3. Mettre à jour l'état du service await service.setProcessId(pairingId); await service.setStateId(stateId); // 4. Appairer le 'device' const myAddress = await service.getDeviceAddress(); await service.pairDevice(pairingId, [myAddress]); // 5. Mettre à jour la BDD try { const currentDevice = await service.getDeviceFromDatabase(); if (currentDevice) { currentDevice.pairing_process_commitment = pairingId; await service.saveDeviceInDatabase(currentDevice); } } catch (err) { console.error( "Échec non-critique de la mise à jour BDD (pairing_process_commitment):", err ); } // 6. Gérer les étapes suivantes du processus await service.handleApiReturn(createPairingProcessReturn); const createPrdUpdateReturn = await service.createPrdUpdate( pairingId, stateId ); await service.handleApiReturn(createPrdUpdateReturn); const approveChangeReturn = await service.approveChange(pairingId, stateId); await service.handleApiReturn(approveChangeReturn); // await service.confirmPairing(); } catch (err) { console.error("Le processus d'appairage a échoué :", err); throw err; } } export async function generateCreateBtn() { try { // Generate CreateBtn const container = getCorrectDOM("login-4nk-component") as HTMLElement; const createBtn = container?.querySelector(".create-btn"); if (createBtn) { createBtn.textContent = "CREATE"; } } catch (err) { console.error(err); } }