style: formatage Prettier sur src/
Some checks failed
CI/CD Pipeline / test (push) Failing after 18s
CI/CD Pipeline / security (push) Has been skipped
CI/CD Pipeline / integration-test (push) Has been skipped

This commit is contained in:
Your Name 2025-08-26 12:49:27 +02:00
parent 2567e2f0da
commit 93d61c1e9c
27 changed files with 1075 additions and 1147 deletions

View File

@ -815,4 +815,4 @@ select[data-multi-select-plugin] {
.custom-select::-webkit-scrollbar-thumb:hover { .custom-select::-webkit-scrollbar-thumb:hover {
background: #555; background: #555;
} }

View File

@ -158,18 +158,18 @@ async function createBackUp() {
const service = await Services.getInstance(); const service = await Services.getInstance();
const backUp = await service.createBackUp(); const backUp = await service.createBackUp();
if (!backUp) { if (!backUp) {
console.error("No device to backup"); console.error('No device to backup');
return; return;
} }
try { try {
const backUpJson = JSON.stringify(backUp, null, 2) const backUpJson = JSON.stringify(backUp, null, 2);
const blob = new Blob([backUpJson], { type: 'application/json' }); const blob = new Blob([backUpJson], { type: 'application/json' });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
a.download = '4nk-backup.json'; a.download = '4nk-backup.json';
a.click(); a.click();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
@ -201,7 +201,7 @@ async function disconnect() {
}); });
const registrations = await navigator.serviceWorker.getRegistrations(); const registrations = await navigator.serviceWorker.getRegistrations();
await Promise.all(registrations.map(registration => registration.unregister())); await Promise.all(registrations.map((registration) => registration.unregister()));
console.log('Service worker unregistered'); console.log('Service worker unregistered');
await navigate('home'); await navigate('home');
@ -209,7 +209,6 @@ async function disconnect() {
setTimeout(() => { setTimeout(() => {
window.location.href = window.location.origin; window.location.href = window.location.origin;
}, 100); }, 100);
} catch (error) { } catch (error) {
console.error('Error during disconnect:', error); console.error('Error during disconnect:', error);
// force reload // force reload
@ -217,4 +216,4 @@ async function disconnect() {
} }
} }
(window as any).disconnect = disconnect; (window as any).disconnect = disconnect;

View File

@ -1,14 +1,14 @@
<div id="creation-modal" class="modal"> <div id="creation-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Login</div> <div class="modal-title">Login</div>
<div class="message"> <div class="message">
Do you want to create a 4NK member?<br /> Do you want to create a 4NK member?<br />
Attempting to create a member with address <br /> Attempting to create a member with address <br />
<strong>{{device1}}</strong> <br /> <strong>{{device1}}</strong> <br />
</div>
<div class="confirmation-box">
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
</div>
</div> </div>
</div> <div class="confirmation-box">
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
</div>
</div>
</div>

View File

@ -1,8 +1,6 @@
<div id="waiting-modal" class="modal"> <div id="waiting-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Login</div> <div class="modal-title">Login</div>
<div class="message"> <div class="message">Waiting for Device 2...</div>
Waiting for Device 2... </div>
</div> </div>
</div>
</div>

View File

@ -1,9 +1,7 @@
<div id="validation-modal" class="validation-modal"> <div id="validation-modal" class="validation-modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Validate Process {{processId}}</div> <div class="modal-title">Validate Process {{processId}}</div>
<div class="validation-box"> <div class="validation-box"></div>
</div>
<div class="modal-action"> <div class="modal-action">
<button onclick="validate()">Validate</button> <button onclick="validate()">Validate</button>
</div> </div>

View File

@ -7,11 +7,11 @@ async function validate() {
} }
export async function initValidationModal(processDiffs: any) { export async function initValidationModal(processDiffs: any) {
console.log("🚀 ~ initValidationModal ~ processDiffs:", processDiffs) console.log('🚀 ~ initValidationModal ~ processDiffs:', processDiffs);
for(const diff of processDiffs.diffs) { for (const diff of processDiffs.diffs) {
let diffs = '' let diffs = '';
for(const value of diff) { for (const value of diff) {
diffs+= ` diffs += `
<div class="radio-buttons"> <div class="radio-buttons">
<label> <label>
<input type="radio" name="validation1" value="old" /> <input type="radio" name="validation1" value="old" />
@ -30,27 +30,27 @@ for(const diff of processDiffs.diffs) {
<pre>+${value.new_value}</pre> <pre>+${value.new_value}</pre>
</div> </div>
</div> </div>
` `;
} }
const state = ` const state = `
<div class="expansion-panel"> <div class="expansion-panel">
<div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div> <div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div>
<div class="expansion-panel-body"> <div class="expansion-panel-body">
${diffs} ${diffs}
</div> </div>
</div> </div>
` `;
const box = document.querySelector('.validation-box') const box = document.querySelector('.validation-box');
if(box) box.innerHTML += state if (box) box.innerHTML += state;
} }
document.querySelectorAll('.expansion-panel-header').forEach((header) => { document.querySelectorAll('.expansion-panel-header').forEach((header) => {
header.addEventListener('click', function (event) { header.addEventListener('click', function (event) {
const target = event.target as HTMLElement; const target = event.target as HTMLElement;
const body = target.nextElementSibling as HTMLElement; const body = target.nextElementSibling as HTMLElement;
if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block'; if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block';
});
}); });
});
} }
(window as any).validate = validate; (window as any).validate = validate;

View File

@ -1,42 +1,25 @@
<div id="validation-rule-modal" style=" <div id="validation-rule-modal" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: none; justify-content: center; align-items: center; z-index: 9999">
position: fixed; <div style="background: white; padding: 2rem; border-radius: 0.5rem; width: 400px; max-width: 90%; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3)">
top: 0; left: 0; right: 0; bottom: 0; <h2 style="font-size: 1.2rem; font-weight: bold; margin-bottom: 1rem">Add Validation Rule</h2>
background: rgba(0,0,0,0.5);
display: none;
justify-content: center;
align-items: center;
z-index: 9999;
">
<div style="
background: white;
padding: 2rem;
border-radius: 0.5rem;
width: 400px;
max-width: 90%;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
">
<h2 style="font-size: 1.2rem; font-weight: bold; margin-bottom: 1rem;">
Add Validation Rule
</h2>
<label style="display: block; margin-bottom: 0.5rem;"> <label style="display: block; margin-bottom: 0.5rem">
Quorum: Quorum:
<input id="vr-quorum" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem;" /> <input id="vr-quorum" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label> </label>
<label style="display: block; margin-bottom: 0.5rem;"> <label style="display: block; margin-bottom: 0.5rem">
Min Sig Member: Min Sig Member:
<input id="vr-minsig" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem;" /> <input id="vr-minsig" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label> </label>
<label style="display: block; margin-bottom: 1rem;"> <label style="display: block; margin-bottom: 1rem">
Fields (comma-separated): Fields (comma-separated):
<input id="vr-fields" type="text" placeholder="e.g. field1, field2" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem;" /> <input id="vr-fields" type="text" placeholder="e.g. field1, field2" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label> </label>
<div style="display: flex; justify-content: flex-end; gap: 1rem;"> <div style="display: flex; justify-content: flex-end; gap: 1rem">
<button id="vr-cancel" style="padding: 0.5rem 1rem;">Cancel</button> <button id="vr-cancel" style="padding: 0.5rem 1rem">Cancel</button>
<button id="vr-submit" style="padding: 0.5rem 1rem; background-color: #4f46e5; color: white; border: none; border-radius: 0.375rem;">Add</button> <button id="vr-submit" style="padding: 0.5rem 1rem; background-color: #4f46e5; color: white; border: none; border-radius: 0.375rem">Add</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -52,7 +52,10 @@ export function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void
const rule: ValidationRule = { const rule: ValidationRule = {
quorum: parseInt(quorumInput.value), quorum: parseInt(quorumInput.value),
min_sig_member: parseInt(minsigInput.value), min_sig_member: parseInt(minsigInput.value),
fields: fieldsInput.value.split(',').map(f => f.trim()).filter(Boolean), fields: fieldsInput.value
.split(',')
.map((f) => f.trim())
.filter(Boolean),
}; };
modal.style.display = 'none'; modal.style.display = 'none';

View File

@ -1,7 +1,7 @@
import { Device, Process, SecretsStore } from "pkg/sdk_client"; import { Device, Process, SecretsStore } from 'pkg/sdk_client';
export interface BackUp { export interface BackUp {
device: Device, device: Device;
secrets: SecretsStore, secrets: SecretsStore;
processes: Record<string, Process>, processes: Record<string, Process>;
} }

View File

@ -1,10 +1,10 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<title>Account</title> <title>Account</title>
</head> </head>
<body> <body>
<account-component></account-component> <account-component></account-component>
<script type="module" src="./account.ts"></script> <script type="module" src="./account.ts"></script>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@ interface State {
} }
export interface Vin { export interface Vin {
txid: string; // The txid of the previous transaction (being spent) txid: string; // The txid of the previous transaction (being spent)
vout: number; // The output index in the previous tx vout: number; // The output index in the previous tx
prevout: { prevout: {
scriptpubkey: string; scriptpubkey: string;
scriptpubkey_asm: string; scriptpubkey_asm: string;
@ -47,8 +47,8 @@ export function getDocumentValidation(container: HTMLElement) {
file: null, file: null,
fileHash: null, fileHash: null,
certificate: null, certificate: null,
commitmentHashes: [] commitmentHashes: [],
} };
container.innerHTML = ''; container.innerHTML = '';
container.style.cssText = ` container.style.cssText = `
@ -60,11 +60,7 @@ export function getDocumentValidation(container: HTMLElement) {
gap: 2rem; gap: 2rem;
`; `;
function createDropButton( function createDropButton(label: string, onDrop: (file: File, updateVisuals: (file: File) => void) => void, accept: string = '*/*'): HTMLElement {
label: string,
onDrop: (file: File, updateVisuals: (file: File) => void) => void,
accept: string = '*/*'
): HTMLElement {
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
wrapper.style.cssText = ` wrapper.style.cssText = `
width: 200px; width: 200px;
@ -120,7 +116,7 @@ export function getDocumentValidation(container: HTMLElement) {
}; };
// === Handle drag-and-drop === // === Handle drag-and-drop ===
wrapper.ondragover = e => { wrapper.ondragover = (e) => {
e.preventDefault(); e.preventDefault();
wrapper.style.background = '#e0e0e0'; wrapper.style.background = '#e0e0e0';
}; };
@ -129,7 +125,7 @@ export function getDocumentValidation(container: HTMLElement) {
wrapper.style.background = '#f8f8f8'; wrapper.style.background = '#f8f8f8';
}; };
wrapper.ondrop = e => { wrapper.ondrop = (e) => {
e.preventDefault(); e.preventDefault();
wrapper.style.background = '#f8f8f8'; wrapper.style.background = '#f8f8f8';
@ -163,17 +159,10 @@ export function getDocumentValidation(container: HTMLElement) {
try { try {
const text = await file.text(); const text = await file.text();
const json = JSON.parse(text); const json = JSON.parse(text);
if ( if (typeof json === 'object' && json !== null && typeof json.pcd_commitment === 'object' && typeof json.state_id === 'string') {
typeof json === 'object' &&
json !== null &&
typeof json.pcd_commitment === 'object' &&
typeof json.state_id === 'string'
) {
state.certificate = json as ProcessState; state.certificate = json as ProcessState;
state.commitmentHashes = Object.values(json.pcd_commitment).map((h: any) => state.commitmentHashes = Object.values(json.pcd_commitment).map((h: any) => (h as string).toLowerCase());
(h as string).toLowerCase()
);
updateVisuals(file); updateVisuals(file);
console.log('Loaded certificate, extracted hashes:', state.commitmentHashes); console.log('Loaded certificate, extracted hashes:', state.commitmentHashes);
@ -200,7 +189,7 @@ export function getDocumentValidation(container: HTMLElement) {
// We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash // We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash
const fileBlob = { const fileBlob = {
type: state.file.type, type: state.file.type,
data: new Uint8Array(await state.file.arrayBuffer()) data: new Uint8Array(await state.file.arrayBuffer()),
}; };
const service = await Services.getInstance(); const service = await Services.getInstance();
const commitedIn = state.certificate.commited_in; const commitedIn = state.certificate.commited_in;
@ -280,7 +269,7 @@ export function getDocumentValidation(container: HTMLElement) {
for (const label of Object.keys(state.certificate.pcd_commitment)) { for (const label of Object.keys(state.certificate.pcd_commitment)) {
// Compute the hash for this label // Compute the hash for this label
console.log(`Computing hash with label ${label}`) console.log(`Computing hash with label ${label}`);
const fileHex = service.getHashForFile(commitedIn, label, fileBlob); const fileHex = service.getHashForFile(commitedIn, label, fileBlob);
console.log(`Found hash ${fileHex}`); console.log(`Found hash ${fileHex}`);
found = state.commitmentHashes.includes(fileHex); found = state.commitmentHashes.includes(fileHex);

View File

@ -33,14 +33,14 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
validationRules: ValidationRule[]; validationRules: ValidationRule[];
}[] = []; }[] = [];
type fileBlob = { type fileBlob = {
type: string, type: string;
data: Uint8Array data: Uint8Array;
}; };
const nonRoleRowStates: { const nonRoleRowStates: {
keyInput: HTMLInputElement, keyInput: HTMLInputElement;
valueInput: HTMLInputElement, valueInput: HTMLInputElement;
fileInput: HTMLInputElement, fileInput: HTMLInputElement;
fileBlob: fileBlob | null fileBlob: fileBlob | null;
}[] = []; }[] = [];
const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;'; const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;';
@ -65,7 +65,7 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
roleName.placeholder = 'Role name'; roleName.placeholder = 'Role name';
members.placeholder = 'members'; members.placeholder = 'members';
storages.placeholder = 'storages'; storages.placeholder = 'storages';
[roleName, members, storages].forEach(input => { [roleName, members, storages].forEach((input) => {
input.type = 'text'; input.type = 'text';
input.style.cssText = inputStyle; input.style.cssText = inputStyle;
}); });
@ -76,7 +76,7 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
const rules: ValidationRule[] = []; const rules: ValidationRule[] = [];
ruleButton.onclick = () => { ruleButton.onclick = () => {
showValidationRuleModal(rule => { showValidationRuleModal((rule) => {
rules.push(rule); rules.push(rule);
ruleButton.textContent = `Rules (${rules.length})`; ruleButton.textContent = `Rules (${rules.length})`;
}); });
@ -122,13 +122,13 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
keyInput, keyInput,
valueInput, valueInput,
fileInput, fileInput,
fileBlob: null as fileBlob | null fileBlob: null as fileBlob | null,
}; };
nonRoleRowStates.push(rowState); nonRoleRowStates.push(rowState);
keyInput.placeholder = 'Key'; keyInput.placeholder = 'Key';
valueInput.placeholder = 'Value'; valueInput.placeholder = 'Value';
[keyInput, valueInput].forEach(input => { [keyInput, valueInput].forEach((input) => {
input.type = 'text'; input.type = 'text';
input.style.cssText = inputStyle; input.style.cssText = inputStyle;
}); });
@ -148,7 +148,7 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
const updateDeleteButtons = () => { const updateDeleteButtons = () => {
const rows = Array.from(rowContainer.children); const rows = Array.from(rowContainer.children);
rows.forEach(row => { rows.forEach((row) => {
const btn = row.querySelector('button:last-child') as HTMLButtonElement; const btn = row.querySelector('button:last-child') as HTMLButtonElement;
if (rows.length === 1) { if (rows.length === 1) {
btn.disabled = true; btn.disabled = true;
@ -172,9 +172,15 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
const key = row.roleNameInput.value.trim(); const key = row.roleNameInput.value.trim();
if (!key) continue; if (!key) continue;
data[key] = { data[key] = {
members: row.membersInput.value.split(',').map(x => x.trim()).filter(Boolean), members: row.membersInput.value
storages: row.storagesInput.value.split(',').map(x => x.trim()).filter(Boolean), .split(',')
validation_rules: row.validationRules .map((x) => x.trim())
.filter(Boolean),
storages: row.storagesInput.value
.split(',')
.map((x) => x.trim())
.filter(Boolean),
validation_rules: row.validationRules,
}; };
} }
return data; return data;
@ -191,6 +197,6 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
} }
return data; return data;
} }
} },
}; };
} }

View File

@ -61,10 +61,10 @@ export async function getProcessCreation(container: HTMLElement) {
const hash = newState.pcd_commitment[label]; const hash = newState.pcd_commitment[label];
const encryptedData = await service.getBlobFromDb(hash); const encryptedData = await service.getBlobFromDb(hash);
if (!encryptedData) continue; if (!encryptedData) continue;
const filename = `${label}-${hash.slice(0,8)}.bin`; const filename = `${label}-${hash.slice(0, 8)}.bin`;
const blob = new Blob([encryptedData], { type: "application/octet-stream" }); const blob = new Blob([encryptedData], { type: 'application/octet-stream' });
const link = document.createElement("a"); const link = document.createElement('a');
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
link.download = filename; link.download = filename;
link.click(); link.click();

View File

@ -1,4 +1,4 @@
export function createProcessTab(container: HTMLElement, processes: { name: string, publicData: Record<string, any> }[]): HTMLElement { export function createProcessTab(container: HTMLElement, processes: { name: string; publicData: Record<string, any> }[]): HTMLElement {
container.id = 'process-tab'; container.id = 'process-tab';
container.style.display = 'block'; container.style.display = 'block';
container.style.cssText = 'padding: 1.5rem;'; container.style.cssText = 'padding: 1.5rem;';
@ -8,7 +8,7 @@ export function createProcessTab(container: HTMLElement, processes: { name: stri
title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;'; title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;';
container.appendChild(title); container.appendChild(title);
processes.forEach(proc => { processes.forEach((proc) => {
const card = document.createElement('div'); const card = document.createElement('div');
card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;'; card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;';

View File

@ -36,7 +36,7 @@
<select name="memberSelect" id="memberSelect" size="5" class="custom-select"> <select name="memberSelect" id="memberSelect" size="5" class="custom-select">
<!-- Options --> <!-- Options -->
</select> </select>
<button id="okButton" style="display: none">OK</button> <button id="okButton" style="display: none">OK</button>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import Routing from '../../services/modal.service'; import Routing from '../../services/modal.service';
import Services from '../../services/service'; import Services from '../../services/service';
import { addSubscription } from '../../utils/subscription.utils'; import { addSubscription } from '../../utils/subscription.utils';
import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji} from '../../utils/sp-address.utils'; import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji } from '../../utils/sp-address.utils';
import { getCorrectDOM } from '../../utils/html.utils'; import { getCorrectDOM } from '../../utils/html.utils';
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component'; import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
import { navigate, registerAllListeners } from '../../router'; import { navigate, registerAllListeners } from '../../router';
@ -25,7 +25,7 @@ export async function initHomePage(): Promise<void> {
// generateQRCode(spAddress); // generateQRCode(spAddress);
generateCreateBtn(); generateCreateBtn();
displayEmojis(spAddress); displayEmojis(spAddress);
// Add this line to populate the select when the page loads // Add this line to populate the select when the page loads
await populateMemberSelect(); await populateMemberSelect();
} }
@ -54,7 +54,7 @@ function scanDevice() {
async function populateMemberSelect() { async function populateMemberSelect() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement; const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const memberSelect = container.querySelector('#memberSelect') as HTMLSelectElement; const memberSelect = container.querySelector('#memberSelect') as HTMLSelectElement;
if (!memberSelect) { if (!memberSelect) {
console.error('Could not find memberSelect element'); console.error('Could not find memberSelect element');
return; return;
@ -66,7 +66,7 @@ async function populateMemberSelect() {
for (const [processId, member] of Object.entries(members)) { for (const [processId, member] of Object.entries(members)) {
const process = await service.getProcess(processId); const process = await service.getProcess(processId);
let memberPublicName; let memberPublicName;
if (process) { if (process) {
const publicMemberData = service.getPublicData(process); const publicMemberData = service.getPublicData(process);
if (publicMemberData) { if (publicMemberData) {
@ -76,14 +76,14 @@ async function populateMemberSelect() {
} }
} }
} }
if (!memberPublicName) { if (!memberPublicName) {
memberPublicName = 'Unnamed Member'; memberPublicName = 'Unnamed Member';
} }
// Récupérer les emojis pour ce processId // Récupérer les emojis pour ce processId
const emojis = await addressToEmoji(processId); const emojis = await addressToEmoji(processId);
const option = document.createElement('option'); const option = document.createElement('option');
option.value = processId; option.value = processId;
option.textContent = `${memberPublicName} (${emojis})`; option.textContent = `${memberPublicName} (${emojis})`;

View File

@ -111,9 +111,9 @@ export async function init(): Promise<void> {
await services.restoreSecretsFromDB(); await services.restoreSecretsFromDB();
if (!isE2E) { if (!isE2E) {
// We connect to all relays now // We connect to all relays now
await services.connectAllRelays(); await services.connectAllRelays();
await services.updateDeviceBlockHeight(); await services.updateDeviceBlockHeight();
} }
// We register all the event listeners if we run in an iframe // We register all the event listeners if we run in an iframe
@ -139,11 +139,11 @@ export async function registerAllListeners() {
{ {
type: MessageType.ERROR, type: MessageType.ERROR,
error: errorMsg, error: errorMsg,
messageId messageId,
}, },
origin origin,
); );
} };
// --- Handler functions --- // --- Handler functions ---
const handleRequestLink = async (event: MessageEvent) => { const handleRequestLink = async (event: MessageEvent) => {
@ -155,15 +155,16 @@ export async function registerAllListeners() {
type: MessageType.LINK_ACCEPTED, type: MessageType.LINK_ACCEPTED,
accessToken: 'e2e-access', accessToken: 'e2e-access',
refreshToken: 'e2e-refresh', refreshToken: 'e2e-refresh',
messageId: event.data.messageId messageId: event.data.messageId,
}; };
window.parent.postMessage(acceptedMsg, event.origin); window.parent.postMessage(acceptedMsg, event.origin);
return; return;
} else { } else {
const modalService = await ModalService.getInstance(); const modalService = await ModalService.getInstance();
const result = await modalService.showConfirmationModal({ const result = await modalService.showConfirmationModal(
title: 'Confirmation de liaison', {
content: ` title: 'Confirmation de liaison',
content: `
<div class="modal-confirmation"> <div class="modal-confirmation">
<h3>Liaison avec ${event.origin}</h3> <h3>Liaison avec ${event.origin}</h3>
<p>Vous êtes sur le point de lier l'identité numérique de la clé securisée propre à votre appareil avec ${event.origin}.</p> <p>Vous êtes sur le point de lier l'identité numérique de la clé securisée propre à votre appareil avec ${event.origin}.</p>
@ -171,12 +172,14 @@ export async function registerAllListeners() {
<p>Voulez-vous continuer ?</p> <p>Voulez-vous continuer ?</p>
</div> </div>
`, `,
confirmText: 'Ajouter un service', confirmText: 'Ajouter un service',
cancelText: 'Annuler' cancelText: 'Annuler',
}, true); },
if (!result) { true,
const errorMsg = 'Failed to pair device: User refused to link'; );
errorResponse(errorMsg, event.origin, event.data.messageId); if (!result) {
const errorMsg = 'Failed to pair device: User refused to link';
errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} }
@ -186,17 +189,14 @@ export async function registerAllListeners() {
type: MessageType.LINK_ACCEPTED, type: MessageType.LINK_ACCEPTED,
accessToken: tokens.accessToken, accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken, refreshToken: tokens.refreshToken,
messageId: event.data.messageId messageId: event.data.messageId,
}; };
window.parent.postMessage( window.parent.postMessage(acceptedMsg, event.origin);
acceptedMsg,
event.origin
);
} catch (error) { } catch (error) {
const errorMsg = `Failed to generate tokens: ${error}`; const errorMsg = `Failed to generate tokens: ${error}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleCreatePairing = async (event: MessageEvent) => { const handleCreatePairing = async (event: MessageEvent) => {
if (event.data.type !== MessageType.CREATE_PAIRING) { if (event.data.type !== MessageType.CREATE_PAIRING) {
@ -230,14 +230,14 @@ export async function registerAllListeners() {
const successMsg = { const successMsg = {
type: MessageType.PAIRING_CREATED, type: MessageType.PAIRING_CREATED,
pairingId, pairingId,
messageId: event.data.messageId messageId: event.data.messageId,
}; };
window.parent.postMessage(successMsg, event.origin); window.parent.postMessage(successMsg, event.origin);
} catch (e) { } catch (e) {
const errorMsg = `Failed to create pairing process: ${e}`; const errorMsg = `Failed to create pairing process: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleGetMyProcesses = async (event: MessageEvent) => { const handleGetMyProcesses = async (event: MessageEvent) => {
if (event.data.type !== MessageType.GET_MY_PROCESSES) { if (event.data.type !== MessageType.GET_MY_PROCESSES) {
@ -263,15 +263,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.GET_MY_PROCESSES, type: MessageType.GET_MY_PROCESSES,
myProcesses, myProcesses,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to get processes: ${e}`; const errorMsg = `Failed to get processes: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleGetProcesses = async (event: MessageEvent) => { const handleGetProcesses = async (event: MessageEvent) => {
if (event.data.type !== MessageType.GET_PROCESSES) { if (event.data.type !== MessageType.GET_PROCESSES) {
@ -300,15 +300,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.PROCESSES_RETRIEVED, type: MessageType.PROCESSES_RETRIEVED,
processes, processes,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to get processes: ${e}`; const errorMsg = `Failed to get processes: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
/// We got a state for some process and return as many clear attributes as we can /// We got a state for some process and return as many clear attributes as we can
const handleDecryptState = async (event: MessageEvent) => { const handleDecryptState = async (event: MessageEvent) => {
@ -333,7 +333,7 @@ export async function registerAllListeners() {
// Retrieve the state for the process // Retrieve the state for the process
const process = await services.getProcess(processId); const process = await services.getProcess(processId);
if (!process) { if (!process) {
throw new Error('Can\'t find process'); throw new Error("Can't find process");
} }
const state = services.getStateFromId(process, stateId); const state = services.getStateFromId(process, stateId);
@ -357,15 +357,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.DATA_RETRIEVED, type: MessageType.DATA_RETRIEVED,
data: res, data: res,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to retrieve data: ${e}`; const errorMsg = `Failed to retrieve data: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleValidateToken = async (event: MessageEvent) => { const handleValidateToken = async (event: MessageEvent) => {
if (event.data.type !== MessageType.VALIDATE_TOKEN) { if (event.data.type !== MessageType.VALIDATE_TOKEN) {
@ -378,25 +378,31 @@ export async function registerAllListeners() {
errorResponse('Failed to validate token: missing access, refresh token or both', event.origin, event.data.messageId); errorResponse('Failed to validate token: missing access, refresh token or both', event.origin, event.data.messageId);
} }
if (isE2E) { if (isE2E) {
window.parent.postMessage({ window.parent.postMessage(
type: MessageType.VALIDATE_TOKEN, {
accessToken, type: MessageType.VALIDATE_TOKEN,
refreshToken, accessToken,
isValid: true, refreshToken,
messageId: event.data.messageId isValid: true,
}, event.origin); messageId: event.data.messageId,
},
event.origin,
);
return; return;
} }
const isValid = await tokenService.validateToken(accessToken, event.origin); const isValid = await tokenService.validateToken(accessToken, event.origin);
window.parent.postMessage({ window.parent.postMessage(
{
type: MessageType.VALIDATE_TOKEN, type: MessageType.VALIDATE_TOKEN,
accessToken, accessToken,
refreshToken, refreshToken,
isValid, isValid,
messageId: event.data.messageId messageId: event.data.messageId,
}, event.origin); },
event.origin,
);
}; };
const handleRenewToken = async (event: MessageEvent) => { const handleRenewToken = async (event: MessageEvent) => {
@ -411,12 +417,15 @@ export async function registerAllListeners() {
throw new Error('No refresh token provided'); throw new Error('No refresh token provided');
} }
if (isE2E) { if (isE2E) {
window.parent.postMessage({ window.parent.postMessage(
type: MessageType.RENEW_TOKEN, {
accessToken: 'e2e-access-2', type: MessageType.RENEW_TOKEN,
refreshToken, accessToken: 'e2e-access-2',
messageId: event.data.messageId refreshToken,
}, event.origin); messageId: event.data.messageId,
},
event.origin,
);
return; return;
} }
@ -426,17 +435,20 @@ export async function registerAllListeners() {
throw new Error('Failed to refresh token'); throw new Error('Failed to refresh token');
} }
window.parent.postMessage({ window.parent.postMessage(
{
type: MessageType.RENEW_TOKEN, type: MessageType.RENEW_TOKEN,
accessToken: newAccessToken, accessToken: newAccessToken,
refreshToken, refreshToken,
messageId: event.data.messageId messageId: event.data.messageId,
}, event.origin); },
event.origin,
);
} catch (error) { } catch (error) {
const errorMsg = `Failed to renew token: ${error}`; const errorMsg = `Failed to renew token: ${error}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleGetPairingId = async (event: MessageEvent) => { const handleGetPairingId = async (event: MessageEvent) => {
if (event.data.type !== MessageType.GET_PAIRING_ID) return; if (event.data.type !== MessageType.GET_PAIRING_ID) return;
@ -460,15 +472,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.GET_PAIRING_ID, type: MessageType.GET_PAIRING_ID,
userPairingId, userPairingId,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to get pairing id: ${e}`; const errorMsg = `Failed to get pairing id: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleCreateProcess = async (event: MessageEvent) => { const handleCreateProcess = async (event: MessageEvent) => {
if (event.data.type !== MessageType.CREATE_PROCESS) return; if (event.data.type !== MessageType.CREATE_PROCESS) return;
@ -483,11 +495,14 @@ export async function registerAllListeners() {
const { processData, privateFields, roles, accessToken } = event.data; const { processData, privateFields, roles, accessToken } = event.data;
if (isE2E) { if (isE2E) {
window.parent.postMessage({ window.parent.postMessage(
type: MessageType.PROCESS_CREATED, {
processCreated: { processId: 'e2e-process', process: {}, processData }, type: MessageType.PROCESS_CREATED,
messageId: event.data.messageId processCreated: { processId: 'e2e-process', process: {}, processData },
}, event.origin); messageId: event.data.messageId,
},
event.origin,
);
return; return;
} }
@ -507,16 +522,19 @@ export async function registerAllListeners() {
const res = { processId, process, processData }; const res = { processId, process, processData };
window.parent.postMessage({ window.parent.postMessage(
{
type: MessageType.PROCESS_CREATED, type: MessageType.PROCESS_CREATED,
processCreated: res, processCreated: res,
messageId: event.data.messageId messageId: event.data.messageId,
}, event.origin); },
event.origin,
);
} catch (e) { } catch (e) {
const errorMsg = `Failed to create process: ${e}`; const errorMsg = `Failed to create process: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleNotifyUpdate = async (event: MessageEvent) => { const handleNotifyUpdate = async (event: MessageEvent) => {
if (event.data.type !== MessageType.NOTIFY_UPDATE) return; if (event.data.type !== MessageType.NOTIFY_UPDATE) return;
@ -544,15 +562,15 @@ export async function registerAllListeners() {
window.parent.postMessage( window.parent.postMessage(
{ {
type: MessageType.UPDATE_NOTIFIED, type: MessageType.UPDATE_NOTIFIED,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to notify update for process: ${e}`; const errorMsg = `Failed to notify update for process: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleValidateState = async (event: MessageEvent) => { const handleValidateState = async (event: MessageEvent) => {
if (event.data.type !== MessageType.VALIDATE_STATE) return; if (event.data.type !== MessageType.VALIDATE_STATE) return;
@ -577,15 +595,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.STATE_VALIDATED, type: MessageType.STATE_VALIDATED,
validatedProcess: res.updated_process, validatedProcess: res.updated_process,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to validate process: ${e}`; const errorMsg = `Failed to validate process: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleUpdateProcess = async (event: MessageEvent) => { const handleUpdateProcess = async (event: MessageEvent) => {
if (event.data.type !== MessageType.UPDATE_PROCESS) return; if (event.data.type !== MessageType.UPDATE_PROCESS) return;
@ -614,7 +632,7 @@ export async function registerAllListeners() {
const firstState = process.states[0]; const firstState = process.states[0];
const roles = firstState.roles; const roles = firstState.roles;
if (services.rolesContainsUs(roles)) { if (services.rolesContainsUs(roles)) {
const approveChangeRes= await services.approveChange(processId, firstState.state_id); const approveChangeRes = await services.approveChange(processId, firstState.state_id);
await services.handleApiReturn(approveChangeRes); await services.handleApiReturn(approveChangeRes);
const prdUpdateRes = await services.createPrdUpdate(processId, firstState.state_id); const prdUpdateRes = await services.createPrdUpdate(processId, firstState.state_id);
await services.handleApiReturn(prdUpdateRes); await services.handleApiReturn(prdUpdateRes);
@ -626,15 +644,15 @@ export async function registerAllListeners() {
} }
} }
// Wait a couple seconds // Wait a couple seconds
await new Promise(resolve => setTimeout(resolve, 2000)); await new Promise((resolve) => setTimeout(resolve, 2000));
lastState = services.getLastCommitedState(process); lastState = services.getLastCommitedState(process);
if (!lastState) { if (!lastState) {
throw new Error('Process doesn\'t have a commited state yet'); throw new Error("Process doesn't have a commited state yet");
} }
} }
const lastStateIndex = services.getLastCommitedStateIndex(process); const lastStateIndex = services.getLastCommitedStateIndex(process);
if (lastStateIndex === null) { if (lastStateIndex === null) {
throw new Error('Process doesn\'t have a commited state yet'); throw new Error("Process doesn't have a commited state yet");
} // Shouldn't happen } // Shouldn't happen
const privateData: Record<string, any> = {}; const privateData: Record<string, any> = {};
@ -686,15 +704,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.PROCESS_UPDATED, type: MessageType.PROCESS_UPDATED,
updatedProcess: res.updated_process, updatedProcess: res.updated_process,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to update process: ${e}`; const errorMsg = `Failed to update process: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleDecodePublicData = async (event: MessageEvent) => { const handleDecodePublicData = async (event: MessageEvent) => {
if (event.data.type !== MessageType.DECODE_PUBLIC_DATA) return; if (event.data.type !== MessageType.DECODE_PUBLIC_DATA) return;
@ -718,15 +736,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.PUBLIC_DATA_DECODED, type: MessageType.PUBLIC_DATA_DECODED,
decodedData, decodedData,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to decode data: ${e}`; const errorMsg = `Failed to decode data: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleHashValue = async (event: MessageEvent) => { const handleHashValue = async (event: MessageEvent) => {
if (event.data.type !== MessageType.HASH_VALUE) return; if (event.data.type !== MessageType.HASH_VALUE) return;
@ -746,15 +764,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.VALUE_HASHED, type: MessageType.VALUE_HASHED,
hash, hash,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to hash value: ${e}`; const errorMsg = `Failed to hash value: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleGetMerkleProof = async (event: MessageEvent) => { const handleGetMerkleProof = async (event: MessageEvent) => {
if (event.data.type !== MessageType.GET_MERKLE_PROOF) return; if (event.data.type !== MessageType.GET_MERKLE_PROOF) return;
@ -772,15 +790,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.MERKLE_PROOF_RETRIEVED, type: MessageType.MERKLE_PROOF_RETRIEVED,
proof, proof,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to get merkle proof: ${e}`; const errorMsg = `Failed to get merkle proof: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
const handleValidateMerkleProof = async (event: MessageEvent) => { const handleValidateMerkleProof = async (event: MessageEvent) => {
if (event.data.type !== MessageType.VALIDATE_MERKLE_PROOF) return; if (event.data.type !== MessageType.VALIDATE_MERKLE_PROOF) return;
@ -796,7 +814,7 @@ export async function registerAllListeners() {
// We will validate it's a MerkleProofResult in the wasm // We will validate it's a MerkleProofResult in the wasm
let parsedMerkleProof: MerkleProofResult; let parsedMerkleProof: MerkleProofResult;
try { try {
parsedMerkleProof= JSON.parse(merkleProof); parsedMerkleProof = JSON.parse(merkleProof);
} catch (e) { } catch (e) {
throw new Error('Provided merkleProof is not a valid json object'); throw new Error('Provided merkleProof is not a valid json object');
} }
@ -807,15 +825,15 @@ export async function registerAllListeners() {
{ {
type: MessageType.MERKLE_PROOF_VALIDATED, type: MessageType.MERKLE_PROOF_VALIDATED,
isValid: res, isValid: res,
messageId: event.data.messageId messageId: event.data.messageId,
}, },
event.origin event.origin,
); );
} catch (e) { } catch (e) {
const errorMsg = `Failed to get merkle proof: ${e}`; const errorMsg = `Failed to get merkle proof: ${e}`;
errorResponse(errorMsg, event.origin, event.data.messageId); errorResponse(errorMsg, event.origin, event.data.messageId);
} }
} };
window.removeEventListener('message', handleMessage); window.removeEventListener('message', handleMessage);
window.addEventListener('message', handleMessage); window.addEventListener('message', handleMessage);
@ -915,8 +933,8 @@ async function injectHeader() {
(window as any).navigate = navigate; (window as any).navigate = navigate;
document.addEventListener('navigate', ((e: Event) => { document.addEventListener('navigate', (e: Event) => {
const event = e as CustomEvent<{page: string, processId?: string}>; const event = e as CustomEvent<{ page: string; processId?: string }>;
if (event.detail.page === 'chat') { if (event.detail.page === 'chat') {
const container = document.querySelector('.container'); const container = document.querySelector('.container');
if (container) container.innerHTML = ''; if (container) container.innerHTML = '';
@ -928,4 +946,4 @@ document.addEventListener('navigate', ((e: Event) => {
chatElement.setAttribute('process-id', event.detail.processId || ''); chatElement.setAttribute('process-id', event.detail.processId || '');
} }
} }
})); });

View File

@ -12,7 +12,7 @@ self.addEventListener('activate', (event) => {
self.addEventListener('message', async (event) => { self.addEventListener('message', async (event) => {
const data = event.data; const data = event.data;
console.log(data); console.log(data);
if (data.type === 'SCAN') { if (data.type === 'SCAN') {
try { try {
const myProcessesId = data.payload; const myProcessesId = data.payload;
@ -20,7 +20,7 @@ self.addEventListener('message', async (event) => {
const toDownload = await scanMissingData(myProcessesId); const toDownload = await scanMissingData(myProcessesId);
if (toDownload.length != 0) { if (toDownload.length != 0) {
console.log('Sending TO_DOWNLOAD message'); console.log('Sending TO_DOWNLOAD message');
event.source.postMessage({ type: 'TO_DOWNLOAD', data: toDownload}); event.source.postMessage({ type: 'TO_DOWNLOAD', data: toDownload });
} }
} else { } else {
event.source.postMessage({ status: 'error', message: 'Empty lists' }); event.source.postMessage({ status: 'error', message: 'Empty lists' });
@ -95,7 +95,7 @@ async function scanMissingData(processesToScan) {
} }
} }
} }
} }
console.log(toDownload); console.log(toDownload);
return Array.from(toDownload); return Array.from(toDownload);
@ -139,7 +139,7 @@ async function getAllProcesses() {
reject(request.error); reject(request.error);
}; };
}); });
}; }
async function getProcesses(processIds) { async function getProcesses(processIds) {
if (!processIds || processIds.length === 0) { if (!processIds || processIds.length === 0) {
@ -160,13 +160,13 @@ async function getProcesses(processIds) {
request.onsuccess = () => resolve(request.result); request.onsuccess = () => resolve(request.result);
request.onerror = () => { request.onerror = () => {
console.error(`Error fetching process ${processId}:`, request.error); console.error(`Error fetching process ${processId}:`, request.error);
resolve(undefined); resolve(undefined);
}; };
}); });
}); });
const results = await Promise.all(requests); const results = await Promise.all(requests);
return results.filter(result => result !== undefined); return results.filter((result) => result !== undefined);
} }
async function getAllDiffsNeedValidation() { async function getAllDiffsNeedValidation() {
@ -204,11 +204,11 @@ async function getAllDiffsNeedValidation() {
} }
const results = Object.values(processMap).map((entry) => { const results = Object.values(processMap).map((entry) => {
const diffs = [] const diffs = [];
for(const state of entry.process) { for (const state of entry.process) {
const filteredDiff = entry.diffs.filter(diff => diff.new_state_merkle_root === state.merkle_root); const filteredDiff = entry.diffs.filter((diff) => diff.new_state_merkle_root === state.merkle_root);
if(filteredDiff && filteredDiff.length) { if (filteredDiff && filteredDiff.length) {
diffs.push(filteredDiff) diffs.push(filteredDiff);
} }
} }
return { return {
@ -253,7 +253,7 @@ async function addDiff(processId, stateId, hash, roles, field) {
getRequest.onerror = () => reject(getRequest.error); getRequest.onerror = () => reject(getRequest.error);
}); });
if (!existingDiff) { if (!existingDiff) {
const newDiff = { const newDiff = {
process_id: processId, process_id: processId,
state_id: stateId, state_id: stateId,
@ -265,7 +265,7 @@ async function addDiff(processId, stateId, hash, roles, field) {
new_value: null, new_value: null,
notify_user: false, notify_user: false,
need_validation: false, need_validation: false,
validation_status: 'None' validation_status: 'None',
}; };
const insertResult = await new Promise((resolve, reject) => { const insertResult = await new Promise((resolve, reject) => {

View File

@ -128,7 +128,7 @@ export class Database {
} else { } else {
// More than one existing worker: unregister them all and register a new one. // More than one existing worker: unregister them all and register a new one.
console.log('Multiple Service Worker(s) detected. Unregistering all...'); console.log('Multiple Service Worker(s) detected. Unregistering all...');
await Promise.all(registrations.map(reg => reg.unregister())); await Promise.all(registrations.map((reg) => reg.unregister()));
console.log('All previous Service Workers unregistered.'); console.log('All previous Service Workers unregistered.');
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' }); this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' });
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope); console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
@ -150,7 +150,7 @@ export class Database {
if (payload && payload.length != 0) { if (payload && payload.length != 0) {
activeWorker?.postMessage({ type: 'SCAN', payload }); activeWorker?.postMessage({ type: 'SCAN', payload });
} }
}, 5000); }, 5000);
} catch (error) { } catch (error) {
console.error('Service Worker registration failed:', error); console.error('Service Worker registration failed:', error);
} }
@ -158,19 +158,19 @@ export class Database {
// Helper function to wait for service worker activation // Helper function to wait for service worker activation
private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> { private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> {
return new Promise((resolve) => { return new Promise((resolve) => {
if (registration.active) {
resolve(registration.active);
} else {
const listener = () => {
if (registration.active) { if (registration.active) {
resolve(registration.active); navigator.serviceWorker.removeEventListener('controllerchange', listener);
} else { resolve(registration.active);
const listener = () => {
if (registration.active) {
navigator.serviceWorker.removeEventListener('controllerchange', listener);
resolve(registration.active);
}
};
navigator.serviceWorker.addEventListener('controllerchange', listener);
} }
}); };
navigator.serviceWorker.addEventListener('controllerchange', listener);
}
});
} }
private async checkForUpdates() { private async checkForUpdates() {
@ -217,15 +217,17 @@ export class Database {
const valueBytes = await service.fetchValueFromStorage(hash); const valueBytes = await service.fetchValueFromStorage(hash);
if (valueBytes) { if (valueBytes) {
// Save data to db // Save data to db
const blob = new Blob([valueBytes], {type: "application/octet-stream"}); const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
await service.saveBlobToDb(hash, blob); await service.saveBlobToDb(hash, blob);
document.dispatchEvent(new CustomEvent('newDataReceived', { document.dispatchEvent(
detail: { new CustomEvent('newDataReceived', {
processId, detail: {
stateId, processId,
hash, stateId,
} hash,
})); },
}),
);
} else { } else {
// We first request the data from managers // We first request the data from managers
console.log('Request data from managers of the process'); console.log('Request data from managers of the process');
@ -256,7 +258,7 @@ export class Database {
const valueBytes = await service.fetchValueFromStorage(hash); const valueBytes = await service.fetchValueFromStorage(hash);
if (valueBytes) { if (valueBytes) {
// Save data to db // Save data to db
const blob = new Blob([valueBytes], {type: "application/octet-stream"}); const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
await service.saveBlobToDb(hash, blob); await service.saveBlobToDb(hash, blob);
} else { } else {
// We first request the data from managers // We first request the data from managers
@ -321,7 +323,7 @@ export class Database {
reject(new Error(`Failed to send message to service worker: ${error}`)); reject(new Error(`Failed to send message to service worker: ${error}`));
} }
}); });
} }
public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> { public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
@ -440,7 +442,7 @@ export class Database {
const getAllRequest = index.getAll(request); const getAllRequest = index.getAll(request);
getAllRequest.onsuccess = () => { getAllRequest.onsuccess = () => {
const allItems = getAllRequest.result; const allItems = getAllRequest.result;
const filtered = allItems.filter(item => item.state_id === request); const filtered = allItems.filter((item) => item.state_id === request);
resolve(filtered); resolve(filtered);
}; };
getAllRequest.onerror = () => reject(getAllRequest.error); getAllRequest.onerror = () => reject(getAllRequest.error);

View File

@ -90,7 +90,7 @@ export default class ModalService {
const container = document.querySelector('#containerId'); const container = document.querySelector('#containerId');
if (container) { if (container) {
let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text()); let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text());
html = interpolate(html, {processId: processDiff.processId}) html = interpolate(html, { processId: processDiff.processId });
container.innerHTML += html; container.innerHTML += html;
// Dynamically load the header JS // Dynamically load the header JS
@ -103,7 +103,7 @@ export default class ModalService {
css.id = 'validation-modal-css'; css.id = 'validation-modal-css';
css.innerText = validationModalStyle; css.innerText = validationModalStyle;
document.head.appendChild(css); document.head.appendChild(css);
initValidationModal(processDiff) initValidationModal(processDiff);
} }
} }
@ -129,7 +129,7 @@ export default class ModalService {
throw new Error('Must have exactly 1 member'); throw new Error('Must have exactly 1 member');
} }
console.log("MEMBER OUTPOINTS:", memberOutPoints); console.log('MEMBER OUTPOINTS:', memberOutPoints);
// We take all the addresses except our own // We take all the addresses except our own
const service = await Services.getInstance(); const service = await Services.getInstance();
const localAddress = service.getDeviceAddress(); const localAddress = service.getDeviceAddress();
@ -158,11 +158,11 @@ export default class ModalService {
if (members[0].sp_addresses.length === 1) { if (members[0].sp_addresses.length === 1) {
await this.injectCreationModal(members); await this.injectCreationModal(members);
this.modal = document.getElementById('creation-modal'); this.modal = document.getElementById('creation-modal');
console.log("LENGTH:", members[0].sp_addresses.length); console.log('LENGTH:', members[0].sp_addresses.length);
} else { } else {
await this.injectModal(members); await this.injectModal(members);
this.modal = document.getElementById('modal'); this.modal = document.getElementById('modal');
console.log("LENGTH:", members[0].sp_addresses.length); console.log('LENGTH:', members[0].sp_addresses.length);
} }
if (this.modal) this.modal.style.display = 'flex'; if (this.modal) this.modal.style.display = 'flex';

View File

@ -12,8 +12,8 @@ export const U32_MAX = 4294967295;
const BASEURL = `http://localhost`; const BASEURL = `http://localhost`;
const BOOTSTRAPURL = [`${BASEURL}:8090`]; const BOOTSTRAPURL = [`${BASEURL}:8090`];
const STORAGEURL = `${BASEURL}:8081` const STORAGEURL = `${BASEURL}:8081`;
const BLINDBITURL = `${BASEURL}:8000` const BLINDBITURL = `${BASEURL}:8000`;
const DEFAULTAMOUNT = 1000n; const DEFAULTAMOUNT = 1000n;
const EMPTY32BYTES = String('').padStart(64, '0'); const EMPTY32BYTES = String('').padStart(64, '0');
@ -94,24 +94,24 @@ export default class Services {
* Waits for at least one handshake message before returning. * Waits for at least one handshake message before returning.
*/ */
public async connectAllRelays(): Promise<void> { public async connectAllRelays(): Promise<void> {
const connectedUrls: string[] = []; const connectedUrls: string[] = [];
// Connect to all relays // Connect to all relays
for (const wsurl of Object.keys(this.relayAddresses)) { for (const wsurl of Object.keys(this.relayAddresses)) {
try { try {
console.log(`Connecting to: ${wsurl}`); console.log(`Connecting to: ${wsurl}`);
await this.addWebsocketConnection(wsurl); await this.addWebsocketConnection(wsurl);
connectedUrls.push(wsurl); connectedUrls.push(wsurl);
console.log(`Successfully connected to: ${wsurl}`); console.log(`Successfully connected to: ${wsurl}`);
} catch (error) { } catch (error) {
console.error(`Failed to connect to ${wsurl}:`, error); console.error(`Failed to connect to ${wsurl}:`, error);
}
} }
}
// Wait for at least one handshake message if we have connections // Wait for at least one handshake message if we have connections
if (connectedUrls.length > 0) { if (connectedUrls.length > 0) {
await this.waitForHandshakeMessage(); await this.waitForHandshakeMessage();
} }
} }
public async addWebsocketConnection(url: string): Promise<void> { public async addWebsocketConnection(url: string): Promise<void> {
@ -125,8 +125,8 @@ export default class Services {
* @param spAddress - The SP Address (value). * @param spAddress - The SP Address (value).
*/ */
public updateRelay(wsurl: string, spAddress: string): void { public updateRelay(wsurl: string, spAddress: string): void {
this.relayAddresses[wsurl] = spAddress; this.relayAddresses[wsurl] = spAddress;
console.log(`Updated: ${wsurl} -> ${spAddress}`); console.log(`Updated: ${wsurl} -> ${spAddress}`);
} }
/** /**
@ -135,7 +135,7 @@ export default class Services {
* @returns The SP Address if found, or undefined if not. * @returns The SP Address if found, or undefined if not.
*/ */
public getSpAddress(wsurl: string): string | undefined { public getSpAddress(wsurl: string): string | undefined {
return this.relayAddresses[wsurl]; return this.relayAddresses[wsurl];
} }
/** /**
@ -143,20 +143,20 @@ export default class Services {
* @returns An array of objects containing wsurl and spAddress. * @returns An array of objects containing wsurl and spAddress.
*/ */
public getAllRelays(): { wsurl: string; spAddress: string }[] { public getAllRelays(): { wsurl: string; spAddress: string }[] {
return Object.entries(this.relayAddresses).map(([wsurl, spAddress]) => ({ return Object.entries(this.relayAddresses).map(([wsurl, spAddress]) => ({
wsurl, wsurl,
spAddress, spAddress,
})); }));
} }
/** /**
* Print all key/value pairs for debugging. * Print all key/value pairs for debugging.
*/ */
public printAllRelays(): void { public printAllRelays(): void {
console.log("Current relay addresses:"); console.log('Current relay addresses:');
for (const [wsurl, spAddress] of Object.entries(this.relayAddresses)) { for (const [wsurl, spAddress] of Object.entries(this.relayAddresses)) {
console.log(`${wsurl} -> ${spAddress}`); console.log(`${wsurl} -> ${spAddress}`);
} }
} }
public isPaired(): boolean { public isPaired(): boolean {
@ -307,27 +307,18 @@ export default class Services {
min_sig_member: 1.0, min_sig_member: 1.0,
}, },
], ],
storages: [STORAGEURL] storages: [STORAGEURL],
}, },
}; };
try { try {
return this.createProcess( return this.createProcess(privateData, publicData, roles);
privateData,
publicData,
roles
);
} catch (e) { } catch (e) {
throw new Error(`Creating process failed:, ${e}`); throw new Error(`Creating process failed:, ${e}`);
} }
} }
private isFileBlob(value: any): value is { type: string, data: Uint8Array } { private isFileBlob(value: any): value is { type: string; data: Uint8Array } {
return ( return typeof value === 'object' && value !== null && typeof value.type === 'string' && value.data instanceof Uint8Array;
typeof value === 'object' &&
value !== null &&
typeof value.type === 'string' &&
value.data instanceof Uint8Array
);
} }
private splitData(obj: Record<string, any>) { private splitData(obj: Record<string, any>) {
@ -345,11 +336,7 @@ export default class Services {
return { jsonCompatibleData, binaryData }; return { jsonCompatibleData, binaryData };
} }
public async createProcess( public async createProcess(privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition>): Promise<ApiReturn> {
privateData: Record<string, any>,
publicData: Record<string, any>,
roles: Record<string, RoleDefinition>,
): Promise<ApiReturn> {
let relayAddress = this.getAllRelays()[0]?.spAddress; let relayAddress = this.getAllRelays()[0]?.spAddress;
if (!relayAddress || relayAddress === '') { if (!relayAddress || relayAddress === '') {
@ -372,11 +359,11 @@ export default class Services {
const publicSplitData = this.splitData(publicData); const publicSplitData = this.splitData(publicData);
const encodedPrivateData = { const encodedPrivateData = {
...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData), ...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData),
...this.sdkClient.encode_binary(privateSplitData.binaryData) ...this.sdkClient.encode_binary(privateSplitData.binaryData),
}; };
const encodedPublicData = { const encodedPublicData = {
...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData), ...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData),
...this.sdkClient.encode_binary(publicSplitData.binaryData) ...this.sdkClient.encode_binary(publicSplitData.binaryData),
}; };
console.log('encoded data:', encodedPrivateData); console.log('encoded data:', encodedPrivateData);
@ -395,16 +382,9 @@ export default class Services {
console.log('members:', members); console.log('members:', members);
await this.checkConnections([...members]); await this.checkConnections([...members]);
const result = this.sdkClient.create_new_process ( const result = this.sdkClient.create_new_process(encodedPrivateData, roles, encodedPublicData, relayAddress, feeRate, this.getAllMembers());
encodedPrivateData,
roles,
encodedPublicData,
relayAddress,
feeRate,
this.getAllMembers()
);
return(result); return result;
} }
public async updateProcess(process: Process, privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition> | null): Promise<ApiReturn> { public async updateProcess(process: Process, privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition> | null): Promise<ApiReturn> {
@ -418,7 +398,7 @@ export default class Services {
let members: Set<Member> = new Set(); let members: Set<Member> = new Set();
for (const role of Object.values(roles!)) { for (const role of Object.values(roles!)) {
for (const member of role.members) { for (const member of role.members) {
members.add(member) members.add(member);
} }
} }
if (members.size === 0) { if (members.size === 0) {
@ -439,11 +419,11 @@ export default class Services {
const publicSplitData = this.splitData(publicData); const publicSplitData = this.splitData(publicData);
const encodedPrivateData = { const encodedPrivateData = {
...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData), ...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData),
...this.sdkClient.encode_binary(privateSplitData.binaryData) ...this.sdkClient.encode_binary(privateSplitData.binaryData),
}; };
const encodedPublicData = { const encodedPublicData = {
...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData), ...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData),
...this.sdkClient.encode_binary(publicSplitData.binaryData) ...this.sdkClient.encode_binary(publicSplitData.binaryData),
}; };
try { try {
return this.sdkClient.update_process(process, encodedPrivateData, roles, encodedPublicData, this.getAllMembers()); return this.sdkClient.update_process(process, encodedPrivateData, roles, encodedPublicData, this.getAllMembers());
@ -544,7 +524,6 @@ export default class Services {
if (waitingModal) { if (waitingModal) {
this.device2Ready = true; this.device2Ready = true;
} }
} catch (e) { } catch (e) {
console.error(`Parsed cipher with error: ${e}`); console.error(`Parsed cipher with error: ${e}`);
} }
@ -612,7 +591,7 @@ export default class Services {
if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) { if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) {
this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send)); this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send));
await new Promise(r => setTimeout(r, 500)); await new Promise((r) => setTimeout(r, 500));
} }
if (apiReturn.secrets) { if (apiReturn.secrets) {
@ -789,7 +768,7 @@ export default class Services {
try { try {
let encodedSpAddressList: number[] = []; let encodedSpAddressList: number[] = [];
if (this.stateId) { if (this.stateId) {
const state = process.states.find(state => state.state_id === this.stateId); const state = process.states.find((state) => state.state_id === this.stateId);
if (state) { if (state) {
encodedSpAddressList = state.public_data['pairedAddresses']; encodedSpAddressList = state.public_data['pairedAddresses'];
} }
@ -858,7 +837,7 @@ export default class Services {
try { try {
const prevDevice = await this.getDeviceFromDatabase(); const prevDevice = await this.getDeviceFromDatabase();
if (prevDevice) { if (prevDevice) {
await db.deleteObject(walletStore, "1"); await db.deleteObject(walletStore, '1');
} }
await db.addObject({ await db.addObject({
storeName: walletStore, storeName: walletStore,
@ -1256,7 +1235,7 @@ export default class Services {
let retries = 0; let retries = 0;
while ((!hash || !key) && retries < maxRetries) { while ((!hash || !key) && retries < maxRetries) {
await new Promise(resolve => setTimeout(resolve, retryDelay)); await new Promise((resolve) => setTimeout(resolve, retryDelay));
// Re-read hash and key after waiting // Re-read hash and key after waiting
hash = state.pcd_commitment[attribute]; hash = state.pcd_commitment[attribute];
key = state.keys[attribute]; key = state.keys[attribute];
@ -1373,7 +1352,6 @@ export default class Services {
this.device2Ready = false; this.device2Ready = false;
} }
// Handle the handshake message // Handle the handshake message
public async handleHandshakeMsg(url: string, parsedMsg: any) { public async handleHandshakeMsg(url: string, parsedMsg: any) {
try { try {
@ -1414,7 +1392,9 @@ export default class Services {
let new_states: string[] = []; let new_states: string[] = [];
let roles: Record<string, RoleDefinition>[] = []; let roles: Record<string, RoleDefinition>[] = [];
for (const state of process.states) { for (const state of process.states) {
if (!state.state_id || state.state_id === EMPTY32BYTES) { continue; } if (!state.state_id || state.state_id === EMPTY32BYTES) {
continue;
}
if (!this.lookForStateId(existing, state.state_id)) { if (!this.lookForStateId(existing, state.state_id)) {
if (this.rolesContainsUs(state.roles)) { if (this.rolesContainsUs(state.roles)) {
new_states.push(state.state_id); new_states.push(state.state_id);
@ -1462,7 +1442,7 @@ export default class Services {
await this.batchSaveProcessesToDb(toSave); await this.batchSaveProcessesToDb(toSave);
} }
}, 500) }, 500);
} catch (e) { } catch (e) {
console.error('Failed to parse init message:', e); console.error('Failed to parse init message:', e);
} }
@ -1515,9 +1495,7 @@ export default class Services {
* @returns Un tableau contenant tous les membres * @returns Un tableau contenant tous les membres
*/ */
public getAllMembersSorted(): Record<string, Member> { public getAllMembersSorted(): Record<string, Member> {
return Object.fromEntries( return Object.fromEntries(Object.entries(this.membersList).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)));
Object.entries(this.membersList).sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
);
} }
public getAllMembers(): Record<string, Member> { public getAllMembers(): Record<string, Member> {
@ -1533,10 +1511,14 @@ export default class Services {
} }
public compareMembers(memberA: string[], memberB: string[]): boolean { public compareMembers(memberA: string[], memberB: string[]): boolean {
if (!memberA || !memberB) { return false } if (!memberA || !memberB) {
if (memberA.length !== memberB.length) { return false } return false;
}
if (memberA.length !== memberB.length) {
return false;
}
const res = memberA.every(item => memberB.includes(item)) && memberB.every(item => memberA.includes(item)); const res = memberA.every((item) => memberB.includes(item)) && memberB.every((item) => memberA.includes(item));
return res; return res;
} }
@ -1545,16 +1527,14 @@ export default class Services {
const content = JSON.parse(response); const content = JSON.parse(response);
const error = content.error; const error = content.error;
const errorMsg = error['GenericError']; const errorMsg = error['GenericError'];
const dontRetry = [ const dontRetry = ['State is identical to the previous state', 'Not enough valid proofs', 'Not enough members to validate'];
'State is identical to the previous state', if (dontRetry.includes(errorMsg)) {
'Not enough valid proofs', return;
'Not enough members to validate', }
];
if (dontRetry.includes(errorMsg)) { return; }
// Wait and retry // Wait and retry
setTimeout(async () => { setTimeout(async () => {
this.sendCommitMessage(JSON.stringify(content)); this.sendCommitMessage(JSON.stringify(content));
}, 1000) }, 1000);
} }
public getRoles(process: Process): Record<string, RoleDefinition> | null { public getRoles(process: Process): Record<string, RoleDefinition> | null {
@ -1587,8 +1567,11 @@ export default class Services {
const lastCommitedState = this.getLastCommitedState(process); const lastCommitedState = this.getLastCommitedState(process);
if (lastCommitedState && lastCommitedState.public_data) { if (lastCommitedState && lastCommitedState.public_data) {
const processName = lastCommitedState!.public_data['processName']; const processName = lastCommitedState!.public_data['processName'];
if (processName) { return this.decodeValue(processName) } if (processName) {
else { return null } return this.decodeValue(processName);
} else {
return null;
}
} else { } else {
return null; return null;
} }
@ -1630,7 +1613,7 @@ export default class Services {
this.myProcesses = newMyProcesses; // atomic update this.myProcesses = newMyProcesses; // atomic update
return Array.from(this.myProcesses); return Array.from(this.myProcesses);
} catch (e) { } catch (e) {
console.error("Failed to get processes:", e); console.error('Failed to get processes:', e);
return null; return null;
} }
} }
@ -1652,12 +1635,12 @@ export default class Services {
const ab = new ArrayBuffer(uint8Array.length); const ab = new ArrayBuffer(uint8Array.length);
const view = new Uint8Array(ab); const view = new Uint8Array(ab);
view.set(uint8Array); view.set(uint8Array);
return new Blob([ab], { type: "application/octet-stream" }); return new Blob([ab], { type: 'application/octet-stream' });
} }
public hexToUInt8Array(hexString: string): Uint8Array { public hexToUInt8Array(hexString: string): Uint8Array {
if (hexString.length % 2 !== 0) { if (hexString.length % 2 !== 0) {
throw new Error("Invalid hex string: length must be even"); throw new Error('Invalid hex string: length must be even');
} }
const uint8Array = new Uint8Array(hexString.length / 2); const uint8Array = new Uint8Array(hexString.length / 2);
for (let i = 0; i < hexString.length; i += 2) { for (let i = 0; i < hexString.length; i += 2) {
@ -1671,7 +1654,7 @@ export default class Services {
const buffer = await blob.arrayBuffer(); const buffer = await blob.arrayBuffer();
const bytes = new Uint8Array(buffer); const bytes = new Uint8Array(buffer);
return Array.from(bytes) return Array.from(bytes)
.map(byte => byte.toString(16).padStart(2, '0')) .map((byte) => byte.toString(16).padStart(2, '0'))
.join(''); .join('');
} }
@ -1743,7 +1726,9 @@ export default class Services {
} }
public isPairingProcess(roles: Record<string, RoleDefinition>): boolean { public isPairingProcess(roles: Record<string, RoleDefinition>): boolean {
if (Object.keys(roles).length != 1) { return false } if (Object.keys(roles).length != 1) {
return false;
}
const pairingRole = roles['pairing']; const pairingRole = roles['pairing'];
if (pairingRole) { if (pairingRole) {
// For now that's enough, we should probably test more things // For now that's enough, we should probably test more things
@ -1755,7 +1740,7 @@ export default class Services {
public async updateMemberPublicName(process: Process, newName: string): Promise<ApiReturn> { public async updateMemberPublicName(process: Process, newName: string): Promise<ApiReturn> {
const publicData = { const publicData = {
'memberPublicName': newName memberPublicName: newName,
}; };
return await this.updateProcess(process, {}, publicData, null); return await this.updateProcess(process, {}, publicData, null);

View File

@ -13,7 +13,7 @@ export async function storeData(servers: string[], key: string, value: Blob, ttl
// Send the encrypted ArrayBuffer as the raw request body. // Send the encrypted ArrayBuffer as the raw request body.
const response = await axios.post(url.toString(), value, { const response = await axios.post(url.toString(), value, {
headers: { headers: {
'Content-Type': 'application/octet-stream' 'Content-Type': 'application/octet-stream',
}, },
}); });
console.log('Data stored successfully:', key); console.log('Data stored successfully:', key);
@ -37,45 +37,45 @@ export async function retrieveData(servers: string[], key: string): Promise<Arra
try { try {
// When fetching the data from the server: // When fetching the data from the server:
const response = await axios.get(`${server}/retrieve/${key}`, { const response = await axios.get(`${server}/retrieve/${key}`, {
responseType: 'arraybuffer' responseType: 'arraybuffer',
}); });
if (response.status !== 200) { if (response.status !== 200) {
console.error('Received response status', response.status); console.error('Received response status', response.status);
continue; continue;
} }
// console.log('Retrieved data:', response.data); // console.log('Retrieved data:', response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error retrieving data:', error); console.error('Error retrieving data:', error);
} }
} }
return null return null;
} }
interface TestResponse { interface TestResponse {
key: string; key: string;
value: boolean; value: boolean;
} }
export async function testData(servers: string[], key: string): Promise<Record<string, boolean | null> | null> { export async function testData(servers: string[], key: string): Promise<Record<string, boolean | null> | null> {
const res: Record<string, boolean | null> = {}; const res: Record<string, boolean | null> = {};
for (const server of servers) { for (const server of servers) {
res[server] = null; res[server] = null;
try { try {
const response = await axios.get(`${server}/test/${key}`); const response = await axios.get(`${server}/test/${key}`);
if (response.status !== 200) { if (response.status !== 200) {
console.error(`${server}: Test response status: ${response.status}`); console.error(`${server}: Test response status: ${response.status}`);
continue; continue;
} }
const data: TestResponse = response.data; const data: TestResponse = response.data;
res[server] = data.value; res[server] = data.value;
} catch (error) { } catch (error) {
console.error('Error retrieving data:', error); console.error('Error retrieving data:', error);
return null; return null;
}
} }
}
return res;
return res;
} }

View File

@ -38,17 +38,9 @@ export default class TokenService {
async generateSessionToken(origin: string): Promise<TokenPair> { async generateSessionToken(origin: string): Promise<TokenPair> {
const secret = new Uint8Array(this.encoder.encode(this.SECRET_KEY)); const secret = new Uint8Array(this.encoder.encode(this.SECRET_KEY));
const accessToken = await new jose.SignJWT({ origin, type: 'access' }) const accessToken = await new jose.SignJWT({ origin, type: 'access' }).setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setExpirationTime(this.ACCESS_TOKEN_EXPIRATION).sign(secret);
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime(this.ACCESS_TOKEN_EXPIRATION)
.sign(secret);
const refreshToken = await new jose.SignJWT({ origin, type: 'refresh' }) const refreshToken = await new jose.SignJWT({ origin, type: 'refresh' }).setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setExpirationTime(this.REFRESH_TOKEN_EXPIRATION).sign(secret);
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime(this.REFRESH_TOKEN_EXPIRATION)
.sign(secret);
return { accessToken, refreshToken }; return { accessToken, refreshToken };
} }
@ -86,11 +78,7 @@ export default class TokenService {
} }
// Générer un nouveau access token // Générer un nouveau access token
const newAccessToken = await new jose.SignJWT({ origin, type: 'access' }) const newAccessToken = await new jose.SignJWT({ origin, type: 'access' }).setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setExpirationTime(this.ACCESS_TOKEN_EXPIRATION).sign(secret);
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime(this.ACCESS_TOKEN_EXPIRATION)
.sign(secret);
return newAccessToken; return newAccessToken;
} catch (error) { } catch (error) {
@ -98,4 +86,4 @@ export default class TokenService {
return null; return null;
} }
} }
} }

View File

@ -3,11 +3,11 @@
declare module 'pkg/sdk_client' { declare module 'pkg/sdk_client' {
// Types de base // Types de base
export type DiffStatus = "None" | "Rejected" | "Validated"; export type DiffStatus = 'None' | 'Rejected' | 'Validated';
export type AnkFlag = "NewTx" | "Faucet" | "Cipher" | "Commit" | "Handshake" | "Sync" | "Unknown"; export type AnkFlag = 'NewTx' | 'Faucet' | 'Cipher' | 'Commit' | 'Handshake' | 'Sync' | 'Unknown';
export type PrdType = "None" | "Connect" | "Message" | "Update" | "List" | "Response" | "Confirm" | "TxProposal" | "Request"; export type PrdType = 'None' | 'Connect' | 'Message' | 'Update' | 'List' | 'Response' | 'Confirm' | 'TxProposal' | 'Request';
export type SyncType = "StateSync" | "ProcessSync" | "MemberSync" | "TxSync" | "BlockSync" | "PeerSync" | "RelaySync" | "HealthSync" | "MetricsSync" | "ConfigSync" | "CapabilitySync"; export type SyncType = 'StateSync' | 'ProcessSync' | 'MemberSync' | 'TxSync' | 'BlockSync' | 'PeerSync' | 'RelaySync' | 'HealthSync' | 'MetricsSync' | 'ConfigSync' | 'CapabilitySync';
export type HealthStatus = "Healthy" | "Warning" | "Critical" | "Offline"; export type HealthStatus = 'Healthy' | 'Warning' | 'Critical' | 'Offline';
export type OutPoint = string; export type OutPoint = string;
export type SilentPaymentAddress = string; export type SilentPaymentAddress = string;
export type AnkSharedSecretHash = string; export type AnkSharedSecretHash = string;
@ -186,52 +186,14 @@ declare module 'pkg/sdk_client' {
export function get_available_amount(): bigint; export function get_available_amount(): bigint;
export function create_transaction(addresses: string[], fee_rate: number): ApiReturn; export function create_transaction(addresses: string[], fee_rate: number): ApiReturn;
export function sign_transaction(partial_tx: TsUnsignedTransaction): ApiReturn; export function sign_transaction(partial_tx: TsUnsignedTransaction): ApiReturn;
export function create_new_process( export function create_new_process(private_data: Pcd, roles: Roles, public_data: Pcd, relay_address: string, fee_rate: number, members_list: OutPointMemberMap): ApiReturn;
private_data: Pcd, export function update_process(process: Process, new_attributes: Pcd, roles: Roles, new_public_data: Pcd, members_list: OutPointMemberMap): ApiReturn;
roles: Roles, export function request_data(process_id: string, state_ids_str: string[], roles: any, members_list: OutPointMemberMap): ApiReturn;
public_data: Pcd, export function create_update_message(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
relay_address: string, export function validate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
fee_rate: number, export function refuse_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
members_list: OutPointMemberMap export function evaluate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
): ApiReturn; export function create_response_prd(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function update_process(
process: Process,
new_attributes: Pcd,
roles: Roles,
new_public_data: Pcd,
members_list: OutPointMemberMap
): ApiReturn;
export function request_data(
process_id: string,
state_ids_str: string[],
roles: any,
members_list: OutPointMemberMap
): ApiReturn;
export function create_update_message(
process: Process,
state_id: string,
members_list: OutPointMemberMap
): ApiReturn;
export function validate_state(
process: Process,
state_id: string,
members_list: OutPointMemberMap
): ApiReturn;
export function refuse_state(
process: Process,
state_id: string,
members_list: OutPointMemberMap
): ApiReturn;
export function evaluate_state(
process: Process,
state_id: string,
members_list: OutPointMemberMap
): ApiReturn;
export function create_response_prd(
process: Process,
state_id: string,
members_list: OutPointMemberMap
): ApiReturn;
export function create_faucet_msg(): string; export function create_faucet_msg(): string;
export function get_storages(process_outpoint: string): string[]; export function get_storages(process_outpoint: string): string[];
export function is_child_role(parent_roles: string, child_roles: string): void; export function is_child_role(parent_roles: string, child_roles: string): void;

View File

@ -1,4 +1,4 @@
export function splitPrivateData(data: Record<string, any>, privateFields: string[]): { privateData: Record<string, any>, publicData: Record<string, any> } { export function splitPrivateData(data: Record<string, any>, privateFields: string[]): { privateData: Record<string, any>; publicData: Record<string, any> } {
const privateData: Record<string, any> = {}; const privateData: Record<string, any> = {};
const publicData: Record<string, any> = {}; const publicData: Record<string, any> = {};
@ -18,7 +18,7 @@ export function isValid32ByteHex(value: string): boolean {
if (value.length !== 64) { if (value.length !== 64) {
return false; return false;
} }
// Check if string only contains valid hex characters // Check if string only contains valid hex characters
return /^[0-9a-fA-F]{64}$/.test(value); return /^[0-9a-fA-F]{64}$/.test(value);
} }

View File

@ -100,7 +100,7 @@ export async function displayEmojis(text: string) {
// Verify Other address // Verify Other address
export function initAddressInput() { export function initAddressInput() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const addressInput = container.querySelector('#addressInput') as HTMLInputElement; const addressInput = container.querySelector('#addressInput') as HTMLInputElement;
const emojiDisplay = container.querySelector('#emoji-display-2'); const emojiDisplay = container.querySelector('#emoji-display-2');
const okButton = container.querySelector('#okButton') as HTMLButtonElement; const okButton = container.querySelector('#okButton') as HTMLButtonElement;
@ -155,7 +155,7 @@ async function onCreateButtonClick() {
const service = await Services.getInstance(); const service = await Services.getInstance();
await service.confirmPairing(); await service.confirmPairing();
} catch (e) { } catch (e) {
console.error(`onCreateButtonClick error: ${e}`); console.error(`onCreateButtonClick error: ${e}`);
} }
} }
@ -170,10 +170,7 @@ export async function prepareAndSendPairingTx(): Promise<void> {
try { try {
const relayAddress = service.getAllRelays(); const relayAddress = service.getAllRelays();
const createPairingProcessReturn = await service.createPairingProcess( const createPairingProcessReturn = await service.createPairingProcess('', []);
"",
[],
);
if (!createPairingProcessReturn.updated_process) { if (!createPairingProcessReturn.updated_process) {
throw new Error('createPairingProcess returned an empty new process'); throw new Error('createPairingProcess returned an empty new process');
@ -183,7 +180,6 @@ export async function prepareAndSendPairingTx(): Promise<void> {
service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id); service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id);
await service.handleApiReturn(createPairingProcessReturn); await service.handleApiReturn(createPairingProcessReturn);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -191,7 +187,7 @@ export async function prepareAndSendPairingTx(): Promise<void> {
export async function generateQRCode(spAddress: string) { export async function generateQRCode(spAddress: string) {
try { try {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const currentUrl = 'https://' + window.location.host; const currentUrl = 'https://' + window.location.host;
const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress); const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress);
const qrCode = container?.querySelector('.qr-code img'); const qrCode = container?.querySelector('.qr-code img');
@ -202,9 +198,9 @@ export async function generateQRCode(spAddress: string) {
} }
export async function generateCreateBtn() { export async function generateCreateBtn() {
try{ try {
//Generate CreateBtn //Generate CreateBtn
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const createBtn = container?.querySelector('.create-btn'); const createBtn = container?.querySelector('.create-btn');
if (createBtn) { if (createBtn) {
createBtn.textContent = 'CREATE'; createBtn.textContent = 'CREATE';
@ -212,5 +208,4 @@ export async function generateCreateBtn() {
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
}
}