diff --git a/src/service.ts b/src/service.ts index 4a0a5a6..c6a015d 100644 --- a/src/service.ts +++ b/src/service.ts @@ -281,4 +281,182 @@ export class Service { throw error; } } + + // WebSocket message methods (stubs for now) + async sendNewTxMessage(message: string) { + console.log('📤 Sending NewTx message:', message); + // TODO: Implement actual WebSocket sending + } + + async sendCommitMessage(message: string) { + console.log('�� Sending Commit message:', message); + // TODO: Implement actual WebSocket sending + } + + async sendCipherMessages(ciphers: string[]) { + console.log('📤 Sending Cipher messages:', ciphers.length, 'ciphers'); + for (let i = 0; i < ciphers.length; i++) { + const cipher = ciphers[i]; + console.log('📤 Sending Cipher:', cipher); + // TODO: Implement actual WebSocket sending + } + } + + // Blob and data storage methods + async saveBlobToDb(hash: string, data: Blob) { + const db = await Database.getInstance(); + try { + await db.addObject({ + storeName: 'data', + object: data, + key: hash, + }); + } catch (e) { + console.error(`Failed to save data to db: ${e}`); + } + } + + async getBlobFromDb(hash: string): Promise { + const db = await Database.getInstance(); + try { + return await db.getObject('data', hash); + } catch (e) { + return null; + } + } + + async saveDataToStorage(hash: string, data: Blob, ttl: number | null) { + console.log('💾 Saving data to storage:', hash); + // TODO: Implement actual storage service + // const storages = [STORAGEURL]; + // try { + // await storeData(storages, hash, data, ttl); + // } catch (e) { + // console.error(`Failed to store data with hash ${hash}: ${e}`); + // } + } + + async saveDiffsToDb(diffs: any[]) { + const db = await Database.getInstance(); + try { + for (const diff of diffs) { + await db.addObject({ + storeName: 'diffs', + object: diff, + key: null, + }); + } + } catch (e) { + throw new Error(`Failed to save diffs: ${e}`); + } + } + + // Utility methods for data conversion + hexToBlob(hexString: string): Blob { + const uint8Array = this.hexToUInt8Array(hexString); + return new Blob([uint8Array], { type: "application/octet-stream" }); + } + + hexToUInt8Array(hexString: string): Uint8Array { + if (hexString.length % 2 !== 0) { + throw new Error("Invalid hex string: length must be even"); + } + 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; + } + + // Main handleApiReturn method + public async handleApiReturn(apiReturn: ApiReturn) { + console.log('🔄 Handling API return:', apiReturn); + + if (apiReturn.partial_tx) { + try { + const res = wasm.sign_transaction(apiReturn.partial_tx); + apiReturn.new_tx_to_send = res.new_tx_to_send; + } catch (e) { + console.error('Failed to sign transaction:', e); + } + } + + if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) { + await this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send)); + await new Promise(r => setTimeout(r, 500)); + } + + if (apiReturn.secrets) { + const unconfirmedSecrets = apiReturn.secrets.unconfirmed_secrets; + const confirmedSecrets = apiReturn.secrets.shared_secrets; + + const db = await Database.getInstance(); + for (const secret of unconfirmedSecrets) { + await db.addObject({ + storeName: 'unconfirmed_secrets', + object: secret, + key: null, + }); + } + const entries = Object.entries(confirmedSecrets).map(([key, value]) => ({ key, value })); + for (const entry of entries) { + try { + await db.addObject({ + storeName: 'shared_secrets', + object: entry.value, + key: entry.key, + }); + } catch (e) { + throw e; + } + } + } + + if (apiReturn.updated_process) { + const updatedProcess = apiReturn.updated_process; + const processId: string = updatedProcess.process_id; + + if (updatedProcess.encrypted_data && Object.keys(updatedProcess.encrypted_data).length != 0) { + for (const [hash, cipher] of Object.entries(updatedProcess.encrypted_data)) { + const blob = this.hexToBlob(cipher); + try { + await this.saveBlobToDb(hash, blob); + } catch (e) { + console.error(e); + } + } + } + + // Save process to db + await this.saveProcessToDb(processId, updatedProcess.current_process); + + if (updatedProcess.diffs && updatedProcess.diffs.length != 0) { + try { + await this.saveDiffsToDb(updatedProcess.diffs); + } catch (e) { + console.error('Failed to save diffs to db:', e); + } + } + } + + if (apiReturn.push_to_storage && apiReturn.push_to_storage.length != 0) { + for (const hash of apiReturn.push_to_storage) { + const blob = await this.getBlobFromDb(hash); + if (blob) { + await this.saveDataToStorage(hash, blob, null); + } else { + console.error('Failed to get data from db'); + } + } + } + + if (apiReturn.commit_to_send) { + const commit = apiReturn.commit_to_send; + await this.sendCommitMessage(JSON.stringify(commit)); + } + + if (apiReturn.ciphers_to_send && apiReturn.ciphers_to_send.length != 0) { + await this.sendCipherMessages(apiReturn.ciphers_to_send); + } + } }