diff --git a/src/router.ts b/src/router.ts index 55efe7d..afc10c9 100755 --- a/src/router.ts +++ b/src/router.ts @@ -135,37 +135,63 @@ export async function init(): Promise { const services = await Services.getInstance(); (window as any).myService = services; await Database.getInstance(); - setTimeout(async () => { - let device = await services.getDeviceFromDatabase(); - console.log('🚀 ~ setTimeout ~ device:', device); + let device = await services.getDeviceFromDatabase(); + console.log('🚀 ~ setTimeout ~ device:', device); - if (!device) { - device = await services.createNewDevice(); - } else { - services.restoreDevice(device); + if (!device) { + device = await services.createNewDevice(); + } else { + services.restoreDevice(device); + } + await services.restoreProcessesFromDB(); + await services.restoreSecretsFromDB(); + + // If we have a service redirection flag, we intercept it here + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const source = urlParams.get('source'); + + if (source === "lecoffre") { + console.log('Detected source \'lecoffre\'') + // We pair first if necessary + if (!services.isPaired()) { + await prepareAndSendPairingTx(false); + await services.confirmPairing(); } - await services.restoreProcessesFromDB(); - await services.restoreSecretsFromDB(); - if (services.isPaired()) { - await navigate('chat'); - } else { - const queryString = window.location.search; - const urlParams = new URLSearchParams(queryString); - const pairingAddress = urlParams.get('sp_address'); - if (pairingAddress) { - setTimeout(async () => { - try { - // check if we have a shared secret with that address - await prepareAndSendPairingTx(pairingAddress); - } catch (e) { - console.error('Failed to pair:', e); - } - }, 2000); + // pop up to inform user that they will be redirected to lecoffre with their 4nk identity + alert("User successfully created, you will be redirected to lecoffre.io"); + // Once paired we get a copy of the device without the spend key + const neuteredDevice = services.dumpNeuteredDevice(); + if (!neuteredDevice) { + console.error('Failed to get a neutered device'); + return; } - await navigate('home'); + // We send the neutered device to the main frame + window.parent.postMessage({ type: 'RESPONSE', payload: JSON.stringify(neuteredDevice) }, 'https://lecoffreio.4nkweb.com'); } - }, 200); + } else { + console.log('No source provided'); + } + + if (services.isPaired()) { + await navigate('account'); + } else { + const pairingAddress = urlParams.get('sp_address'); + if (pairingAddress) { + setTimeout(async () => { + try { + // check if we have a shared secret with that address + await prepareAndSendPairingTx(pairingAddress); + } catch (e) { + console.error('Failed to pair:', e); + } + await navigate('account'); + }, 2000); + } + console.log('here'); + await navigate('home'); + } } catch (error) { console.error(error); await navigate('home'); diff --git a/src/services/modal.service.ts b/src/services/modal.service.ts index f5b1f9b..78902a9 100755 --- a/src/services/modal.service.ts +++ b/src/services/modal.service.ts @@ -164,93 +164,37 @@ export default class ModalService { if (this.modal) this.modal.style.display = 'none'; } - async confirmPairing() { - const service = await Services.getInstance(); - if (this.modal) this.modal.style.display = 'none'; + // async confirmPairing() { + // const service = await Services.getInstance(); + // if (this.modal) this.modal.style.display = 'none'; - if (service.device1) { - console.log("Device 1 detected"); - // We send the prd update - if (this.stateId && this.processId) { - try { - // Device B shouldn't do this again - const createPrdUpdateReturn = service.createPrdUpdate(this.processId, this.stateId); - await service.handleApiReturn(createPrdUpdateReturn); - } catch (e) { - throw e; - } - } else { - throw new Error('No currentPcdCommitment'); - } + // // We send the prd update + // if (this.stateId && this.processId) { + // try { + // const createPrdUpdateReturn = service.createPrdUpdate(this.processId, this.stateId); + // await service.handleApiReturn(createPrdUpdateReturn); + // } catch (e) { + // throw e; + // } + // } else { + // throw new Error('No currentPcdCommitment'); + // } - // We send confirmation that we validate the change - try { - const approveChangeReturn = await service.approveChange(this.processId!, this.stateId!); - await service.handleApiReturn(approveChangeReturn); + // try { + // const approveChangeReturn = await service.approveChange(this.processId!, this.stateId!); + // await service.handleApiReturn(approveChangeReturn); - await this.injectWaitingModal(); - const waitingModal = document.getElementById('waiting-modal'); - if (waitingModal) waitingModal.style.display = 'flex'; - - if (!service.device2Ready) { - while (!service.device2Ready) { - await new Promise(resolve => setTimeout(resolve, 1000)); - } - console.log("Device 2 is ready - Device 1 can now proceed"); - } - service.pairDevice(this.paired_addresses, this.processId); - this.paired_addresses = []; - this.processId = null; - this.stateId = null; - const newDevice = service.dumpDeviceFromMemory(); - console.log(newDevice); - await service.saveDeviceInDatabase(newDevice); - navigate('chat'); - service.resetState(); - - } catch (e) { - throw e; - } - - // try { - // service.pairDevice(this.paired_addresses); - // } catch (e) { - // throw e; - // } - } else { - console.log("Device 2 detected"); - - // if (this.stateId && this.processId) { - // try { - // // Device B shouldn't do this again - // const createPrdUpdateReturn = service.createPrdUpdate(this.processId, this.stateId); - // await service.handleApiReturn(createPrdUpdateReturn); - // } catch (e) { - // throw e; - // } - // } else { - // throw new Error('No currentPcdCommitment'); - // } - - // We send confirmation that we validate the change - try { - const approveChangeReturn = await service.approveChange(this.processId!, this.stateId!); - await service.handleApiReturn(approveChangeReturn); - } catch (e) { - throw e; - } - - service.pairDevice(this.paired_addresses, this.processId!); - - this.paired_addresses = []; - this.processId = null; - this.stateId = null; - const newDevice = service.dumpDeviceFromMemory(); - console.log(newDevice); - await service.saveDeviceInDatabase(newDevice); - navigate('chat'); - } - } + // service.pairDevice(this.paired_addresses, this.processId); + // this.paired_addresses = []; + // this.processId = null; + // this.stateId = null; + // const newDevice = service.dumpDeviceFromMemory(); + // console.log(newDevice); + // await service.saveDeviceInDatabase(newDevice); + // } catch (e) { + // throw e; + // } + // } async closeConfirmationModal() { const service = await Services.getInstance(); diff --git a/src/services/service.ts b/src/services/service.ts index 5bf5094..171bbf0 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -20,8 +20,8 @@ const EMPTY32BYTES = String('').padStart(64, '0'); export default class Services { private static initializing: Promise | null = null; private static instance: Services; - private currentProcess: string | null = null; - private currentUpdateMerkleRoot: string | null = null; + private processId: string | null = null; + private stateId: string | null = null; private sdkClient: any; private myProcesses: Set = new Set(); private notifications: any[] | null = null; @@ -64,6 +64,24 @@ export default class Services { await this.connectAllRelays(); } + public setProcessId(processId: string | null) { + console.log('this.processId', this.processId); + this.processId = processId; + } + + public setStateId(stateId: string | null) { + console.log('this.stateId', this.stateId); + this.stateId = stateId; + } + + public getProcessId(): string | null { + return this.processId; + } + + public getStateId(): string | null { + return this.stateId; + } + /** * Calls `this.addWebsocketConnection` for each `wsurl` in relayAddresses. */ @@ -246,11 +264,11 @@ export default class Services { pairWith.push(myAddress); const roles: Record = { pairing: { - members: [{ sp_addresses: pairWith }], + members: [], validation_rules: [ { quorum: 1.0, - fields: ['description', 'counter', 'roles', 'memberPublicName'], + fields: ['description', 'counter', 'roles', 'memberPublicName', 'pairedAddresses'], min_sig_member: 1.0, }, ], @@ -262,15 +280,17 @@ export default class Services { counter: 0, }; const publicData = { - memberPublicName: userName - } + memberPublicName: userName, + pairedAddresses: pairWith, + }; try { return this.sdkClient.create_new_process( pairingTemplate, roles, publicData, relayAddress, - feeRate + feeRate, + this.getAllMembers() ); } catch (e) { throw new Error(`Creating process failed:, ${e}`); @@ -719,9 +739,51 @@ export default class Services { } } - pairDevice(spAddressList: string[], pairingProcess: string) { + public async confirmPairing() { + if (!this.processId || !this.stateId) { + console.error('Missing process and/or state ID'); + return; + } + let createPrdUpdateReturn; try { - this.sdkClient.pair_device(pairingProcess, spAddressList); + createPrdUpdateReturn = await this.createPrdUpdate(this.processId, this.stateId); + } catch (e) { + throw new Error(`createPrdUpdate failed: ${e}`); + } + await this.handleApiReturn(createPrdUpdateReturn); + + let approveChangeReturn; + try { + approveChangeReturn = await this.approveChange(this.processId, this.stateId); + } catch (e) { + throw new Error(`approveChange failed: ${e}`); + } + await this.handleApiReturn(approveChangeReturn); + + await this.pairDevice(); + + this.processId = null; + this.stateId = null; + const newDevice = this.dumpDeviceFromMemory(); + console.log(newDevice); + await this.saveDeviceInDatabase(newDevice); + navigate('account'); + } + + public async pairDevice() { + if (!this.processId) { + console.error('No processId set'); + return; + } + const process = await this.getProcess(this.processId); + if (!process) { + console.error('Unknown process'); + return; + } + const spAddressList = process.states[0].public_data['pairedAddresses']; + console.log(spAddressList); + try { + this.sdkClient.pair_device(this.processId, spAddressList); } catch (e) { throw new Error(`Failed to pair device: ${e}`); } diff --git a/src/utils/sp-address.utils.ts b/src/utils/sp-address.utils.ts index a659ea7..2fbc023 100755 --- a/src/utils/sp-address.utils.ts +++ b/src/utils/sp-address.utils.ts @@ -168,17 +168,16 @@ async function onOkButtonClick() { async function onCreateButtonClick() { try { await prepareAndSendPairingTx(); + const service = await Services.getInstance(); + await service.confirmPairing(); } catch (e) { console.error(`onCreateButtonClick error: ${e}`); } } -export async function prepareAndSendPairingTx(promptName: boolean = false) { +export async function prepareAndSendPairingTx(promptName: boolean = false): Promise { const service = await Services.getInstance(); - // Device 1 wait Device 2 - // service.device1 = true; - try { await service.checkConnections([]); } catch (e) { @@ -193,11 +192,8 @@ export async function prepareAndSendPairingTx(promptName: boolean = false) { userName = ""; } - // Create the process after a delay. - setTimeout(async () => { + try { const relayAddress = service.getAllRelays(); - - // Pass the userName as an additional parameter. const createPairingProcessReturn = await service.createPairingProcess( userName, [], @@ -207,11 +203,17 @@ export async function prepareAndSendPairingTx(promptName: boolean = false) { ); if (!createPairingProcessReturn.updated_process) { - throw new Error('createPairingProcess returned an empty new process'); // This should never happen + throw new Error('createPairingProcess returned an empty new process'); } + service.setProcessId(createPairingProcessReturn.updated_process.process_id); + service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id); + await service.handleApiReturn(createPairingProcessReturn); - }, 1000); + + } catch (err) { + console.error(err); + } } export async function generateQRCode(spAddress: string) {