UNPKG

evtjs

Version:

Javascript API Bindings for the everiToken blockchain.

1,023 lines (811 loc) 36.5 kB
"use strict"; var _assign = require("babel-runtime/core-js/object/assign"); var _assign2 = _interopRequireDefault(_assign); var _isInteger = require("babel-runtime/core-js/number/is-integer"); var _isInteger2 = _interopRequireDefault(_isInteger); var _regenerator = require("babel-runtime/regenerator"); var _regenerator2 = _interopRequireDefault(_regenerator); var _getIterator2 = require("babel-runtime/core-js/get-iterator"); var _getIterator3 = _interopRequireDefault(_getIterator2); var _promise = require("babel-runtime/core-js/promise"); var _promise2 = _interopRequireDefault(_promise); var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator"); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); /** * Calculate the value of keyProvider * @param {string | string[] | function} keyProvider * @returns {string[]} */ var __calcKeyProvider = function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(keyProvider) { var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, key; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (keyProvider) { _context.next = 2; break; } return _context.abrupt("return", []); case 2: // if keyProvider is function if (keyProvider.apply && keyProvider.call) { keyProvider = keyProvider(); } // resolve for Promise _context.next = 5; return _promise2.default.resolve(keyProvider); case 5: keyProvider = _context.sent; if (!Array.isArray(keyProvider)) { keyProvider = [keyProvider]; } _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; _context.prev = 10; _iterator = (0, _getIterator3.default)(keyProvider); case 12: if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { _context.next = 19; break; } key = _step.value; if (EvtKey.isValidPrivateKey(key)) { _context.next = 16; break; } throw new Error("Invalid private key"); case 16: _iteratorNormalCompletion = true; _context.next = 12; break; case 19: _context.next = 25; break; case 21: _context.prev = 21; _context.t0 = _context["catch"](10); _didIteratorError = true; _iteratorError = _context.t0; case 25: _context.prev = 25; _context.prev = 26; if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } case 28: _context.prev = 28; if (!_didIteratorError) { _context.next = 31; break; } throw _iteratorError; case 31: return _context.finish(28); case 32: return _context.finish(25); case 33: return _context.abrupt("return", keyProvider); case 34: case "end": return _context.stop(); } } }, _callee, this, [[10, 21, 25, 33], [26,, 28, 32]]); })); return function __calcKeyProvider(_x) { return _ref.apply(this, arguments); }; }(); /** * @param {number} flag The flag of EvtLink * @param {Buffer[]} segments List of segments * @param {object} params QR options */ var __getQRCode = function () { var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(flag, segments, params) { var flagBuffer, segmentsBytes, _qrPrefix, text, sigBufs, i, key, sig; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: // sort by key segments = segments.sort(function (x, y) { return x[0] - y[0]; }); if (!params.keyProvider) { _context2.next = 7; break; } _context2.next = 4; return __calcKeyProvider(params.keyProvider); case 4: params.keyProvider = _context2.sent; if (!(params.keyProvider.length > 3)) { _context2.next = 7; break; } throw new Error("Exceed max private key limit: 3"); case 7: flagBuffer = new Buffer(2); flagBuffer.writeInt16BE(flag, 0); segmentsBytes = Buffer.concat([flagBuffer].concat(segments)); _qrPrefix = ""; if ((flag & 16) == 16) { _qrPrefix = qrPrefix; } text = "" + _qrPrefix + EvtLink.b2dec(segmentsBytes); if (!(params.keyProvider && params.keyProvider.length > 0)) { _context2.next = 26; break; } sigBufs = []; i = 0; case 16: if (!(i < params.keyProvider.length)) { _context2.next = 25; break; } key = params.keyProvider[i]; _context2.next = 20; return ecc.sign(segmentsBytes, key); case 20: sig = _context2.sent; sigBufs.push(ecc.Signature.from(sig).toBuffer()); case 22: ++i; _context2.next = 16; break; case 25: text += "_" + EvtLink.b2dec(Buffer.concat(sigBufs)); case 26: return _context2.abrupt("return", text); case 27: case "end": return _context2.stop(); } } }, _callee2, this); })); return function __getQRCode(_x2, _x3, _x4) { return _ref2.apply(this, arguments); }; }(); /** * parse EvtLink's text * @param {object} params the text of EvtLink */ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ecc = require("./ecc/index"); var qrcode = require("qrcode"); var BigInteger = require("./bigi"); var EvtKey = require("./key"); var randomBytes = require("randombytes"); var qrPrefix = "https://evt.li/"; var baseUsed = 42; var EvtLink = function EvtLink() { (0, _classCallCheck3.default)(this, EvtLink); }; /** * Convert a buffer to base10 representation. * @param {Buffer} buffer The buffer-like object to be converted. */ EvtLink.b2dec = function (buffer) { if (buffer.length == 0) return ""; var ret = BigInteger.fromBuffer(buffer).toString(baseUsed); if (ret == "0") ret = ""; var i = 0; while (buffer[i++] == 0) { ret = "0" + ret; } //console.log("+++" + ret); return ret.toUpperCase(); }; /** * Get current time using remote server time. The return value will fallback to local time if remote server time is not available. */ EvtLink.getFixedCurrentTime = function getFixedCurrentTime() { var remoteDiff = 0; if ((global || window) && (global || window).__evtjs_timeDiff) { remoteDiff = remoteDiff || (global || window).__evtjs_timeDiff; console.log("[evtjs] using timestamp with diff:" + remoteDiff); } else { console.log("[evtjs] warning: can not get time from node; it's recommended to use EvtLink function after initializing one APICaller instance with valid endpoint."); } return new Date().getTime() + remoteDiff; }; /** * Convert a base10 representation to buffer. * @param {string} base10 string. */ EvtLink.dec2b = function (base42) { if (base42 == "") return new Buffer(); var zeroCount = 0, i = 0; while (base42[i++] === "0") { zeroCount++; } var alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$+-/:*"; var b10bn = new BigInteger(); var baseBN = BigInteger.fromHex("2a"); for (var _i = 0; _i < base42.length; ++_i) { var index = alphabet.indexOf(base42[_i]); if (index == -1) throw new Error("Decode from base42 to binary failed: base42 out of range"); b10bn = b10bn.multiply(baseBN).add(new BigInteger(index.toString(), 10)); } var buf = b10bn.toBuffer(0); var ret = Buffer.concat([Buffer.alloc(zeroCount, 0), buf]); return ret; }; /** * create a buffer representing a segment. * Different typeKey has different data type, this is the detail: * 0 - 20 1-byte unsigned integer * 21 - 40 2-byte unsigned integer (BE) * 41 - 90 4-byte unsigned integer (BE) * 91 - 155 string * 156 - 165 uuid * 166 - 180 byte string * > 180 remained * * @param {*} typeKey the typeKey, different key has different type and meanings (0 - 254) * @param {*} value the value, must has the right data type according to typeKey */ function createSegment(typeKey, value) { // 1-byte unsigned integer if (typeKey <= 20) { return new Buffer([typeKey, value]); } // 2-byte unsigned integer if (typeKey <= 40) { var content = new Buffer(3); content.writeUInt8(typeKey, 0); content.writeUInt16BE(value, 1); return content; } // 4-byte unsigned integer else if (typeKey <= 90) { var _content = new Buffer(5); _content.writeUInt8(typeKey, 0); _content.writeUInt32BE(value, 1); return _content; } // string else if (typeKey <= 155) { if (typeof value !== "string") throw new Error("value must be string."); var _content2 = Buffer.from(value); if (_content2.length > 255) throw new Error("Length of 'value' exceed the limitation (255)."); var header = new Buffer([typeKey, _content2.length]); return Buffer.concat([header, _content2]); } // uuid else if (typeKey <= 165) { return Buffer.concat([new Buffer([typeKey]), value]); } // byte string else if (typeKey <= 180) { var _content3 = value; var _header = new Buffer([typeKey, _content3.length]); return Buffer.concat([_header, _content3]); } else { throw new Error("typeKey not supported"); } } /** * Parse a segment and convert it into json. * @param {Buffer} buffer * @param {number} offset */ function parseSegment(buffer, offset) { var typeKey = buffer[offset]; if (typeKey <= 20) { if (buffer[offset + 1] == undefined) throw new Error("ParseError: No value for uint8"); return { typeKey: typeKey, value: buffer[offset + 1], bufferLength: 2 }; } if (typeKey <= 40) { if (buffer[offset + 2] == undefined) throw new Error("ParseError: Incomplete value for uint16"); return { typeKey: typeKey, value: buffer.readUInt16BE(offset + 1), bufferLength: 3 }; } else if (typeKey <= 90) { if (buffer[offset + 4] == undefined) throw new Error("ParseError: Incomplete value for uint32"); return { typeKey: typeKey, value: buffer.readUInt32BE(offset + 1), bufferLength: 5 }; } else if (typeKey <= 155) { if (buffer[offset + 1] == undefined) throw new Error("ParseError: Incomplete length value for string"); var len = buffer.readUInt8(offset + 1); if (buffer[offset + 1 + len] == undefined) throw new Error("ParseError: Incomplete value for string"); var value = buffer.toString("utf8", offset + 2, offset + 2 + len); return { typeKey: typeKey, value: value, bufferLength: 2 + len }; } else if (typeKey <= 165) { if (buffer[offset + 16] == undefined) throw new Error("ParseError: Incomplete value for uuid"); var _len = 16; var _value = new Buffer(_len); buffer.copy(_value, 0, offset + 1, offset + 1 + _len); return { typeKey: typeKey, value: _value, bufferLength: 1 + _len }; } else if (typeKey <= 180) { if (buffer[offset + 1] == undefined) throw new Error("ParseError: Incomplete length value for byte string"); var _len2 = buffer.readUInt8(offset + 1); if (buffer[offset + _len2 + 1] == undefined) throw new Error("ParseError: Incomplete value for byte string"); var _value2 = new Buffer(_len2); buffer.copy(_value2, 0, offset + 2, offset + 2 + _len2); return { typeKey: typeKey, value: _value2, bufferLength: 2 + _len2 }; } else { throw new Error("typeKey not supported"); } } /** * Parse a buffer to a array of segments * @param {Buffer} buffer */ function parseSegments(buffer) { if (buffer.length == 0) throw new Error("bad segments stream"); var pointer = 0; var segments = []; while (pointer < buffer.length) { var seg = parseSegment(buffer, pointer); segments.push(seg); pointer += seg.bufferLength; delete seg.bufferLength; } if (pointer != buffer.length) { throw new Error("Bad / incomplete segments"); } return segments; } /** * Parse a everiToken's QRCode Text * @param {string} text */ function parseQRCode(text, options) { if (text.length < 3 || text.length > 2000) throw new Error("Invalid length of EvtLink"); var textSplited = text.split("_"); if (textSplited.length > 2) return null; var rawText = void 0; if (textSplited[0].startsWith(qrPrefix)) { rawText = textSplited[0].substr(qrPrefix.length); } else { rawText = textSplited[0]; } // decode segments base42 var segmentsBytes = EvtLink.dec2b(rawText); if (segmentsBytes.length < 2) throw new Error("no flag in segment"); var flag = segmentsBytes.readInt16BE(0); if ((flag & 1) == 0) { // check version of EvtLink throw new Error("The EvtLink is invalid or its version is newer than version 1 and is not supported by evtjs yet"); } var segmentsBytesRaw = new Buffer(segmentsBytes.length - 2); segmentsBytes.copy(segmentsBytesRaw, 0, 2, segmentsBytes.length); var publicKeys = []; var signatures = []; if (textSplited[1]) { var buf = EvtLink.dec2b(textSplited[1]); var i = 0; if (buf.length % 65 !== 0) { throw new Error("length of signature is invalid"); } while (i * 65 < buf.length) { var current = new Buffer(65); buf.copy(current, 0, i * 65, i * 65 + 65); var signature = ecc.Signature.fromBuffer(current); signatures.push(signature.toString()); if (!options || options.recoverPublicKeys) { publicKeys.push(signature.recover(segmentsBytes).toString()); } ++i; } } return { flag: flag, segments: parseSegments(segmentsBytesRaw), publicKeys: publicKeys, signatures: signatures }; }EvtLink.parseEvtLink = function () { var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(text, options) { return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: return _context3.abrupt("return", parseQRCode(text, options)); case 1: case "end": return _context3.stop(); } } }, _callee3, this); })); return function (_x5, _x6) { return _ref3.apply(this, arguments); }; }(); EvtLink.parseEvtLinkSync = function (text, options) { // console.log("[parseEvtLink] " + text); return parseQRCode(text, options); }; EvtLink.validateEveriPassUnsafe = function () { var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(options) { var timestamp, domain, tokenName, list; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: if (options.parsedEvtLink) { _context4.next = 4; break; } _context4.next = 3; return EvtLink.parseEvtLink(options.evtLink); case 3: options.parsedEvtLink = _context4.sent; case 4: // check time timestamp = void 0, domain = void 0, tokenName = void 0; _context4.prev = 5; if (options.parsedEvtLink.flag & 2) { _context4.next = 8; break; } throw new Error("Flag is not correct for everiPass"); case 8: timestamp = options.parsedEvtLink.segments.filter(function (x) { return x.typeKey == 42; })[0].value * 1000 || 0; domain = options.parsedEvtLink.segments.filter(function (x) { return x.typeKey == 91; })[0].value; tokenName = options.parsedEvtLink.segments.filter(function (x) { return x.typeKey == 92; })[0].value; _context4.next = 16; break; case 13: _context4.prev = 13; _context4.t0 = _context4["catch"](5); throw new Error("everiPass is in wrong format: the evtLink is not a well-formatted everiPass string."); case 16: if (!(Math.abs(timestamp - EvtLink.getFixedCurrentTime()) > 60000)) { _context4.next = 18; break; } throw new Error("everiPass is expired"); case 18: if (!(options.parsedEvtLink.publicKeys.length !== 1)) { _context4.next = 20; break; } throw new Error("For unsafe validation of everiPass, evtLink must have one and only one signature."); case 20: _context4.next = 22; return options.apiCaller.getOwnedTokens(options.parsedEvtLink.publicKeys); case 22: list = _context4.sent; if (!(list.filter(function (x) { return x.domain == domain && x.name == tokenName; }).length == 1)) { _context4.next = 25; break; } return _context4.abrupt("return", { valid: true, domain: domain, name: tokenName }); case 25: return _context4.abrupt("return", { valid: false, domain: domain, name: tokenName }); case 26: case "end": return _context4.stop(); } } }, _callee4, this, [[5, 13]]); })); function validateEveriPassUnsafe(_x7) { return _ref4.apply(this, arguments); } return validateEveriPassUnsafe; }(); // list of available typeKey: // typeKey description // 41 flag // 1 protocol version 1 (required) // 2 everiPass // 4 everiPay // 8 should destory the NFT after validate the token in everiPass // 16 collection code // 42 unix timestamp in seconds // 43 max allowed amount for payment (optionl) // 44 (uint32) symbol id to be paid in everiPay (for example: "1" for EVT) // 45 (uint32) symbol id to be received in PayeeCode (for example: "1" for EVT) // 46 fixed amount (optionl) // 44 symbol id to be paid in everiPay (for example: "5") // 91 domain name to be validated in everiPass // 92 token name to be validated in everiPass // 94 max allowed amount for payment (optionl, string format remained only for amount >= 2 ^ 32) // 95 public key (address) for receiving points or coins // 96 (string) count to receive in PayeeCode, should use decimal with proper precision // 97 fixed amount (optionl, string format remained only for amount >= 2 ^ 32) // 98 memo (optionl, length can not exceed 255) // 99 redirect url (https prefix will automatically be added) when user use browsers to open evtlink // 156 global-unique link id /** * Get a cryptography-strong unique link id that is mostly unique. */ EvtLink.getUniqueLinkId = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5() { var ret; return _regenerator2.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: ret = randomBytes(16); return _context5.abrupt("return", ret.toString("hex")); case 2: case "end": return _context5.stop(); } } }, _callee5, this); })); /** * get everiPass's text from specific private key and token name * @deprecated * @param {object} params the params of the pass */ EvtLink.getEveriPassText = function () { var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(params) { var byteSegments, flag; return _regenerator2.default.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: if (params) { _context6.next = 2; break; } throw new Error("Invalid params"); case 2: byteSegments = []; if (!(params.autoDestroying !== true && params.autoDestroying !== false)) { _context6.next = 5; break; } throw new Error("Must provide the value of autoDestroying"); case 5: if (params.domainName) { _context6.next = 7; break; } throw new Error("Must provide the value of domainName"); case 7: if (params.tokenName) { _context6.next = 9; break; } throw new Error("Must provide the value of tokenName"); case 9: // add segments flag = 1 + 2 + (params.autoDestroying ? 8 : 0); // everiPass byteSegments.push(createSegment(42, Math.floor(EvtLink.getFixedCurrentTime() / 1000))); // timestamp if (params.domainName) byteSegments.push(createSegment(91, params.domainName)); // domainName for everiPass if (params.tokenName) byteSegments.push(createSegment(92, params.tokenName)); // tokenName for everiPass if (params.memo) byteSegments.push(createSegment(98, params.memo)); // memo for everiPass // byteSegments.push(createSegment(156, Buffer.from(params.linkId, "hex") )); // random link id // convert buffer of segments to text using base10 _context6.next = 16; return __getQRCode(flag, byteSegments, params); case 16: _context6.t0 = _context6.sent; return _context6.abrupt("return", { rawText: _context6.t0 }); case 18: case "end": return _context6.stop(); } } }, _callee6, this); })); return function (_x8) { return _ref6.apply(this, arguments); }; }(); /** * get everiPay's text from specific private key and token name * @param {object} params the params of the everiPay QRCode */ EvtLink.getEvtLinkForEveriPass = EvtLink.getEveriPassText; /** * get everiPay's text from specific private key and token name * @deprecated * @param {object} params the params of the everiPay QRCode */ EvtLink.getEveriPayText = function () { var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(params) { var byteSegments, flag; return _regenerator2.default.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: if (params) { _context7.next = 2; break; } throw new Error("Invalid params"); case 2: byteSegments = []; if (!(!params.symbol || !(0, _isInteger2.default)(params.symbol))) { _context7.next = 5; break; } throw new Error("Must specify the value of symbol (integer)"); case 5: if (!(!params.linkId || params.linkId.length !== 32)) { _context7.next = 7; break; } throw new Error("linkId is required"); case 7: if (!(!params.maxAmount || !(0, _isInteger2.default)(params.maxAmount))) { _context7.next = 9; break; } throw new Error("maxAmount is required, and must be a integer"); case 9: if (!(params.fixedAmount && !(0, _isInteger2.default)(params.fixedAmount))) { _context7.next = 11; break; } throw new Error("fixedAmount must be a integer"); case 11: // add segments flag = 1 + 4; // everiPay byteSegments.push(createSegment(42, Math.floor(EvtLink.getFixedCurrentTime() / 1000))); // timestamp byteSegments.push(createSegment(44, params.symbol.toString())); // symbol for everiPay if (params.maxAmount && params.maxAmount < 4294967295) byteSegments.push(createSegment(43, params.maxAmount)); // max amount if (params.maxAmount && params.maxAmount >= 4294967295) byteSegments.push(createSegment(94, params.maxAmount.toString())); // max amount if (params.fixedAmount && params.fixedAmount < 4294967295) byteSegments.push(createSegment(46, params.fixedAmount)); // fixed amount if (params.fixedAmount && params.fixedAmount >= 4294967295) byteSegments.push(createSegment(97, params.fixedAmount.toString())); // fixed amount byteSegments.push(createSegment(156, Buffer.from(params.linkId, "hex"))); // random link id // convert buffer of segments to text using base10 _context7.next = 21; return __getQRCode(flag, byteSegments, params); case 21: _context7.t0 = _context7.sent; return _context7.abrupt("return", { rawText: _context7.t0 }); case 23: case "end": return _context7.stop(); } } }, _callee7, this); })); return function (_x9) { return _ref7.apply(this, arguments); }; }(); /** * get everiPay's text from specific private key and token name * @param {object} params the params of the everiPay QRCode */ EvtLink.getEvtLinkForEveriPay = EvtLink.getEveriPayText; /** * get evt link for payee code * @param {object} params the params of the pass */ EvtLink.getEvtLinkForPayeeCode = function () { var _ref8 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee8(params) { var byteSegments, flag; return _regenerator2.default.wrap(function _callee8$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: if (params) { _context8.next = 2; break; } throw new Error("Invalid params"); case 2: byteSegments = []; if (!(!params.address || typeof params.address !== "string")) { _context8.next = 5; break; } throw new Error("Must specify the value of address"); case 5: // add segments flag = 1 + 16; // collection code byteSegments.push(createSegment(95, params.address)); // payeeCode delete params.keyProvider; if (!params.fungibleId) { _context8.next = 12; break; } if ((0, _isInteger2.default)(params.fungibleId)) { _context8.next = 11; break; } throw new Error("fungibleId must be a integer"); case 11: byteSegments.push(createSegment(45, params.fungibleId)); case 12: if (!params.amount) { _context8.next = 18; break; } if (!(typeof params.amount !== "string")) { _context8.next = 15; break; } throw new Error("amount must be a decimal string with proper precision (like asset type doing)"); case 15: if (params.fungibleId) { _context8.next = 17; break; } throw new Error("If amount is provided, fungibleId is required."); case 17: byteSegments.push(createSegment(96, params.amount)); case 18: _context8.next = 20; return __getQRCode(flag, byteSegments, params); case 20: _context8.t0 = _context8.sent; return _context8.abrupt("return", { rawText: _context8.t0 }); case 22: case "end": return _context8.stop(); } } }, _callee8, this); })); return function (_x10) { return _ref8.apply(this, arguments); }; }(); /** * get everiPass's qr code image address from specific private key and token name * @param {object} params the params of the pass */ EvtLink.getEVTLinkQrImage = function (qrType, qrParams, imgParams, callback) { var intervalId = void 0; if (imgParams.autoReload) { intervalId = setInterval(function () { return EvtLink.getEVTLinkQrImage(qrType, qrParams, (0, _assign2.default)(imgParams, { autoReload: false, intervalId: intervalId }), callback); }, 5000); } var errorCorrectionLevel = "M"; var func = void 0; switch (qrType) { case "everiPass": func = EvtLink.getEvtLinkForEveriPass; break; case "everiPay": func = EvtLink.getEvtLinkForEveriPay; break; case "payeeCode": func = EvtLink.getEvtLinkForPayeeCode; break; default: throw new Error("invalid QR Type"); } var time = EvtLink.getFixedCurrentTime(); func(qrParams).then(function (res) { time = EvtLink.getFixedCurrentTime() - time; if (res.rawText.length > 300) { errorCorrectionLevel = "M"; } if (res.rawText.length > 260) { errorCorrectionLevel = "L"; } if (imgParams.canvas) { qrcode.toCanvas(imgParams.canvas, res.rawText, { errorCorrectionLevel: errorCorrectionLevel, scale: 16, "color": { dark: "#000000" } }, function (err) { callback(err, { rawText: res.rawText, timeConsumed: time, intervalId: intervalId || imgParams.intervalId }); }); } else { qrcode.toDataURL(res.rawText, { errorCorrectionLevel: errorCorrectionLevel, scale: 16, "color": { dark: "#000000" } }, function (err, url) { callback(err, { dataUrl: url, rawText: res.rawText, timeConsumed: time, intervalId: intervalId || imgParams.intervalId }); }); } }).catch(function (e) { callback(e); }); return { intervalId: intervalId, autoReloadInterval: 5000 }; }; module.exports = EvtLink;