UNPKG

@trezor/blockchain-link

Version:

High-level javascript interface for blockchain communication

148 lines 5.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseWorker = exports.CONTEXT = void 0; const socks_proxy_agent_1 = require("socks-proxy-agent"); const constants_1 = require("@trezor/blockchain-link-types/lib/constants"); const errors_1 = require("@trezor/blockchain-link-types/lib/constants/errors"); const state_1 = require("./state"); const utils_1 = require("./utils"); exports.CONTEXT = (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) || typeof importScripts !== 'undefined' ? 'worker' : 'main'; class BaseWorker { api; proxyAgent; settings = {}; state; post; constructor() { if (exports.CONTEXT === 'worker') { this.post = (data) => self.postMessage(data); } else { this.post = (data) => this.onmessage({ data }); } this.state = new state_1.WorkerState(); setTimeout(() => { this.post({ id: -1, type: constants_1.MESSAGES.HANDSHAKE }); }, 10); } debug(...args) { if (!this.settings.debug) return; const debugPrefix = `[Worker "${this.settings.name}"]:`; const fn = args[0]; if (fn === 'warn' || fn === 'error') { console[fn](debugPrefix, ...args.slice(1)); } else { console.log(debugPrefix, ...args); } } cleanup() { this.api = undefined; this.state.cleanup(); } connectPromise; connect() { if (this.isConnected(this.api)) { return Promise.resolve(this.api); } if (!this.connectPromise) { const urls = Array.isArray(this.settings.server) ? this.settings.server.filter(url => typeof url === 'string') : []; if (urls.length < 1) { throw new errors_1.CustomError('connect', 'Endpoint not set'); } const endpoints = (0, utils_1.prioritizeEndpoints)(urls); this.connectPromise = this.connectRecursive(endpoints) .then(api => { this.debug('Connected'); this.api = api; return api; }) .finally(() => { this.connectPromise = undefined; }); } return this.connectPromise; } connectRecursive([url, ...rest]) { if (!url) { throw new errors_1.CustomError('connect', 'All backends are down'); } if (this.proxyAgent) { this.proxyAgent.protocol = /^(https|wss):/.test(url) ? 'https:' : 'http:'; } this.debug('Connecting to', url); return this.tryConnect(url).catch(error => { this.debug('Connection failed', error); return this.connectRecursive(rest); }); } disconnect() { } async messageHandler(event) { if (!event.data) return true; const { data } = event; const { id } = data; this.debug('onmessage', data); if (data.type === constants_1.MESSAGES.HANDSHAKE) { this.settings = data.settings; const { proxy } = data.settings; if (proxy) { const agentUri = typeof proxy === 'string' ? proxy : `socks://${proxy.host}:${proxy.port}`; const socketOptions = typeof proxy === 'object' ? { timeout: proxy?.timeout } : undefined; this.proxyAgent = new socks_proxy_agent_1.SocksProxyAgent(agentUri, socketOptions); } else { this.proxyAgent = undefined; } return true; } if (data.type === constants_1.MESSAGES.CONNECT) { await this.connect(); this.post({ id, type: constants_1.RESPONSES.CONNECT, payload: true }); return true; } if (data.type === constants_1.MESSAGES.DISCONNECT) { await this.disconnect(); this.post({ id, type: constants_1.RESPONSES.DISCONNECTED, payload: true }); return true; } if (data.type === constants_1.MESSAGES.TERMINATE) { this.disconnect(); this.cleanup(); return true; } } errorResponse(id, error) { const payload = { code: '', message: '' }; if (error instanceof Error) { payload.message = error.message; payload.code = error instanceof errors_1.CustomError && error.code ? error.code : ''; } this.post({ id, type: constants_1.RESPONSES.ERROR, payload, }); } postMessage(data) { this.messageHandler({ data }); } onmessage(_evt) { } onmessageerror(_error) { } onerror(_error) { } terminate() { this.postMessage({ id: -1, type: constants_1.MESSAGES.TERMINATE }); } } exports.BaseWorker = BaseWorker; //# sourceMappingURL=baseWorker.js.map