UNPKG

@0xsequence/connect

Version:
232 lines 8.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProviderTransport = void 0; const isBrowser = typeof window !== 'undefined'; class ProviderTransport { walletOrigin; walletWindow = null; callbacks = new Map(); connectionState = 'disconnected'; session; walletCheckInterval; constructor(walletUrl) { const url = new URL(walletUrl); this.walletOrigin = url.origin; if (isBrowser) { window.addEventListener('message', this.handleMessage); this.loadSession(); this.observeCallbacks(); } } observeCallbacks() { const originalSet = this.callbacks.set.bind(this.callbacks); const originalDelete = this.callbacks.delete.bind(this.callbacks); this.callbacks.set = (key, value) => { const result = originalSet(key, value); this.updateWalletCheck(); return result; }; this.callbacks.delete = key => { const result = originalDelete(key); this.updateWalletCheck(); return result; }; } updateWalletCheck() { if (this.callbacks.size > 0) { this.ensureWalletCheckActive(); } else { this.ensureWalletCheckInactive(); } } ensureWalletCheckActive() { if (!isBrowser) { return; } if (this.walletCheckInterval === undefined) { this.walletCheckInterval = window.setInterval(() => { if (!this.isWalletOpen()) { this.handleWalletClosed(); } }, 500); // Check every half second } } ensureWalletCheckInactive() { if (!isBrowser) { return; } if (this.walletCheckInterval !== undefined) { clearInterval(this.walletCheckInterval); this.walletCheckInterval = undefined; } } loadSession() { if (!isBrowser) { return; } try { const sessionData = localStorage.getItem('walletSession'); if (sessionData) { this.session = JSON.parse(sessionData); this.connectionState = 'connected'; } } catch (error) { console.warn('Failed to load wallet session:', error); } } saveSession(walletAddress) { if (!isBrowser) { return; } try { this.session = { walletAddress, lastConnected: Date.now() }; localStorage.setItem('walletSession', JSON.stringify(this.session)); } catch (error) { console.warn('Failed to save wallet session:', error); } } async connect(auxData) { if (this.connectionState === 'connected' && this.session) { return { walletAddress: this.session.walletAddress }; } this.connectionState = 'connecting'; const connectionId = isBrowser && 'randomUUID' in crypto ? crypto.randomUUID() : Math.random().toString(36).slice(2); const connectionRequest = { type: 'connection', id: connectionId, ...(auxData ? { auxData } : {}) }; return new Promise((resolve, reject) => { this.callbacks.set(connectionId, response => { if (response.type === 'connection' && response.status === 'accepted') { this.connectionState = 'connected'; this.saveSession(response.walletAddress); resolve({ walletAddress: response.walletAddress }); this.walletWindow?.close(); } else { this.connectionState = 'disconnected'; reject(new Error('Connection rejected')); this.walletWindow?.close(); } }); this.openWalletAndPostMessage(connectionRequest); }); } async sendRequest(method, params, chainId) { if (!isBrowser) { throw new Error('ProviderTransport is only available in browser environment'); } if (this.connectionState !== 'connected') { throw new Error('Not connected to wallet. Call connect() first.'); } const id = isBrowser && 'randomUUID' in crypto ? crypto.randomUUID() : Math.random().toString(36).slice(2); const request = { type: 'request', id, method, params, chainId }; return new Promise((resolve, reject) => { const sendMessage = async () => { if (!this.isWalletOpen()) { try { await this.openWalletAndPostMessage(request); } catch (error) { this.callbacks.delete(id); reject(error); return; } } else { this.postMessageToWallet(request); } }; this.callbacks.set(id, response => { if (response.error) { reject(new Error(response.error.message)); } else { resolve(response.result); } // Close the wallet window after receiving the response if (this.isWalletOpen()) { this.walletWindow.close(); this.walletWindow = null; } }); sendMessage().catch(reject); }); } openWalletAndPostMessage(message) { if (!isBrowser) { return Promise.reject(new Error('ProviderTransport is only available in browser environment')); } return new Promise((resolve, reject) => { console.log('Opening wallet and posting message:', message); if (!this.isWalletOpen()) { this.walletWindow = window.open(this.walletOrigin, 'Wallet', 'width=375,height=667'); if (!this.walletWindow) { reject(new Error('Failed to open wallet window. Please check your pop-up blocker settings.')); return; } const waitForReady = (event) => { if (event.origin === this.walletOrigin && event.data === 'ready') { console.log('Received ready message from wallet'); window.removeEventListener('message', waitForReady); this.postMessageToWallet(message); resolve(); } }; window.addEventListener('message', waitForReady); } else { this.postMessageToWallet(message); resolve(); } }); } postMessageToWallet(message) { console.log('Posting message to wallet:', message); this.walletWindow.postMessage(message, { targetOrigin: this.walletOrigin }); } isWalletOpen() { return this.walletWindow !== null && !this.walletWindow?.closed; } handleWalletClosed() { this.walletWindow = null; this.callbacks.forEach(callback => { callback({ error: { message: 'Wallet window was closed' } }); }); this.callbacks.clear(); } handleMessage = (event) => { if (event.origin !== this.walletOrigin) { return; } const response = event.data; const callback = this.callbacks.get(response.id); if (callback) { callback(response); this.callbacks.delete(response.id); } }; disconnect() { this.connectionState = 'disconnected'; this.session = undefined; if (isBrowser) { localStorage.removeItem('walletSession'); if (this.isWalletOpen()) { this.walletWindow.close(); } } this.walletWindow = null; this.handleWalletClosed(); } getWalletAddress() { return this.session?.walletAddress; } } exports.ProviderTransport = ProviderTransport; //# sourceMappingURL=providerTransport.js.map