UNPKG

@ylide/everscale

Version:

Ylide Protocol SDK implementation for EverScale blockchain

153 lines 5.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GqlSender = void 0; const gql_1 = require("everscale-standalone-client/client/ConnectionController/gql"); const gqlQueries_1 = require("./gqlQueries"); class GqlSender { params; latencyDetectionInterval; endpoints; nextLatencyDetectionTime = 0; currentEndpoint; resolutionPromise; constructor(params) { this.params = params; this.latencyDetectionInterval = params.latencyDetectionInterval || 60000; this.endpoints = params.endpoints.map(e => gql_1.GqlSocket.expandAddress(e)); if (this.endpoints.length === 1) { this.currentEndpoint = this.endpoints[0]; this.nextLatencyDetectionTime = Number.MAX_VALUE; } } isLocal() { return !!this.params.local; } async send(data) { const now = Date.now(); try { let endpoint; if (this.currentEndpoint != null && now < this.nextLatencyDetectionTime) { // Default route endpoint = this.currentEndpoint; } else if (this.resolutionPromise != null) { // Already resolving endpoint = await this.resolutionPromise; delete this.resolutionPromise; } else { delete this.currentEndpoint; // Start resolving (current endpoint is null, or it is time to refresh) this.resolutionPromise = this._selectQueryingEndpoint().then(_endpoint => { this.currentEndpoint = _endpoint; this.nextLatencyDetectionTime = Date.now() + this.latencyDetectionInterval; return _endpoint; }); endpoint = await this.resolutionPromise; delete this.resolutionPromise; } return fetch(endpoint.url, { method: 'post', headers: { 'Content-Type': 'application/json', }, body: data, }).then(response => response.json()); } catch (e) { throw e; } } async _selectQueryingEndpoint() { const maxLatency = this.params.maxLatency || 60000; const endpointCount = this.endpoints.length; for (let retryCount = 0; retryCount < 5; ++retryCount) { let handlers; const promise = new Promise((resolve, reject) => { handlers = { resolve: (endpoint) => resolve(endpoint), reject: () => reject(undefined), }; }); let checkedEndpoints = 0; let lastLatency; for (const endpoint of this.endpoints) { gql_1.GqlSocket.checkLatency(endpoint).then(latency => { ++checkedEndpoints; if (latency !== undefined && latency <= maxLatency) { return handlers.resolve(endpoint); } if (lastLatency === undefined || lastLatency.latency === undefined || (latency !== undefined && latency < lastLatency.latency)) { lastLatency = { endpoint, latency }; } if (checkedEndpoints >= endpointCount) { if (lastLatency?.latency !== undefined) { handlers.resolve(lastLatency.endpoint); } else { handlers.reject(); } } }); } try { return await promise; } catch (e) { let resolveDelay; const delayPromise = new Promise(resolve => { resolveDelay = () => resolve(); }); setTimeout(() => resolveDelay(), Math.min(100 * retryCount, 5000)); await delayPromise; } } throw new Error('Not available endpoint found'); } async query(query, variables = {}) { return this.send(JSON.stringify({ query, variables, })); } async queryContractMessages(dst, contractAddress, limit) { const query = (0, gqlQueries_1.getContractMessagesQuery)(dst, contractAddress, limit); return await this.queryMessages(query); } async queryMessage(query, variables = {}) { const data = await this.query(query, variables); if (!data || !data.data || !data.data.blockchain || !data.data.blockchain.message) { return null; } const m = data.data.blockchain.message; return { ...m, id: m.id.startsWith('message/') ? m.id.split('message/')[1] : m.id, cursor: null, }; } async queryMessages(query, variables = {}) { const data = await this.query(query, variables); if (!data || !data.data || !data.data.blockchain || !data.data.blockchain.account || !data.data.blockchain.account.messages || !data.data.blockchain.account.messages.edges || !Array.isArray(data.data.blockchain.account.messages.edges) || !data.data.blockchain.account.messages.edges.length) { return []; } const msgs = data.data.blockchain.account.messages.edges.map((e) => ({ ...e.node, id: e.node.id.startsWith('message/') ? e.node.id.split('message/')[1] : e.node.id, cursor: e.cursor, })); msgs.sort((a, b) => b.created_at - a.created_at); return msgs; } } exports.GqlSender = GqlSender; //# sourceMappingURL=GqlSender.js.map