/ src / server / lightning.js
lightning.js
  1  import chalk from 'chalk'
  2  import express from 'express'
  3  import bitcoin from 'bitcoin'
  4  
  5  import { config } from './configParser.js'
  6  import allEvents from './events.js'
  7  import LightningClient from './lightning-client.js'
  8  import state from './state.js'
  9  const { serverState } = state
 10  
 11  
 12  //const lightningRouter = express.Router()
 13  
 14  let client = {}
 15  let bitClient = {}
 16  
 17  var nodeInfo = { 
 18      id: '',
 19      alias: '',
 20      address: [],
 21      bitcoinblocks: 0,
 22      lightningblocks: 0,
 23      initialblockdownload: true, 
 24      verificationprogress: null,
 25      channels: [],
 26      outputs: [],
 27      smartfee: 0,
 28      feepercentiles: []
 29  }
 30  
 31  const initClient = async (config) => {
 32      client = new LightningClient(config.lightningdir, true);
 33      //bitClient = new bitcoin.Client({
 34      //    host: 'localhost',
 35      //    user: 'ao',
 36      //    pass: config.bitcoinrpcpass 
 37      //}) 
 38      bitClient = new bitcoin.Client({
 39          host: '192.168.1.23',
 40          user: 'zen',
 41          pass: config.bitcoinrpcpass 
 42      }) 
 43  
 44      bitClient.getBlockchainInfo(async (err, res) => {
 45          if (!err) {
 46              let x = res
 47              if (x.initialblockdownload){
 48                  console.log('Initial bitcoin sync detected', chalk.red((100 * x.verificationprogress).toFixed(2)), '% complete')
 49                  nodeInfo.initialblockdownload = x.initialblockdownload
 50                  nodeInfo.verificationprogress = x.verificationprogress
 51              } else {
 52                  let sats = 100000000
 53                  let halving = 210000
 54                  let supply = 0
 55                  let blocks = x.blocks
 56                  let reward = 50
 57                  while(blocks > halving){
 58                      supply += halving * reward
 59                      reward /= 2
 60                      blocks -= halving
 61                  }
 62                  supply += reward * blocks
 63                  console.log(
 64                      chalk.bold.yellow('bitcoind verified\n'),
 65                      chalk.bold.yellow( (supply * sats).toLocaleString(), 'total sats \n'),
 66                      chalk.bold.cyan('block reward of', (reward * sats).toLocaleString(), '\n'),
 67                      chalk.bold.green('halving in', Math.round((halving - blocks) * 10 / 60 / 24).toString() , 'days')
 68                  )
 69              }
 70          } else {
 71              console.log(chalk.bold.red('bitcoind error', err))
 72          }
 73      })
 74  }
 75  
 76  
 77  function getDecode (rawx){
 78      return bitClient.getRawTransaction(rawx)
 79          .then((rawTransaction) => {
 80                return bitClient.decodeRawTransaction(rawTransaction)
 81          })
 82          .catch(err => {})
 83  }
 84  function peerInfo(){
 85      return {
 86          nodeid:'',
 87          alias: '',
 88          channel: null,
 89          address:''
 90      }
 91  }
 92  
 93  function createInvoice(sat, label, description, expiresInSec){
 94      let numSat = Number(sat)
 95      let msat
 96      if (numSat > 0){
 97          msat = numSat * 1000
 98      } else {
 99          msat = "any"
100      }
101      let objj = {
102          amount_msat: msat, 
103          label, 
104          description, 
105          expiry: expiresInSec    
106      }
107      return client.invoice(objj)
108  }
109  
110  function newAddress(){
111      return client.newaddr()
112  }
113  
114  function updateAll(){
115      checkFunds()
116      checkLightning()
117      checkBitcoin()
118  }
119  
120  function watchOnChain(){
121      setInterval(updateAll, 1000 * 60 * 60)
122      setTimeout( () => {
123          updateAll()
124      }, 560)
125  }
126  
127  function checkFunds(){
128      return client
129          .listfunds()
130          .then(result => {
131              nodeInfo.channels = result.channels
132              nodeInfo.outputs = result.outputs
133  
134              try {
135                  result.outputs.forEach( o => {
136                      if (o.status === 'confirmed' && serverState.cash.usedTxIds.indexOf(o.txid) === -1){
137                          serverState.tasks.forEach( t => {
138                              if (t.btcAddr === o.address){
139                                  allEvents.taskBoosted(t.taskId, o.value, o.txid)
140                              }
141                          })
142                      }
143                  })
144              } catch (err) {console.log("lighting error; lightningd not running?")}
145          })
146          .catch(err => {})
147  }
148  
149  function stormWallet(){
150      return client.stormwallet()
151          .then(sw => {
152              console.log (
153                  chalk.bold.blue('storm active')
154              )
155          })
156          .catch(e => console.log('no storm') )
157  }
158  
159  function checkLightning(){
160  	client.listfunds().then(funds => {
161  		return client
162  			.getinfo()
163  			.then(mainInfo => {
164  				nodeInfo.alias = mainInfo.alias
165  				nodeInfo.id = mainInfo.id
166  				nodeInfo.lightningblocks = mainInfo.blockheight
167  				nodeInfo.address = mainInfo.address[0].address
168  				allEvents.getNodeInfo({...mainInfo, ...funds, ...nodeInfo})
169  			}).catch(e => console.log("catch checklightning", e))
170  	})
171  }
172  
173  function checkBitcoin(){
174      bitClient.getBlockchainInfo(async (err, res) => {
175          if (!err) {
176              let x = res
177              nodeInfo.bitcoinblocks = x.blocks
178              nodeInfo.initialblockdownload = x.initialblockdownload
179              nodeInfo.verificationprogress = x.verificationprogress
180              return bitClient.cmd('getblockstats', nodeInfo.bitcoinblocks, ["feerate_percentiles"], async (err, res) => {
181  		if (!err) {
182  		    let blockfo = res
183                      nodeInfo.feepercentiles = blockfo.feerate_percentiles
184                      bitClient.cmd('estimatesmartfee', 5, async (err, res) => {
185  			if (!err) {
186                              nodeInfo.smartfee = res.feerate
187  			}
188                      })
189  		}
190  	    })
191          } else {
192              console.log(chalk.bold.red('bitcoind error', err))
193          }
194      })
195  }
196  
197  function recordEveryInvoice(start){
198      client.waitanyinvoice({
199              "lastpay_index": start
200          })
201          .then(invoice => {
202              serverState.tasks.forEach( t => {
203                  if (t.payment_hash === invoice.payment_hash){
204                      allEvents.taskBoostedLightning(t.taskId, invoice.amount_msat / 1000, invoice.payment_hash, invoice.pay_index)
205                  }
206              })
207              recordEveryInvoice(start + 1) 
208          })
209          .catch(err => {})
210  }
211  
212  export default {
213      initClient,
214      stormWallet,
215      createInvoice,
216      newAddress,
217      recordEveryInvoice,
218      watchOnChain,
219  }