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 }