UNPKG

madeline-ton

Version:

Pure JS client-side implementation of the Telegram TON blockchain protocol

245 lines (206 loc) 7.75 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _adnl = _interopRequireDefault(require("./network/adnl")); var _crypto = _interopRequireDefault(require("./crypto")); var _tools = require("./tools"); var _random = require("./crypto-sync/random"); var _parser = _interopRequireDefault(require("./TL/parser")); var _stream = _interopRequireDefault(require("./TL/stream")); var ADNLConnection = /*#__PURE__*/ function () { /** * * @param {Parser} TLParser * @param {Object} endpoint * @param {string} URI */ function ADNLConnection(TLParser, key, uri) { (0, _classCallCheck2["default"])(this, ADNLConnection); (0, _defineProperty2["default"])(this, "requests", {}); (0, _defineProperty2["default"])(this, "pings", {}); this.TLParser = TLParser; this.key = key; this.uri = uri; this.crypto = new _crypto["default"](this.TLParser); } (0, _createClass2["default"])(ADNLConnection, [{ key: "connect", value: function () { var _connect = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee() { var _this = this; var _ref, pub, secret, init, ctx, digest, key, iv, processor, encryptedInit, id, socket; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return this.crypto.initEC(this.key['key']); case 2: _ref = _context.sent; pub = _ref.pub; secret = _ref.secret; _context.next = 7; return this.crypto.secureRandom(new Uint32Array(40)); case 7: init = _context.sent; //init = new Uint32Array(hexToBytes('e9c77267d521ec3644410f78d555ecc5857e9a5dc84dc575ac5b611d42b1874696e1b5a0cfe4bc45fb2feccf02061f4df5b5d5be679afe46177d8561aaea8cc37ded93ee999b9e086b0c4d65a519d6000968316e63755d3519818fa941df37ba8bce3dca622c78eedbf04af4253b510fd16df084e6ffc4b5d417aef6443385ff41e12749bbbbd5c770f961db642ca82105e7918427e217129bc4b3c58723da7e').buffer) ctx = { crypto: this.crypto, decrypt: [init.slice(0, 8), init.slice(16, 20)], encrypt: [init.slice(8, 16), init.slice(20, 24)], uri: this.uri }; _context.next = 11; return this.crypto.sha256(init); case 11: digest = _context.sent; init = new Uint8Array(init.buffer); digest = new Uint8Array(digest); key = (0, _tools.bufferConcat)(secret.slice(0, 16), digest.slice(16, 32)); iv = (0, _tools.bufferConcat)(digest.slice(0, 4), secret.slice(20, 32)); _context.next = 18; return this.crypto.getCtr(key, iv); case 18: processor = _context.sent; _context.t0 = Uint8Array; _context.next = 22; return processor.process(init); case 22: _context.t1 = _context.sent; encryptedInit = new _context.t0(_context.t1); processor.close(); _context.t2 = Uint8Array; _context.next = 28; return this.crypto.sha256(this.TLParser.serialize(new _stream["default"](), this.key).uBuf); case 28: _context.t3 = _context.sent; id = new _context.t2(_context.t3); ctx['init'] = (0, _tools.bufferConcat)((0, _tools.bufferConcat)(id, pub), digest, encryptedInit); socket = new _adnl["default"](); socket.onClose = function () { return console.log("Closed connection!"); }; socket.onMessage = function (message) { return _this.onMessage(message); }; _context.next = 36; return socket.connect(ctx); case 36: this.socket = socket; this.pingId = setInterval(function () { _this.ping(); }, 5000); case 38: case "end": return _context.stop(); } } }, _callee, this); })); function connect() { return _connect.apply(this, arguments); } return connect; }() /** * Incoming message * @param {Stream} message Incoming message */ }, { key: "onMessage", value: function onMessage(message) { message = this.TLParser.deserialize(message); if (message['_'] === 'tcp.pong') { this.pings[message['random_id']].res(message); delete this.pings[message['random_id']]; return; } if (message['_'] !== 'adnl.message.answer') { console.log("Weird message: ", message); return; } clearTimeout(this.requests[message['query_id']]['timeoutId']); this.requests[message['query_id']].res(this.TLParser.deserialize(new _stream["default"](message['answer'].buffer))); delete this.requests[message['query_id']]; } /** * Send ADNL query * @param {Uint8Array} query Query */ }, { key: "query", value: function query(_query) { var _this2 = this; var query_id = (0, _random.fastRandom)(new Uint32Array(8)); _query = this.TLParser.serialize(this.socket.getBuffer(), { _: 'adnl.message.query', query_id: query_id, query: _query }); var promise = new Promise(function (res, rej) { var timeoutId = setTimeout(_this2.timeout.bind(_this2), 10000, query_id); _this2.requests[query_id] = { res: res, rej: rej, timeoutId: timeoutId }; }); return this.socket.write(_query).then(function () { return promise; }); } }, { key: "timeout", value: function timeout(query_id) { this.requests[query_id].rej(new Error("Timeout!")); delete this.requests[query_id]; } /** * Send ping */ }, { key: "ping", value: function ping() { var _this3 = this; if (!this.socket) return; var random_id = (0, _random.fastRandom)(new Int32Array(2)); var ping = this.TLParser.serialize(this.socket.getBuffer(), { _: 'tcp.ping', random_id: random_id }); var promise = new Promise(function (res, rej) { _this3.pings[random_id] = { res: res, rej: rej }; }); return this.socket.write(ping).then(function () { return promise; }); } }, { key: "close", value: function close() { if (this.socket) { this.socket.close(); this.socket = undefined; clearInterval(this.pingId); } } }]); return ADNLConnection; }(); var _default = ADNLConnection; exports["default"] = _default;