UNPKG

@trezor/connect-common

Version:

Collection of assets and utils used by trezor-connect library.

168 lines (167 loc) 4.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractMessageChannel = void 0; const utils_1 = require("@trezor/utils"); class AbstractMessageChannel extends utils_1.TypedEmitter { messagePromises = {}; messagesQueue = []; messageID = 0; isConnected = false; handshakeMaxRetries = 5; handshakeRetryInterval = 2000; handshakeFinished; lazyHandshake; legacyMode; logger; sendFn; channel; constructor({ sendFn, channel, logger, lazyHandshake = false, legacyMode = false }) { super(); this.channel = channel; this.sendFn = sendFn; this.lazyHandshake = lazyHandshake; this.legacyMode = legacyMode; this.logger = logger; } init() { if (!this.handshakeFinished) { this.handshakeFinished = (0, utils_1.createDeferred)(); if (this.legacyMode) { setTimeout(() => { this.handshakeFinished?.resolve(); }, 500); } if (!this.lazyHandshake) { this.handshakeWithPeer(); } } return this.handshakeFinished.promise; } handshakeWithPeer() { this.logger?.log(this.channel.here, 'handshake'); return (0, utils_1.scheduleAction)(async () => { this.postMessage({ type: 'channel-handshake-request', data: { success: true, payload: undefined } }, { usePromise: false, useQueue: false }); await this.handshakeFinished?.promise; }, { attempts: this.handshakeMaxRetries, timeout: this.handshakeRetryInterval }).then(() => { this.logger?.log(this.channel.here, 'handshake confirmed'); this.messagesQueue.forEach(message => { message.channel = this.channel; this.sendFn(message); }); this.messagesQueue = []; }).catch(() => { this.handshakeFinished?.reject(new Error('handshake failed')); this.handshakeFinished = undefined; }); } onMessage(_message) { let message = _message; if (this.legacyMode && message.type === undefined && 'data' in message && typeof message.data === 'object' && message.data !== null && 'type' in message.data && typeof message.data.type === 'string') { message = message.data; } const { channel, id, type, ...data } = message; if (!this.legacyMode) { if (!channel?.peer || channel.peer !== this.channel.here) { return; } if (!channel?.here || this.channel.peer !== channel.here) { return; } } if (type === 'channel-handshake-request') { this.postMessage({ type: 'channel-handshake-confirm', data: { success: true, payload: undefined } }, { usePromise: false, useQueue: false }); if (this.lazyHandshake) { this.handshakeWithPeer(); } return; } if (type === 'channel-handshake-confirm') { this.handshakeFinished?.resolve(undefined); return; } if (this.messagePromises[id]) { this.messagePromises[id].resolve({ id, ...data }); delete this.messagePromises[id]; } const messagePromisesLength = Object.keys(this.messagePromises).length; if (messagePromisesLength > 5) { this.logger?.warn(`too many message promises (${messagePromisesLength}). this feels unexpected!`); } this.emit('message', message); } postMessage(message, { usePromise = true, useQueue = true } = {}) { message.channel = this.channel; if (!usePromise) { try { this.sendFn(message); } catch { if (useQueue) { this.messagesQueue.push(message); } } return; } this.messageID++; message.id = this.messageID; this.messagePromises[message.id] = (0, utils_1.createDeferred)(); try { this.sendFn(message); } catch { if (useQueue) { this.messagesQueue.push(message); } } return this.messagePromises[message.id].promise; } resolveMessagePromises(resolvePayload) { Object.keys(this.messagePromises).forEach(id => this.messagePromises[id].resolve({ id, payload: resolvePayload })); } clear() { this.handshakeFinished = undefined; } } exports.AbstractMessageChannel = AbstractMessageChannel; //# sourceMappingURL=abstract.js.map