You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
11 KiB
334 lines
11 KiB
5 years ago
|
"use strict";
|
||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
});
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
const ByteBuffer = require("bytebuffer");
|
||
|
const fs = require("fs");
|
||
|
const grpc = require("grpc");
|
||
|
const helpers_1 = require("../helpers");
|
||
|
const sha = require("js-sha256");
|
||
|
const crypto = require("crypto");
|
||
|
// var protoLoader = require('@grpc/proto-loader')
|
||
|
const env = process.env.NODE_ENV || 'development';
|
||
|
const config = require(__dirname + '/../../config/app.json')[env];
|
||
|
const LND_KEYSEND_KEY = 5482373484;
|
||
|
exports.LND_KEYSEND_KEY = LND_KEYSEND_KEY;
|
||
|
const SPHINX_CUSTOM_RECORD_KEY = 133773310;
|
||
|
exports.SPHINX_CUSTOM_RECORD_KEY = SPHINX_CUSTOM_RECORD_KEY;
|
||
|
var lightningClient = null;
|
||
|
var walletUnlocker = null;
|
||
|
const loadCredentials = () => {
|
||
|
var lndCert = fs.readFileSync(config.tls_location);
|
||
|
var sslCreds = grpc.credentials.createSsl(lndCert);
|
||
|
var m = fs.readFileSync(config.macaroon_location);
|
||
|
var macaroon = m.toString('hex');
|
||
|
var metadata = new grpc.Metadata();
|
||
|
metadata.add('macaroon', macaroon);
|
||
|
var macaroonCreds = grpc.credentials.createFromMetadataGenerator((_args, callback) => {
|
||
|
callback(null, metadata);
|
||
|
});
|
||
|
return grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
|
||
|
};
|
||
|
exports.loadCredentials = loadCredentials;
|
||
|
// async function loadLightningNew() {
|
||
|
// if (lightningClient) {
|
||
|
// return lightningClient
|
||
|
// } else {
|
||
|
// var credentials = loadCredentials()
|
||
|
// const packageDefinition = await protoLoader.load("rpc.proto", {})
|
||
|
// const lnrpcDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
||
|
// var { lnrpc } = lnrpcDescriptor;
|
||
|
// lightningClient = new lnrpc.Lightning(config.node_ip + ':' + config.lnd_port, credentials);
|
||
|
// return lightningClient
|
||
|
// }
|
||
|
// }
|
||
|
const loadLightning = () => {
|
||
|
if (lightningClient) {
|
||
|
return lightningClient;
|
||
|
}
|
||
|
else {
|
||
|
try {
|
||
|
var credentials = loadCredentials();
|
||
|
var lnrpcDescriptor = grpc.load("rpc.proto");
|
||
|
var lnrpc = lnrpcDescriptor.lnrpc;
|
||
|
lightningClient = new lnrpc.Lightning(config.node_ip + ':' + config.lnd_port, credentials);
|
||
|
return lightningClient;
|
||
|
}
|
||
|
catch (e) {
|
||
|
throw e;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
exports.loadLightning = loadLightning;
|
||
|
const loadWalletUnlocker = () => {
|
||
|
if (walletUnlocker) {
|
||
|
return walletUnlocker;
|
||
|
}
|
||
|
else {
|
||
|
var credentials = loadCredentials();
|
||
|
try {
|
||
|
var lnrpcDescriptor = grpc.load("rpc.proto");
|
||
|
var lnrpc = lnrpcDescriptor.lnrpc;
|
||
|
walletUnlocker = new lnrpc.WalletUnlocker(config.node_ip + ':' + config.lnd_port, credentials);
|
||
|
return walletUnlocker;
|
||
|
}
|
||
|
catch (e) {
|
||
|
console.log(e);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
exports.loadWalletUnlocker = loadWalletUnlocker;
|
||
|
const getHeaders = (req) => {
|
||
|
return {
|
||
|
"X-User-Token": req.headers['x-user-token'],
|
||
|
"X-User-Email": req.headers['x-user-email']
|
||
|
};
|
||
|
};
|
||
|
exports.getHeaders = getHeaders;
|
||
|
var isLocked = false;
|
||
|
let lockTimeout;
|
||
|
const getLock = () => isLocked;
|
||
|
exports.getLock = getLock;
|
||
|
const setLock = (value) => {
|
||
|
isLocked = value;
|
||
|
console.log({ isLocked });
|
||
|
if (lockTimeout)
|
||
|
clearTimeout(lockTimeout);
|
||
|
lockTimeout = setTimeout(() => {
|
||
|
isLocked = false;
|
||
|
console.log({ isLocked });
|
||
|
}, 1000 * 60 * 2);
|
||
|
};
|
||
|
exports.setLock = setLock;
|
||
|
const getRoute = (pub_key, amt, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
||
|
let lightning = yield loadLightning();
|
||
|
lightning.queryRoutes({ pub_key, amt }, (err, response) => callback(err, response));
|
||
|
});
|
||
|
exports.getRoute = getRoute;
|
||
|
const keysend = (opts) => {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
let lightning = yield loadLightning();
|
||
|
const randoStr = crypto.randomBytes(32).toString('hex');
|
||
|
const preimage = ByteBuffer.fromHex(randoStr);
|
||
|
const options = {
|
||
|
amt: opts.amt,
|
||
|
final_cltv_delta: 10,
|
||
|
dest: ByteBuffer.fromHex(opts.dest),
|
||
|
dest_custom_records: {
|
||
|
[`${LND_KEYSEND_KEY}`]: preimage,
|
||
|
[`${SPHINX_CUSTOM_RECORD_KEY}`]: ByteBuffer.fromUTF8(opts.data),
|
||
|
},
|
||
|
payment_hash: sha.sha256.arrayBuffer(preimage.toBuffer()),
|
||
|
dest_features: [9],
|
||
|
};
|
||
|
const call = lightning.sendPayment();
|
||
|
call.on('data', function (payment) {
|
||
|
if (payment.payment_error) {
|
||
|
reject(payment.payment_error);
|
||
|
}
|
||
|
else {
|
||
|
resolve(payment);
|
||
|
}
|
||
|
});
|
||
|
call.on('error', function (err) {
|
||
|
reject(err);
|
||
|
});
|
||
|
call.write(options);
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
const MAX_MSG_LENGTH = 972; // 1146 - 20
|
||
|
function keysendMessage(opts) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
if (!opts.data || typeof opts.data !== 'string') {
|
||
|
return reject('string plz');
|
||
|
}
|
||
|
if (opts.data.length < MAX_MSG_LENGTH) {
|
||
|
try {
|
||
|
const res = yield keysend(opts);
|
||
|
resolve(res);
|
||
|
}
|
||
|
catch (e) {
|
||
|
reject(e);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
// too long! need to send serial
|
||
|
const n = Math.ceil(opts.data.length / MAX_MSG_LENGTH);
|
||
|
let success = false;
|
||
|
let fail = false;
|
||
|
let res = null;
|
||
|
const ts = new Date().valueOf();
|
||
|
yield asyncForEach(Array.from(Array(n)), (u, i) => __awaiter(this, void 0, void 0, function* () {
|
||
|
const spliti = Math.ceil(opts.data.length / n);
|
||
|
const m = opts.data.substr(i * spliti, spliti);
|
||
|
try {
|
||
|
res = yield keysend(Object.assign(Object.assign({}, opts), { data: `${ts}_${i}_${n}_${m}` }));
|
||
|
success = true;
|
||
|
yield helpers_1.sleep(432);
|
||
|
}
|
||
|
catch (e) {
|
||
|
console.log(e);
|
||
|
fail = true;
|
||
|
}
|
||
|
}));
|
||
|
if (success && !fail) {
|
||
|
resolve(res);
|
||
|
}
|
||
|
else {
|
||
|
reject(new Error('fail'));
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
exports.keysendMessage = keysendMessage;
|
||
|
function asyncForEach(array, callback) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
for (let index = 0; index < array.length; index++) {
|
||
|
yield callback(array[index], index, array);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
function signAscii(ascii) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
try {
|
||
|
const sig = yield signMessage(ascii_to_hexa(ascii));
|
||
|
return sig;
|
||
|
}
|
||
|
catch (e) {
|
||
|
throw e;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
exports.signAscii = signAscii;
|
||
|
function listInvoices() {
|
||
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
||
|
const lightning = yield loadLightning();
|
||
|
lightning.listInvoices({
|
||
|
num_max_invoices: 100000,
|
||
|
reversed: true,
|
||
|
}, (err, response) => {
|
||
|
if (!err) {
|
||
|
resolve(response);
|
||
|
}
|
||
|
else {
|
||
|
reject(err);
|
||
|
}
|
||
|
});
|
||
|
}));
|
||
|
}
|
||
|
exports.listInvoices = listInvoices;
|
||
|
function listPayments() {
|
||
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
||
|
const lightning = yield loadLightning();
|
||
|
lightning.listPayments({}, (err, response) => {
|
||
|
if (!err) {
|
||
|
resolve(response);
|
||
|
}
|
||
|
else {
|
||
|
reject(err);
|
||
|
}
|
||
|
});
|
||
|
}));
|
||
|
}
|
||
|
exports.listPayments = listPayments;
|
||
|
const signMessage = (msg) => {
|
||
|
return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
||
|
let lightning = yield loadLightning();
|
||
|
try {
|
||
|
const options = { msg: ByteBuffer.fromHex(msg) };
|
||
|
lightning.signMessage(options, function (err, sig) {
|
||
|
if (err || !sig.signature) {
|
||
|
reject(err);
|
||
|
}
|
||
|
else {
|
||
|
resolve(sig.signature);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
reject(e);
|
||
|
}
|
||
|
}));
|
||
|
};
|
||
|
exports.signMessage = signMessage;
|
||
|
const signBuffer = (msg) => {
|
||
|
return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
||
|
let lightning = yield loadLightning();
|
||
|
try {
|
||
|
const options = { msg };
|
||
|
lightning.signMessage(options, function (err, sig) {
|
||
|
if (err || !sig.signature) {
|
||
|
reject(err);
|
||
|
}
|
||
|
else {
|
||
|
resolve(sig.signature);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
reject(e);
|
||
|
}
|
||
|
}));
|
||
|
};
|
||
|
exports.signBuffer = signBuffer;
|
||
|
const verifyMessage = (msg, sig) => {
|
||
|
return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
||
|
let lightning = yield loadLightning();
|
||
|
try {
|
||
|
const options = {
|
||
|
msg: ByteBuffer.fromHex(msg),
|
||
|
signature: sig,
|
||
|
};
|
||
|
console.log(options);
|
||
|
lightning.verifyMessage(options, function (err, res) {
|
||
|
if (err || !res.pubkey) {
|
||
|
reject(err);
|
||
|
}
|
||
|
else {
|
||
|
resolve(res);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
reject(e);
|
||
|
}
|
||
|
}));
|
||
|
};
|
||
|
exports.verifyMessage = verifyMessage;
|
||
|
function checkConnection() {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
const lightning = loadLightning();
|
||
|
lightning.getInfo({}, function (err, response) {
|
||
|
if (err == null) {
|
||
|
resolve(response);
|
||
|
}
|
||
|
else {
|
||
|
reject(err);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
exports.checkConnection = checkConnection;
|
||
|
function ascii_to_hexa(str) {
|
||
|
var arr1 = [];
|
||
|
for (var n = 0, l = str.length; n < l; n++) {
|
||
|
var hex = Number(str.charCodeAt(n)).toString(16);
|
||
|
arr1.push(hex);
|
||
|
}
|
||
|
return arr1.join('');
|
||
|
}
|
||
|
//# sourceMappingURL=lightning.js.map
|