lighstorm 0.0.14 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +7 -7
  4. data/README.md +7 -7
  5. data/adapters/bitcoin/address.rb +19 -0
  6. data/adapters/bitcoin/transaction.rb +34 -0
  7. data/adapters/lightning/connections/channel_node/fee.rb +28 -0
  8. data/adapters/lightning/connections/channel_node/policy.rb +63 -0
  9. data/adapters/lightning/connections/channel_node.rb +77 -0
  10. data/adapters/lightning/connections/payment_channel.rb +30 -0
  11. data/adapters/lightning/edges/channel.rb +98 -0
  12. data/adapters/lightning/edges/forward.rb +42 -0
  13. data/adapters/lightning/edges/payment/purpose.rb +45 -0
  14. data/adapters/lightning/edges/payment.rb +89 -0
  15. data/adapters/lightning/invoice.rb +186 -0
  16. data/adapters/lightning/nodes/node.rb +113 -0
  17. data/controllers/action.rb +1 -1
  18. data/controllers/bitcoin/address/actions/create.rb +91 -0
  19. data/controllers/bitcoin/address/actions/pay.rb +119 -0
  20. data/controllers/bitcoin/address.rb +24 -0
  21. data/controllers/bitcoin/transaction/all.rb +65 -0
  22. data/controllers/bitcoin/transaction.rb +25 -0
  23. data/controllers/concerns/impersonatable.rb +5 -3
  24. data/controllers/connection.rb +1 -1
  25. data/controllers/lightning/channel/actions/apply_gossip.rb +201 -0
  26. data/controllers/lightning/channel/actions/update_fee.rb +94 -0
  27. data/controllers/lightning/channel/all.rb +85 -0
  28. data/controllers/lightning/channel/find_by_id.rb +155 -0
  29. data/controllers/lightning/channel/mine.rb +116 -0
  30. data/controllers/lightning/channel.rb +43 -0
  31. data/controllers/lightning/forward/all.rb +250 -0
  32. data/controllers/lightning/forward/group_by_channel.rb +91 -0
  33. data/controllers/lightning/forward.rb +36 -0
  34. data/controllers/lightning/invoice/actions/create.rb +90 -0
  35. data/controllers/lightning/invoice/actions/pay.rb +97 -0
  36. data/controllers/lightning/invoice/actions/pay_through_route.rb +73 -0
  37. data/controllers/lightning/invoice/all.rb +82 -0
  38. data/controllers/lightning/invoice/decode.rb +50 -0
  39. data/controllers/lightning/invoice/find_by_code.rb +76 -0
  40. data/controllers/lightning/invoice/find_by_secret_hash.rb +56 -0
  41. data/controllers/lightning/invoice.rb +64 -0
  42. data/controllers/lightning/node/actions/apply_gossip.rb +114 -0
  43. data/controllers/lightning/node/actions/pay.rb +117 -0
  44. data/controllers/lightning/node/all.rb +69 -0
  45. data/controllers/lightning/node/find_by_public_key.rb +55 -0
  46. data/controllers/lightning/node/myself.rb +36 -0
  47. data/controllers/lightning/node.rb +35 -0
  48. data/controllers/lightning/payment/actions/pay.rb +110 -0
  49. data/controllers/lightning/payment/all.rb +439 -0
  50. data/controllers/lightning/payment.rb +37 -0
  51. data/controllers/lightning/secret/valid_proof.rb +60 -0
  52. data/controllers/lightning/secret.rb +16 -0
  53. data/controllers/wallet/activity/all.rb +196 -0
  54. data/controllers/wallet/activity.rb +28 -0
  55. data/controllers/wallet/balance.rb +3 -3
  56. data/controllers/wallet.rb +1 -1
  57. data/docs/README.md +229 -148
  58. data/docs/_coverpage.md +1 -1
  59. data/docs/index.html +1 -1
  60. data/lighstorm.gemspec +1 -1
  61. data/models/bitcoin/address.rb +49 -0
  62. data/models/bitcoin/transaction.rb +41 -0
  63. data/models/concerns/protectable.rb +1 -1
  64. data/models/errors.rb +7 -8
  65. data/models/lightning/connections/channel_node/accounting.rb +27 -0
  66. data/models/lightning/connections/channel_node/fee.rb +82 -0
  67. data/models/lightning/connections/channel_node/htlc/blocks/delta.rb +41 -0
  68. data/models/lightning/connections/channel_node/htlc.rb +88 -0
  69. data/models/lightning/connections/channel_node/policy.rb +41 -0
  70. data/models/lightning/connections/channel_node.rb +86 -0
  71. data/models/lightning/connections/forward_channel.rb +31 -0
  72. data/models/lightning/connections/payment_channel.rb +58 -0
  73. data/models/lightning/edges/channel/accounting.rb +87 -0
  74. data/models/lightning/edges/channel/hop.rb +67 -0
  75. data/models/lightning/edges/channel.rb +197 -0
  76. data/models/lightning/edges/forward.rb +51 -0
  77. data/models/lightning/edges/groups/channel_forwards/analysis.rb +71 -0
  78. data/models/lightning/edges/groups/channel_forwards.rb +39 -0
  79. data/models/lightning/edges/payment.rb +104 -0
  80. data/models/lightning/invoice.rb +115 -0
  81. data/models/lightning/nodes/node/lightning.rb +33 -0
  82. data/models/lightning/nodes/node/platform.rb +50 -0
  83. data/models/lightning/nodes/node.rb +145 -0
  84. data/models/lightning/rate.rb +37 -0
  85. data/models/lightning/secret.rb +57 -0
  86. data/models/satoshis.rb +1 -1
  87. data/models/wallet/activity.rb +54 -0
  88. data/models/wallet/balance.rb +42 -0
  89. data/ports/dsl/lighstorm.rb +29 -16
  90. data/static/cache.rb +2 -0
  91. data/static/spec.rb +1 -1
  92. metadata +76 -70
  93. data/adapters/connections/channel_node/fee.rb +0 -26
  94. data/adapters/connections/channel_node/policy.rb +0 -61
  95. data/adapters/connections/channel_node.rb +0 -75
  96. data/adapters/connections/payment_channel.rb +0 -28
  97. data/adapters/edges/channel.rb +0 -96
  98. data/adapters/edges/forward.rb +0 -40
  99. data/adapters/edges/payment/purpose.rb +0 -43
  100. data/adapters/edges/payment.rb +0 -87
  101. data/adapters/invoice.rb +0 -184
  102. data/adapters/nodes/node.rb +0 -111
  103. data/adapters/transaction.rb +0 -23
  104. data/controllers/activity/all.rb +0 -194
  105. data/controllers/activity.rb +0 -26
  106. data/controllers/channel/actions/apply_gossip.rb +0 -193
  107. data/controllers/channel/actions/update_fee.rb +0 -91
  108. data/controllers/channel/all.rb +0 -83
  109. data/controllers/channel/find_by_id.rb +0 -153
  110. data/controllers/channel/mine.rb +0 -114
  111. data/controllers/channel.rb +0 -41
  112. data/controllers/forward/all.rb +0 -248
  113. data/controllers/forward/group_by_channel.rb +0 -89
  114. data/controllers/forward.rb +0 -34
  115. data/controllers/invoice/actions/create.rb +0 -88
  116. data/controllers/invoice/actions/pay.rb +0 -95
  117. data/controllers/invoice/actions/pay_through_route.rb +0 -71
  118. data/controllers/invoice/all.rb +0 -80
  119. data/controllers/invoice/decode.rb +0 -44
  120. data/controllers/invoice/find_by_code.rb +0 -70
  121. data/controllers/invoice/find_by_secret_hash.rb +0 -54
  122. data/controllers/invoice.rb +0 -62
  123. data/controllers/node/actions/apply_gossip.rb +0 -112
  124. data/controllers/node/actions/pay.rb +0 -115
  125. data/controllers/node/all.rb +0 -67
  126. data/controllers/node/find_by_public_key.rb +0 -53
  127. data/controllers/node/myself.rb +0 -34
  128. data/controllers/node.rb +0 -33
  129. data/controllers/payment/actions/pay.rb +0 -108
  130. data/controllers/payment/all.rb +0 -437
  131. data/controllers/payment.rb +0 -35
  132. data/controllers/secret/valid_proof.rb +0 -58
  133. data/controllers/transaction/all.rb +0 -61
  134. data/controllers/transaction.rb +0 -25
  135. data/models/activity.rb +0 -52
  136. data/models/connections/channel_node/accounting.rb +0 -25
  137. data/models/connections/channel_node/fee.rb +0 -80
  138. data/models/connections/channel_node/htlc/blocks/delta.rb +0 -39
  139. data/models/connections/channel_node/htlc.rb +0 -86
  140. data/models/connections/channel_node/policy.rb +0 -39
  141. data/models/connections/channel_node.rb +0 -84
  142. data/models/connections/forward_channel.rb +0 -29
  143. data/models/connections/payment_channel.rb +0 -56
  144. data/models/edges/channel/accounting.rb +0 -85
  145. data/models/edges/channel/hop.rb +0 -65
  146. data/models/edges/channel.rb +0 -195
  147. data/models/edges/forward.rb +0 -49
  148. data/models/edges/groups/channel_forwards/analysis.rb +0 -69
  149. data/models/edges/groups/channel_forwards.rb +0 -37
  150. data/models/edges/payment.rb +0 -102
  151. data/models/invoice.rb +0 -113
  152. data/models/nodes/node/lightning.rb +0 -31
  153. data/models/nodes/node/platform.rb +0 -48
  154. data/models/nodes/node.rb +0 -143
  155. data/models/rate.rb +0 -35
  156. data/models/secret.rb +0 -55
  157. data/models/transaction.rb +0 -39
  158. data/models/wallet.rb +0 -40
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../ports/grpc'
4
+ require_relative '../../../adapters/lightning/nodes/node'
5
+
6
+ module Lighstorm
7
+ module Controller
8
+ module Lightning
9
+ module Node
10
+ module Myself
11
+ def self.fetch(components)
12
+ {
13
+ at: Time.now,
14
+ get_info: components[:grpc].lightning.get_info.to_h
15
+ }
16
+ end
17
+
18
+ def self.adapt(raw)
19
+ { get_info: Lighstorm::Adapter::Lightning::Node.get_info(raw[:get_info]) }
20
+ end
21
+
22
+ def self.data(components, &vcr)
23
+ raw = vcr.nil? ? fetch(components) : vcr.call(-> { fetch(components) })
24
+
25
+ adapted = adapt(raw)
26
+ adapted[:get_info].merge(myself: true)
27
+ end
28
+
29
+ def self.model(data, components)
30
+ Lighstorm::Model::Lightning::Node.new(data, components)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../concerns/impersonatable'
4
+
5
+ require_relative './node/myself'
6
+ require_relative './node/all'
7
+ require_relative './node/find_by_public_key'
8
+
9
+ module Lighstorm
10
+ module Controller
11
+ module Lightning
12
+ module Node
13
+ extend Impersonatable
14
+
15
+ class DSL < Impersonatable::DSL
16
+ def myself
17
+ Myself.model(Myself.data(components), components)
18
+ end
19
+
20
+ def all(limit: nil)
21
+ All.model(All.data(components, limit: limit), components)
22
+ end
23
+
24
+ def find_by_public_key(public_key)
25
+ FindByPublicKey.model(FindByPublicKey.data(components, public_key), components)
26
+ end
27
+
28
+ def adapt(dump: nil, gossip: nil)
29
+ Model::Lightning::Node.adapt(dump: dump, gossip: gossip)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'digest'
5
+
6
+ require_relative '../../../../ports/grpc'
7
+ require_relative '../../../../models/errors'
8
+ require_relative '../../../../models/lightning/edges/payment'
9
+ require_relative '../../../../adapters/lightning/edges/payment'
10
+ require_relative '../../node/myself'
11
+ require_relative '../../invoice/decode'
12
+
13
+ module Lighstorm
14
+ module Controller
15
+ module Lightning
16
+ module Payment
17
+ module Pay
18
+ def self.call(components, grpc_request)
19
+ result = []
20
+ components[:grpc].send(grpc_request[:service]).send(
21
+ grpc_request[:method], grpc_request[:params]
22
+ ) do |response|
23
+ result << response.to_h
24
+ end
25
+ { response: result, exception: nil }
26
+ rescue StandardError => e
27
+ { exception: e }
28
+ end
29
+
30
+ def self.dispatch(components, grpc_request, &vcr)
31
+ if vcr.nil?
32
+ call(components, grpc_request)
33
+ else
34
+ vcr.call(-> { call(components, grpc_request) }, :dispatch)
35
+ end
36
+ end
37
+
38
+ def self.fetch_all(components, code)
39
+ {
40
+ invoice_decode: code.nil? ? nil : Invoice::Decode.data(components, code),
41
+ node_myself: Node::Myself.data(components)
42
+ }
43
+ end
44
+
45
+ def self.fetch(components, code = nil, &vcr)
46
+ raw = vcr.nil? ? fetch_all(components, code) : vcr.call(-> { fetch_all(components, code) })
47
+ end
48
+
49
+ def self.adapt(grpc_data, fetch_data)
50
+ Adapter::Lightning::Payment.send_payment_v2(
51
+ grpc_data[:response].last,
52
+ fetch_data[:node_myself],
53
+ fetch_data[:invoice_decode]
54
+ )
55
+ end
56
+
57
+ def self.model(data, components)
58
+ Model::Lightning::Payment.new(data, components)
59
+ end
60
+
61
+ def self.raise_error_if_exists!(request, response)
62
+ return if response[:exception].nil?
63
+
64
+ if response[:exception].is_a?(GRPC::AlreadyExists)
65
+ raise AlreadyPaidError.new(
66
+ 'The invoice is already paid.',
67
+ request: request, grpc: response[:exception]
68
+ )
69
+ end
70
+
71
+ if response[:exception].message =~ /amount must not be specified when paying a non-zero/
72
+ raise AmountForNonZeroError.new(
73
+ 'Millisatoshis must not be specified when paying a non-zero amount invoice.',
74
+ request: request, grpc: response[:exception]
75
+ )
76
+ end
77
+
78
+ if response[:exception].message =~ /amount must be specified when paying a zero amount/
79
+ raise MissingMillisatoshisError.new(
80
+ 'Millisatoshis must be specified when paying a zero amount invoice.',
81
+ request: request, grpc: response[:exception]
82
+ )
83
+ end
84
+
85
+ raise PaymentError.new(
86
+ response[:exception].message,
87
+ request: request, grpc: response[:exception]
88
+ )
89
+ end
90
+
91
+ def self.raise_failure_if_exists!(model, request, response)
92
+ return unless model.state == 'failed'
93
+
94
+ if response[:response].last[:failure_reason] == :FAILURE_REASON_NO_ROUTE
95
+ raise NoRouteFoundError.new(
96
+ response[:response].last[:failure_reason],
97
+ request: request, response: response[:response], result: model
98
+ )
99
+ else
100
+ raise PaymentError.new(
101
+ response[:response].last[:failure_reason],
102
+ request: request, response: response[:response], result: model
103
+ )
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,439 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../ports/grpc'
4
+ require_relative '../../../adapters/lightning/nodes/node'
5
+ require_relative '../../../adapters/lightning/edges/payment'
6
+ require_relative '../../../adapters/lightning/invoice'
7
+ require_relative '../../../adapters/lightning/edges/payment/purpose'
8
+
9
+ require_relative '../../../models/lightning/edges/payment'
10
+
11
+ module Lighstorm
12
+ module Controller
13
+ module Lightning
14
+ module Payment
15
+ module All
16
+ def self.fetch(components, purpose: nil, invoice_code: nil, secret_hash: nil, limit: nil, fetch: {})
17
+ at = Time.now
18
+
19
+ grpc = components[:grpc].session
20
+
21
+ get_info = grpc.lightning.get_info.to_h
22
+
23
+ last_offset = 0
24
+
25
+ payments = []
26
+
27
+ loop do
28
+ response = grpc.lightning.list_payments(
29
+ index_offset: last_offset
30
+ )
31
+
32
+ response.payments.each do |payment|
33
+ payment = payment.to_h
34
+
35
+ next unless invoice_code.nil? || payment[:payment_request] == invoice_code
36
+
37
+ next unless secret_hash.nil? || payment[:payment_hash] == secret_hash
38
+
39
+ payment_purpose = Adapter::Lightning::Purpose.list_payments(payment, get_info)
40
+
41
+ case purpose
42
+ when 'self-payment', 'self'
43
+ payments << payment if payment_purpose == 'self-payment'
44
+ when 'peer-to-peer', 'p2p'
45
+ payments << payment if payment_purpose == 'peer-to-peer'
46
+ when '!peer-to-peer', '!p2p'
47
+ payments << payment unless payment_purpose == 'peer-to-peer'
48
+ when 'rebalance'
49
+ payments << payment if payment_purpose == 'rebalance'
50
+ when '!rebalance'
51
+ payments << payment unless payment_purpose == 'rebalance'
52
+ when '!payment'
53
+ payments << payment unless payment_purpose == 'payment'
54
+ when 'payment'
55
+ payments << payment if payment_purpose == 'payment'
56
+ else
57
+ payments << payment
58
+ end
59
+ end
60
+
61
+ # TODO: How to optimize this?
62
+ # break if !limit.nil? && payments.size >= limit
63
+
64
+ break if last_offset == response.last_index_offset || last_offset > response.last_index_offset
65
+
66
+ last_offset = response.last_index_offset
67
+ end
68
+
69
+ payments = payments.sort_by { |raw_payment| -raw_payment[:creation_time_ns] }
70
+
71
+ payments = payments[0..limit - 1] unless limit.nil?
72
+
73
+ data = {
74
+ at: at,
75
+ get_info: get_info,
76
+ fee_report: grpc.lightning.fee_report.to_h,
77
+ list_payments: payments,
78
+ list_channels: {},
79
+ get_chan_info: {},
80
+ get_node_info: {},
81
+ lookup_invoice: {},
82
+ decode_pay_req: {}
83
+ }
84
+
85
+ payments.each do |payment|
86
+ unless fetch[:decode_pay_req] == false || payment[:payment_request] == '' || data[:decode_pay_req][payment[:payment_request]]
87
+ data[:decode_pay_req][payment[:payment_request]] = grpc.lightning.decode_pay_req(
88
+ pay_req: payment[:payment_request]
89
+ ).to_h
90
+ end
91
+
92
+ unless fetch[:lookup_invoice] == false || data[:lookup_invoice][payment[:payment_hash]]
93
+ begin
94
+ data[:lookup_invoice][payment[:payment_hash]] = grpc.lightning.lookup_invoice(
95
+ r_hash_str: payment[:payment_hash]
96
+ ).to_h
97
+ rescue StandardError => e
98
+ data[:lookup_invoice][payment[:payment_hash]] = { _error: e }
99
+ end
100
+ end
101
+
102
+ payment[:htlcs].each do |htlc|
103
+ htlc[:route][:hops].each do |hop|
104
+ unless fetch[:get_chan_info] == false || data[:get_chan_info][hop[:chan_id]]
105
+ begin
106
+ data[:get_chan_info][hop[:chan_id]] = grpc.lightning.get_chan_info(
107
+ chan_id: hop[:chan_id]
108
+ ).to_h
109
+ rescue GRPC::Unknown => e
110
+ data[:get_chan_info][hop[:chan_id]] = { _error: e }
111
+ end
112
+ end
113
+
114
+ next if fetch[:get_node_info] == false || data[:get_node_info][hop[:pub_key]]
115
+
116
+ begin
117
+ data[:get_node_info][hop[:pub_key]] = grpc.lightning.get_node_info(
118
+ pub_key: hop[:pub_key]
119
+ ).to_h
120
+ rescue StandardError => e
121
+ data[:get_node_info][hop[:pub_key]] = { _error: e }
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ if fetch[:lookup_invoice] != false
128
+ data[:lookup_invoice].each_value do |invoice|
129
+ if fetch[:decode_pay_req] == false || invoice[:_error] || invoice[:payment_request] == '' || data[:decode_pay_req][invoice[:payment_request]]
130
+ next
131
+ end
132
+
133
+ data[:decode_pay_req][invoice[:payment_request]] = grpc.lightning.decode_pay_req(
134
+ pay_req: invoice[:payment_request]
135
+ ).to_h
136
+ end
137
+ end
138
+
139
+ list_channels_done = {}
140
+
141
+ data[:get_chan_info].each_value do |channel|
142
+ next if channel[:_error]
143
+
144
+ partners = [channel[:node1_pub], channel[:node2_pub]]
145
+
146
+ is_mine = partners.include?(data[:get_info][:identity_pubkey])
147
+
148
+ if is_mine
149
+ partner = partners.find { |p| p != data[:get_info][:identity_pubkey] }
150
+
151
+ unless list_channels_done[partner]
152
+ grpc.lightning.list_channels(
153
+ peer: [partner].pack('H*')
154
+ ).channels.map(&:to_h).each do |list_channels|
155
+ data[:list_channels][list_channels[:chan_id]] = list_channels
156
+ end
157
+
158
+ list_channels_done[partner] = true
159
+ end
160
+ end
161
+
162
+ unless fetch[:get_node_info] == false || data[:get_node_info][channel[:node1_pub]]
163
+ begin
164
+ data[:get_node_info][channel[:node1_pub]] = grpc.lightning.get_node_info(
165
+ pub_key: channel[:node1_pub]
166
+ ).to_h
167
+ rescue StandardError => e
168
+ data[:get_node_info][channel[:node1_pub]] = { _error: e }
169
+ end
170
+ end
171
+
172
+ next if fetch[:get_node_info] == false || data[:get_node_info][channel[:node2_pub]]
173
+
174
+ begin
175
+ data[:get_node_info][channel[:node2_pub]] = grpc.lightning.get_node_info(
176
+ pub_key: channel[:node2_pub]
177
+ ).to_h
178
+ rescue StandardError => e
179
+ data[:get_node_info][channel[:node2_pub]] = { _error: e }
180
+ end
181
+ end
182
+
183
+ data[:list_channels].each_value do |channel|
184
+ next if fetch[:get_node_info] == false || data[:get_node_info][channel[:remote_pubkey]]
185
+
186
+ begin
187
+ data[:get_node_info][channel[:remote_pubkey]] = grpc.lightning.get_node_info(
188
+ pub_key: channel[:remote_pubkey]
189
+ ).to_h
190
+ rescue StandardError => e
191
+ data[:get_node_info][channel[:remote_pubkey]] = { _error: e }
192
+ end
193
+ end
194
+
195
+ data[:@meta] = { calls: grpc.calls }
196
+
197
+ data
198
+ end
199
+
200
+ def self.adapt(raw)
201
+ adapted = {
202
+ get_info: Lighstorm::Adapter::Lightning::Node.get_info(raw[:get_info]),
203
+ list_payments: raw[:list_payments].map do |raw_payment|
204
+ Lighstorm::Adapter::Lightning::Payment.list_payments(raw_payment, raw[:get_info])
205
+ end,
206
+ fee_report: raw[:fee_report][:channel_fees].map do |raw_fee|
207
+ Lighstorm::Adapter::Lightning::Fee.fee_report(raw_fee.to_h)
208
+ end,
209
+ lookup_invoice: {},
210
+ list_channels: {},
211
+ get_chan_info: {},
212
+ get_node_info: {},
213
+ decode_pay_req: {}
214
+ }
215
+
216
+ raw[:decode_pay_req].each_key do |key|
217
+ next if raw[:decode_pay_req][key][:_error]
218
+
219
+ adapted[:decode_pay_req][key] = Lighstorm::Adapter::Lightning::Invoice.decode_pay_req(
220
+ raw[:decode_pay_req][key]
221
+ )
222
+ end
223
+
224
+ raw[:lookup_invoice].each_key do |key|
225
+ next if raw[:lookup_invoice][key][:_error]
226
+
227
+ adapted[:lookup_invoice][key] = Lighstorm::Adapter::Lightning::Invoice.lookup_invoice(
228
+ raw[:lookup_invoice][key], raw[:at]
229
+ )
230
+ end
231
+
232
+ raw[:get_chan_info].each_key do |key|
233
+ next if raw[:get_chan_info][key][:_error]
234
+
235
+ adapted[:get_chan_info][key] = Lighstorm::Adapter::Lightning::Channel.get_chan_info(
236
+ raw[:get_chan_info][key]
237
+ )
238
+ end
239
+
240
+ raw[:list_channels].each_key do |key|
241
+ adapted[:list_channels][key] = Lighstorm::Adapter::Lightning::Channel.list_channels(
242
+ raw[:list_channels][key], raw[:at]
243
+ )
244
+ end
245
+
246
+ raw[:get_node_info].each_key do |key|
247
+ next if raw[:get_node_info][key][:_error]
248
+
249
+ adapted[:get_node_info][key] = Lighstorm::Adapter::Lightning::Node.get_node_info(
250
+ raw[:get_node_info][key]
251
+ )
252
+ end
253
+
254
+ adapted
255
+ end
256
+
257
+ def self.transform_channel(data, adapted)
258
+ if adapted[:get_chan_info][data[:id].to_i]
259
+ target = data[:target]
260
+ data = adapted[:get_chan_info][data[:id].to_i]
261
+ data[:target] = target
262
+ data[:known] = true
263
+ else
264
+ data[:_key] = Digest::SHA256.hexdigest(data[:id])
265
+ end
266
+
267
+ data[:mine] = true if data[:partners].size == 1
268
+
269
+ [0, 1].each do |i|
270
+ next unless data[:partners] && data[:partners][i]
271
+
272
+ if data[:partners][i][:node][:public_key] == adapted[:get_info][:public_key]
273
+ data[:partners][i][:node] = adapted[:get_info]
274
+ end
275
+
276
+ data[:partners].each do |partner|
277
+ if data[:partners][i][:node][:public_key] == partner[:node][:public_key]
278
+ data[:partners][i][:policy] = partner[:policy]
279
+ end
280
+ end
281
+
282
+ if data[:partners][i][:node][:public_key] == adapted[:get_info][:public_key]
283
+ data[:partners][i][:node][:platform] = adapted[:get_info][:platform]
284
+ data[:partners][i][:node][:myself] = true
285
+ data[:mine] = true
286
+ adapted[:fee_report].each do |channel|
287
+ next unless data[:id] == channel[:id]
288
+
289
+ if data[:partners][i][:policy].nil?
290
+ data[:partners][i][:policy] = channel[:partner][:policy]
291
+ else
292
+ data[:partners][i][:policy][:fee] = channel[:partner][:policy][:fee]
293
+ end
294
+ break
295
+ end
296
+ else
297
+ if adapted[:get_node_info][data[:partners][i][:node][:public_key]]
298
+ data[:partners][i][:node] = adapted[:get_node_info][data[:partners][i][:node][:public_key]]
299
+ end
300
+ data[:partners][i][:node][:platform] = {
301
+ blockchain: adapted[:get_info][:platform][:blockchain],
302
+ network: adapted[:get_info][:platform][:network]
303
+ }
304
+
305
+ data[:partners][i][:node][:myself] = false
306
+ end
307
+ end
308
+
309
+ channel = adapted[:list_channels][data[:id].to_i]
310
+
311
+ return data unless channel
312
+
313
+ channel.each_key do |key|
314
+ next if data.key?(key)
315
+
316
+ data[key] = channel[key]
317
+ end
318
+
319
+ data[:accounting] = channel[:accounting]
320
+
321
+ channel[:partners].each do |partner|
322
+ data[:partners].each_index do |i|
323
+ partner.each_key do |key|
324
+ next if data[:partners][i].key?(key)
325
+
326
+ data[:partners][i][key] = partner[key]
327
+ end
328
+ end
329
+ end
330
+
331
+ data
332
+ end
333
+
334
+ def self.transform(list_payments, adapted)
335
+ if adapted[:lookup_invoice][list_payments[:secret][:hash]] &&
336
+ !adapted[:lookup_invoice][list_payments[:secret][:hash]][:_error]
337
+
338
+ if list_payments[:invoice]
339
+ lookup = adapted[:lookup_invoice][list_payments[:secret][:hash]]
340
+
341
+ list_payments[:invoice][:description] = lookup[:description]
342
+
343
+ lookup.each_key do |key|
344
+ if lookup[key].is_a?(Hash)
345
+ unless list_payments[:invoice].key?(key) && !list_payments[:invoice][key].nil?
346
+ list_payments[:invoice][key] = lookup[:key]
347
+ end
348
+
349
+ next
350
+ end
351
+
352
+ unless list_payments[:invoice].key?(key) && !list_payments[:invoice][key].nil? &&
353
+ (!list_payments[:invoice][key].is_a?(String) || !list_payments[:invoice][key].empty?)
354
+ list_payments[:invoice][key] = lookup[key]
355
+ end
356
+ end
357
+ else
358
+ list_payments[:invoice] = adapted[:lookup_invoice][list_payments[:secret][:hash]]
359
+ end
360
+ end
361
+
362
+ list_payments[:hops].each do |hop|
363
+ hop[:channel] = transform_channel(hop[:channel], adapted)
364
+ end
365
+
366
+ if adapted[:decode_pay_req][list_payments[:invoice][:code]]
367
+ decoded = adapted[:decode_pay_req][list_payments[:invoice][:code]]
368
+ invoice = list_payments[:invoice]
369
+
370
+ decoded.each_key do |key|
371
+ if !decoded[key].is_a?(Hash)
372
+ invoice[key] = decoded[key]
373
+ elsif decoded[key].is_a?(Hash)
374
+ invoice[key] = {} unless invoice.key?(key)
375
+
376
+ next if key == :secret
377
+
378
+ decoded[key].each_key do |sub_key|
379
+ next if decoded[key][sub_key].nil? ||
380
+ (decoded[key][sub_key].is_a?(String) && decoded[key][sub_key].empty?)
381
+
382
+ invoice[key][sub_key] = decoded[key][sub_key]
383
+ end
384
+ end
385
+ end
386
+ end
387
+
388
+ if list_payments[:invoice][:code]
389
+ if list_payments[:invoice][:payable] == 'once'
390
+ list_payments[:through] = 'non-amp'
391
+ elsif list_payments[:invoice][:payable] == 'indefinitely'
392
+ list_payments[:through] = 'amp'
393
+ end
394
+ end
395
+
396
+ list_payments
397
+ end
398
+
399
+ def self.data(
400
+ components,
401
+ purpose: nil, invoice_code: nil, secret_hash: nil, limit: nil,
402
+ fetch: {}, &vcr
403
+ )
404
+ raw = if vcr.nil?
405
+ self.fetch(
406
+ components,
407
+ purpose: purpose, invoice_code: invoice_code, secret_hash: secret_hash,
408
+ limit: limit, fetch: fetch
409
+ )
410
+ else
411
+ vcr.call(lambda {
412
+ self.fetch(
413
+ components,
414
+ purpose: purpose, invoice_code: invoice_code, secret_hash: secret_hash,
415
+ limit: limit, fetch: fetch
416
+ )
417
+ })
418
+ end
419
+
420
+ adapted = adapt(raw)
421
+
422
+ {
423
+ data: adapted[:list_payments].map do |data|
424
+ transform(data, adapted)
425
+ end,
426
+ meta: raw[:@meta]
427
+ }
428
+ end
429
+
430
+ def self.model(data, components)
431
+ data[:data].map do |node_data|
432
+ Lighstorm::Model::Lightning::Payment.new(node_data, components)
433
+ end
434
+ end
435
+ end
436
+ end
437
+ end
438
+ end
439
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../concerns/impersonatable'
4
+
5
+ require_relative './payment/all'
6
+
7
+ module Lighstorm
8
+ module Controller
9
+ module Lightning
10
+ module Payment
11
+ extend Impersonatable
12
+
13
+ class DSL < Impersonatable::DSL
14
+ def all(purpose: nil, limit: nil, fetch: {})
15
+ All.model(All.data(components, purpose: purpose, limit: limit, fetch: fetch), components)
16
+ end
17
+
18
+ def first(purpose: nil, fetch: {})
19
+ All.model(All.data(components, purpose: purpose, fetch: fetch), components).first
20
+ end
21
+
22
+ def last(purpose: nil, fetch: {})
23
+ All.model(All.data(components, purpose: purpose, fetch: fetch), components).last
24
+ end
25
+
26
+ def find_by_secret_hash(secret_hash, &vcr)
27
+ All.model(All.data(components, secret_hash: secret_hash, &vcr), components).first
28
+ end
29
+
30
+ def find_by_invoice_code(invoice_code, &vcr)
31
+ All.model(All.data(components, invoice_code: invoice_code, &vcr), components).first
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end