/ src / components / Lightning.vue
Lightning.vue
  1  <template lang='pug'>
  2  
  3  #nodes
  4      div node stuff
  5      .breathing
  6      .boxy(v-if='$store.state.cash.info.id')
  7          div {{ $store.state.cash.info.alias}} 
  8          .nodeaddress {{ $store.state.cash.info.id }}
  9          span @{{ $store.state.cash.info.address }}    
 10          button.ptr(@click='clicktopay') deposit
 11      .price(v-if='sats > 0') 1 CAD = {{ sats }} sats
 12      .price(v-else) 1 Bitcoin = 100 000 000 sats
 13      .flexrow
 14          .third 
 15              block-info
 16          .twothirds.boxy(v-if='$store.state.cash.info.channels')
 17              .section(v-if='$store.state.cash.info.id') {{ $store.state.cash.info.channels.length }} &#9889;channels
 18                  div(v-if='Math.abs($store.state.cash.info.lightningblocks - $store.state.cash.info.bitcoinblocks) > 1') warning: desync detected
 19              .row.channellimiter
 20                  .chanfo(v-if='selectedPeer < 0') pubkey: {{ $store.state.cash.info.id }}
 21                  .ptr(v-for='(n, i) in $store.state.cash.info.channels' :key='n.peer_id')
 22                      .localremote.bordy(v-show='selectedPeer === i'   @click='selectedPeer = false')
 23                          .localbar.tall(:style='l(n)'  :class='{abnormal:n.state !== "CHANNELD_NORMAL"}')  {{ (n.amount_msat ).toLocaleString() }}
 24                          .remotebar.tall(:style='r(n)'  :class='{abnormal:n.state !== "CHANNELD_NORMAL"}')  {{ ( n.amount_msat - n.our_amount_msat ).toLocaleString() }}
 25                      .localremote(v-show='selectedPeer !== i'   @click='selectPeer(i)')
 26                          .localbar(:style='l(n, true)' :class='{abnormal:n.state !== "CHANNELD_NORMAL"}')
 27                          .remotebar(:style='r(n, true)'  :class='{abnormal:n.state !== "CHANNELD_NORMAL"}')
 28      .chanfo(v-if='selectedPeer >= 0 && areChannels && selectedChannel')
 29          label Channel Info: 
 30          div nodeid: {{ fetchedPeer.nodeid }}
 31          div alias: {{fetchedPeer.alias}}
 32          div(@click='checkTxid(selectedChannel.funding_txid)') txid: {{ selectedChannel.funding_txid }}
 33          div(v-if='selectedChannel.state !== "CHANNELD_NORMAL"') state: {{ selectedChannel.state }}
 34          div in: {{ fetchedPeer.channel.in_payments_fulfilled }} / {{ fetchedPeer.channel.in_payments_offered }} out: {{ fetchedPeer.channel.out_payments_fulfilled }} / {{ fetchedPeer.channel.out_payments_offered }}
 35      // input(v-model='txnCheck'  type='text'  placeholder='check txid'  @keypress.enter='checkTxid(txnCheck)')
 36      // button(v-if='txnCheck'  @click='checkTxid(txnCheck)') get transaction
 37  </template>
 38  
 39  <script>
 40  
 41  import calculations from '../calculations'
 42  import request from 'superagent'
 43  import BlockInfo from './BlockInfo.vue'
 44  export default {
 45      components: { BlockInfo },
 46      data(){
 47          return {
 48              showOutputs: false,
 49              fetchedTxn: {},
 50              fetchedPeer: {},
 51              txnCheck: '',
 52              selectedPeer: false,
 53              open: false,
 54              sampleIndex: 0,
 55          }
 56      },
 57      computed: {
 58          confirmedBalance(){
 59            let cb = 0
 60            this.$store.state.cash.info.outputs.forEach(o => {
 61                if (o.status === "confirmed"){
 62                    cb += o.value
 63                }
 64            })
 65            return cb
 66          },
 67          selectedChannel(){
 68              return this.$store.state.cash.info.channels[this.selectedPeer]
 69          },
 70          filteredOut(){
 71              if (this.fetchedTxn.utxo){
 72                  let unspents = this.fetchedTxn.utxo.filter(x => x !== null).map(x => x.txid)
 73                  return this.fetchedTxn.vout.filter( y => {
 74                      return unspents.indexOf(y.txid) === -1
 75                  })
 76              } else {
 77                  return this.fetchedTxn.vout.filter(() => true)
 78              }
 79          },
 80          fetchedTxnStatus(){
 81              if (this.fetchedTxn.memPool){
 82                  return 'unconfirmed'
 83              }
 84              if (this.fetchedTxn.utxo){
 85                  return 'confirmed, unspent'
 86              }
 87              return 'confirmed, spent'
 88          },
 89          areChannels(){
 90              return this.$store.state.cash.info.channels
 91          },
 92          sats(){
 93              return calculations.cadToSats(1, this.$store.state.cash.spot)
 94          },
 95          nn(){
 96              let totals = {
 97                  channel_sat: 0,
 98                  channel_total_sat: 0,
 99              }
100              this.$store.state.cash.info.channels.forEach(n => {
101                  if (n.state === "CHANNELD_NORMAL"){
102                      totals.channel_sat += n.our_amount_msat
103                      totals.channel_total_sat += n.amount_msat
104                  }
105              })
106              if (totals.channel_sat + totals.channel_total_sat === 0){
107                  totals.channel_sat = 0
108                  totals.channel_total_sat = 0
109              }
110              return totals
111          }
112      },
113      methods:{
114          clicktopay(){
115              this.$store.commit("toggleNodeInfo")
116              this.$store.commit("setMode", 3)
117              this.$store.commit("setPayMode", 0)
118              if (!this.$store.getters.contextCard.btcAddr){
119                  this.$store.dispatch("makeEvent", {
120                    type: 'address-updated',
121                    taskId: this.$store.getters.contextCard.taskId
122                  })
123  
124              }
125          },
126          checkPeer(x){
127              request
128                  .post('/lightning/peer')
129                  .send({pubkey: x})
130                  .set("Authorization", this.$store.state.loader.token)
131                  .end( (err, res) => {
132                      if (!err) {
133                          this.fetchedPeer = res.body
134                      }
135                  })
136          },
137          checkTxid(x){
138              request
139                  .post('/bitcoin/transaction')
140                  .send({txid : x})
141                  .set("Authorization", this.$store.state.loader.token)
142                  .end((err, res)=>{
143                      if (!err){
144                          this.fetchedTxn = res.body
145                      }
146                  })
147              this.txnCheck = ''
148          },
149          selectPeer(pId){
150              if (pId === this.selectedPeer){
151                  return this.selectedPeer = false
152              }
153              this.selectedPeer = pId
154              this.checkPeer(this.selectedChannel.peer_id)
155          },
156          r(n, nolimits){
157              let local =  n.our_amount_msat 
158  
159              let remote = n.amount_msat - n.our_amount_msat 
160  
161              let capacity = local + remote
162              let remotePercent =  remote / capacity
163  
164              if (!nolimits && remotePercent < 0.2 && remotePercent > 0) {
165                  remotePercent = 0.2
166              }
167              if (!nolimits && remotePercent < 1 && remotePercent > 0.8) {
168                  remotePercent = 0.8
169              }
170  
171              let w = (remotePercent * 100).toFixed(7) + "%"
172              return {
173                  width: w
174              }
175          },
176          l(n, nolimits){
177            let local = n.our_amount_msat 
178            let remote = n.amount_msat - local 
179  
180            let capacity = local + remote
181            let localPercent =  n.channel_sat / capacity
182  
183            if (!nolimits && localPercent > 0.8 && localPercent < 1) {
184                localPercent = 0.8
185            }
186            if (!nolimits && localPercent > 0 && localPercent < 0.2) {
187                localPercent = 0.2
188            }
189            let w = (localPercent * 100).toFixed(7) + "%"
190            return {
191                width: w
192            }
193          },
194      }
195  }
196  </script>
197  
198  <style lang='stylus' scoped>
199  
200  @import '../styles/colours'
201  @import '../styles/button'
202  @import '../styles/input'
203  .flexrow
204      display: flex 
205  
206  .third 
207      flex: 1 1 auto
208  .twothirds
209      flex: 4 4 auto
210  .price 
211      text-align: center
212      padding-bottom: .9em
213  
214  .nodeaddress
215      line-break: anywhere
216  
217  .boxy
218      box-shadow: 0 3px 10px rgb(0 0 0 / 0.2)
219      padding: .378em
220      margin-bottom: 1em
221  
222  .bordy
223      margin-top:0.2em
224      margin-left: 0.25em
225  
226  .fr
227      float: right
228  
229  .bg
230      background: lightGrey
231      padding: 0.33em
232      border-radius: 3%
233  
234  .section
235      color:main
236      font-size: 0.9em
237      margin-bottom: .9em
238      text-align: left
239  
240  .chanfo
241      word-break: break-all
242      overflow-wrap: break-word;
243      text-align: left
244  .ptr
245      cursor: pointer
246  
247  .localbar.tall
248      height: 2em
249  .remotebar.tall
250      height: 2em
251  
252  #nodes
253      overflow-y: scroll;
254      max-height: 100vh;
255      position: relative;
256      right: 0;
257      margin-bottom: 5em;
258      bottom: 0;
259      background-color: rgba(228,241,242,.667);
260      padding: 2em;
261  
262  .inactive
263      opacity: 0.3456
264  
265  .center
266      text-align: center
267      word-break: break-all
268      overflow-wrap: break-word;
269      font-size: 0.5em
270  
271  .center.nowx
272      margin-top: 0.3em
273      margin-bottom: 0.3em
274      height: 2em
275  
276  .fw
277      width: 100%
278  
279  .container
280      content-align: center
281  
282  h3
283      text-align: center
284  
285  a
286      color: purple
287  
288  h1
289      text-align: center
290  
291  .h
292      height: 2em
293  
294  label
295      word-break: break-all
296  
297  .break
298      overflow-wrap: break-word;
299  
300  #worf
301      height: 23em
302  
303  #palm
304      width:110%
305  
306  .setupyourown
307      margin-top: 2.2345em
308      padding: 2em
309      color: purple
310      font-size: 1.12em
311  
312  .small
313      font-size: .68em
314      word-break: break-all
315  
316  p
317      text-align: center
318  
319  .fl
320      float: left
321  .fr
322      float: right
323  
324  .local
325      margin: 0 0 .1em 0
326      background: lightGrey
327      padding: 1em
328      text-align: center
329  
330  .remote
331      margin: 0 0 .1em 0
332      background: none
333      text-align: right
334      padding: 1em
335      text-align: center
336  
337  .chain
338      // height: 1.7em
339      // margin: 0
340      // text-align: center
341      // position: relative
342      // padding-top: 0.6em
343      // opacity: 0.8
344  
345  .outputs
346    cursor: pointer
347  
348  .break
349      overflow-wrap: break-word;
350  
351  #worf
352      float: right
353  
354  .lim
355    color: black
356  
357  .block
358      float: right
359      font-size: .77em
360  
361  h5
362      text-align: center
363      color: lightGrey
364      opacity: 0.77
365  
366  .bdoge
367      width: 100%
368      opacity: 0.77
369      height: 5em
370      margin-top: 1em
371  
372  .localremote
373      width: 100%
374      height: 0.622em
375  
376  .localbar
377      height: 0.622em
378      float: left
379      outline-right: solid
380      background: linear-gradient(to right, wrexno 0%, wrexno 98.1337%, black 98.1337%, black)
381      padding-top: 0.23em
382  
383  
384  .localbar.abnormal
385      background: red
386  
387  .remotebar
388      height: 0.622em
389      float: right
390      padding-top: 0.23em
391  .remotebar.abnormal
392      background: red
393  
394  .breathing
395      height: 3.5em
396  
397  .breathing1
398      height: 1.35em
399  .spacer
400      padding-top: 3.21em
401      margin-bottom: .7654321em
402  .sampler
403      cursor: pointer
404  .channellimiter
405      max-height: 13em
406      overflow-y: scroll;
407  </style>
408