lighstorm 0.0.4 → 0.0.6

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-rspec-tests.yml +39 -0
  3. data/Gemfile.lock +3 -3
  4. data/README.md +5 -5
  5. data/adapters/connections/channel_node/policy.rb +61 -0
  6. data/adapters/connections/channel_node.rb +40 -18
  7. data/adapters/edges/channel.rb +23 -7
  8. data/adapters/edges/forward.rb +1 -2
  9. data/adapters/edges/payment/purpose.rb +0 -2
  10. data/adapters/edges/payment.rb +2 -5
  11. data/adapters/invoice.rb +2 -3
  12. data/adapters/nodes/node.rb +39 -5
  13. data/adapters/payment_request.rb +0 -1
  14. data/controllers/channel/actions/apply_gossip.rb +194 -0
  15. data/controllers/channel/find_by_id.rb +1 -1
  16. data/controllers/channel/mine.rb +1 -1
  17. data/controllers/channel.rb +4 -0
  18. data/controllers/invoice/actions/create.rb +10 -9
  19. data/controllers/invoice.rb +1 -1
  20. data/controllers/node/actions/apply_gossip.rb +112 -0
  21. data/controllers/node.rb +4 -0
  22. data/controllers/payment/all.rb +52 -36
  23. data/controllers/payment.rb +6 -6
  24. data/docs/README.md +109 -13
  25. data/docs/_coverpage.md +1 -1
  26. data/docs/index.html +1 -1
  27. data/models/concerns/protectable.rb +23 -0
  28. data/models/connections/channel_node/accounting.rb +4 -0
  29. data/models/connections/channel_node/fee.rb +27 -18
  30. data/models/connections/channel_node/htlc/blocks/delta.rb +39 -0
  31. data/models/connections/channel_node/htlc.rb +48 -14
  32. data/models/connections/channel_node/policy.rb +11 -2
  33. data/models/connections/channel_node.rb +33 -1
  34. data/models/edges/channel/accounting.rb +17 -0
  35. data/models/edges/channel.rb +39 -5
  36. data/models/edges/forward.rb +0 -1
  37. data/models/edges/payment.rb +0 -1
  38. data/models/errors.rb +3 -0
  39. data/models/nodes/node/lightning.rb +6 -0
  40. data/models/nodes/node/platform.rb +6 -0
  41. data/models/nodes/node.rb +51 -0
  42. data/models/payment_request.rb +6 -3
  43. data/ports/grpc/session.rb +26 -0
  44. data/ports/grpc.rb +23 -5
  45. data/static/spec.rb +1 -1
  46. metadata +9 -2
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ require_relative '../../../ports/grpc'
6
+ require_relative '../../../models/errors'
7
+ require_relative '../../../models/edges/channel'
8
+ require_relative '../../../adapters/edges/channel'
9
+
10
+ module Lighstorm
11
+ module Controllers
12
+ module Channel
13
+ module ApplyGossip
14
+ SKIPABLE = [
15
+ '_key',
16
+ '_source',
17
+ 'partners/0/_source',
18
+ 'partners/0/policy/_source',
19
+ 'partners/1/_source',
20
+ 'partners/1/policy/_source'
21
+ ].freeze
22
+
23
+ NOT_ALLOWED = [
24
+ 'id'
25
+ ].freeze
26
+
27
+ APPLICABLE = [
28
+ 'accounting/capacity/milisatoshis',
29
+ 'partners/0/policy/fee/base/milisatoshis',
30
+ 'partners/0/state',
31
+ 'partners/1/policy/fee/base/milisatoshis',
32
+ 'partners/1/state',
33
+ 'partners/1/policy/fee/rate/parts_per_million',
34
+ 'partners/0/policy/fee/rate/parts_per_million',
35
+ 'partners/0/policy/htlc/minimum/milisatoshis',
36
+ 'partners/1/policy/htlc/minimum/milisatoshis',
37
+ 'partners/0/policy/htlc/maximum/milisatoshis',
38
+ 'partners/1/policy/htlc/maximum/milisatoshis',
39
+ 'partners/0/policy/htlc/blocks/delta/minimum',
40
+ 'partners/1/policy/htlc/blocks/delta/minimum'
41
+ ].freeze
42
+
43
+ def self.perform(actual, gossip)
44
+ updated = Models::Channel.new(Adapter::Channel.subscribe_channel_graph(gossip))
45
+
46
+ actual_dump = actual.dump
47
+ updated_dump = updated.dump
48
+
49
+ if actual.partners.first.node.public_key == updated.partners.last.node.public_key &&
50
+ actual.partners.last.node.public_key == updated.partners.first.node.public_key
51
+ a = updated_dump[:partners][0]
52
+ b = updated_dump[:partners][1]
53
+
54
+ updated_dump[:partners][0] = b
55
+ updated_dump[:partners][1] = a
56
+ end
57
+
58
+ diff = generate_diff(actual_dump, updated_dump)
59
+
60
+ diff.each do |change|
61
+ key = change[:path].join('/')
62
+ next unless NOT_ALLOWED.include?(key)
63
+
64
+ raise IncoherentGossipError, "Gossip doesn't belong to this Channel"
65
+ end
66
+
67
+ diff.filter do |change|
68
+ key = change[:path].join('/')
69
+ if SKIPABLE.include?(key)
70
+ false
71
+ elsif APPLICABLE.include?(key)
72
+ apply!(actual, key, change)
73
+ true
74
+ else
75
+ raise Lighstorm::Errors::MissingGossipHandlerError, "don't know how to apply '#{key}'"
76
+ end
77
+ end
78
+ end
79
+
80
+ def self.apply!(actual, key, change)
81
+ case key
82
+ when 'accounting/capacity/milisatoshis'
83
+ token = SecureRandom.hex
84
+ actual.accounting.prepare_token!(token)
85
+ actual.accounting.capacity = {
86
+ value: Models::Satoshis.new(milisatoshis: change[:to]),
87
+ token: token
88
+ }
89
+ when 'partners/0/policy/htlc/maximum/milisatoshis',
90
+ 'partners/1/policy/htlc/maximum/milisatoshis' then
91
+ policy = actual.partners[change[:path][1]].policy
92
+
93
+ token = SecureRandom.hex
94
+ policy.htlc.prepare_token!(token)
95
+ policy.htlc.maximum = {
96
+ value: Models::Satoshis.new(milisatoshis: change[:to]),
97
+ token: token
98
+ }
99
+ when 'partners/0/policy/htlc/minimum/milisatoshis',
100
+ 'partners/1/policy/htlc/minimum/milisatoshis' then
101
+ if actual.partners[change[:path][1]].policy.nil?
102
+ actual.partners[change[:path][1]].policy = Lighstorm::Models::Policy.new({})
103
+ end
104
+
105
+ policy = actual.partners[change[:path][1]].policy
106
+
107
+ token = SecureRandom.hex
108
+ policy.htlc.prepare_token!(token)
109
+ policy.htlc.minimum = {
110
+ value: Models::Satoshis.new(milisatoshis: change[:to]),
111
+ token: token
112
+ }
113
+ when 'partners/0/policy/htlc/blocks/delta/minimum',
114
+ 'partners/1/policy/htlc/blocks/delta/minimum' then
115
+ if actual.partners[change[:path][1]].policy.nil?
116
+ actual.partners[change[:path][1]].policy = Lighstorm::Models::Policy.new({})
117
+ end
118
+
119
+ policy = actual.partners[change[:path][1]].policy
120
+
121
+ token = SecureRandom.hex
122
+ policy.htlc.blocks.delta.prepare_token!(token)
123
+ policy.htlc.blocks.delta.minimum = {
124
+ value: change[:to],
125
+ token: token
126
+ }
127
+ when 'partners/0/policy/fee/rate/parts_per_million',
128
+ 'partners/1/policy/fee/rate/parts_per_million' then
129
+ policy = actual.partners[change[:path][1]].policy
130
+
131
+ token = SecureRandom.hex
132
+ policy.fee.prepare_token!(token)
133
+ policy.fee.rate = {
134
+ value: Models::Rate.new(parts_per_million: change[:to]),
135
+ token: token
136
+ }
137
+ when 'partners/0/policy/fee/base/milisatoshis',
138
+ 'partners/1/policy/fee/base/milisatoshis' then
139
+ policy = actual.partners[change[:path][1]].policy
140
+
141
+ token = SecureRandom.hex
142
+ policy.fee.prepare_token!(token)
143
+ policy.fee.base = {
144
+ value: Models::Satoshis.new(milisatoshis: change[:to]),
145
+ token: token
146
+ }
147
+ when 'partners/0/state',
148
+ 'partners/1/state' then
149
+ partner = actual.partners[change[:path][1]]
150
+
151
+ token = SecureRandom.hex
152
+ partner.prepare_token!(token)
153
+ partner.state = { value: change[:to], token: token }
154
+ else
155
+ raise Lighstorm::Errors::MissingGossipHandlerError, "don't know how to apply '#{key}'"
156
+ end
157
+ end
158
+
159
+ def self.generate_diff(actual, node, path = [], diff = [])
160
+ case node
161
+ when Hash
162
+ result = {}
163
+ node.each_key do |key|
164
+ result[key] = generate_diff(actual, node[key], path.dup.push(key), diff)
165
+ end
166
+ when Array
167
+ result = []
168
+ node.each_with_index do |value, i|
169
+ result << generate_diff(actual, value, path.dup.push(i), diff)
170
+ end
171
+ else
172
+ new_value = node
173
+
174
+ unless new_value.nil?
175
+ actual_value = actual
176
+ path.each do |key|
177
+ if actual_value[key]
178
+ actual_value = actual_value[key]
179
+ else
180
+ actual_value = nil
181
+ break
182
+ end
183
+ end
184
+
185
+ diff << { path: path, from: actual_value, to: new_value } if actual_value != new_value
186
+ end
187
+ end
188
+
189
+ diff
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -73,7 +73,7 @@ module Lighstorm
73
73
  def self.transform(data, adapted)
74
74
  [0, 1].each do |i|
75
75
  adapted[:list_channels].each_index do |c|
76
- if adapted[:list_channels][c][:partners][i][:node][:public_key].nil?
76
+ if adapted[:list_channels][c][:partners][i][:node].nil?
77
77
  adapted[:list_channels][c][:partners][i][:node] = adapted[:get_info]
78
78
  end
79
79
  end
@@ -63,7 +63,7 @@ module Lighstorm
63
63
 
64
64
  def self.transform(data, adapted)
65
65
  [0, 1].each do |i|
66
- data[:partners][i][:node] = adapted[:get_info] if data[:partners][i][:node][:public_key].nil?
66
+ data[:partners][i][:node] = adapted[:get_info] if data[:partners][i][:node].nil?
67
67
 
68
68
  adapted[:get_chan_info][data[:id].to_i][:partners].each do |partner|
69
69
  if data[:partners][i][:node][:public_key] == partner[:node][:public_key]
@@ -18,6 +18,10 @@ module Lighstorm
18
18
  def self.find_by_id(id)
19
19
  FindById.model(FindById.data(id))
20
20
  end
21
+
22
+ def self.adapt(dump: nil, gossip: nil)
23
+ Models::Channel.adapt(dump: dump, gossip: gossip)
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -2,14 +2,13 @@
2
2
 
3
3
  require_relative '../../../ports/grpc'
4
4
  require_relative '../../../models/errors'
5
+ require_relative '../../invoice'
5
6
 
6
7
  module Lighstorm
7
8
  module Controllers
8
9
  module Invoice
9
10
  module Create
10
- def self.perform(description: nil, milisatoshis: nil, preview: false, fake: false)
11
- raise Errors::ToDoError, self
12
-
11
+ def self.perform(description: nil, milisatoshis: nil, preview: false, fake: nil)
13
12
  grpc_request = {
14
13
  service: :lightning,
15
14
  method: :add_invoice,
@@ -22,13 +21,15 @@ module Lighstorm
22
21
  return grpc_request if preview
23
22
 
24
23
  # expiry: Default is 86400 (24 hours).
25
- response = LND.instance.middleware("lightning.#{grpc_request[:method]}") do
26
- LND.instance.client.lightning.send(grpc_request[:method], grpc_request[:params])
27
- end
24
+ response = if fake.nil?
25
+ LND.instance.middleware("lightning.#{grpc_request[:method]}") do
26
+ LND.instance.client.lightning.send(grpc_request[:method], grpc_request[:params])
27
+ end.to_h
28
+ else
29
+ fake
30
+ end
28
31
 
29
- # TODO
30
- # find_by_secret_hash(invoice.r_hash.unpack1('H*'))
31
- # response
32
+ Invoice.find_by_secret_hash(response[:r_hash].unpack1('H*'))
32
33
  end
33
34
  end
34
35
  end
@@ -23,7 +23,7 @@ module Lighstorm
23
23
  FindBySecretHash.model(FindBySecretHash.data(secret_hash))
24
24
  end
25
25
 
26
- def self.create(description: nil, milisatoshis: nil, preview: false, fake: false)
26
+ def self.create(description: nil, milisatoshis: nil, preview: false, fake: nil)
27
27
  Create.perform(
28
28
  description: description,
29
29
  milisatoshis: milisatoshis,
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ require_relative '../../../ports/grpc'
6
+ require_relative '../../../models/errors'
7
+ require_relative '../../../models/nodes/node'
8
+ require_relative '../../../adapters/nodes/node'
9
+
10
+ module Lighstorm
11
+ module Controllers
12
+ module Node
13
+ module ApplyGossip
14
+ SKIPABLE = %w[
15
+ _source
16
+ _key
17
+ ].freeze
18
+
19
+ NOT_ALLOWED = [
20
+ 'public_key'
21
+ ].freeze
22
+
23
+ APPLICABLE = %w[
24
+ alias
25
+ color
26
+ ].freeze
27
+
28
+ def self.perform(actual, gossip)
29
+ updated = Models::Node.new(Adapter::Node.subscribe_channel_graph(gossip))
30
+
31
+ actual_dump = actual.dump
32
+ updated_dump = updated.dump
33
+
34
+ diff = generate_diff(actual_dump, updated_dump)
35
+
36
+ diff.each do |change|
37
+ key = change[:path].join('/')
38
+ next unless NOT_ALLOWED.include?(key)
39
+
40
+ raise IncoherentGossipError, "Gossip doesn't belong to this Node"
41
+ end
42
+
43
+ diff.filter do |change|
44
+ key = change[:path].join('/')
45
+ if SKIPABLE.include?(key)
46
+ false
47
+ elsif APPLICABLE.include?(key)
48
+ apply!(actual, key, change)
49
+ true
50
+ else
51
+ raise Lighstorm::Errors::MissingGossipHandlerError, "don't know how to apply '#{key}'"
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.apply!(actual, key, change)
57
+ case key
58
+ when 'alias'
59
+ token = SecureRandom.hex
60
+ actual.prepare_token!(token)
61
+ actual.alias = {
62
+ value: change[:to],
63
+ token: token
64
+ }
65
+ when 'color'
66
+ token = SecureRandom.hex
67
+ actual.prepare_token!(token)
68
+ actual.color = {
69
+ value: change[:to],
70
+ token: token
71
+ }
72
+ else
73
+ raise Lighstorm::Errors::MissingGossipHandlerError, "don't know how to apply '#{key}'"
74
+ end
75
+ end
76
+
77
+ def self.generate_diff(actual, node, path = [], diff = [])
78
+ case node
79
+ when Hash
80
+ result = {}
81
+ node.each_key do |key|
82
+ result[key] = generate_diff(actual, node[key], path.dup.push(key), diff)
83
+ end
84
+ when Array
85
+ result = []
86
+ node.each_with_index do |value, i|
87
+ result << generate_diff(actual, value, path.dup.push(i), diff)
88
+ end
89
+ else
90
+ new_value = node
91
+
92
+ unless new_value.nil?
93
+ actual_value = actual
94
+ path.each do |key|
95
+ if actual_value[key]
96
+ actual_value = actual_value[key]
97
+ else
98
+ actual_value = nil
99
+ break
100
+ end
101
+ end
102
+
103
+ diff << { path: path, from: actual_value, to: new_value } if actual_value != new_value
104
+ end
105
+ end
106
+
107
+ diff
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
data/controllers/node.rb CHANGED
@@ -18,6 +18,10 @@ module Lighstorm
18
18
  def self.find_by_public_key(public_key)
19
19
  FindByPublicKey.model(FindByPublicKey.data(public_key))
20
20
  end
21
+
22
+ def self.adapt(dump: nil, gossip: nil)
23
+ Models::Node.adapt(dump: dump, gossip: gossip)
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -12,16 +12,19 @@ module Lighstorm
12
12
  module Controllers
13
13
  module Payment
14
14
  module All
15
- def self.fetch(purpose: nil, limit: nil)
15
+ def self.fetch(purpose: nil, limit: nil, fetch: {})
16
16
  at = Time.now
17
- get_info = Ports::GRPC.lightning.get_info.to_h
17
+
18
+ grpc = Ports::GRPC.session
19
+
20
+ get_info = grpc.lightning.get_info.to_h
18
21
 
19
22
  last_offset = 0
20
23
 
21
24
  payments = []
22
25
 
23
26
  loop do
24
- response = Ports::GRPC.lightning.list_payments(
27
+ response = grpc.lightning.list_payments(
25
28
  index_offset: last_offset
26
29
  )
27
30
 
@@ -64,8 +67,8 @@ module Lighstorm
64
67
 
65
68
  data = {
66
69
  at: at,
67
- get_info: Ports::GRPC.lightning.get_info.to_h,
68
- fee_report: Ports::GRPC.lightning.fee_report.to_h,
70
+ get_info: get_info,
71
+ fee_report: grpc.lightning.fee_report.to_h,
69
72
  list_payments: payments,
70
73
  list_channels: {},
71
74
  get_chan_info: {},
@@ -75,15 +78,15 @@ module Lighstorm
75
78
  }
76
79
 
77
80
  payments.each do |payment|
78
- unless payment[:payment_request] == '' || data[:decode_pay_req][payment[:payment_request]]
79
- data[:decode_pay_req][payment[:payment_request]] = Ports::GRPC.lightning.decode_pay_req(
81
+ unless fetch[:decode_pay_req] == false || payment[:payment_request] == '' || data[:decode_pay_req][payment[:payment_request]]
82
+ data[:decode_pay_req][payment[:payment_request]] = grpc.lightning.decode_pay_req(
80
83
  pay_req: payment[:payment_request]
81
84
  ).to_h
82
85
  end
83
86
 
84
- unless data[:lookup_invoice][payment[:payment_hash]]
87
+ unless fetch[:lookup_invoice] == false || data[:lookup_invoice][payment[:payment_hash]]
85
88
  begin
86
- data[:lookup_invoice][payment[:payment_hash]] = Ports::GRPC.lightning.lookup_invoice(
89
+ data[:lookup_invoice][payment[:payment_hash]] = grpc.lightning.lookup_invoice(
87
90
  r_hash_str: payment[:payment_hash]
88
91
  ).to_h
89
92
  rescue StandardError => e
@@ -93,9 +96,9 @@ module Lighstorm
93
96
 
94
97
  payment[:htlcs].each do |htlc|
95
98
  htlc[:route][:hops].each do |hop|
96
- unless data[:get_chan_info][hop[:chan_id]]
99
+ unless fetch[:get_chan_info] == false || data[:get_chan_info][hop[:chan_id]]
97
100
  begin
98
- data[:get_chan_info][hop[:chan_id]] = Ports::GRPC.lightning.get_chan_info(
101
+ data[:get_chan_info][hop[:chan_id]] = grpc.lightning.get_chan_info(
99
102
  chan_id: hop[:chan_id]
100
103
  ).to_h
101
104
  rescue GRPC::Unknown => e
@@ -103,23 +106,25 @@ module Lighstorm
103
106
  end
104
107
  end
105
108
 
106
- next if data[:get_node_info][hop[:pub_key]]
109
+ next if fetch[:get_node_info] == false || data[:get_node_info][hop[:pub_key]]
107
110
 
108
- data[:get_node_info][hop[:pub_key]] = Ports::GRPC.lightning.get_node_info(
111
+ data[:get_node_info][hop[:pub_key]] = grpc.lightning.get_node_info(
109
112
  pub_key: hop[:pub_key]
110
113
  ).to_h
111
114
  end
112
115
  end
113
116
  end
114
117
 
115
- data[:lookup_invoice].each_value do |invoice|
116
- if invoice[:_error] || invoice[:payment_request] == '' || data[:decode_pay_req][invoice[:payment_request]]
117
- next
118
- end
118
+ if fetch[:lookup_invoice] != false
119
+ data[:lookup_invoice].each_value do |invoice|
120
+ if fetch[:decode_pay_req] == false || invoice[:_error] || invoice[:payment_request] == '' || data[:decode_pay_req][invoice[:payment_request]]
121
+ next
122
+ end
119
123
 
120
- data[:decode_pay_req][invoice[:payment_request]] = Ports::GRPC.lightning.decode_pay_req(
121
- pay_req: invoice[:payment_request]
122
- ).to_h
124
+ data[:decode_pay_req][invoice[:payment_request]] = grpc.lightning.decode_pay_req(
125
+ pay_req: invoice[:payment_request]
126
+ ).to_h
127
+ end
123
128
  end
124
129
 
125
130
  list_channels_done = {}
@@ -135,7 +140,7 @@ module Lighstorm
135
140
  partner = partners.find { |p| p != data[:get_info][:identity_pubkey] }
136
141
 
137
142
  unless list_channels_done[partner]
138
- Ports::GRPC.lightning.list_channels(
143
+ grpc.lightning.list_channels(
139
144
  peer: [partner].pack('H*')
140
145
  ).channels.map(&:to_h).each do |list_channels|
141
146
  data[:list_channels][list_channels[:chan_id]] = list_channels
@@ -145,27 +150,29 @@ module Lighstorm
145
150
  end
146
151
  end
147
152
 
148
- unless data[:get_node_info][channel[:node1_pub]]
149
- data[:get_node_info][channel[:node1_pub]] = Ports::GRPC.lightning.get_node_info(
153
+ unless fetch[:get_node_info] == false || data[:get_node_info][channel[:node1_pub]]
154
+ data[:get_node_info][channel[:node1_pub]] = grpc.lightning.get_node_info(
150
155
  pub_key: channel[:node1_pub]
151
156
  ).to_h
152
157
  end
153
158
 
154
- next if data[:get_node_info][channel[:node2_pub]]
159
+ next if fetch[:get_node_info] == false || data[:get_node_info][channel[:node2_pub]]
155
160
 
156
- data[:get_node_info][channel[:node2_pub]] = Ports::GRPC.lightning.get_node_info(
161
+ data[:get_node_info][channel[:node2_pub]] = grpc.lightning.get_node_info(
157
162
  pub_key: channel[:node2_pub]
158
163
  ).to_h
159
164
  end
160
165
 
161
166
  data[:list_channels].each_value do |channel|
162
- next if data[:get_node_info][channel[:remote_pubkey]]
167
+ next if fetch[:get_node_info] == false || data[:get_node_info][channel[:remote_pubkey]]
163
168
 
164
- data[:get_node_info][channel[:remote_pubkey]] = Ports::GRPC.lightning.get_node_info(
169
+ data[:get_node_info][channel[:remote_pubkey]] = grpc.lightning.get_node_info(
165
170
  pub_key: channel[:remote_pubkey]
166
171
  ).to_h
167
172
  end
168
173
 
174
+ data[:@meta] = { calls: grpc.calls }
175
+
169
176
  data
170
177
  end
171
178
 
@@ -256,11 +263,17 @@ module Lighstorm
256
263
  adapted[:fee_report].each do |channel|
257
264
  next unless data[:id] == channel[:id]
258
265
 
259
- data[:partners][i][:policy][:fee] = channel[:partner][:policy][:fee]
266
+ if data[:partners][i][:policy].nil?
267
+ data[:partners][i][:policy] = channel[:partner][:policy]
268
+ else
269
+ data[:partners][i][:policy][:fee] = channel[:partner][:policy][:fee]
270
+ end
260
271
  break
261
272
  end
262
273
  else
263
- data[:partners][i][:node] = adapted[:get_node_info][data[:partners][i][:node][:public_key]]
274
+ if adapted[:get_node_info][data[:partners][i][:node][:public_key]]
275
+ data[:partners][i][:node] = adapted[:get_node_info][data[:partners][i][:node][:public_key]]
276
+ end
264
277
  data[:partners][i][:node][:platform] = {
265
278
  blockchain: adapted[:get_info][:platform][:blockchain],
266
279
  network: adapted[:get_info][:platform][:network]
@@ -327,22 +340,25 @@ module Lighstorm
327
340
  list_payments
328
341
  end
329
342
 
330
- def self.data(purpose: nil, limit: nil, &vcr)
343
+ def self.data(purpose: nil, limit: nil, fetch: {}, &vcr)
331
344
  raw = if vcr.nil?
332
- fetch(purpose: purpose, limit: limit)
345
+ self.fetch(purpose: purpose, limit: limit, fetch: fetch)
333
346
  else
334
- vcr.call(-> { fetch(purpose: purpose, limit: limit) })
347
+ vcr.call(-> { self.fetch(purpose: purpose, limit: limit, fetch: fetch) })
335
348
  end
336
349
 
337
350
  adapted = adapt(raw)
338
351
 
339
- adapted[:list_payments].map do |data|
340
- transform(data, adapted)
341
- end
352
+ {
353
+ data: adapted[:list_payments].map do |data|
354
+ transform(data, adapted)
355
+ end,
356
+ meta: raw[:@meta]
357
+ }
342
358
  end
343
359
 
344
360
  def self.model(data)
345
- data.map do |node_data|
361
+ data[:data].map do |node_data|
346
362
  Lighstorm::Models::Payment.new(node_data)
347
363
  end
348
364
  end
@@ -5,16 +5,16 @@ require_relative './payment/all'
5
5
  module Lighstorm
6
6
  module Controllers
7
7
  module Payment
8
- def self.all(purpose: nil, limit: nil)
9
- All.model(All.data(purpose: purpose, limit: limit))
8
+ def self.all(purpose: nil, limit: nil, fetch: {})
9
+ All.model(All.data(purpose: purpose, limit: limit, fetch: fetch))
10
10
  end
11
11
 
12
- def self.first(purpose: nil)
13
- All.model(All.data(purpose: purpose)).first
12
+ def self.first(purpose: nil, fetch: {})
13
+ All.model(All.data(purpose: purpose, fetch: fetch)).first
14
14
  end
15
15
 
16
- def self.last(purpose: nil)
17
- All.model(All.data(purpose: purpose)).last
16
+ def self.last(purpose: nil, fetch: {})
17
+ All.model(All.data(purpose: purpose, fetch: fetch)).last
18
18
  end
19
19
  end
20
20
  end