refactor(core): découpage du service principal en modules métier et centralisation de la configuration globale
This commit is contained in:
parent
3eeef3fc9a
commit
04996ceaa5
31
src/config/constants.ts
Normal file
31
src/config/constants.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
// --- Cryptographie & Limites ---
|
||||||
|
U32_MAX: 4294967295,
|
||||||
|
EMPTY_32_BYTES: String('').padStart(64, '0'),
|
||||||
|
|
||||||
|
// --- Économie ---
|
||||||
|
DEFAULT_AMOUNT: 1000n,
|
||||||
|
FEE_RATE: 1, // Sat/vByte ou unité arbitraire selon le SDK
|
||||||
|
|
||||||
|
// --- Délais & Timeouts (ms) ---
|
||||||
|
TIMEOUTS: {
|
||||||
|
POLLING_INTERVAL: 100, // Vérification rapide (ex: handshake)
|
||||||
|
API_DELAY: 500, // Petit délai pour laisser respirer le réseau (hack)
|
||||||
|
RETRY_DELAY: 1000, // Délai avant de réessayer une action
|
||||||
|
FAUCET_WAIT: 2000, // Attente après appel faucet
|
||||||
|
WORKER_CHECK: 5000, // Vérification périodique du worker
|
||||||
|
HANDSHAKE: 10000, // Timeout max pour le handshake
|
||||||
|
KEY_REQUEST: 15000, // Timeout pour recevoir une clé d'un pair
|
||||||
|
WS_RECONNECT_MAX: 30000, // Délai max entre deux tentatives de reco WS
|
||||||
|
WS_HEARTBEAT: 30000, // Ping WebSocket
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- URLs (Environnement) ---
|
||||||
|
URLS: {
|
||||||
|
BASE: import.meta.env.VITE_BASEURL || 'http://localhost',
|
||||||
|
BOOTSTRAP: [import.meta.env.VITE_BOOTSTRAPURL || `${import.meta.env.VITE_BASEURL || 'http://localhost'}:8090`],
|
||||||
|
STORAGE: import.meta.env.VITE_STORAGEURL || `${import.meta.env.VITE_BASEURL || 'http://localhost'}:8081`,
|
||||||
|
BLINDBIT: import.meta.env.VITE_BLINDBITURL || `${import.meta.env.VITE_BASEURL || 'http://localhost'}:8000`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
85
src/services/core/network.service.ts
Normal file
85
src/services/core/network.service.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { initWebsocket, sendMessage } from '../websockets.service.ts';
|
||||||
|
import { AnkFlag } from '../../../pkg/sdk_client';
|
||||||
|
|
||||||
|
export class NetworkService {
|
||||||
|
private relayAddresses: { [wsurl: string]: string } = {};
|
||||||
|
private relayReadyResolver: (() => void) | null = null;
|
||||||
|
private relayReadyPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
|
constructor(private bootstrapUrls: string[]) {}
|
||||||
|
|
||||||
|
public async connectAllRelays(): Promise<void> {
|
||||||
|
const connectedUrls: string[] = [];
|
||||||
|
for (const wsurl of Object.keys(this.relayAddresses)) {
|
||||||
|
try {
|
||||||
|
await this.addWebsocketConnection(wsurl);
|
||||||
|
connectedUrls.push(wsurl);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Network] ❌ Échec connexion ${wsurl}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- AJOUT ---
|
||||||
|
public async addWebsocketConnection(url: string): Promise<void> {
|
||||||
|
console.log(`[Network] 🔌 Connexion à: ${url}`);
|
||||||
|
await initWebsocket(url);
|
||||||
|
}
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
public initRelays() {
|
||||||
|
for (const wsurl of this.bootstrapUrls) {
|
||||||
|
this.updateRelay(wsurl, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateRelay(url: string, spAddress: string) {
|
||||||
|
console.log(`[Network] Mise à jour relais ${url} -> ${spAddress}`);
|
||||||
|
this.relayAddresses[url] = spAddress;
|
||||||
|
if (spAddress) this.resolveRelayReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAvailableRelayAddress(): Promise<string> {
|
||||||
|
let relayAddress = Object.values(this.relayAddresses).find((addr) => addr !== '');
|
||||||
|
if (relayAddress) return Promise.resolve(relayAddress);
|
||||||
|
|
||||||
|
console.log("[Network] ⏳ Attente d'un relais disponible...");
|
||||||
|
return this.getRelayReadyPromise().then(() => {
|
||||||
|
const addr = Object.values(this.relayAddresses).find((a) => a !== '');
|
||||||
|
if (!addr) throw new Error('Aucun relais disponible');
|
||||||
|
return addr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public printAllRelays(): void {
|
||||||
|
console.log('[Network] Adresses relais actuelles:');
|
||||||
|
for (const [wsurl, spAddress] of Object.entries(this.relayAddresses)) {
|
||||||
|
console.log(`${wsurl} -> ${spAddress}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRelayReadyPromise(): Promise<void> {
|
||||||
|
if (!this.relayReadyPromise) {
|
||||||
|
this.relayReadyPromise = new Promise<void>((resolve) => {
|
||||||
|
this.relayReadyResolver = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this.relayReadyPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
private resolveRelayReady(): void {
|
||||||
|
if (this.relayReadyResolver) {
|
||||||
|
this.relayReadyResolver();
|
||||||
|
this.relayReadyResolver = null;
|
||||||
|
this.relayReadyPromise = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAllRelays() {
|
||||||
|
return this.relayAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendMessage(flag: AnkFlag, message: string) {
|
||||||
|
sendMessage(flag, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/services/core/sdk.service.ts
Normal file
26
src/services/core/sdk.service.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { ApiReturn, Device } from '../../../pkg/sdk_client';
|
||||||
|
|
||||||
|
export class SdkService {
|
||||||
|
private client: any;
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
this.client = await import('../../../pkg/sdk_client');
|
||||||
|
this.client.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getClient(): any {
|
||||||
|
if (!this.client) throw new Error('SDK not initialized');
|
||||||
|
return this.client;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes utilitaires directes du SDK
|
||||||
|
public encodeJson(data: any): any {
|
||||||
|
return this.client.encode_json(data);
|
||||||
|
}
|
||||||
|
public encodeBinary(data: any): any {
|
||||||
|
return this.client.encode_binary(data);
|
||||||
|
}
|
||||||
|
public decodeValue(value: number[]): any {
|
||||||
|
return this.client.decode_value(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import Services from './service';
|
import Services from './service';
|
||||||
|
import { APP_CONFIG } from '../config/constants';
|
||||||
|
|
||||||
export class Database {
|
export class Database {
|
||||||
private static instance: Database;
|
private static instance: Database;
|
||||||
@ -161,7 +162,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);
|
}, APP_CONFIG.TIMEOUTS.WORKER_CHECK);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Database] 💥 Erreur critique Service Worker:', error);
|
console.error('[Database] 💥 Erreur critique Service Worker:', error);
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/services/domain/crypto.service.ts
Normal file
58
src/services/domain/crypto.service.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { MerkleProofResult, ProcessState } from '../../../pkg/sdk_client';
|
||||||
|
import { SdkService } from '../core/sdk.service';
|
||||||
|
|
||||||
|
export class CryptoService {
|
||||||
|
constructor(private sdk: SdkService) {}
|
||||||
|
|
||||||
|
public hexToBlob(hexString: string): Blob {
|
||||||
|
const uint8Array = this.hexToUInt8Array(hexString);
|
||||||
|
return new Blob([uint8Array], { type: 'application/octet-stream' });
|
||||||
|
}
|
||||||
|
|
||||||
|
public hexToUInt8Array(hexString: string): Uint8Array {
|
||||||
|
if (hexString.length % 2 !== 0) throw new Error('Invalid hex string');
|
||||||
|
const uint8Array = new Uint8Array(hexString.length / 2);
|
||||||
|
for (let i = 0; i < hexString.length; i += 2) {
|
||||||
|
uint8Array[i / 2] = parseInt(hexString.substr(i, 2), 16);
|
||||||
|
}
|
||||||
|
return uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async blobToHex(blob: Blob): Promise<string> {
|
||||||
|
const buffer = await blob.arrayBuffer();
|
||||||
|
const bytes = new Uint8Array(buffer);
|
||||||
|
return Array.from(bytes)
|
||||||
|
.map((byte) => byte.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHashForFile(commitedIn: string, label: string, fileBlob: { type: string; data: Uint8Array }): string {
|
||||||
|
return this.sdk.getClient().hash_value(fileBlob, commitedIn, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMerkleProofForFile(processState: ProcessState, attributeName: string): MerkleProofResult {
|
||||||
|
return this.sdk.getClient().get_merkle_proof(processState, attributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public validateMerkleProof(proof: MerkleProofResult, hash: string): boolean {
|
||||||
|
return this.sdk.getClient().validate_merkle_proof(proof, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public splitData(obj: Record<string, any>) {
|
||||||
|
const jsonCompatibleData: Record<string, any> = {};
|
||||||
|
const binaryData: Record<string, { type: string; data: Uint8Array }> = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (this.isFileBlob(value)) {
|
||||||
|
binaryData[key] = value;
|
||||||
|
} else {
|
||||||
|
jsonCompatibleData[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { jsonCompatibleData, binaryData };
|
||||||
|
}
|
||||||
|
|
||||||
|
private isFileBlob(value: any): value is { type: string; data: Uint8Array } {
|
||||||
|
return typeof value === 'object' && value !== null && typeof value.type === 'string' && value.data instanceof Uint8Array;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/services/domain/process.service.ts
Normal file
100
src/services/domain/process.service.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { Process, ProcessState, RoleDefinition } from '../../../pkg/sdk_client';
|
||||||
|
import { SdkService } from '../core/sdk.service';
|
||||||
|
import Database from '../database.service';
|
||||||
|
|
||||||
|
const EMPTY32BYTES = String('').padStart(64, '0');
|
||||||
|
|
||||||
|
export class ProcessService {
|
||||||
|
private processesCache: Record<string, Process> = {};
|
||||||
|
private myProcesses: Set<string> = new Set();
|
||||||
|
|
||||||
|
constructor(private sdk: SdkService) {}
|
||||||
|
|
||||||
|
public async getProcess(processId: string): Promise<Process | null> {
|
||||||
|
if (this.processesCache[processId]) return this.processesCache[processId];
|
||||||
|
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
const process = await db.getObject('processes', processId);
|
||||||
|
if (process) this.processesCache[processId] = process;
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getProcesses(): Promise<Record<string, Process>> {
|
||||||
|
if (Object.keys(this.processesCache).length > 0) return this.processesCache;
|
||||||
|
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
this.processesCache = await db.dumpStore('processes');
|
||||||
|
return this.processesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveProcessToDb(processId: string, process: Process) {
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
await db.addObject({ storeName: 'processes', object: process, key: processId });
|
||||||
|
this.processesCache[processId] = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async batchSaveProcesses(processes: Record<string, Process>) {
|
||||||
|
if (Object.keys(processes).length === 0) return;
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
await db.batchWriting({ storeName: 'processes', objects: Object.entries(processes).map(([key, value]) => ({ key, object: value })) });
|
||||||
|
this.processesCache = { ...this.processesCache, ...processes };
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLastCommitedState(process: Process): ProcessState | null {
|
||||||
|
if (process.states.length === 0) return null;
|
||||||
|
const processTip = process.states[process.states.length - 1].commited_in;
|
||||||
|
return process.states.findLast((state) => state.commited_in !== processTip) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getUncommitedStates(process: Process): ProcessState[] {
|
||||||
|
if (process.states.length === 0) return [];
|
||||||
|
const processTip = process.states[process.states.length - 1].commited_in;
|
||||||
|
return process.states.filter((state) => state.commited_in === processTip).filter((state) => state.state_id !== EMPTY32BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getStateFromId(process: Process, stateId: string): ProcessState | null {
|
||||||
|
return process.states.find((state) => state.state_id === stateId) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRoles(process: Process): Record<string, RoleDefinition> | null {
|
||||||
|
const last = this.getLastCommitedState(process);
|
||||||
|
if (last?.roles && Object.keys(last.roles).length > 0) return last.roles;
|
||||||
|
|
||||||
|
const first = process.states[0];
|
||||||
|
if (first?.roles && Object.keys(first.roles).length > 0) return first.roles;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public rolesContainsMember(roles: Record<string, RoleDefinition>, memberId: string): boolean {
|
||||||
|
return Object.values(roles).some((role) => role.members.includes(memberId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getMyProcesses(pairingProcessId: string): Promise<string[]> {
|
||||||
|
const processes = await this.getProcesses();
|
||||||
|
const newMyProcesses = new Set<string>(this.myProcesses);
|
||||||
|
if (pairingProcessId) newMyProcesses.add(pairingProcessId);
|
||||||
|
|
||||||
|
for (const [processId, process] of Object.entries(processes)) {
|
||||||
|
if (newMyProcesses.has(processId)) continue;
|
||||||
|
const roles = this.getRoles(process);
|
||||||
|
if (roles && this.rolesContainsMember(roles, pairingProcessId)) {
|
||||||
|
newMyProcesses.add(processId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.myProcesses = newMyProcesses;
|
||||||
|
return Array.from(this.myProcesses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- AJOUT : Méthode manquante ---
|
||||||
|
public getLastCommitedStateIndex(process: Process): number | null {
|
||||||
|
if (process.states.length === 0) return null;
|
||||||
|
const processTip = process.states[process.states.length - 1].commited_in;
|
||||||
|
for (let i = process.states.length - 1; i >= 0; i--) {
|
||||||
|
if (process.states[i].commited_in !== processTip) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/services/domain/wallet.service.ts
Normal file
101
src/services/domain/wallet.service.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import { Device } from '../../../pkg/sdk_client';
|
||||||
|
import { SdkService } from '../core/sdk.service';
|
||||||
|
import Database from '../database.service';
|
||||||
|
|
||||||
|
export class WalletService {
|
||||||
|
constructor(private sdk: SdkService) {}
|
||||||
|
|
||||||
|
public isPaired(): boolean {
|
||||||
|
try {
|
||||||
|
return this.sdk.getClient().is_paired();
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAmount(): BigInt {
|
||||||
|
return this.sdk.getClient().get_available_amount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDeviceAddress(): string {
|
||||||
|
return this.sdk.getClient().get_address();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPairingProcessId(): string {
|
||||||
|
return this.sdk.getClient().get_pairing_process_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async createNewDevice(chainTip: number): Promise<string> {
|
||||||
|
const spAddress = await this.sdk.getClient().create_new_device(0, 'signet');
|
||||||
|
const device = this.dumpDeviceFromMemory();
|
||||||
|
if (device.sp_wallet.birthday === 0) {
|
||||||
|
device.sp_wallet.birthday = chainTip;
|
||||||
|
device.sp_wallet.last_scan = chainTip;
|
||||||
|
this.sdk.getClient().restore_device(device);
|
||||||
|
}
|
||||||
|
await this.saveDeviceInDatabase(device);
|
||||||
|
return spAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public dumpDeviceFromMemory(): Device {
|
||||||
|
return this.sdk.getClient().dump_device();
|
||||||
|
}
|
||||||
|
|
||||||
|
public dumpNeuteredDevice(): Device | null {
|
||||||
|
try {
|
||||||
|
return this.sdk.getClient().dump_neutered_device();
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- AJOUTS (Manquants) ---
|
||||||
|
public async dumpWallet(): Promise<any> {
|
||||||
|
return await this.sdk.getClient().dump_wallet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getMemberFromDevice(): Promise<string[] | null> {
|
||||||
|
try {
|
||||||
|
const device = await this.getDeviceFromDatabase();
|
||||||
|
if (device) {
|
||||||
|
const pairedMember = device['paired_member'];
|
||||||
|
return pairedMember.sp_addresses;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`[WalletService] Échec: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
public async saveDeviceInDatabase(device: Device): Promise<void> {
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
await db.deleteObject('wallet', '1').catch(() => {});
|
||||||
|
await db.addObject({
|
||||||
|
storeName: 'wallet',
|
||||||
|
object: { pre_id: '1', device },
|
||||||
|
key: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getDeviceFromDatabase(): Promise<Device | null> {
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
const res = await db.getObject('wallet', '1');
|
||||||
|
return res ? res['device'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public restoreDevice(device: Device) {
|
||||||
|
this.sdk.getClient().restore_device(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
public pairDevice(processId: string, spAddressList: string[]): void {
|
||||||
|
this.sdk.getClient().pair_device(processId, spAddressList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async unpairDevice(): Promise<void> {
|
||||||
|
this.sdk.getClient().unpair_device();
|
||||||
|
const newDevice = this.dumpDeviceFromMemory();
|
||||||
|
await this.saveDeviceInDatabase(newDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { MessageType } from '../types/index';
|
import { MessageType } from '../types/index';
|
||||||
import Services from './service';
|
import Services from './service';
|
||||||
import TokenService from './token';
|
import TokenService from './token.service';
|
||||||
import { cleanSubscriptions } from '../utils/subscription.utils';
|
import { cleanSubscriptions } from '../utils/subscription.utils';
|
||||||
import { splitPrivateData, isValid32ByteHex } from '../utils/service.utils';
|
import { splitPrivateData, isValid32ByteHex } from '../utils/service.utils';
|
||||||
import { MerkleProofResult } from '../../pkg/sdk_client';
|
import { MerkleProofResult } from '../../pkg/sdk_client';
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,11 @@
|
|||||||
import { AnkFlag } from '../../pkg/sdk_client'; // Vérifie le chemin vers pkg
|
import { AnkFlag } from '../../pkg/sdk_client'; // Vérifie le chemin vers pkg
|
||||||
import Services from './service';
|
import Services from './service';
|
||||||
|
import { APP_CONFIG } from '../config/constants';
|
||||||
|
|
||||||
let ws: WebSocket | null = null;
|
let ws: WebSocket | null = null;
|
||||||
let messageQueue: string[] = [];
|
let messageQueue: string[] = [];
|
||||||
let reconnectInterval = 1000; // Délai initial de 1s avant reconnexion
|
let reconnectInterval = APP_CONFIG.TIMEOUTS.RETRY_DELAY;
|
||||||
const MAX_RECONNECT_INTERVAL = 30000; // Max 30s
|
const MAX_RECONNECT_INTERVAL = APP_CONFIG.TIMEOUTS.WS_RECONNECT_MAX;
|
||||||
let isConnecting = false;
|
let isConnecting = false;
|
||||||
let urlReference: string = '';
|
let urlReference: string = '';
|
||||||
let pingIntervalId: any = null;
|
let pingIntervalId: any = null;
|
||||||
@ -24,7 +25,7 @@ function connect() {
|
|||||||
ws.onopen = async () => {
|
ws.onopen = async () => {
|
||||||
console.log('[WS] ✅ Connexion établie !');
|
console.log('[WS] ✅ Connexion établie !');
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
reconnectInterval = 1000; // Reset du délai
|
reconnectInterval = APP_CONFIG.TIMEOUTS.RETRY_DELAY; // Reset du délai
|
||||||
|
|
||||||
// Démarrer le Heartbeat (Ping pour garder la connexion vivante)
|
// Démarrer le Heartbeat (Ping pour garder la connexion vivante)
|
||||||
startHeartbeat();
|
startHeartbeat();
|
||||||
@ -95,7 +96,7 @@ function startHeartbeat() {
|
|||||||
// Adapter selon ce que ton serveur attend comme Ping, ou envoyer un message vide
|
// Adapter selon ce que ton serveur attend comme Ping, ou envoyer un message vide
|
||||||
// ws.send(JSON.stringify({ flag: 'Ping', content: '' }));
|
// ws.send(JSON.stringify({ flag: 'Ping', content: '' }));
|
||||||
}
|
}
|
||||||
}, 30000);
|
}, APP_CONFIG.TIMEOUTS.WS_HEARTBEAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopHeartbeat() {
|
function stopHeartbeat() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user