load pairing device ok

This commit is contained in:
NicolasCantu 2025-03-19 16:09:12 +01:00
parent afe45ad960
commit a42141246d
3 changed files with 242 additions and 57 deletions

View File

@ -1423,3 +1423,64 @@ body {
font-size: 12px;
color: #666;
}
.pairing-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.pairing-modal-content {
background-color: white;
padding: 2rem;
border-radius: 8px;
width: 90%;
max-width: 500px;
}
.pairing-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-group label {
font-weight: bold;
}
.button-group {
display: flex;
gap: 1rem;
justify-content: flex-end;
margin-top: 1rem;
}
.button-group button {
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
}
.confirm-button {
background-color: var(--accent-color);
color: white;
border: none;
}
.cancel-button {
background-color: #ccc;
border: none;
}

View File

@ -20,7 +20,7 @@ declare global {
updateNavbarBanner: (bannerUrl: string) => void;
saveBannerToLocalStorage: (bannerUrl: string) => void;
loadSavedBanner: () => void;
cancelAddRow: () => void;
cancelAddRowPairing: () => void;
saveName: (cell: HTMLElement, input: HTMLInputElement) => void;
showProcessNotifications: (processName: string) => void;
handleLogout: () => void;
@ -29,10 +29,10 @@ declare global {
updateNavbarName: (name: string) => void;
updateNavbarLastName: (lastName: string) => void;
showAlert: (title: string, text?: string, icon?: string) => void;
addRow: () => void;
confirmRow: () => void;
cancelRow: () => void;
deleteRow: (button: HTMLButtonElement) => void;
addRowPairing: () => void;
confirmRowPairing: () => void;
cancelRowPairing: () => void;
deleteRowPairing: (button: HTMLButtonElement) => void;
generateRecoveryWords: () => string[];
exportUserData: () => void;
updateActionButtons: () => void;
@ -154,18 +154,18 @@ class AccountElement extends HTMLElement {
</ul>
<ul class="parameter-list-ul" onclick="window.showPairing()">Pairing 🔗</ul>
<ul class="parameter-list-ul" onclick="window.showWallet()">Wallet 👛</ul>
<!-- <ul class="parameter-list-ul" onclick="window.showWallet()">Wallet 👛</ul> -->
<ul class="parameter-list-ul" onclick="window.showProcess()">Process </ul>
<ul class="parameter-list-ul" onclick="window.showData()">Data 💾</ul>
<!-- <ul class="parameter-list-ul" onclick="window.showData()">Data 💾</ul> -->
</div>
<!-- Parameter Area -->
<div class="parameter-area">
<div class="content-container">
<div id="pairing-content"></div>
<div id="wallet-content"></div>
<div id="process-content"></div>
<div id="data-content"></div>
<!-- <div id="wallet-content"></div> -->
<div id="process-content"></div>
<!-- <div id="data-content"></div> -->
</div>
</div>
</div>
@ -184,10 +184,10 @@ class AccountElement extends HTMLElement {
window.handleLogout = () => this.handleLogout();
window.confirmDeleteAccount = () => this.confirmDeleteAccount();
window.showContractPopup = (contractId: string) => this.showContractPopup(contractId);
window.addRow = () => this.addRow();
window.deleteRow = (button: HTMLButtonElement) => this.deleteRow(button);
window.confirmRow = () => this.confirmRow();
window.cancelRow = () => this.cancelRow();
window.addRowPairing = () => this.addRowPairing();
window.deleteRowPairing = (button: HTMLButtonElement) => this.deleteRowPairing(button);
window.confirmRowPairing = () => this.confirmRowPairing();
window.cancelRowPairing = () => this.cancelRowPairing();
window.updateNavbarBanner = (bannerUrl: string) => this.updateNavbarBanner(bannerUrl);
window.saveBannerToLocalStorage = (bannerUrl: string) => this.saveBannerToLocalStorage(bannerUrl);
window.loadSavedBanner = () => this.loadSavedBanner();
@ -488,7 +488,7 @@ private getConfirmFunction(): string {
case 'process':
return 'window.confirmProcessRow()';
default:
return 'window.confirmRow()';
return 'window.confirmRowPairing()';
}
}
@ -499,50 +499,94 @@ private getCancelFunction(): string {
case 'process':
return 'window.cancelProcessRow()';
default:
return 'window.cancelRow()';
return 'window.cancelRowPairing()';
}
}
// Fonctions de gestion des tableaux
private addRow(): void {
private addRowPairing(): void {
if (isAddingRow) return;
isAddingRow = true;
const table = this.shadowRoot?.querySelector<HTMLTableElement>('#pairing-table tbody');
if (!table) return;
currentRow = table.insertRow();
const cells = ['SP Address', 'Device Name', 'SP Emojis'];
cells.forEach((_, index) => {
const cell = currentRow!.insertCell();
const input = document.createElement('input');
input.type = 'text';
input.className = 'edit-input';
// Ajouter un événement pour mettre à jour automatiquement les emojis
if (index === 0) {
input.addEventListener('input', async (e) => {
const addressInput = e.target as HTMLInputElement;
const emojiCell = currentRow!.cells[2];
const emojis = await addressToEmoji(addressInput.value);
if (emojiCell.querySelector('input')) {
(emojiCell.querySelector('input') as HTMLInputElement).value = emojis;
}
});
}
if (index === 2) {
input.readOnly = true;
}
cell.appendChild(input);
// Créer la popup
const modal = document.createElement('div');
modal.className = 'pairing-modal';
modal.innerHTML = `
<div class="pairing-modal-content">
<h3>Add New Device</h3>
<div class="pairing-form">
<div class="form-group">
<label for="sp-address">SP Address</label>
<input type="text" id="sp-address" class="edit-input" placeholder="Enter SP Address">
</div>
<div class="form-group">
<label for="device-name">Device Name</label>
<input type="text" id="device-name" class="edit-input" placeholder="Enter Device Name">
</div>
<div class="form-group">
<label for="sp-emojis">SP Emojis</label>
<input type="text" id="sp-emojis" class="edit-input" readonly>
</div>
<div class="button-group">
<button class="confirm-button">Confirm</button>
<button class="cancel-button">Cancel</button>
</div>
</div>
</div>
`;
this.shadowRoot?.appendChild(modal);
// Ajouter les event listeners
const spAddressInput = modal.querySelector('#sp-address') as HTMLInputElement;
const spEmojisInput = modal.querySelector('#sp-emojis') as HTMLInputElement;
const deviceNameInput = modal.querySelector('#device-name') as HTMLInputElement;
const confirmButton = modal.querySelector('.confirm-button');
const cancelButton = modal.querySelector('.cancel-button');
// Mettre à jour les emojis automatiquement
spAddressInput?.addEventListener('input', async () => {
const emojis = await addressToEmoji(spAddressInput.value);
if (spEmojisInput) spEmojisInput.value = emojis;
});
const deleteCell = currentRow.insertCell();
deleteCell.style.width = '40px';
// Gérer la confirmation
confirmButton?.addEventListener('click', () => {
const spAddress = spAddressInput?.value.trim();
const deviceName = deviceNameInput?.value.trim();
const spEmojis = spEmojisInput?.value.trim();
this.updateActionButtons();
if (!spAddress || !deviceName) {
this.showAlert('Please fill in all required fields');
return;
}
//if (spAddress.length !== 118) {
// this.showAlert('SP Address must be exactly 118 characters long');
// return;
//}
const newRow: Row = {
column1: spAddress,
column2: deviceName,
column3: spEmojis || ''
};
const storageKey = STORAGE_KEYS[currentMode];
const rows: Row[] = JSON.parse(localStorage.getItem(storageKey) || '[]');
rows.push(newRow);
localStorage.setItem(storageKey, JSON.stringify(rows));
this.updateTableContent(rows);
modal.remove();
isAddingRow = false;
});
// Gérer l'annulation
cancelButton?.addEventListener('click', () => {
modal.remove();
isAddingRow = false;
});
}
// Fonctions de mise à jour de l'interface
@ -552,7 +596,6 @@ private updateTableContent(rows: Row[]): void {
tbody.innerHTML = rows.map(row => `
<tr>
<td>${row.column1}</td>
<td class="device-name" onclick="window.editDeviceName(this)">${row.column2}</td>
<td>${row.column3}</td>
<td>
@ -563,7 +606,7 @@ private updateTableContent(rows: Row[]): void {
onclick="window.showQRCodeModal('${encodeURIComponent(row.column1)}')">
</td>
<td>
<button class="delete-button" onclick="window.deleteRow(this)">
<button class="delete-button" onclick="window.deleteRowPairing(this)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="16" height="16" fill="red">
<path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/>
</svg>
@ -575,7 +618,7 @@ private updateTableContent(rows: Row[]): void {
private confirmRow(): void {
private confirmRowPairing(): void {
if (!currentRow) return;
const inputs = currentRow.getElementsByTagName('input');
@ -611,7 +654,7 @@ private confirmRow(): void {
this.updateTableContent(rows);
}
private cancelRow(): void {
private cancelRowPairing(): void {
if (!currentRow) return;
currentRow.remove();
@ -626,11 +669,11 @@ private resetButtonContainer(): void {
if (!buttonContainer) return;
buttonContainer.innerHTML = `
<button class="add-row-button button-style" onclick="window.addRow()">Add a line</button>
<button class="add-row-button button-style" onclick="window.addRowPairing()">Add a line</button>
`;
}
private deleteRow(button: HTMLButtonElement): void {
private deleteRowPairing(button: HTMLButtonElement): void {
const row = button.closest('tr');
if (!row) return;
@ -930,7 +973,6 @@ private async showPairing(): Promise<void> {
<table class="parameter-table" id="pairing-table">
<thead>
<tr>
<th>SP Address</th>
<th>Device Name</th>
<th>SP Emojis</th>
<th>QR Code</th>
@ -940,7 +982,7 @@ private async showPairing(): Promise<void> {
<tbody></tbody>
</table>
<div class="button-container">
<button class="add-row-button button-style" onclick="window.addRow()">Add a line</button>
<button class="add-row-button button-style" onclick="window.addRowPairing()">Add a line</button>
</div>
</div>
`;

View File

@ -357,6 +357,88 @@ export default class Services {
}
}
public async createNotaryProcess(notaryTokens: string[]): Promise<ApiReturn> {
const notaryProcess = this.lookForNotaryProcess();
if (notaryProcess) {
throw new Error('There is already a notary process');
}
const myProcessId: string = this.getPairingProcessId();
const roles: Record<string, RoleDefinition> = {
notary: {
members: [{ process_id: myProcessId }],
validation_rules: [
{
quorum: 0,
fields: ['roles', 'idNotTokens'],
min_sig_member: 0,
},
],
storages: [STORAGEURL]
},
};
const pairingTemplate = {
description: 'notary',
};
const publicData = {
idNotTokens: notaryTokens,
}
const relayAddress = this.getAllRelays()[0]['spAddress'];
const feeRate = 1;
try {
return this.sdkClient.create_new_process(
pairingTemplate,
roles,
publicData,
relayAddress,
feeRate
);
} catch (e) {
throw new Error(`Creating process failed:, ${e}`);
}
}
private async lookForNotaryProcess(): Promise<string | null> {
const processes = await this.getMyProcesses();
for (const processId of processes) {
try {
const process = await this.getProcess(processId);
const roles = this.getRoles(process);
const roleKeys = Object.keys(roles);
if (roleKeys.includes("notary")) {
let publicData;
const lastCommitedState = this.getLastCommitedState(process);
if (lastCommitedState) {
publicData = lastCommitedState.public_data;
} else {
publicData = process.states[0].public_data;
}
const publicDataKeys = Object.keys(publicData);
if (publicDataKeys.includes("idNotTokens")){
return processId;
} else {
continue;
}
} else {
continue;
}
} catch (e) {
console.error(e);
}
}
return null;
}
public async updateProcess(process: Process, new_state: any, roles: Record<string, RoleDefinition> | null): Promise<ApiReturn> {
// If roles is null, we just take the last commited state roles
if (!roles) {