UNPKG

@ton3/liteclient

Version:
114 lines 3.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LiteClient = void 0; const events_1 = __importDefault(require("events")); const adnl_1 = require("adnl"); const blockchain_1 = require("./blockchain"); const liteapi_1 = require("./liteapi"); const process_1 = require("process"); const PING_INTERVAL = 1000; const SYNC_INTERVAL = 2000; const MEASUREMENT_WINDOW = 60; class LiteClient { constructor(_url, _publicKey) { this._url = _url; this._publicKey = _publicKey; this._isReady = false; this.roundTimeTrips = []; this.outOfSyncs = []; this.events = new events_1.default(); const adnlClient = this._url.toLowerCase().startsWith('tcp://') ? new adnl_1.ADNLClientTCP(this._url, this.publicKey) : new adnl_1.ADNLClientWS(this._url, this.publicKey); adnlClient.on('error', this.onError.bind(this)); adnlClient.on('ready', this.onReady.bind(this)); this.adnl = adnlClient; this.api = new blockchain_1.BlockchainClient(new liteapi_1.LiteApi(adnlClient)); adnlClient.connect(); } onReady() { this._isReady = true; this.loop(this.ping.bind(this), PING_INTERVAL); this.loop(this.sync.bind(this)); } onError(err) { } static create(url, publicKey) { const liteServer = new LiteClient(url, publicKey); return liteServer; } async ping() { if (!this.isReady) return Promise.resolve(); const start = (0, process_1.hrtime)(); await this.api.getTime(); const [sec, nano] = (0, process_1.hrtime)(start); const rtt = Math.round((sec * 1e9 + nano) / 1e6); if (this.roundTimeTrips.unshift(rtt) > MEASUREMENT_WINDOW) { this.roundTimeTrips.pop(); } } async sync() { if (!this.isReady) return Promise.resolve(); const wait = this.seqno ? { seqno: this.seqno + 1 } : undefined; const last = await this.api.getMasterchainInfo(wait); const { info } = await this.api.getBlock(last); const outOfSync = Math.floor(Date.now() / 1000) - info.gen_utime; this.events.emit('block', last); this.seqno = info.seq_no; this.utime = info.gen_utime; if (this.outOfSyncs.unshift(outOfSync) > MEASUREMENT_WINDOW) { this.outOfSyncs.pop(); } } async delay(timeout) { return new Promise(res => setTimeout(() => res(null), timeout)); } async loop(action, sleep) { while (this.isReady) { try { await action(); if (!sleep) { continue; } await this.delay(sleep); } catch (err) { } } } get url() { return this._url; } get publicKey() { return this._publicKey; } get stats() { const roundTimeTrip = this.roundTimeTrips.reduce((acc, el) => acc + el, 0) / this.roundTimeTrips.length; const outOfSync = this.outOfSyncs.reduce((acc, el) => acc + el, 0) / this.outOfSyncs.length; return { roundTimeTrip: Math.round(roundTimeTrip), outOfSync: Math.round(outOfSync), head: this.seqno }; } get isReady() { return this._isReady; } get isSynced() { if (!this.isReady || !this.utime) return false; const now = Math.round(Date.now() / 1000); const diff = now - this.utime; return diff <= 30; } get isAlive() { return this.isReady && this.isSynced; } } exports.LiteClient = LiteClient; //# sourceMappingURL=index.js.map