import { MessageType } from '../models/process.model'; import Services from './service'; import { // generateWordsDisplay, // Unused import discoverAndJoinPairingProcessWithWords, prepareAndSendPairingTx, } from '../utils/sp-address.utils'; export default class IframePairingService { private static instance: IframePairingService; private parentWindow: Window | null = null; private _isCreator = false; private _isJoiner = false; public static getInstance(): IframePairingService { if (!IframePairingService.instance) { IframePairingService.instance = new IframePairingService(); } return IframePairingService.instance; } constructor() { this.init(); } private init() { // Listen for messages from parent window window.addEventListener('message', this.handleMessage.bind(this)); // Detect if we're in an iframe if (window.parent !== window) { this.parentWindow = window.parent; console.log('🔗 Iframe pairing service initialized'); } } private async handleMessage(event: MessageEvent) { try { const { type, data } = event.data; switch (type) { case MessageType.PAIRING_4WORDS_CREATE: await this.handleCreatePairing(data); break; case MessageType.PAIRING_4WORDS_JOIN: await this.handleJoinPairing(data); break; default: // Ignore other message types break; } } catch (error) { console.error('Error handling iframe pairing message:', error); this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, { error: (error as Error).message }); } } private async handleCreatePairing(_data: any) { try { console.log('🔐 Creating pairing process via iframe...'); this._isCreator = true; // Update status this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: 'Creating pairing process...', type: 'creator', }); // Create pairing process await prepareAndSendPairingTx(); // Get the service instance to access the generated words const service = await Services.getInstance(); const _device = service.dumpDeviceFromMemory(); // Use _device variable console.log('Device from memory:', _device); const creatorAddress = service.getDeviceAddress(); if (creatorAddress) { // Generate and send the 4 words const words = await this.addressToWords(creatorAddress); this.sendMessage(MessageType.PAIRING_4WORDS_WORDS_GENERATED, { words: words, type: 'creator', }); // Update status this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: '4 words generated! Share them with the other device.', type: 'creator', }); } } catch (error) { console.error('Error creating pairing:', error); this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, { error: (error as Error).message, type: 'creator', }); } } private async handleJoinPairing(data: { words: string }) { try { console.log('🔗 Joining pairing process via iframe with words:', data.words); this._isJoiner = true; // Update status this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: 'Discovering pairing process...', type: 'joiner', }); // Join pairing process with 4 words await discoverAndJoinPairingProcessWithWords(data.words); // Update status this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: 'Pairing process found! Synchronizing...', type: 'joiner', }); const service = await Services.getInstance(); const pairingId = service.getProcessId(); if (pairingId) { // Wait for pairing commitment this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: 'Synchronizing with network...', type: 'joiner', }); await service.waitForPairingCommitment(pairingId); // Confirm pairing this.sendMessage(MessageType.PAIRING_4WORDS_STATUS_UPDATE, { status: 'Confirming pairing...', type: 'joiner', }); await service.confirmPairing(); // Success this.sendMessage(MessageType.PAIRING_4WORDS_SUCCESS, { message: 'Pairing successful!', type: 'joiner', }); } } catch (error) { console.error('Error joining pairing:', error); this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, { error: (error as Error).message, type: 'joiner', }); } } private async addressToWords(address: string): Promise { // This should match the existing addressToWords function // For now, we'll use a simple implementation const words = address .split('') .slice(0, 4) .map( char => [ 'abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract', 'absurd', 'abuse', ][char.charCodeAt(0) % 10] ) .join(' '); return words; } private sendMessage(type: MessageType, data: any) { if (this.parentWindow) { this.parentWindow.postMessage({ type, data }, '*'); } } // Public methods for external use public async createPairing(): Promise { await this.handleCreatePairing({}); } public async joinPairing(words: string): Promise { await this.handleJoinPairing({ words }); } }