"use strict";

var _express = _interopRequireDefault(require("express"));

var _clightningClient = _interopRequireDefault(require("clightning-client"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

// Extend clightning-client with custom RPC commands
Object.assign(_clightningClient["default"].LightningClient.prototype, require('./cmd').commands);

var proute = function proute(fn) {
  return function (req, res, next) {
    return fn(req, res)["catch"](next);
  };
};

_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
  var app, ln, connFailed, lninfo, qrterm, qrKey, serviceReady;
  return regeneratorRuntime.wrap(function _callee2$(_context2) {
    while (1) {
      switch (_context2.prev = _context2.next) {
        case 0:
          serviceReady = function _serviceReady(name, url) {
            url = url.replace(/\/$/, '');
            console.log("\n".concat(name, " running on ").concat(url));

            if (qrterm) {
              if (!url.includes('://localhost:')) {
                console.log("Scan QR to ".concat(qrKey ? 'pair with' : 'open', " ").concat(name, ":"));
                qrterm.generate("".concat(url, "/").concat(qrKey), {
                  small: true
                });
                qrKey && console.log('[NOTE: This QR contains your secret access key, which provides full access to your wallet.]\n');
              } else if (!process.env.ONION) {
                // Display a warning if we don't have a publicly accessible URL and onion is off
                console.error('Refusing to generate a QR for localhost; Please specify --host, --public-url or --onion to have a publicly accessible URL that can be reached from other devices.');
              }
            }

            if (process.env.PAIRING_URL) {
              console.log('Pairing URL:', "".concat(url, "/?access-key=").concat(app.settings.accessKey));
              console.log('[NOTE: This URL contains your secret access key, which provides full access to your wallet.]\n');
            }

            process.send && process.send({
              serverUrl: url
            });
          };

          // IIFE
          app = (0, _express["default"])(), ln = (0, _clightningClient["default"])(process.env.LN_PATH); // Test connection

          if (process.env.NO_TEST_CONN) {
            _context2.next = 10;
            break;
          }

          connFailed = function connFailed(err) {
            throw err;
          };

          ln.on('error', connFailed);
          _context2.next = 7;
          return ln.getinfo();

        case 7:
          lninfo = _context2.sent;
          ln.removeListener('error', connFailed);
          console.log("Connected to c-lightning ".concat(lninfo.version, " with id ").concat(lninfo.id, " on network ").concat(lninfo.network, " at ").concat(ln.rpcPath));

        case 10:
          // Settings
          app.set('port', process.env.PORT || 9737);
          app.set('host', process.env.HOST || 'localhost');
          app.set('trust proxy', process.env.PROXIED || 'loopback');
          app.set('tls', !process.env.NO_TLS && (app.settings.host !== 'localhost' || process.env.FORCE_TLS)); // Middlewares

          app.use(require('morgan')('dev'));
          app.use(require('body-parser').json());
          app.use(require('./auth')(app, process.env.COOKIE_FILE, process.env.LOGIN));
          app.use(require('compression')());
          app.use(require('helmet')({
            contentSecurityPolicy: {
              directives: {
                defaultSrc: ["'self'"],
                scriptSrc: ["'self'", "'unsafe-eval'"],
                fontSrc: ["'self'", 'data:'],
                imgSrc: ["'self'", 'data:']
              }
            },
            ieNoOpen: false
          })); // CSRF protection. Require the X-Access header or access-key query string arg for POST requests.

          app.post('*', function (req, res, next) {
            return !req.csrfSafe ? res.sendStatus(403) : next();
          }); // CORS

          process.env.ALLOW_CORS && app.use(function (req, res, next) {
            res.set('Access-Control-Allow-Origin', process.env.ALLOW_CORS);
            res.set('Access-Control-Allow-Headers', 'Content-Type, Accept');
            res.set('Access-Control-Allow-Methods', 'POST');
            next();
          }); // RPC API

          app.post('/rpc', proute( /*#__PURE__*/function () {
            var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(req, res) {
              return regeneratorRuntime.wrap(function _callee$(_context) {
                while (1) {
                  switch (_context.prev = _context.next) {
                    case 0:
                      req.setTimeout(5 * 60 * 1000);
                      _context.t0 = res;
                      _context.next = 4;
                      return ln[req.body.method] ? ln[req.body.method].apply(ln, _toConsumableArray(req.body.params)) : ln.call(req.body.method, req.body.params);

                    case 4:
                      _context.t1 = _context.sent;

                      _context.t0.send.call(_context.t0, _context.t1);

                    case 6:
                    case "end":
                      return _context.stop();
                  }
                }
              }, _callee);
            }));

            return function (_x, _x2) {
              return _ref2.apply(this, arguments);
            };
          }())); // Streaming API

          app.get('/stream', require('./stream')(ln)); // Frontend

          process.env.NO_WEBUI || require('./webui')(app); // Error handler

          app.use(function (err, req, res, next) {
            console.error(err.stack || err.toString());
            res.status(err.status || 500).send(err.type && err || err.message || err);
          }); // HTTPS server (the default for non-localhost hosts)

          app.enabled('tls') ? require('./transport/tls')(app, process.env.TLS_NAME, process.env.TLS_PATH, process.env.LETSENCRYPT).then(function (url) {
            return serviceReady('HTTPS server', process.env.PUBLIC_URL || url);
          }) // HTTP server (for localhost or when --no-tls is specified)
          : require('./transport/http')(app).then(function (url) {
            return serviceReady('HTTP server', process.env.PUBLIC_URL || url);
          }); // Tor Onion Hidden Service

          process.env.ONION && require('./transport/onion')(app, process.env.ONION_PATH).then(function (url) {
            return serviceReady('Tor Onion Hidden Service v3', url);
          });
          qrterm = process.env.PRINT_QR && require('qrcode-terminal'), qrKey = process.env.PAIRING_QR ? "?access-key=".concat(app.settings.accessKey) : '';
          process.env.PRINT_KEY && console.log('Access key for remote API access:', app.settings.accessKey);

        case 29:
        case "end":
          return _context2.stop();
      }
    }
  }, _callee2);
}))();

['unhandledRejection', 'uncaughtException'].forEach(function (ev) {
  return process.on(ev, function (err) {
    process.send && process.send({
      error: err.toString()
    });
    console.error("".concat(ev, ", stopping process"));
    console.error(err.stack || err);
    process.exit(1);
  });
});
process.on('SIGTERM', function (err) {
  console.error('Caught SIGTERM, shutting down');
  process.exit(0);
});