lighstorm 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +7 -7
  4. data/adapters/bitcoin/address.rb +19 -0
  5. data/adapters/bitcoin/transaction.rb +34 -0
  6. data/adapters/lightning/connections/channel_node/fee.rb +28 -0
  7. data/adapters/lightning/connections/channel_node/policy.rb +63 -0
  8. data/adapters/lightning/connections/channel_node.rb +77 -0
  9. data/adapters/lightning/connections/payment_channel.rb +30 -0
  10. data/adapters/lightning/edges/channel.rb +98 -0
  11. data/adapters/lightning/edges/forward.rb +42 -0
  12. data/adapters/lightning/edges/payment/purpose.rb +45 -0
  13. data/adapters/lightning/edges/payment.rb +89 -0
  14. data/adapters/lightning/invoice.rb +186 -0
  15. data/adapters/lightning/nodes/node.rb +113 -0
  16. data/controllers/action.rb +1 -1
  17. data/controllers/bitcoin/address/actions/create.rb +91 -0
  18. data/controllers/bitcoin/address/actions/pay.rb +119 -0
  19. data/controllers/bitcoin/address.rb +24 -0
  20. data/controllers/bitcoin/transaction/all.rb +65 -0
  21. data/controllers/bitcoin/transaction.rb +25 -0
  22. data/controllers/concerns/impersonatable.rb +5 -3
  23. data/controllers/connection.rb +1 -1
  24. data/controllers/lightning/channel/actions/apply_gossip.rb +201 -0
  25. data/controllers/lightning/channel/actions/update_fee.rb +94 -0
  26. data/controllers/lightning/channel/all.rb +85 -0
  27. data/controllers/lightning/channel/find_by_id.rb +155 -0
  28. data/controllers/lightning/channel/mine.rb +116 -0
  29. data/controllers/lightning/channel.rb +43 -0
  30. data/controllers/lightning/forward/all.rb +250 -0
  31. data/controllers/lightning/forward/group_by_channel.rb +91 -0
  32. data/controllers/lightning/forward.rb +36 -0
  33. data/controllers/lightning/invoice/actions/create.rb +90 -0
  34. data/controllers/lightning/invoice/actions/pay.rb +97 -0
  35. data/controllers/lightning/invoice/actions/pay_through_route.rb +73 -0
  36. data/controllers/lightning/invoice/all.rb +82 -0
  37. data/controllers/lightning/invoice/decode.rb +50 -0
  38. data/controllers/lightning/invoice/find_by_code.rb +76 -0
  39. data/controllers/lightning/invoice/find_by_secret_hash.rb +56 -0
  40. data/controllers/lightning/invoice.rb +64 -0
  41. data/controllers/lightning/node/actions/apply_gossip.rb +114 -0
  42. data/controllers/lightning/node/actions/pay.rb +117 -0
  43. data/controllers/lightning/node/all.rb +69 -0
  44. data/controllers/lightning/node/find_by_public_key.rb +55 -0
  45. data/controllers/lightning/node/myself.rb +36 -0
  46. data/controllers/lightning/node.rb +35 -0
  47. data/controllers/lightning/payment/actions/pay.rb +110 -0
  48. data/controllers/lightning/payment/all.rb +439 -0
  49. data/controllers/lightning/payment.rb +37 -0
  50. data/controllers/lightning/secret/valid_proof.rb +60 -0
  51. data/controllers/lightning/secret.rb +16 -0
  52. data/controllers/wallet/activity/all.rb +196 -0
  53. data/controllers/wallet/activity.rb +28 -0
  54. data/controllers/wallet/balance.rb +3 -3
  55. data/controllers/wallet.rb +1 -1
  56. data/docs/README.md +229 -148
  57. data/docs/_coverpage.md +1 -1
  58. data/docs/index.html +1 -1
  59. data/models/bitcoin/address.rb +49 -0
  60. data/models/bitcoin/transaction.rb +41 -0
  61. data/models/concerns/protectable.rb +1 -1
  62. data/models/errors.rb +7 -8
  63. data/models/lightning/connections/channel_node/accounting.rb +27 -0
  64. data/models/lightning/connections/channel_node/fee.rb +82 -0
  65. data/models/lightning/connections/channel_node/htlc/blocks/delta.rb +41 -0
  66. data/models/lightning/connections/channel_node/htlc.rb +88 -0
  67. data/models/lightning/connections/channel_node/policy.rb +41 -0
  68. data/models/lightning/connections/channel_node.rb +86 -0
  69. data/models/lightning/connections/forward_channel.rb +31 -0
  70. data/models/lightning/connections/payment_channel.rb +58 -0
  71. data/models/lightning/edges/channel/accounting.rb +87 -0
  72. data/models/lightning/edges/channel/hop.rb +67 -0
  73. data/models/lightning/edges/channel.rb +197 -0
  74. data/models/lightning/edges/forward.rb +51 -0
  75. data/models/lightning/edges/groups/channel_forwards/analysis.rb +71 -0
  76. data/models/lightning/edges/groups/channel_forwards.rb +39 -0
  77. data/models/lightning/edges/payment.rb +104 -0
  78. data/models/lightning/invoice.rb +115 -0
  79. data/models/lightning/nodes/node/lightning.rb +33 -0
  80. data/models/lightning/nodes/node/platform.rb +50 -0
  81. data/models/lightning/nodes/node.rb +145 -0
  82. data/models/lightning/rate.rb +37 -0
  83. data/models/lightning/secret.rb +57 -0
  84. data/models/satoshis.rb +1 -1
  85. data/models/wallet/activity.rb +54 -0
  86. data/models/wallet/balance.rb +42 -0
  87. data/ports/dsl/lighstorm.rb +29 -16
  88. data/static/cache.rb +2 -0
  89. data/static/spec.rb +1 -1
  90. metadata +74 -68
  91. data/adapters/connections/channel_node/fee.rb +0 -26
  92. data/adapters/connections/channel_node/policy.rb +0 -61
  93. data/adapters/connections/channel_node.rb +0 -75
  94. data/adapters/connections/payment_channel.rb +0 -28
  95. data/adapters/edges/channel.rb +0 -96
  96. data/adapters/edges/forward.rb +0 -40
  97. data/adapters/edges/payment/purpose.rb +0 -43
  98. data/adapters/edges/payment.rb +0 -87
  99. data/adapters/invoice.rb +0 -184
  100. data/adapters/nodes/node.rb +0 -111
  101. data/adapters/transaction.rb +0 -23
  102. data/controllers/activity/all.rb +0 -194
  103. data/controllers/activity.rb +0 -26
  104. data/controllers/channel/actions/apply_gossip.rb +0 -193
  105. data/controllers/channel/actions/update_fee.rb +0 -91
  106. data/controllers/channel/all.rb +0 -83
  107. data/controllers/channel/find_by_id.rb +0 -153
  108. data/controllers/channel/mine.rb +0 -114
  109. data/controllers/channel.rb +0 -41
  110. data/controllers/forward/all.rb +0 -248
  111. data/controllers/forward/group_by_channel.rb +0 -89
  112. data/controllers/forward.rb +0 -34
  113. data/controllers/invoice/actions/create.rb +0 -88
  114. data/controllers/invoice/actions/pay.rb +0 -95
  115. data/controllers/invoice/actions/pay_through_route.rb +0 -71
  116. data/controllers/invoice/all.rb +0 -80
  117. data/controllers/invoice/decode.rb +0 -44
  118. data/controllers/invoice/find_by_code.rb +0 -70
  119. data/controllers/invoice/find_by_secret_hash.rb +0 -54
  120. data/controllers/invoice.rb +0 -62
  121. data/controllers/node/actions/apply_gossip.rb +0 -112
  122. data/controllers/node/actions/pay.rb +0 -115
  123. data/controllers/node/all.rb +0 -67
  124. data/controllers/node/find_by_public_key.rb +0 -53
  125. data/controllers/node/myself.rb +0 -34
  126. data/controllers/node.rb +0 -33
  127. data/controllers/payment/actions/pay.rb +0 -108
  128. data/controllers/payment/all.rb +0 -437
  129. data/controllers/payment.rb +0 -35
  130. data/controllers/secret/valid_proof.rb +0 -58
  131. data/controllers/transaction/all.rb +0 -61
  132. data/controllers/transaction.rb +0 -25
  133. data/models/activity.rb +0 -52
  134. data/models/connections/channel_node/accounting.rb +0 -25
  135. data/models/connections/channel_node/fee.rb +0 -80
  136. data/models/connections/channel_node/htlc/blocks/delta.rb +0 -39
  137. data/models/connections/channel_node/htlc.rb +0 -86
  138. data/models/connections/channel_node/policy.rb +0 -39
  139. data/models/connections/channel_node.rb +0 -84
  140. data/models/connections/forward_channel.rb +0 -29
  141. data/models/connections/payment_channel.rb +0 -56
  142. data/models/edges/channel/accounting.rb +0 -85
  143. data/models/edges/channel/hop.rb +0 -65
  144. data/models/edges/channel.rb +0 -195
  145. data/models/edges/forward.rb +0 -49
  146. data/models/edges/groups/channel_forwards/analysis.rb +0 -69
  147. data/models/edges/groups/channel_forwards.rb +0 -37
  148. data/models/edges/payment.rb +0 -102
  149. data/models/invoice.rb +0 -113
  150. data/models/nodes/node/lightning.rb +0 -31
  151. data/models/nodes/node/platform.rb +0 -48
  152. data/models/nodes/node.rb +0 -143
  153. data/models/rate.rb +0 -35
  154. data/models/secret.rb +0 -55
  155. data/models/transaction.rb +0 -39
  156. data/models/wallet.rb +0 -40
@@ -1,248 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'digest'
4
-
5
- require_relative '../../ports/grpc'
6
- require_relative '../../adapters/nodes/node'
7
- require_relative '../../adapters/edges/channel'
8
- require_relative '../../adapters/edges/forward'
9
- require_relative '../../adapters/connections/channel_node/fee'
10
-
11
- require_relative '../../models/edges/forward'
12
-
13
- module Lighstorm
14
- module Controllers
15
- module Forward
16
- module All
17
- def self.fetch(components, limit: nil)
18
- at = Time.now
19
-
20
- last_offset = 0
21
-
22
- forwards = []
23
-
24
- loop do
25
- response = components[:grpc].lightning.forwarding_history(index_offset: last_offset)
26
-
27
- response.forwarding_events.each { |forward| forwards << forward.to_h }
28
-
29
- # TODO: How to optimize this?
30
- # break if !limit.nil? && forwards.size >= limit
31
-
32
- break if last_offset == response.last_offset_index || last_offset > response.last_offset_index
33
-
34
- last_offset = response.last_offset_index
35
- end
36
-
37
- forwards = forwards.sort_by { |raw_forward| -raw_forward[:timestamp_ns] }
38
-
39
- forwards = forwards[0..limit - 1] unless limit.nil?
40
-
41
- data = {
42
- at: at,
43
- get_info: components[:grpc].lightning.get_info.to_h,
44
- fee_report: components[:grpc].lightning.fee_report.to_h,
45
- forwarding_history: forwards,
46
- list_channels: {},
47
- get_chan_info: {},
48
- get_node_info: {}
49
- }
50
-
51
- forwards.each do |forward|
52
- unless data[:get_chan_info][forward[:chan_id_in]]
53
- begin
54
- data[:get_chan_info][forward[:chan_id_in]] = components[:grpc].lightning.get_chan_info(
55
- chan_id: forward[:chan_id_in]
56
- ).to_h
57
- rescue GRPC::Unknown => e
58
- data[:get_chan_info][forward[:chan_id_in]] = { _error: e }
59
- end
60
- end
61
-
62
- next if data[:get_chan_info][forward[:chan_id_out]]
63
-
64
- begin
65
- data[:get_chan_info][forward[:chan_id_out]] = components[:grpc].lightning.get_chan_info(
66
- chan_id: forward[:chan_id_out]
67
- ).to_h
68
- rescue GRPC::Unknown => e
69
- data[:get_chan_info][forward[:chan_id_out]] = { _error: e }
70
- end
71
- end
72
-
73
- list_channels_done = {}
74
-
75
- data[:get_chan_info].each_value do |channel|
76
- next if channel[:_error]
77
-
78
- partners = [channel[:node1_pub], channel[:node2_pub]]
79
-
80
- is_mine = partners.include?(data[:get_info][:identity_pubkey])
81
-
82
- if is_mine
83
- partner = partners.find { |p| p != data[:get_info][:identity_pubkey] }
84
-
85
- unless list_channels_done[partner]
86
- components[:grpc].lightning.list_channels(
87
- peer: [partner].pack('H*')
88
- ).channels.map(&:to_h).each do |list_channels|
89
- data[:list_channels][list_channels[:chan_id]] = list_channels
90
- end
91
-
92
- list_channels_done[partner] = true
93
- end
94
- end
95
-
96
- unless data[:get_node_info][channel[:node1_pub]]
97
- data[:get_node_info][channel[:node1_pub]] = components[:grpc].lightning.get_node_info(
98
- pub_key: channel[:node1_pub]
99
- ).to_h
100
- end
101
-
102
- next if data[:get_node_info][channel[:node2_pub]]
103
-
104
- data[:get_node_info][channel[:node2_pub]] = components[:grpc].lightning.get_node_info(
105
- pub_key: channel[:node2_pub]
106
- ).to_h
107
- end
108
-
109
- data[:list_channels].each_value do |channel|
110
- next if data[:get_node_info][channel[:remote_pubkey]]
111
-
112
- data[:get_node_info][channel[:remote_pubkey]] = components[:grpc].lightning.get_node_info(
113
- pub_key: channel[:remote_pubkey]
114
- ).to_h
115
- end
116
-
117
- data
118
- end
119
-
120
- def self.adapt(raw)
121
- adapted = {
122
- get_info: Lighstorm::Adapter::Node.get_info(raw[:get_info]),
123
- forwarding_history: raw[:forwarding_history].map do |raw_forward|
124
- Lighstorm::Adapter::Forward.forwarding_history(raw_forward)
125
- end,
126
- fee_report: raw[:fee_report][:channel_fees].map do |raw_fee|
127
- Lighstorm::Adapter::Fee.fee_report(raw_fee.to_h)
128
- end,
129
- list_channels: {},
130
- get_chan_info: {},
131
- get_node_info: {}
132
- }
133
-
134
- raw[:get_chan_info].each_key do |key|
135
- next if raw[:get_chan_info][key][:_error]
136
-
137
- adapted[:get_chan_info][key] = Lighstorm::Adapter::Channel.get_chan_info(
138
- raw[:get_chan_info][key]
139
- )
140
- end
141
-
142
- raw[:list_channels].each_key do |key|
143
- adapted[:list_channels][key] = Lighstorm::Adapter::Channel.list_channels(
144
- raw[:list_channels][key], raw[:at]
145
- )
146
- end
147
-
148
- raw[:get_node_info].each_key do |key|
149
- adapted[:get_node_info][key] = Lighstorm::Adapter::Node.get_node_info(
150
- raw[:get_node_info][key]
151
- )
152
- end
153
-
154
- adapted
155
- end
156
-
157
- def self.transform(data, adapted)
158
- unless adapted[:get_chan_info][data[:id].to_i]
159
- data[:_key] = Digest::SHA256.hexdigest(data[:id])
160
- return data
161
- end
162
-
163
- data = adapted[:get_chan_info][data[:id].to_i]
164
- data[:known] = true
165
-
166
- [0, 1].each do |i|
167
- if data[:partners][i][:node][:public_key] == adapted[:get_info][:public_key]
168
- data[:partners][i][:node] =
169
- adapted[:get_info]
170
- end
171
-
172
- adapted[:get_chan_info][data[:id].to_i][:partners].each do |partner|
173
- if data[:partners][i][:node][:public_key] == partner[:node][:public_key]
174
- data[:partners][i][:policy] = partner[:policy]
175
- end
176
- end
177
-
178
- if data[:partners][i][:node][:public_key] == adapted[:get_info][:public_key]
179
- data[:partners][i][:node][:platform] = adapted[:get_info][:platform]
180
- data[:partners][i][:node][:myself] = true
181
- data[:mine] = true
182
- adapted[:fee_report].each do |channel|
183
- next unless data[:id] == channel[:id]
184
-
185
- data[:partners][i][:policy][:fee] = channel[:partner][:policy][:fee]
186
- break
187
- end
188
- else
189
- data[:partners][i][:node] = adapted[:get_node_info][data[:partners][i][:node][:public_key]]
190
- data[:partners][i][:node][:platform] = {
191
- blockchain: adapted[:get_info][:platform][:blockchain],
192
- network: adapted[:get_info][:platform][:network]
193
- }
194
-
195
- data[:partners][i][:node][:myself] = false
196
- end
197
- end
198
-
199
- channel = adapted[:list_channels][data[:id].to_i]
200
-
201
- return data unless channel
202
-
203
- channel.each_key do |key|
204
- next if data.key?(key)
205
-
206
- data[key] = channel[key]
207
- end
208
-
209
- data[:accounting] = channel[:accounting]
210
-
211
- channel[:partners].each do |partner|
212
- data[:partners].each_index do |i|
213
- partner.each_key do |key|
214
- next if data[:partners][i].key?(key)
215
-
216
- data[:partners][i][key] = partner[key]
217
- end
218
- end
219
- end
220
-
221
- data
222
- end
223
-
224
- def self.data(components, limit: nil, &vcr)
225
- raw = if vcr.nil?
226
- fetch(components, limit: limit)
227
- else
228
- vcr.call(-> { fetch(components, limit: limit) })
229
- end
230
-
231
- adapted = adapt(raw)
232
-
233
- adapted[:forwarding_history].map do |data|
234
- data[:in][:channel] = transform(data[:in][:channel], adapted)
235
- data[:out][:channel] = transform(data[:out][:channel], adapted)
236
- data
237
- end
238
- end
239
-
240
- def self.model(data)
241
- data.map do |node_data|
242
- Lighstorm::Models::Forward.new(node_data)
243
- end
244
- end
245
- end
246
- end
247
- end
248
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'digest'
4
-
5
- require_relative './all'
6
-
7
- require_relative '../../models/edges/groups/channel_forwards'
8
-
9
- module Lighstorm
10
- module Controllers
11
- module Forward
12
- module GroupByChannel
13
- def self.filter(forwards, hours_ago)
14
- return forwards if hours_ago.nil?
15
-
16
- forwards.filter do |forward|
17
- forward_hours_ago = (Time.now - Time.parse(forward[:at].to_s)).to_f / 3600
18
- forward_hours_ago <= hours_ago
19
- end
20
- end
21
-
22
- def self.group(forwards, direction)
23
- groups = {}
24
-
25
- forwards.each do |forward|
26
- key = forward[direction][:channel][:id]
27
- groups[key] = [] unless groups.key?(key)
28
- groups[key] << forward
29
- end
30
-
31
- groups.values
32
- end
33
-
34
- def self.analyze(forwards, direction)
35
- group = {
36
- last_at: nil,
37
- analysis: {
38
- count: 0,
39
- sums: { amount: { millisatoshis: 0 }, fee: { millisatoshis: 0 } }
40
- },
41
- channel: nil
42
- }
43
-
44
- forwards.each do |forward|
45
- group[:last_at] = forward[:at] if group[:last_at].nil? || forward[:at] > group[:last_at]
46
-
47
- group[:channel] = forward[direction][:channel] if group[:channel].nil?
48
-
49
- group[:analysis][:count] += 1
50
- group[:analysis][:sums][:amount][:millisatoshis] += forward[:in][:amount][:millisatoshis]
51
- group[:analysis][:sums][:fee][:millisatoshis] += forward[:fee][:millisatoshis]
52
- end
53
-
54
- group[:_key] = _key(group)
55
-
56
- group
57
- end
58
-
59
- def self._key(group)
60
- Digest::SHA256.hexdigest(
61
- [group[:last_at], group[:analysis][:count], group[:channel][:id]].join('/')
62
- )
63
- end
64
-
65
- def self.sort(groups)
66
- groups.sort_by { |group| - Time.parse(group[:last_at].to_s).to_f }
67
- .sort_by { |group| - group[:analysis][:count] }
68
- end
69
-
70
- def self.data(components, direction: :out, hours_ago: nil, limit: nil, &vcr)
71
- data = All.data(components, &vcr)
72
-
73
- filtered = filter(data, hours_ago)
74
- groups = group(filtered, direction)
75
- analyzed = groups.map { |group| analyze(group, direction) }
76
- sorted = sort(analyzed)
77
-
78
- sorted = sorted[0..limit - 1] unless limit.nil?
79
-
80
- sorted
81
- end
82
-
83
- def self.model(data)
84
- data.map { |group| Models::ChannelForwardsGroup.new(group) }
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './concerns/impersonatable'
4
-
5
- require_relative './forward/all'
6
- require_relative './forward/group_by_channel'
7
-
8
- module Lighstorm
9
- module Controllers
10
- module Forward
11
- extend Impersonatable
12
-
13
- class DSL < Impersonatable::DSL
14
- def all(limit: nil)
15
- All.model(All.data(components, limit: limit))
16
- end
17
-
18
- def first
19
- All.model(All.data(components)).first
20
- end
21
-
22
- def last
23
- All.model(All.data(components)).last
24
- end
25
-
26
- def group_by_channel(direction: :out, hours_ago: nil, limit: nil)
27
- GroupByChannel.model(
28
- GroupByChannel.data(components, direction: direction, hours_ago: hours_ago, limit: limit)
29
- )
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../../ports/grpc'
4
- require_relative '../../../models/errors'
5
- require_relative '../../../helpers/time_expression'
6
- require_relative '../../invoice'
7
- require_relative '../../action'
8
-
9
- module Lighstorm
10
- module Controllers
11
- module Invoice
12
- module Create
13
- def self.call(components, grpc_request)
14
- components[:grpc].send(grpc_request[:service]).send(
15
- grpc_request[:method], grpc_request[:params]
16
- ).to_h
17
- end
18
-
19
- def self.prepare(payable:, expires_in:, description: nil, amount: nil)
20
- request = {
21
- service: :lightning,
22
- method: :add_invoice,
23
- params: {
24
- memo: description,
25
- # Lightning Invoice Expiration: UX Considerations
26
- # https://d.elor.me/2022/01/lightning-invoice-expiration-ux-considerations/
27
- expiry: Helpers::TimeExpression.seconds(expires_in)
28
- }
29
- }
30
-
31
- request[:params][:value_msat] = amount[:millisatoshis] unless amount.nil?
32
-
33
- if payable.to_sym == :indefinitely
34
- request[:params][:is_amp] = true
35
- elsif payable.to_sym != :once
36
- raise Errors::ArgumentError, "payable: accepts 'indefinitely' or 'once', '#{payable}' is not valid."
37
- end
38
-
39
- request
40
- end
41
-
42
- def self.dispatch(components, grpc_request, &vcr)
43
- if vcr.nil?
44
- call(components, grpc_request)
45
- else
46
- vcr.call(-> { call(components, grpc_request) }, :dispatch)
47
- end
48
- end
49
-
50
- def self.adapt(response)
51
- Lighstorm::Adapter::Invoice.add_invoice(response)
52
- end
53
-
54
- def self.fetch(components, adapted, &vcr)
55
- FindBySecretHash.data(components, adapted[:secret][:hash], &vcr)
56
- end
57
-
58
- def self.model(data, components)
59
- FindBySecretHash.model(data, components)
60
- end
61
-
62
- def self.perform(
63
- components,
64
- payable:, expires_in:, description: nil, amount: nil,
65
- preview: false, &vcr
66
- )
67
- grpc_request = prepare(
68
- description: description,
69
- amount: amount,
70
- expires_in: expires_in,
71
- payable: payable
72
- )
73
-
74
- return grpc_request if preview
75
-
76
- response = dispatch(components, grpc_request, &vcr)
77
-
78
- adapted = adapt(response)
79
-
80
- data = fetch(components, adapted, &vcr)
81
- model = self.model(data, components)
82
-
83
- Action::Output.new({ request: grpc_request, response: response, result: model })
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../../ports/grpc'
4
- require_relative '../../../models/errors'
5
- require_relative '../../../models/edges/payment'
6
- require_relative '../../../adapters/edges/payment'
7
- require_relative '../../invoice'
8
- require_relative '../../action'
9
- require_relative '../../node/myself'
10
-
11
- require_relative '../../payment/actions/pay'
12
-
13
- module Lighstorm
14
- module Controllers
15
- module Invoice
16
- module Pay
17
- def self.dispatch(components, grpc_request, &vcr)
18
- Payment::Pay.dispatch(components, grpc_request, &vcr)
19
- end
20
-
21
- def self.fetch(components, code, &vcr)
22
- Payment::Pay.fetch(components, code, &vcr)
23
- end
24
-
25
- def self.adapt(data, node_get_info)
26
- Payment::Pay.adapt(data, node_get_info)
27
- end
28
-
29
- def self.model(data, components)
30
- Payment::Pay.model(data, components)
31
- end
32
-
33
- def self.prepare(code:, times_out_in:, amount: nil, fee: nil, message: nil)
34
- request = {
35
- service: :router,
36
- method: :send_payment_v2,
37
- params: {
38
- payment_request: code,
39
- timeout_seconds: Helpers::TimeExpression.seconds(times_out_in),
40
- allow_self_payment: true,
41
- dest_custom_records: {}
42
- }
43
- }
44
-
45
- request[:params][:amt_msat] = amount[:millisatoshis] unless amount.nil?
46
-
47
- unless fee.nil? || fee[:maximum].nil? || fee[:maximum][:millisatoshis].nil?
48
- request[:params][:fee_limit_msat] = fee[:maximum][:millisatoshis]
49
- end
50
-
51
- if !message.nil? && !message.empty?
52
- # https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md
53
- request[:params][:dest_custom_records][34_349_334] = message
54
- end
55
-
56
- request[:params].delete(:dest_custom_records) if request[:params][:dest_custom_records].empty?
57
-
58
- request
59
- end
60
-
61
- def self.perform(
62
- components,
63
- times_out_in:, code:,
64
- amount: nil, fee: nil,
65
- message: nil,
66
- preview: false, &vcr
67
- )
68
- grpc_request = prepare(
69
- code: code,
70
- amount: amount,
71
- fee: fee,
72
- message: message,
73
- times_out_in: times_out_in
74
- )
75
-
76
- return grpc_request if preview
77
-
78
- response = dispatch(components, grpc_request, &vcr)
79
-
80
- Payment::Pay.raise_error_if_exists!(grpc_request, response)
81
-
82
- data = fetch(components, code, &vcr)
83
-
84
- adapted = adapt(response, data)
85
-
86
- model = self.model(adapted, components)
87
-
88
- Payment::Pay.raise_failure_if_exists!(model, grpc_request, response)
89
-
90
- Action::Output.new({ request: grpc_request, response: response[:response], result: model })
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,71 +0,0 @@
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(components, _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, components)
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.millisatoshis,
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
@@ -1,80 +0,0 @@
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(components, limit: nil, spontaneous: false)
12
- at = Time.now
13
-
14
- last_offset = 0
15
-
16
- invoices = []
17
-
18
- loop do
19
- response = components[:grpc].lightning.list_invoices(
20
- index_offset: last_offset,
21
- num_max_invoices: 10
22
- )
23
-
24
- response.invoices.each do |invoice|
25
- invoices << invoice.to_h if spontaneous || !invoice.payment_request.empty?
26
- end
27
-
28
- # TODO: How to optimize this?
29
- # break if !limit.nil? && invoices.size >= limit
30
-
31
- break if last_offset == response.last_index_offset || last_offset > response.last_index_offset
32
-
33
- last_offset = response.last_index_offset
34
- end
35
-
36
- invoices = invoices.sort_by { |raw_invoice| -raw_invoice[:creation_date] }
37
-
38
- invoices = invoices[0..limit - 1] unless limit.nil?
39
-
40
- { at: at, list_invoices: invoices }
41
- end
42
-
43
- def self.adapt(raw)
44
- raise 'missing at' if raw[:at].nil?
45
-
46
- {
47
- list_invoices: raw[:list_invoices].map do |raw_invoice|
48
- Lighstorm::Adapter::Invoice.list_invoices(raw_invoice, raw[:at])
49
- end
50
- }
51
- end
52
-
53
- def self.transform(adapted)
54
- adapted[:list_invoices].map do |invoice|
55
- invoice[:known] = true
56
- invoice
57
- end
58
- end
59
-
60
- def self.data(components, limit: nil, spontaneous: false, &vcr)
61
- raw = if vcr.nil?
62
- fetch(components, limit: limit, spontaneous: spontaneous)
63
- else
64
- vcr.call(-> { fetch(components, limit: limit, spontaneous: spontaneous) })
65
- end
66
-
67
- adapted = adapt(raw)
68
-
69
- transform(adapted)
70
- end
71
-
72
- def self.model(data, components)
73
- data.map do |node_data|
74
- Lighstorm::Models::Invoice.new(node_data, components)
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end