lighstorm 0.0.2 → 0.0.4

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +5 -0
  3. data/.gitignore +1 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +10 -0
  6. data/Gemfile +5 -1
  7. data/Gemfile.lock +32 -8
  8. data/README.md +30 -341
  9. data/adapters/connections/channel_node/fee.rb +26 -0
  10. data/adapters/connections/channel_node.rb +52 -0
  11. data/adapters/connections/payment_channel.rb +28 -0
  12. data/adapters/edges/channel.rb +80 -0
  13. data/adapters/edges/forward.rb +41 -0
  14. data/adapters/edges/payment/purpose.rb +34 -0
  15. data/adapters/edges/payment.rb +53 -0
  16. data/adapters/invoice.rb +50 -0
  17. data/adapters/nodes/node.rb +77 -0
  18. data/adapters/payment_request.rb +77 -0
  19. data/components/cache.rb +3 -2
  20. data/components/lnd.rb +5 -1
  21. data/controllers/channel/actions/update_fee.rb +76 -0
  22. data/controllers/channel/all.rb +79 -0
  23. data/controllers/channel/find_by_id.rb +153 -0
  24. data/controllers/channel/mine.rb +114 -0
  25. data/controllers/channel.rb +23 -0
  26. data/controllers/forward/all.rb +244 -0
  27. data/controllers/forward/group_by_channel.rb +89 -0
  28. data/controllers/forward.rb +28 -0
  29. data/controllers/invoice/actions/create.rb +36 -0
  30. data/controllers/invoice/actions/pay.rb +28 -0
  31. data/controllers/invoice/actions/pay_through_route.rb +71 -0
  32. data/controllers/invoice/all.rb +70 -0
  33. data/controllers/invoice/find_by_secret_hash.rb +42 -0
  34. data/controllers/invoice.rb +36 -0
  35. data/controllers/node/all.rb +63 -0
  36. data/controllers/node/find_by_public_key.rb +49 -0
  37. data/controllers/node/myself.rb +34 -0
  38. data/controllers/node.rb +23 -0
  39. data/controllers/payment/all.rb +352 -0
  40. data/controllers/payment.rb +21 -0
  41. data/docs/.nojekyll +0 -0
  42. data/docs/README.md +655 -0
  43. data/docs/_coverpage.md +12 -0
  44. data/docs/index.html +26 -0
  45. data/docs/vendor/docsify/docsify@4.js +1 -0
  46. data/docs/vendor/docsify-themeable/theme-simple-dark.css +3 -0
  47. data/docs/vendor/docsify-themeable/theme-simple-dark.css.map +1 -0
  48. data/docs/vendor/prismjs/prism-bash.min.js +1 -0
  49. data/docs/vendor/prismjs/prism-ruby.min.js +1 -0
  50. data/docs/vendor/prismjs/prism-tomorrow.min.css +1 -0
  51. data/lighstorm.gemspec +4 -2
  52. data/models/connections/channel_node/accounting.rb +3 -12
  53. data/models/connections/channel_node/fee.rb +44 -56
  54. data/models/connections/channel_node/htlc.rb +52 -0
  55. data/models/connections/channel_node/policy.rb +11 -12
  56. data/models/connections/channel_node.rb +20 -19
  57. data/models/connections/forward_channel.rb +8 -43
  58. data/models/connections/payment_channel.rb +18 -39
  59. data/models/edges/channel/accounting.rb +42 -18
  60. data/models/edges/channel/hop.rb +65 -0
  61. data/models/edges/channel.rb +98 -120
  62. data/models/edges/forward.rb +9 -118
  63. data/models/edges/groups/{analysis.rb → channel_forwards/analysis.rb} +9 -9
  64. data/models/edges/groups/channel_forwards.rb +10 -40
  65. data/models/edges/payment.rb +29 -214
  66. data/models/errors.rb +29 -0
  67. data/models/invoice.rb +49 -0
  68. data/models/nodes/node/lightning.rb +5 -16
  69. data/models/nodes/node/platform.rb +7 -13
  70. data/models/nodes/node.rb +19 -56
  71. data/models/payment_request.rb +69 -0
  72. data/models/rate.rb +11 -1
  73. data/models/satoshis.rb +5 -6
  74. data/ports/dsl/lighstorm/errors.rb +5 -0
  75. data/ports/dsl/lighstorm.rb +12 -8
  76. data/ports/grpc.rb +62 -0
  77. data/static/cache.rb +12 -0
  78. data/static/spec.rb +3 -1
  79. metadata +58 -8
  80. data/models/connections/channel_node/constraints.rb +0 -24
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../ports/grpc'
4
+ require_relative '../../../models/errors'
5
+
6
+ module Lighstorm
7
+ module Controllers
8
+ module Invoice
9
+ module Pay
10
+ def self.perform(_invoice, preview: false, fake: false)
11
+ raise Errors::ToDoError, self
12
+
13
+ LND.instance.middleware('router.send_payment_v2') do
14
+ result = []
15
+ LND.instance.client.router.send_payment_v2(
16
+ payment_request: request,
17
+ timeout_seconds: 5,
18
+ allow_self_payment: true
19
+ ) do |response|
20
+ result << response
21
+ end
22
+ result
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../ports/grpc'
4
+ require_relative '../../../models/errors'
5
+
6
+ module Lighstorm
7
+ module Controllers
8
+ module Invoice
9
+ module PayThroughRoute
10
+ def self.perform(_invoice, route:, preview: false, fake: false)
11
+ raise Errors::ToDoError, self
12
+
13
+ channels = route.map do |channel_id|
14
+ Channel.find_by_id(channel_id)
15
+ end
16
+
17
+ outgoing_channel_id = channels.first.id
18
+
19
+ hops_public_keys = []
20
+
21
+ hops_public_keys << if channels.first.mine?
22
+ channels.first.partner.node.public_key
23
+ else
24
+ channels.first.partners.last.node.public_key
25
+ end
26
+
27
+ channels[1..channels.size - 2].each do |channel|
28
+ hops_public_keys << channel.partners.last.node.public_key
29
+ end
30
+
31
+ hops_public_keys << if channels.last.mine?
32
+ channels.last.myself.node.public_key
33
+ else
34
+ channels.last.partners.last.node.public_key
35
+ end
36
+ begin
37
+ route = LND.instance.middleware('router.build_route') do
38
+ LND.instance.client.router.build_route(
39
+ amt_msat: amount.milisatoshis,
40
+ outgoing_chan_id: channels.first.id.to_i,
41
+ hop_pubkeys: hops_public_keys.map { |hpk| [hpk].pack('H*') },
42
+ payment_addr: [address].pack('H*')
43
+ )
44
+ end
45
+
46
+ if preview
47
+ return {
48
+ method: :send_to_route_v2,
49
+ params: {
50
+ payment_hash: hash,
51
+ route: route.to_h[:route],
52
+ skip_temp_err: true
53
+ }
54
+ }
55
+ end
56
+
57
+ LND.instance.middleware('router.send_to_route_v2') do
58
+ LND.instance.client.router.send_to_route_v2(
59
+ payment_hash: [hash].pack('H*'),
60
+ route: route.to_h[:route],
61
+ skip_temp_err: true
62
+ )
63
+ end
64
+ rescue StandardError => e
65
+ e
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../ports/grpc'
4
+ require_relative '../../adapters/invoice'
5
+ require_relative '../../models/invoice'
6
+
7
+ module Lighstorm
8
+ module Controllers
9
+ module Invoice
10
+ module All
11
+ def self.fetch(limit: nil)
12
+ last_offset = 0
13
+
14
+ invoices = []
15
+
16
+ loop do
17
+ response = Ports::GRPC.lightning.list_invoices(
18
+ index_offset: last_offset,
19
+ num_max_invoices: 10
20
+ )
21
+
22
+ response.invoices.each { |invoice| invoices << invoice.to_h }
23
+
24
+ # TODO: How to optimize this?
25
+ # break if !limit.nil? && invoices.size >= limit
26
+
27
+ break if last_offset == response.last_index_offset || last_offset > response.last_index_offset
28
+
29
+ last_offset = response.last_index_offset
30
+ end
31
+
32
+ invoices = invoices.sort_by { |raw_invoice| -raw_invoice[:creation_date] }
33
+
34
+ invoices = invoices[0..limit - 1] unless limit.nil?
35
+
36
+ { list_invoices: invoices }
37
+ end
38
+
39
+ def self.adapt(raw)
40
+ {
41
+ list_invoices: raw[:list_invoices].map do |raw_invoice|
42
+ Lighstorm::Adapter::Invoice.list_invoices(raw_invoice)
43
+ end
44
+ }
45
+ end
46
+
47
+ def self.transform(adapted)
48
+ adapted[:list_invoices].map do |invoice|
49
+ invoice[:known] = true
50
+ invoice
51
+ end
52
+ end
53
+
54
+ def self.data(limit: nil, &vcr)
55
+ raw = vcr.nil? ? fetch(limit: limit) : vcr.call(-> { fetch(limit: limit) })
56
+
57
+ adapted = adapt(raw)
58
+
59
+ transform(adapted)
60
+ end
61
+
62
+ def self.model(data)
63
+ data.map do |node_data|
64
+ Lighstorm::Models::Invoice.new(node_data)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../ports/grpc'
4
+ require_relative '../../adapters/invoice'
5
+ require_relative '../../models/invoice'
6
+
7
+ module Lighstorm
8
+ module Controllers
9
+ module Invoice
10
+ module FindBySecretHash
11
+ def self.fetch(secret_hash)
12
+ {
13
+ lookup_invoice: Ports::GRPC.lightning.lookup_invoice(r_hash_str: secret_hash).to_h
14
+ }
15
+ end
16
+
17
+ def self.adapt(raw)
18
+ {
19
+ lookup_invoice: Lighstorm::Adapter::Invoice.lookup_invoice(raw[:lookup_invoice])
20
+ }
21
+ end
22
+
23
+ def self.transform(adapted)
24
+ adapted[:lookup_invoice][:known] = true
25
+ adapted[:lookup_invoice]
26
+ end
27
+
28
+ def self.data(secret_hash, &vcr)
29
+ raw = vcr.nil? ? fetch(secret_hash) : vcr.call(-> { fetch(secret_hash) })
30
+
31
+ adapted = adapt(raw)
32
+
33
+ transform(adapted)
34
+ end
35
+
36
+ def self.model(data)
37
+ Lighstorm::Models::Invoice.new(data)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './invoice/all'
4
+ require_relative './invoice/find_by_secret_hash'
5
+ require_relative './invoice/actions/create'
6
+
7
+ module Lighstorm
8
+ module Controllers
9
+ module Invoice
10
+ def self.all(limit: nil)
11
+ All.model(All.data(limit: limit))
12
+ end
13
+
14
+ def self.first
15
+ All.model(All.data).first
16
+ end
17
+
18
+ def self.last
19
+ All.model(All.data).last
20
+ end
21
+
22
+ def self.find_by_secret_hash(secret_hash)
23
+ FindBySecretHash.model(FindBySecretHash.data(secret_hash))
24
+ end
25
+
26
+ def self.create(description: nil, milisatoshis: nil, preview: false, fake: false)
27
+ Create.perform(
28
+ description: description,
29
+ milisatoshis: milisatoshis,
30
+ preview: preview,
31
+ fake: fake
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../ports/grpc'
4
+ require_relative '../../adapters/nodes/node'
5
+
6
+ module Lighstorm
7
+ module Controllers
8
+ module Node
9
+ module All
10
+ def self.fetch(limit: nil)
11
+ data = {
12
+ at: Time.now,
13
+ get_info: Ports::GRPC.lightning.get_info.to_h,
14
+ describe_graph: Ports::GRPC.lightning.describe_graph.nodes
15
+ }
16
+
17
+ data[:describe_graph] = data[:describe_graph][0..limit - 1] unless limit.nil?
18
+
19
+ data
20
+ end
21
+
22
+ def self.adapt(raw)
23
+ {
24
+ get_info: Lighstorm::Adapter::Node.get_info(raw[:get_info]),
25
+ describe_graph: raw[:describe_graph].map do |raw|
26
+ Lighstorm::Adapter::Node.describe_graph(raw.to_h)
27
+ end
28
+ }
29
+ end
30
+
31
+ def self.transform(describe_graph, get_info)
32
+ if get_info[:public_key] == describe_graph[:public_key]
33
+ get_info.merge(myself: true)
34
+ else
35
+ describe_graph.merge(
36
+ platform: {
37
+ blockchain: get_info[:platform][:blockchain],
38
+ network: get_info[:platform][:network]
39
+ },
40
+ myself: false
41
+ )
42
+ end
43
+ end
44
+
45
+ def self.data(limit: nil, &vcr)
46
+ raw = vcr.nil? ? fetch(limit: limit) : vcr.call(-> { fetch(limit: limit) })
47
+
48
+ adapted = adapt(raw)
49
+
50
+ adapted[:describe_graph].map do |data|
51
+ transform(data, adapted[:get_info])
52
+ end
53
+ end
54
+
55
+ def self.model(data)
56
+ data.map do |node_data|
57
+ Lighstorm::Models::Node.new(node_data)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../ports/grpc'
4
+ require_relative '../../adapters/nodes/node'
5
+
6
+ module Lighstorm
7
+ module Controllers
8
+ module Node
9
+ module FindByPublicKey
10
+ def self.fetch(public_key)
11
+ {
12
+ at: Time.now,
13
+ get_info: Ports::GRPC.lightning.get_info.to_h,
14
+ get_node_info: Ports::GRPC.lightning.get_node_info(pub_key: public_key).to_h
15
+ }
16
+ end
17
+
18
+ def self.adapt(raw)
19
+ {
20
+ get_info: Lighstorm::Adapter::Node.get_info(raw[:get_info]),
21
+ get_node_info: Lighstorm::Adapter::Node.get_node_info(raw[:get_node_info])
22
+ }
23
+ end
24
+
25
+ def self.data(public_key, &vcr)
26
+ raw = vcr.nil? ? fetch(public_key) : vcr.call(-> { fetch(public_key) })
27
+
28
+ adapted = adapt(raw)
29
+
30
+ if adapted[:get_info][:public_key] == adapted[:get_node_info][:public_key]
31
+ adapted[:get_info].merge(myself: true)
32
+ else
33
+ adapted[:get_node_info].merge(
34
+ platform: {
35
+ blockchain: adapted[:get_info][:platform][:blockchain],
36
+ network: adapted[:get_info][:platform][:network]
37
+ },
38
+ myself: false
39
+ )
40
+ end
41
+ end
42
+
43
+ def self.model(data)
44
+ Lighstorm::Models::Node.new(data)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../ports/grpc'
4
+ require_relative '../../adapters/nodes/node'
5
+
6
+ module Lighstorm
7
+ module Controllers
8
+ module Node
9
+ module Myself
10
+ def self.fetch
11
+ {
12
+ at: Time.now,
13
+ get_info: Ports::GRPC.lightning.get_info.to_h
14
+ }
15
+ end
16
+
17
+ def self.adapt(raw)
18
+ { get_info: Lighstorm::Adapter::Node.get_info(raw[:get_info]) }
19
+ end
20
+
21
+ def self.data(&vcr)
22
+ raw = vcr.nil? ? fetch : vcr.call(-> { fetch })
23
+
24
+ adapted = adapt(raw)
25
+ adapted[:get_info].merge(myself: true)
26
+ end
27
+
28
+ def self.model(data)
29
+ Lighstorm::Models::Node.new(data)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './node/myself'
4
+ require_relative './node/all'
5
+ require_relative './node/find_by_public_key'
6
+
7
+ module Lighstorm
8
+ module Controllers
9
+ module Node
10
+ def self.myself
11
+ Myself.model(Myself.data)
12
+ end
13
+
14
+ def self.all(limit: nil)
15
+ All.model(All.data(limit: limit))
16
+ end
17
+
18
+ def self.find_by_public_key(public_key)
19
+ FindByPublicKey.model(FindByPublicKey.data(public_key))
20
+ end
21
+ end
22
+ end
23
+ end