From d0e6b0349b3bd4b99da9a32def81b1b18a1f4c3e Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Thu, 3 Jun 2021 19:50:31 +0200 Subject: [PATCH] request channel --- src/routes.js | 11 ++-- utils/lightningServices/channelRequests.js | 68 ++++++++++++++++++++++ utils/lightningServices/v2.js | 41 ++++++++++++- 3 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 utils/lightningServices/channelRequests.js diff --git a/src/routes.js b/src/routes.js index 313c4e65..95a14930 100644 --- a/src/routes.js +++ b/src/routes.js @@ -36,6 +36,7 @@ const LV2 = require('../utils/lightningServices/v2') const GunWriteRPC = require('../services/gunDB/rpc') const Key = require('../services/gunDB/contact-api/key') const { startedStream, endStream } = require('../services/streams') +const channelRequest = require('../utils/lightningServices/channelRequests') const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10 const SESSION_ID = uuid() @@ -619,7 +620,7 @@ module.exports = async ( // If we're connected to lnd, unlock the wallet using the password supplied // and generate an auth token if that operation was successful. if (health.LNDStatus.success && walletInitialized) { - const { alias, password } = req.body + const { alias, password, invite } = req.body await recreateLnServices() @@ -798,6 +799,7 @@ module.exports = async ( onNewChannelBackup() + channelRequest(invite) res.json({ authorization: token, user: { @@ -840,7 +842,7 @@ module.exports = async ( app.post('/api/lnd/wallet', async (req, res) => { try { const { walletUnlocker } = LightningServices.services - const { password, alias } = req.body + const { password, alias, invite } = req.body const healthResponse = await checkHealth() if (!alias) { return res.status(400).json({ @@ -958,6 +960,7 @@ module.exports = async ( await LightningServices.init() const token = await auth.generateToken() + channelRequest(invite) return res.json({ mnemonicPhrase, authorization: token, @@ -1005,7 +1008,7 @@ module.exports = async ( app.post('/api/lnd/wallet/existing', async (req, res) => { try { - const { password, alias } = req.body + const { password, alias, invite } = req.body const healthResponse = await checkHealth() const exists = await walletExists() if (!exists) { @@ -1062,7 +1065,7 @@ module.exports = async ( // Generate Access Token const token = await auth.generateToken() - + channelRequest(invite) res.json({ authorization: token, user: { diff --git a/utils/lightningServices/channelRequests.js b/utils/lightningServices/channelRequests.js new file mode 100644 index 00000000..d8a969eb --- /dev/null +++ b/utils/lightningServices/channelRequests.js @@ -0,0 +1,68 @@ +const logger = require('winston') +const fetch = require('node-fetch') +const Storage = require('node-persist') +const { listPeers, connectPeer,getInfo } = require('./v2') + +const handlerBaseUrl = "https://channels.shock.network" + +/** + * + * @param {string} inviteFromAuth + */ +module.exports = async (inviteFromAuth) => { + /** + * @type string | undefined + */ + const invite = inviteFromAuth || process.env.HOSTING_INVITE + if(!invite) { + return + } + try{ + await Storage.getItem('processedInvites') + } catch(e) { + await Storage.setItem('processedInvites',[]) + } + try { + /** + * @type string[] + */ + const invites = await Storage.getItem('processedInvites') + if(invites.includes(invite)){ + return + } + + const me = await getInfo() + const {identity_pubkey} = me + //@ts-expect-error + const connectReq = await fetch(`${handlerBaseUrl}/connect`) + if(connectReq.status !== 200 ){ + return + } + + const connJson = await connectReq.json() + const [uri] = connJson.uris + const [pub,host] = uri.split("@") + const peers = await listPeers() + if(peers.findIndex(peer => peer.pub_key === pub) === -1){ + await connectPeer(pub,host) + } + + //@ts-expect-error + const res = await fetch(`${handlerBaseUrl}/channel`,{ + method:'POST', + body:JSON.stringify({ + userPubKey:identity_pubkey, + invite, + lndTo:pub, + }) + }) + + invites.push(invite) + await Storage.setItem('processedInvites',invites) + + } catch(e){ + logger.error("error sending invite to channels handler") + console.error(e) + } + +} \ No newline at end of file diff --git a/utils/lightningServices/v2.js b/utils/lightningServices/v2.js index a32572cf..bd2b3eb3 100644 --- a/utils/lightningServices/v2.js +++ b/utils/lightningServices/v2.js @@ -631,6 +631,43 @@ const subscribeTransactions = (dataCb, errorCb) => { }) } +const getInfo = () => + Common.makePromise((res, rej) => { + const { lightning } = lightningServices.getServices() + + lightning.getInfo({}, (err, resp) => { + if (err) { + rej(new Error(err.message)) + } else { + // Needs cast because typescript refuses to assign Record + // to an actual object :shrugs + res(resp) + } + }) + }) +/** + * + * @param {string} pubkey + * @param {string} host + * @returns + */ +const connectPeer = (pubkey, host) => + Common.makePromise((res, rej) => { + const { lightning } = lightningServices.getServices() + const connectRequest = { + addr: { pubkey, host }, + perm: true + } + lightning.connectPeer(connectRequest, (err, resp) => { + if (err) { + rej(new Error(err.message)) + } else { + // Needs cast because typescript refuses to assign Record + // to an actual object :shrugs + res(resp) + } + }) + }) module.exports = { sendPaymentV2Keysend, sendPaymentV2Invoice, @@ -644,5 +681,7 @@ module.exports = { pendingChannels, addInvoice, subscribeInvoices, - subscribeTransactions + subscribeTransactions, + getInfo, + connectPeer }