ihm_client/src/utils/sp-address.utils.ts

242 lines
7.1 KiB
TypeScript
Executable File

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<string> {
//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<void> {
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);
}
}