lighstorm 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +5 -0
  3. data/.github/workflows/ruby-rspec-tests.yml +39 -0
  4. data/.gitignore +1 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +10 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +26 -2
  9. data/README.md +30 -371
  10. data/adapters/connections/channel_node/fee.rb +26 -0
  11. data/adapters/connections/channel_node/policy.rb +61 -0
  12. data/adapters/connections/channel_node.rb +74 -0
  13. data/adapters/connections/payment_channel.rb +28 -0
  14. data/adapters/edges/channel.rb +96 -0
  15. data/adapters/edges/forward.rb +40 -0
  16. data/adapters/edges/payment/purpose.rb +32 -0
  17. data/adapters/edges/payment.rb +50 -0
  18. data/adapters/invoice.rb +49 -0
  19. data/adapters/nodes/node.rb +111 -0
  20. data/adapters/payment_request.rb +76 -0
  21. data/components/cache.rb +3 -2
  22. data/components/lnd.rb +5 -1
  23. data/controllers/channel/actions/apply_gossip.rb +194 -0
  24. data/controllers/channel/actions/update_fee.rb +76 -0
  25. data/controllers/channel/all.rb +79 -0
  26. data/controllers/channel/find_by_id.rb +153 -0
  27. data/controllers/channel/mine.rb +114 -0
  28. data/controllers/channel.rb +27 -0
  29. data/controllers/forward/all.rb +244 -0
  30. data/controllers/forward/group_by_channel.rb +89 -0
  31. data/controllers/forward.rb +28 -0
  32. data/controllers/invoice/actions/create.rb +36 -0
  33. data/controllers/invoice/actions/pay.rb +28 -0
  34. data/controllers/invoice/actions/pay_through_route.rb +71 -0
  35. data/controllers/invoice/all.rb +70 -0
  36. data/controllers/invoice/find_by_secret_hash.rb +42 -0
  37. data/controllers/invoice.rb +36 -0
  38. data/controllers/node/actions/apply_gossip.rb +112 -0
  39. data/controllers/node/all.rb +63 -0
  40. data/controllers/node/find_by_public_key.rb +49 -0
  41. data/controllers/node/myself.rb +34 -0
  42. data/controllers/node.rb +27 -0
  43. data/controllers/payment/all.rb +368 -0
  44. data/controllers/payment.rb +21 -0
  45. data/docs/.nojekyll +0 -0
  46. data/docs/README.md +731 -0
  47. data/docs/_coverpage.md +12 -0
  48. data/docs/index.html +26 -0
  49. data/docs/vendor/docsify/docsify@4.js +1 -0
  50. data/docs/vendor/docsify-themeable/theme-simple-dark.css +3 -0
  51. data/docs/vendor/docsify-themeable/theme-simple-dark.css.map +1 -0
  52. data/docs/vendor/prismjs/prism-bash.min.js +1 -0
  53. data/docs/vendor/prismjs/prism-ruby.min.js +1 -0
  54. data/docs/vendor/prismjs/prism-tomorrow.min.css +1 -0
  55. data/lighstorm.gemspec +3 -1
  56. data/models/concerns/protectable.rb +23 -0
  57. data/models/connections/channel_node/accounting.rb +7 -14
  58. data/models/connections/channel_node/fee.rb +55 -84
  59. data/models/connections/channel_node/htlc/blocks/delta.rb +39 -0
  60. data/models/connections/channel_node/htlc.rb +65 -11
  61. data/models/connections/channel_node/policy.rb +15 -18
  62. data/models/connections/channel_node.rb +48 -22
  63. data/models/connections/forward_channel.rb +8 -43
  64. data/models/connections/payment_channel.rb +18 -39
  65. data/models/edges/channel/accounting.rb +45 -20
  66. data/models/edges/channel/hop.rb +65 -0
  67. data/models/edges/channel.rb +111 -169
  68. data/models/edges/forward.rb +9 -119
  69. data/models/edges/groups/{analysis.rb → channel_forwards/analysis.rb} +9 -9
  70. data/models/edges/groups/channel_forwards.rb +10 -40
  71. data/models/edges/payment.rb +29 -215
  72. data/models/errors.rb +32 -0
  73. data/models/invoice.rb +49 -0
  74. data/models/nodes/node/lightning.rb +11 -16
  75. data/models/nodes/node/platform.rb +13 -13
  76. data/models/nodes/node.rb +59 -103
  77. data/models/payment_request.rb +72 -0
  78. data/models/rate.rb +11 -1
  79. data/models/satoshis.rb +5 -6
  80. data/ports/dsl/lighstorm/errors.rb +5 -0
  81. data/ports/dsl/lighstorm.rb +11 -9
  82. data/ports/grpc/session.rb +26 -0
  83. data/ports/grpc.rb +80 -0
  84. data/static/cache.rb +12 -0
  85. data/static/spec.rb +3 -1
  86. metadata +62 -6
  87. data/models/connections/channel_node/constraints.rb +0 -24
data/docs/README.md ADDED
@@ -0,0 +1,731 @@
1
+ > ⚠️ Warning: Early-stage project, breaking changes are expected.
2
+
3
+ # About
4
+
5
+ > Lighstorm: API for interacting with a [Lightning Node](https://lightning.network).
6
+
7
+ _Lighstorm_ is an opinionated abstraction layer on top of the [lnd-client](https://github.com/icebaker/lnd-client).
8
+
9
+ It brings an [object-oriented](https://en.wikipedia.org/wiki/Object-oriented_programming) approach for interacting with a [Lightning Node](https://github.com/lightningnetwork/lnd), influenced by the [Active Record Pattern](https://www.martinfowler.com/eaaCatalog/activeRecord.html) and [Active Record Models](https://guides.rubyonrails.org/active_record_basics.html) conventions.
10
+
11
+ Although it tries to stay close to [Lightning's terminologies](https://docs.lightning.engineering/lightning-network-tools/lnd), it brings its own vocabulary and [data modeling](#data-modeling), optimizing for [programmer happiness](https://rubyonrails.org/doctrine).
12
+
13
+ # Getting Started
14
+
15
+ ![Lighstorm text written stylized with an illustration of a Graph connecting two Nodes.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/lighstorm.png)
16
+
17
+ ```ruby
18
+ Lighstorm::Channel.mine.first.myself.node.alias
19
+ ```
20
+
21
+ ## Installing
22
+
23
+ Add to your `Gemfile`:
24
+
25
+ ```ruby
26
+ gem 'lighstorm', '~> 0.0.5'
27
+ ```
28
+
29
+ Run `bundle install`.
30
+
31
+ ## Credentials
32
+
33
+ Set the following _Environment Variables_ or create a `.env` file:
34
+ ```bash
35
+ LIGHSTORM_LND_ADDRESS=127.0.0.1:10009
36
+ LIGHSTORM_CERTIFICATE_PATH=/lnd/tls.cert
37
+ LIGHSTORM_MACAROON_PATH=/lnd/data/chain/bitcoin/mainnet/admin.macaroon
38
+ ```
39
+
40
+ It will automatically load your credentials.
41
+
42
+ Alternatively, you can set the credentials at runtime:
43
+
44
+ ```ruby
45
+ require 'lighstorm'
46
+
47
+ Lighstorm.config!(
48
+ lnd_address: '127.0.0.1:10009',
49
+ certificate_path: '/lnd/tls.cert',
50
+ macaroon_path: '/lnd/data/chain/bitcoin/mainnet/admin.macaroon',
51
+ )
52
+
53
+ ```
54
+
55
+ ## Examples
56
+ ```ruby
57
+ require 'lighstorm'
58
+
59
+ puts Lighstorm.version # => 0.0.5
60
+
61
+ Lighstorm::Satoshis.new(
62
+ milisatoshis: 75_621_650
63
+ ).satoshis # => 75_621
64
+
65
+ Lighstorm::Node.myself.alias # => icebaker/old-stone
66
+ Lighstorm::Node.myself.public_key # => 02d3...e997
67
+
68
+ Lighstorm::Node.myself.to_h #> { ... }
69
+
70
+ Lighstorm::Node.myself.channels.count # => 5
71
+
72
+ Lighstorm::Channel.mine.first.partner.node.alias
73
+
74
+ forward = Lighstorm::Forward.all(limit: 10).first
75
+
76
+ forward.in.amount.milisatoshis # => 75621650
77
+ forward.in.amount.satoshis # => 75621
78
+ forward.in.amount.bitcoins # => 0.0007562165
79
+ forward.in.channel.partner.node.alias
80
+ forward.out.channel.partner.node.alias
81
+
82
+ forward.to_h # => { ... }
83
+
84
+ payment = Lighstorm::Payment.all.first
85
+
86
+ payment.from.channel.id # => 850099509773795329
87
+ payment.to.channel.id # => 821539695188246532
88
+ payment.amount.sats # => 957262
89
+ payment.hops.size # => 4
90
+ payment.hops.first.channel.partner.node.alias
91
+ ```
92
+
93
+ # Data Modeling
94
+
95
+ ## Graph Theory
96
+
97
+ [Graphs](https://en.wikipedia.org/wiki/Graph_theory) provide a great representation to abstract the [Lightning Network](https://lightning.network) data.
98
+
99
+ So, we are going to think in terms of _Edges_, _Nodes_, and _Connections_:
100
+
101
+ [![This is an image describing Graphs and their terminologies.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-theory.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-theory.png)
102
+ <center style="margin-top: -1.4em;">
103
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-theory.png" rel="noopener noreferrer" target="_blank">
104
+ click to zoom
105
+ </a>
106
+ </center>
107
+
108
+ ## Channel
109
+
110
+ ```ruby
111
+ channel = Lighstorm::Channel.mine.first
112
+
113
+ channel.id
114
+
115
+ channel.accounting.capacity.milisatoshis
116
+
117
+ channel.partner.accounting.balance.milisatoshis
118
+ channel.partner.node.alias
119
+ channel.partner.policy.fee.rate.parts_per_million
120
+
121
+ channel.myself.accounting.balance.milisatoshis
122
+ channel.myself.node.alias
123
+ channel.myself.policy.fee.rate.parts_per_million
124
+ ```
125
+
126
+ [![This is an image representing Channel as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png)
127
+ <center style="margin-top: -1.4em;">
128
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png" rel="noopener noreferrer" target="_blank">
129
+ click to zoom
130
+ </a>
131
+ </center>
132
+
133
+ ## Forward
134
+
135
+ ```ruby
136
+ forward = Lighstorm::Forward.last
137
+
138
+ forward.at
139
+
140
+ forward.fee.milisatoshis
141
+ forward.fee.parts_per_million
142
+
143
+ forward.in.amount.milisatoshis
144
+ forward.out.amount.milisatoshis
145
+
146
+ forward.in.channel.id
147
+ forward.in.channel.partner.node.alias
148
+
149
+ forward.out.channel.id
150
+ forward.out.channel.partner.node.alias
151
+ ```
152
+
153
+ [![This is an image representing Forward as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png)
154
+ <center style="margin-top: -1.4em;">
155
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png" rel="noopener noreferrer" target="_blank">
156
+ click to zoom
157
+ </a>
158
+ </center>
159
+
160
+ ## Payment
161
+
162
+ ```ruby
163
+ payment = Payment.last
164
+
165
+ payment.status
166
+ payment.created_at
167
+
168
+ # https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
169
+ payment.request.code # "lnbc20m1pv...qqdhhwkj"
170
+
171
+ payment.request.amount.milisatoshis
172
+
173
+ payment.from.hop
174
+ payment.from.amount.milisatoshis
175
+ payment.from.fee.milisatoshis
176
+ payment.from.channel.id
177
+ payment.from.channel.target.alias
178
+ payment.from.channel.exit.alias
179
+
180
+ payment.to.hop
181
+ payment.to.amount.milisatoshis
182
+ payment.to.fee.milisatoshis
183
+ payment.to.channel.id
184
+ payment.to.channel.target.alias
185
+
186
+ payment.hops[0].hop
187
+ payment.hops[0].amount.milisatoshis
188
+ payment.hops[0].fee.milisatoshis
189
+ payment.hops[0].channel.id
190
+ payment.hops[0].channel.target.alias
191
+ ```
192
+
193
+ [![This is an image representing Payment as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png)
194
+ <center style="margin-top: -1.4em;">
195
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png" rel="noopener noreferrer" target="_blank">
196
+ click to zoom
197
+ </a>
198
+ </center>
199
+
200
+ # Error Handling
201
+
202
+ ## Rescuing
203
+ ```ruby
204
+ require 'lighstorm'
205
+
206
+ channel = Lighstorm::Channel.mine.first
207
+
208
+ begin
209
+ channel.myself.policy.fee.update(
210
+ { rate: { parts_per_million: -1 } }, preview: true
211
+ )
212
+ rescue Lighstorm::Errors::NegativeNotAllowedError => error
213
+ puts error.message # 'fee rate can't be negative: -1'
214
+ end
215
+
216
+ begin
217
+ channel.myself.policy.fee.update(
218
+ { rate: { parts_per_million: -1 } }, preview: true
219
+ )
220
+ rescue Lighstorm::Errors::LighstormError => error
221
+ puts error.message # 'fee rate can't be negative: -1'
222
+ end
223
+ ```
224
+
225
+ ### For Short
226
+
227
+ ```ruby
228
+ require 'lighstorm'
229
+ require 'lighstorm/errors'
230
+
231
+ channel = Lighstorm::Channel.mine.first
232
+
233
+ begin
234
+ channel.myself.policy.fee.update(
235
+ { rate: { parts_per_million: -1 } }, preview: true
236
+ )
237
+ rescue NegativeNotAllowedError => error
238
+ puts error.message # "fee rate can't be negative: -1"
239
+ end
240
+
241
+ begin
242
+ channel.myself.policy.fee.update(
243
+ { rate: { parts_per_million: -1 } }, preview: true
244
+ )
245
+ rescue LighstormError => error
246
+ puts error.message # "fee rate can't be negative: -1"
247
+ end
248
+ ```
249
+
250
+ ## Errors
251
+ ```ruby
252
+ LighstormError
253
+
254
+ IncoherentGossipError
255
+
256
+ TooManyArgumentsError
257
+ MissingCredentialsError
258
+ MissingGossipHandlerError
259
+ MissingMilisatoshisError
260
+ MissingPartsPerMillionError
261
+ MissingTTLError
262
+
263
+ NegativeNotAllowedError
264
+
265
+ NotYourChannelError
266
+ NotYourNodeError
267
+ UnknownChannelError
268
+
269
+ OperationNotAllowedError
270
+ UnexpectedNumberOfHTLCsError
271
+ UpdateChannelPolicyError
272
+ ```
273
+
274
+ # API
275
+
276
+ ## Node
277
+ ```ruby
278
+ Lighstorm::Node
279
+
280
+ Lighstorm::Node.myself # Your Node.
281
+ Lighstorm::Node.all # All 18k+ Nodes on the Network.
282
+ Lighstorm::Node.all(limit: 10)
283
+ Lighstorm::Node.find_by_public_key(
284
+ '02d3c80335a8ccb2ed364c06875f32240f36f7edb37d80f8dbe321b4c364b6e997'
285
+ )
286
+
287
+ # _key is helpful for reactive javascript frameworks.
288
+ # Please don't consider it as a unique identifier
289
+ # for the item. Instead, use it as a volatile key for
290
+ # the item's current state that may change at any moment.
291
+ node._key
292
+
293
+ node.to_h
294
+
295
+ node.channels
296
+
297
+ node.alias
298
+ node.public_key
299
+ node.color
300
+ node.myself?
301
+
302
+ node.platform.blockchain
303
+ node.platform.network
304
+ node.platform.lightning.implementation
305
+ node.platform.lightning.version
306
+ ```
307
+
308
+ ## Channel
309
+
310
+ [![This is an image representing Channel as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png)
311
+ <center style="margin-top: -1.4em;">
312
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-channel.png" rel="noopener noreferrer" target="_blank">
313
+ click to zoom
314
+ </a>
315
+ </center>
316
+
317
+ ```ruby
318
+ Lighstorm::Channel
319
+ Lighstorm::Channel.mine # Your Node's Channels.
320
+ Lighstorm::Channel.all # All 80k+ Channels on the Network.
321
+ Lighstorm::Channel.all(limit: 10)
322
+ Lighstorm::Channel.find_by_id('850099509773795329')
323
+
324
+ # _key is helpful for reactive javascript frameworks.
325
+ # Please don't consider it as a unique identifier
326
+ # for the item. Instead, use it as a volatile key for
327
+ # the item's current state that may change at any moment.
328
+ channel._key
329
+
330
+ channel.to_h
331
+
332
+ channel.mine?
333
+
334
+ channel.id
335
+ channel.opened_at
336
+ channel.up_at
337
+ channel.state
338
+ channel.active?
339
+ channel.exposure
340
+
341
+ channel.accounting.capacity.milisatoshis
342
+ channel.accounting.sent.milisatoshis
343
+ channel.accounting.received.milisatoshis
344
+ channel.accounting.unsettled.milisatoshis
345
+
346
+ # Channels that don't belong to you:
347
+ channel.partners
348
+
349
+ channel.partners[0]
350
+ channel.partners[0].node.alias
351
+
352
+ channel.partners[1]
353
+ channel.partners[1].node.alias
354
+
355
+ # Channels that belong to you:
356
+ channel.transaction.funding.id
357
+ channel.transaction.funding.index
358
+
359
+ channel.partner
360
+ channel.partner.state
361
+ channel.partner.active?
362
+
363
+ channel.partner.node.public_key
364
+ channel.partner.node.alias
365
+ channel.partner.node.color
366
+
367
+ channel.partner.accounting.balance.milisatoshis
368
+
369
+ channel.partner.policy.fee.base.milisatoshis
370
+ channel.partner.policy.fee.rate.parts_per_million
371
+
372
+ channel.partner.policy.htlc.minimum.milisatoshis
373
+ channel.partner.policy.htlc.maximum.milisatoshis
374
+ channel.partner.policy.htlc.blocks.delta.minimum
375
+
376
+ channel.myself
377
+ channel.myself.state
378
+ channel.myself.active?
379
+
380
+ channel.myself.node.public_key
381
+ channel.myself.node.alias
382
+ channel.myself.node.color
383
+
384
+ channel.myself.accounting.balance.milisatoshis
385
+
386
+ channel.myself.policy.fee.base.milisatoshis
387
+ channel.myself.policy.fee.rate.parts_per_million
388
+
389
+ channel.myself.policy.htlc.minimum.milisatoshis
390
+ channel.myself.policy.htlc.maximum.milisatoshis
391
+ channel.myself.policy.htlc.blocks.delta.minimum
392
+ ```
393
+
394
+ ### Operations
395
+
396
+ ```ruby
397
+ channel = Lighstorm::Channel.mine.first
398
+
399
+ channel.myself.policy.fee.update(
400
+ { rate: { parts_per_million: 25 } }, preview: true
401
+ )
402
+
403
+ channel.myself.policy.fee.update(
404
+ { base: { milisatoshis: 1 } }
405
+ )
406
+
407
+ channel.myself.policy.fee.update(
408
+ { rate: { parts_per_million: 25 } }
409
+ )
410
+
411
+ channel.myself.policy.fee.update(
412
+ { base: { milisatoshis: 1 }, rate: { parts_per_million: 25 } }
413
+ )
414
+ ```
415
+
416
+ ## Invoice
417
+
418
+ ```ruby
419
+ Lighstorm::Invoice
420
+ Lighstorm::Invoice.all
421
+ Lighstorm::Invoice.all(limit: 10)
422
+ Lighstorm::Invoice.first
423
+ Lighstorm::Invoice.last
424
+
425
+ Lighstorm::Invoice.find_by_secret_hash(
426
+ '1d438b8100518c9fba0a607e3317d6b36f74ceef3a6591836eb2f679c6853501'
427
+ )
428
+
429
+ # _key is helpful for reactive javascript frameworks.
430
+ # Please don't consider it as a unique identifier
431
+ # for the item. Instead, use it as a volatile key for
432
+ # the item's current state that may change at any moment.
433
+ invoice._key
434
+
435
+ invoice.created_at
436
+ invoice.settle_at
437
+
438
+ invoice.state
439
+
440
+ # https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
441
+ invoice.request.code # "lnbc20m1pv...qqdhhwkj"
442
+
443
+ invoice.request.amount.milisatoshis
444
+
445
+ invoice.request.description.memo
446
+ invoice.request.description.hash
447
+
448
+ # https://docs.lightning.engineering/the-lightning-network/multihop-payments
449
+ invoice.request.secret.preimage
450
+ invoice.request.secret.hash
451
+
452
+ invoice.request.address
453
+ ```
454
+
455
+ ## Payment
456
+
457
+ [![This is an image representing Payment as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png)
458
+ <center style="margin-top: -1.4em;">
459
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-payment.png" rel="noopener noreferrer" target="_blank">
460
+ click to zoom
461
+ </a>
462
+ </center>
463
+
464
+ ```ruby
465
+ Lighstorm::Payment
466
+ Lighstorm::Payment.all
467
+ Lighstorm::Payment.first
468
+ Lighstorm::Payment.last
469
+ Lighstorm::Payment.all(limit: 10, purpose: 'rebalance')
470
+
471
+ # Possible Purposes:
472
+ ['self-payment', 'peer-to-peer', 'rebalance', 'payment']
473
+
474
+ # _key is helpful for reactive javascript frameworks.
475
+ # Please don't consider it as a unique identifier
476
+ # for the item. Instead, use it as a volatile key for
477
+ # the item's current state that may change at any moment.
478
+ payment._key
479
+
480
+ payment.to_h
481
+
482
+ payment.status
483
+ payment.created_at
484
+ payment.settled_at
485
+ payment.purpose
486
+
487
+ payment.fee.milisatoshis
488
+ payment.fee.parts_per_million(
489
+ payment.request.amount.milisatoshis
490
+ )
491
+
492
+ # https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
493
+ payment.request.code # "lnbc20m1pv...qqdhhwkj"
494
+
495
+ payment.request.amount.milisatoshis
496
+
497
+ # https://docs.lightning.engineering/the-lightning-network/multihop-payments
498
+ payment.request.secret.preimage
499
+ payment.request.secret.hash
500
+
501
+ payment.request.address
502
+
503
+ payment.request.description.memo
504
+ payment.request.description.hash
505
+
506
+ payment.from.hop
507
+ payment.from.amount.milisatoshis
508
+ payment.from.fee.milisatoshis
509
+ payment.from.fee.parts_per_million(payment.from.amount.milisatoshis)
510
+
511
+ payment.from.channel.id
512
+
513
+ payment.from.channel.target.public_key
514
+ payment.from.channel.target.alias
515
+ payment.from.channel.target.color
516
+
517
+ payment.from.channel.exit.public_key
518
+ payment.from.channel.exit.alias
519
+ payment.from.channel.exit.color
520
+
521
+ payment.to.hop
522
+ payment.to.amount.milisatoshis
523
+ payment.to.fee.milisatoshis
524
+ payment.to.fee.parts_per_million(payment.to.amount.milisatoshis)
525
+
526
+ payment.to.channel.id
527
+
528
+ payment.to.channel.target.public_key
529
+ payment.to.channel.target.alias
530
+ payment.to.channel.target.color
531
+
532
+ payment.to.channel.entry.public_key
533
+ payment.to.channel.entry.alias
534
+ payment.to.channel.entry.color
535
+
536
+ payment.hops.size
537
+
538
+ payment.hops[0].first?
539
+ payment.hops[0].last?
540
+
541
+ payment.hops[0].hop
542
+ payment.hops[0].amount.milisatoshis
543
+ payment.hops[0].fee.milisatoshis
544
+ payment.hops[0].fee.parts_per_million(payment.hops[0].amount.milisatoshis)
545
+
546
+ payment.hops[0].channel.id
547
+
548
+ payment.hops[0].channel.target.public_key
549
+ payment.hops[0].channel.target.alias
550
+ payment.hops[0].channel.target.color
551
+
552
+ payment.hops[0].channel.entry.public_key
553
+ payment.hops[0].channel.entry.alias
554
+ payment.hops[0].channel.entry.color
555
+ ```
556
+ ### Performance
557
+ Avoid fetching data that you don't need:
558
+ ```ruby
559
+ Lighstorm::Payment.all(
560
+ fetch: {
561
+ get_node_info: false,
562
+ lookup_invoice: false,
563
+ decode_pay_req: false,
564
+ get_chan_info: false }
565
+ )
566
+ ```
567
+
568
+ ## Forward
569
+
570
+ [![This is an image representing Forward as a graph.](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png)](https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png)
571
+ <center style="margin-top: -1.4em;">
572
+ <a href="https://raw.githubusercontent.com/icebaker/assets/main/lighstorm/graph-forward.png" rel="noopener noreferrer" target="_blank">
573
+ click to zoom
574
+ </a>
575
+ </center>
576
+
577
+ ```ruby
578
+ Lighstorm::Forward
579
+ Lighstorm::Forward.all
580
+ Lighstorm::Forward.first
581
+ Lighstorm::Forward.last
582
+ Lighstorm::Forward.all(limit: 10)
583
+
584
+ forward.to_h
585
+
586
+ # _key is helpful for reactive javascript frameworks.
587
+ # Please don't consider it as a unique identifier
588
+ # for the item. Instead, use it as a volatile key for
589
+ # the item's current state that may change at any moment.
590
+ forward._key
591
+
592
+ forward.at
593
+
594
+ forward.fee.milisatoshis
595
+ forward.fee.parts_per_million(
596
+ forward.in.amount.milisatoshis
597
+ )
598
+
599
+ forward.in.amount.milisatoshis
600
+
601
+ forward.in.channel.id
602
+ forward.in.channel.partner.node.alias
603
+ forward.in.channel.partner.node.public_key
604
+ forward.in.channel.partner.node.color
605
+
606
+ forward.out.amount.milisatoshis
607
+
608
+ forward.out.channel.id
609
+ forward.out.channel.partner.node.alias
610
+ forward.out.channel.partner.node.public_key
611
+ forward.out.channel.partner.node.color
612
+ ```
613
+
614
+ ### Grouping
615
+
616
+ ```ruby
617
+ Lighstorm::Forward.group_by_channel(direction: :in, hours_ago: 24, limit: 5)
618
+
619
+ group.to_h
620
+
621
+ # _key is helpful for reactive javascript frameworks.
622
+ # Please don't consider it as a unique identifier
623
+ # for the item. Instead, use it as a volatile key for
624
+ # the item's current state that may change at any moment.
625
+ group._key
626
+
627
+ group.last_at
628
+ group.analysis.count
629
+ group.analysis.sums.amount.milisatoshis
630
+ group.analysis.sums.fee.milisatoshis
631
+ group.analysis.averages.amount.milisatoshis
632
+ group.analysis.averages.fee.milisatoshis
633
+ group.analysis.averages.fee.parts_per_million(
634
+ group.analysis.averages.amount.milisatoshis
635
+ )
636
+
637
+ group.channel.id
638
+ group.channel.partner.node.alias
639
+ group.channel.partner.node.public_key
640
+ group.channel.partner.node.color
641
+
642
+ Lighstorm::Forward.group_by_channel(direction: :out)
643
+
644
+ group.to_h
645
+
646
+ group.last_at
647
+ group.analysis.count
648
+
649
+ group.channel.id
650
+ group.channel.partner.node.alias
651
+ group.channel.partner.node.public_key
652
+ group.channel.partner.node.color
653
+ ```
654
+
655
+ ## Gossip
656
+
657
+ [The Gossip Network](https://docs.lightning.engineering/the-lightning-network/the-gossip-network)
658
+
659
+ ### Node
660
+
661
+ ```ruby
662
+ gossip = {
663
+ 'identityKey' => '02d3c80335a8ccb2ed364c06875f32240f36f7edb37d80f8dbe321b4c364b6e997',
664
+ 'alias' => 'icebaker',
665
+ 'color' => '#eb34a4'
666
+ }
667
+
668
+ Lighstorm::Node.adapt(gossip: gossip)
669
+
670
+ node = Lighstorm::Node.find_by_public_key(
671
+ '02d3c80335a8ccb2ed364c06875f32240f36f7edb37d80f8dbe321b4c364b6e997'
672
+ )
673
+
674
+ diff = node.apply!(gossip: gossip)
675
+
676
+ Lighstorm::Node.adapt(dump: node.dump)
677
+ ```
678
+
679
+ ### Channel
680
+
681
+ ```ruby
682
+ gossip = {
683
+ 'chanId' => '850099509773795329',
684
+ 'capacity' => '5000000',
685
+ 'routingPolicy' => {
686
+ 'timeLockDelta' => 144,
687
+ 'minHtlc' => '1000',
688
+ 'feeBaseMsat' => '1000',
689
+ 'feeRateMilliMsat' => '300',
690
+ 'maxHtlcMsat' => '4950000000'
691
+ },
692
+ 'advertisingNode' => '02d3c80335a8ccb2ed364c06875f32240f36f7edb37d80f8dbe321b4c364b6e997'
693
+ }
694
+
695
+ Lighstorm::Channel.adapt(gossip: gossip)
696
+
697
+ channel = Lighstorm::Channel.find_by_id('850099509773795329')
698
+
699
+ diff = channel.apply!(gossip: gossip)
700
+
701
+ Lighstorm::Channel.adapt(dump: channel.dump)
702
+ ```
703
+
704
+ ## Satoshis
705
+
706
+ ```ruby
707
+ Lighstorm::Satoshis
708
+ Lighstorm::Satoshis.new(milisatoshis: 75_621_650)
709
+
710
+ satoshis.to_h
711
+
712
+ satoshis.milisatoshis
713
+ satoshis.satoshis
714
+ satoshis.bitcoins
715
+
716
+ satoshis.msats
717
+ satoshis.sats
718
+ satoshis.btc
719
+
720
+ reference_in_milisatoshis = 75_621_650_000
721
+ satoshis.parts_per_million(reference_in_milisatoshis)
722
+ ```
723
+ _________________
724
+
725
+ <center>
726
+ lighstorm 0.0.5
727
+ |
728
+ <a href="https://github.com/icebaker/lighstorm" rel="noopener noreferrer" target="_blank">GitHub</a>
729
+ |
730
+ <a href="https://rubygems.org/gems/lighstorm" rel="noopener noreferrer" target="_blank">RubyGems</a>
731
+ </center>