@ton3/liteclient
Version:
TON Blockchain LiteClient
114 lines • 3.88 kB
JavaScript
"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