lighstorm 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.example +5 -0
- data/.github/workflows/ruby-rspec-tests.yml +39 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -2
- data/README.md +30 -371
- data/adapters/connections/channel_node/fee.rb +26 -0
- data/adapters/connections/channel_node/policy.rb +61 -0
- data/adapters/connections/channel_node.rb +74 -0
- data/adapters/connections/payment_channel.rb +28 -0
- data/adapters/edges/channel.rb +96 -0
- data/adapters/edges/forward.rb +40 -0
- data/adapters/edges/payment/purpose.rb +32 -0
- data/adapters/edges/payment.rb +50 -0
- data/adapters/invoice.rb +49 -0
- data/adapters/nodes/node.rb +111 -0
- data/adapters/payment_request.rb +76 -0
- data/components/cache.rb +3 -2
- data/components/lnd.rb +5 -1
- data/controllers/channel/actions/apply_gossip.rb +194 -0
- data/controllers/channel/actions/update_fee.rb +76 -0
- data/controllers/channel/all.rb +79 -0
- data/controllers/channel/find_by_id.rb +153 -0
- data/controllers/channel/mine.rb +114 -0
- data/controllers/channel.rb +27 -0
- data/controllers/forward/all.rb +244 -0
- data/controllers/forward/group_by_channel.rb +89 -0
- data/controllers/forward.rb +28 -0
- data/controllers/invoice/actions/create.rb +36 -0
- data/controllers/invoice/actions/pay.rb +28 -0
- data/controllers/invoice/actions/pay_through_route.rb +71 -0
- data/controllers/invoice/all.rb +70 -0
- data/controllers/invoice/find_by_secret_hash.rb +42 -0
- data/controllers/invoice.rb +36 -0
- data/controllers/node/actions/apply_gossip.rb +112 -0
- data/controllers/node/all.rb +63 -0
- data/controllers/node/find_by_public_key.rb +49 -0
- data/controllers/node/myself.rb +34 -0
- data/controllers/node.rb +27 -0
- data/controllers/payment/all.rb +368 -0
- data/controllers/payment.rb +21 -0
- data/docs/.nojekyll +0 -0
- data/docs/README.md +731 -0
- data/docs/_coverpage.md +12 -0
- data/docs/index.html +26 -0
- data/docs/vendor/docsify/docsify@4.js +1 -0
- data/docs/vendor/docsify-themeable/theme-simple-dark.css +3 -0
- data/docs/vendor/docsify-themeable/theme-simple-dark.css.map +1 -0
- data/docs/vendor/prismjs/prism-bash.min.js +1 -0
- data/docs/vendor/prismjs/prism-ruby.min.js +1 -0
- data/docs/vendor/prismjs/prism-tomorrow.min.css +1 -0
- data/lighstorm.gemspec +3 -1
- data/models/concerns/protectable.rb +23 -0
- data/models/connections/channel_node/accounting.rb +7 -14
- data/models/connections/channel_node/fee.rb +55 -84
- data/models/connections/channel_node/htlc/blocks/delta.rb +39 -0
- data/models/connections/channel_node/htlc.rb +65 -11
- data/models/connections/channel_node/policy.rb +15 -18
- data/models/connections/channel_node.rb +48 -22
- data/models/connections/forward_channel.rb +8 -43
- data/models/connections/payment_channel.rb +18 -39
- data/models/edges/channel/accounting.rb +45 -20
- data/models/edges/channel/hop.rb +65 -0
- data/models/edges/channel.rb +111 -169
- data/models/edges/forward.rb +9 -119
- data/models/edges/groups/{analysis.rb → channel_forwards/analysis.rb} +9 -9
- data/models/edges/groups/channel_forwards.rb +10 -40
- data/models/edges/payment.rb +29 -215
- data/models/errors.rb +32 -0
- data/models/invoice.rb +49 -0
- data/models/nodes/node/lightning.rb +11 -16
- data/models/nodes/node/platform.rb +13 -13
- data/models/nodes/node.rb +59 -103
- data/models/payment_request.rb +72 -0
- data/models/rate.rb +11 -1
- data/models/satoshis.rb +5 -6
- data/ports/dsl/lighstorm/errors.rb +5 -0
- data/ports/dsl/lighstorm.rb +11 -9
- data/ports/grpc/session.rb +26 -0
- data/ports/grpc.rb +80 -0
- data/static/cache.rb +12 -0
- data/static/spec.rb +3 -1
- metadata +62 -6
- data/models/connections/channel_node/constraints.rb +0 -24
data/models/edges/channel.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'time'
|
4
|
-
|
4
|
+
|
5
|
+
require_relative '../../ports/grpc'
|
6
|
+
require_relative '../../adapters/edges/channel'
|
5
7
|
|
6
8
|
require_relative '../../components/lnd'
|
7
9
|
require_relative '../../components/cache'
|
@@ -9,246 +11,186 @@ require_relative '../../components/cache'
|
|
9
11
|
require_relative '../nodes/node'
|
10
12
|
require_relative 'channel/accounting'
|
11
13
|
|
14
|
+
require_relative '../../controllers/channel/actions/apply_gossip'
|
12
15
|
require_relative '../connections/channel_node'
|
13
16
|
require_relative '../satoshis'
|
14
17
|
|
18
|
+
require_relative '../errors'
|
19
|
+
|
15
20
|
module Lighstorm
|
16
21
|
module Models
|
17
22
|
class Channel
|
18
|
-
|
23
|
+
attr_reader :data, :_key, :id
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
def self.all
|
23
|
-
response = LND.instance.middleware('lightning.describe_graph') do
|
24
|
-
LND.instance.client.lightning.describe_graph
|
25
|
-
end
|
25
|
+
def initialize(data)
|
26
|
+
@data = data
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
28
|
+
@_key = data[:_key]
|
29
|
+
@id = data[:id]
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
34
|
-
LND.instance.middleware('lightning.list_channels') do
|
35
|
-
LND.instance.client.lightning.list_channels
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
response.channels.map do |channel|
|
40
|
-
Channel.find_by_id(channel.chan_id.to_s)
|
41
|
-
end
|
32
|
+
def known?
|
33
|
+
@data[:known] == true
|
42
34
|
end
|
43
35
|
|
44
|
-
def
|
45
|
-
|
46
|
-
end
|
36
|
+
def mine?
|
37
|
+
ensure_known!
|
47
38
|
|
48
|
-
|
49
|
-
# Standard JSON don't support BigInt, so, a String is safer.
|
50
|
-
@id.to_s
|
39
|
+
@data[:mine]
|
51
40
|
end
|
52
41
|
|
53
|
-
def
|
54
|
-
|
55
|
-
begin
|
56
|
-
response = Cache.for('lightning.get_chan_info', params: { chan_id: params[:id].to_i }) do
|
57
|
-
LND.instance.middleware('lightning.get_chan_info') do
|
58
|
-
LND.instance.client.lightning.get_chan_info(chan_id: params[:id].to_i)
|
59
|
-
end
|
60
|
-
end
|
42
|
+
def exposure
|
43
|
+
ensure_known!
|
61
44
|
|
62
|
-
|
63
|
-
|
64
|
-
rescue StandardError => e
|
65
|
-
@data = { get_chan_info: nil, error: e }
|
66
|
-
@id = params[:id]
|
67
|
-
end
|
68
|
-
elsif params[:describe_graph]
|
69
|
-
@data = { describe_graph: params[:describe_graph] }
|
70
|
-
@id = @data[:describe_graph].channel_id
|
71
|
-
end
|
45
|
+
@data[:exposure]
|
46
|
+
end
|
72
47
|
|
73
|
-
|
48
|
+
def opened_at
|
49
|
+
ensure_mine!
|
74
50
|
|
75
|
-
|
76
|
-
calculate_times_after_list_channels!
|
51
|
+
@data[:opened_at]
|
77
52
|
end
|
78
53
|
|
79
|
-
def
|
80
|
-
|
81
|
-
end
|
54
|
+
def up_at
|
55
|
+
ensure_mine!
|
82
56
|
|
83
|
-
|
84
|
-
@data[:error]
|
57
|
+
@data[:up_at]
|
85
58
|
end
|
86
59
|
|
87
|
-
def active
|
88
|
-
|
89
|
-
end
|
60
|
+
def active?
|
61
|
+
ensure_mine!
|
90
62
|
|
91
|
-
|
92
|
-
|
63
|
+
@data[:state] == 'active'
|
64
|
+
end
|
93
65
|
|
94
|
-
|
66
|
+
def state
|
67
|
+
ensure_mine!
|
95
68
|
|
96
|
-
@data[:
|
69
|
+
@data[:state]
|
97
70
|
end
|
98
71
|
|
99
|
-
def
|
100
|
-
|
101
|
-
DateTime.parse(
|
102
|
-
(Time.now - @data[:list_channels][:channels].first.lifetime).to_s
|
103
|
-
)
|
104
|
-
end
|
105
|
-
end
|
72
|
+
def accounting
|
73
|
+
ensure_known!
|
106
74
|
|
107
|
-
|
108
|
-
@up_at ||= if @data[:list_channels]
|
109
|
-
DateTime.parse(
|
110
|
-
(Time.now - @data[:list_channels][:channels].first.uptime).to_s
|
111
|
-
)
|
112
|
-
end
|
75
|
+
@accounting ||= @data[:accounting] ? ChannelAccounting.new(@data[:accounting], mine?) : nil
|
113
76
|
end
|
114
77
|
|
115
|
-
def
|
116
|
-
@
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
@partners ||= if mine?
|
121
|
-
[myself, partner]
|
122
|
-
elsif @data[:describe_graph]
|
123
|
-
[
|
124
|
-
ChannelNode.new(
|
125
|
-
self,
|
126
|
-
Node.new({ public_key: @data[:describe_graph].node1_pub }, fetch: fetch)
|
127
|
-
),
|
128
|
-
ChannelNode.new(
|
129
|
-
self,
|
130
|
-
Node.new({ public_key: @data[:describe_graph].node2_pub }, fetch: fetch)
|
131
|
-
)
|
132
|
-
]
|
133
|
-
elsif @data[:get_chan_info]
|
134
|
-
[
|
135
|
-
ChannelNode.new(
|
136
|
-
self,
|
137
|
-
Node.new({ public_key: @data[:get_chan_info].node1_pub }, fetch: fetch)
|
138
|
-
),
|
139
|
-
ChannelNode.new(
|
140
|
-
self,
|
141
|
-
Node.new({ public_key: @data[:get_chan_info].node2_pub }, fetch: fetch)
|
142
|
-
)
|
143
|
-
]
|
78
|
+
def partners
|
79
|
+
@partners ||= if @data[:partners]
|
80
|
+
@data[:partners].map do |data|
|
81
|
+
ChannelNode.new(data, known? ? mine? : nil, transaction)
|
82
|
+
end
|
144
83
|
else
|
145
|
-
|
84
|
+
[]
|
146
85
|
end
|
147
86
|
end
|
148
87
|
|
149
|
-
def mine?
|
150
|
-
my_node = Node.myself.public_key
|
151
|
-
|
152
|
-
if @data[:get_chan_info]
|
153
|
-
(
|
154
|
-
@data[:get_chan_info].node1_pub == my_node || @data[:get_chan_info].node2_pub == my_node
|
155
|
-
)
|
156
|
-
elsif @data[:describe_graph]
|
157
|
-
(
|
158
|
-
@data[:describe_graph].node1_pub == my_node || @data[:describe_graph].node2_pub == my_node
|
159
|
-
)
|
160
|
-
else
|
161
|
-
false
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
88
|
def myself
|
166
|
-
|
89
|
+
ensure_mine!
|
167
90
|
|
168
|
-
@myself ||=
|
91
|
+
@myself ||= partners.find { |partner| partner.node.myself? }
|
169
92
|
end
|
170
93
|
|
171
94
|
def partner
|
172
|
-
|
95
|
+
ensure_mine!
|
173
96
|
|
174
|
-
|
97
|
+
@partner ||= partners.find { |partner| !partner.node.myself? }
|
98
|
+
end
|
175
99
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
100
|
+
def transaction
|
101
|
+
Struct.new(:data) do
|
102
|
+
def funding
|
103
|
+
Struct.new(:data) do
|
104
|
+
def id
|
105
|
+
data[:id]
|
106
|
+
end
|
181
107
|
|
182
|
-
|
183
|
-
|
108
|
+
def index
|
109
|
+
data[:index]
|
110
|
+
end
|
184
111
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
112
|
+
def to_h
|
113
|
+
{ id: id, index: index }
|
114
|
+
end
|
115
|
+
end.new(data[:funding])
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_h
|
119
|
+
{ funding: funding.to_h }
|
120
|
+
end
|
121
|
+
end.new(@data[:transaction])
|
193
122
|
end
|
194
123
|
|
195
124
|
def to_h
|
196
|
-
if
|
125
|
+
if !known? && partners.size.positive?
|
126
|
+
{ _key: _key, id: id, partners: partners.map(&:to_h) }
|
127
|
+
elsif !known?
|
128
|
+
{ _key: _key, id: id }
|
129
|
+
elsif mine?
|
197
130
|
{
|
131
|
+
_key: _key,
|
198
132
|
id: id,
|
199
133
|
opened_at: opened_at,
|
200
134
|
up_at: up_at,
|
201
|
-
|
135
|
+
state: state,
|
202
136
|
exposure: exposure,
|
203
137
|
accounting: accounting.to_h,
|
204
138
|
partner: partner.to_h,
|
205
139
|
myself: myself.to_h
|
206
140
|
}
|
207
|
-
|
141
|
+
elsif @data[:accounting]
|
208
142
|
{
|
143
|
+
_key: _key,
|
209
144
|
id: id,
|
210
145
|
accounting: accounting.to_h,
|
211
146
|
partners: partners.map(&:to_h)
|
212
147
|
}
|
148
|
+
else
|
149
|
+
{
|
150
|
+
_key: _key,
|
151
|
+
id: id,
|
152
|
+
partners: partners.map(&:to_h)
|
153
|
+
}
|
213
154
|
end
|
214
155
|
end
|
215
156
|
|
216
|
-
|
157
|
+
def dump
|
158
|
+
result = Marshal.load(Marshal.dump(@data)).merge(
|
159
|
+
{ partners: partners.map(&:dump) }
|
160
|
+
)
|
217
161
|
|
218
|
-
|
219
|
-
def fetch_from_fee_report!
|
220
|
-
response = Cache.for('lightning.fee_report') do
|
221
|
-
LND.instance.middleware('lightning.fee_report') do
|
222
|
-
LND.instance.client.lightning.fee_report
|
223
|
-
end
|
224
|
-
end
|
162
|
+
result[:accounting] = accounting.dump if known?
|
225
163
|
|
226
|
-
|
227
|
-
if channel.chan_id == @id
|
228
|
-
@data[:fee_report] = { channel_fees: [channel] }
|
229
|
-
break
|
230
|
-
end
|
231
|
-
end
|
164
|
+
result
|
232
165
|
end
|
233
166
|
|
234
|
-
def
|
235
|
-
|
236
|
-
LND.instance.middleware('lightning.list_channels') do
|
237
|
-
LND.instance.client.lightning.list_channels
|
238
|
-
end
|
239
|
-
end
|
167
|
+
def self.adapt(gossip: nil, dump: nil)
|
168
|
+
raise TooManyArgumentsError, 'you need to pass gossip: or dump:, not both' if !gossip.nil? && !dump.nil?
|
240
169
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
170
|
+
raise ArgumentError, 'missing gossip: or dump:' if gossip.nil? && dump.nil?
|
171
|
+
|
172
|
+
if !gossip.nil?
|
173
|
+
new(Adapter::Channel.subscribe_channel_graph(gossip))
|
174
|
+
elsif !dump.nil?
|
175
|
+
new(dump)
|
246
176
|
end
|
247
177
|
end
|
248
178
|
|
249
|
-
def
|
250
|
-
|
251
|
-
|
179
|
+
def apply!(gossip:)
|
180
|
+
Controllers::Channel::ApplyGossip.perform(
|
181
|
+
self, gossip
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def ensure_known!
|
188
|
+
raise Errors::UnknownChannelError unless known?
|
189
|
+
end
|
190
|
+
|
191
|
+
def ensure_mine!
|
192
|
+
ensure_known!
|
193
|
+
raise Errors::NotYourChannelError if @data[:mine] == false
|
252
194
|
end
|
253
195
|
end
|
254
196
|
end
|
data/models/edges/forward.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'digest'
|
4
3
|
require 'time'
|
5
|
-
require 'date'
|
6
4
|
|
7
5
|
require_relative '../satoshis'
|
8
6
|
|
@@ -12,130 +10,30 @@ require_relative 'groups/channel_forwards'
|
|
12
10
|
module Lighstorm
|
13
11
|
module Models
|
14
12
|
class Forward
|
15
|
-
|
13
|
+
attr_reader :_key, :at
|
16
14
|
|
17
|
-
|
15
|
+
def initialize(data)
|
16
|
+
@data = data
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
forwards = []
|
23
|
-
|
24
|
-
loop do
|
25
|
-
response = Cache.for(
|
26
|
-
'lightning.forwarding_history',
|
27
|
-
params: { peer_alias_lookup: true, index_offset: last_offset }
|
28
|
-
) do
|
29
|
-
LND.instance.middleware('lightning.forwarding_history') do
|
30
|
-
LND.instance.client.lightning.forwarding_history(
|
31
|
-
peer_alias_lookup: true, index_offset: last_offset
|
32
|
-
)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
response.forwarding_events.each { |raw_forward| forwards << raw_forward }
|
37
|
-
|
38
|
-
# Unfortunately, forwards aren't sorted in descending order. :(
|
39
|
-
# break if !limit.nil? && forwards.size >= limit
|
40
|
-
|
41
|
-
break if last_offset == response.last_offset_index || last_offset > response.last_offset_index
|
42
|
-
|
43
|
-
last_offset = response.last_offset_index
|
44
|
-
end
|
45
|
-
|
46
|
-
forwards = forwards.sort_by { |raw_forward| -raw_forward.timestamp_ns }
|
47
|
-
|
48
|
-
forwards = forwards[0..limit - 1] unless limit.nil?
|
49
|
-
|
50
|
-
return forwards if raw
|
51
|
-
|
52
|
-
forwards.map { |raw_forward| Forward.new(raw_forward, respond_info: info) }
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.first
|
56
|
-
all(limit: 1).first
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.last
|
60
|
-
all.last
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.group_by_channel(direction: :out, hours_ago: nil, limit: nil, info: true)
|
64
|
-
raw_forwards = all(raw: true)
|
65
|
-
|
66
|
-
direction = direction.to_sym
|
67
|
-
|
68
|
-
groups = {}
|
69
|
-
|
70
|
-
raw_forwards.each do |raw_forward|
|
71
|
-
channel_id = direction == :in ? raw_forward.chan_id_in : raw_forward.chan_id_out
|
72
|
-
|
73
|
-
if hours_ago
|
74
|
-
forward_hours_ago = (
|
75
|
-
Time.now - Time.at(raw_forward.timestamp_ns / 1e+9)
|
76
|
-
).to_f / 3600
|
77
|
-
|
78
|
-
next if forward_hours_ago > hours_ago
|
79
|
-
end
|
80
|
-
|
81
|
-
unless groups[channel_id]
|
82
|
-
groups[channel_id] = {
|
83
|
-
last_at: nil,
|
84
|
-
analysis: { count: 0, sums: { amount: 0, fee: 0 } },
|
85
|
-
direction => { id: channel_id }
|
86
|
-
}
|
87
|
-
end
|
88
|
-
|
89
|
-
groups[channel_id][:analysis][:count] += 1
|
90
|
-
groups[channel_id][:analysis][:sums][:amount] += raw_forward.amt_in_msat
|
91
|
-
groups[channel_id][:analysis][:sums][:fee] += raw_forward.fee_msat
|
92
|
-
|
93
|
-
if groups[channel_id][:last_at].nil? || raw_forward.timestamp_ns > groups[channel_id][:last_at]
|
94
|
-
groups[channel_id][:last_at] = raw_forward.timestamp_ns
|
95
|
-
groups[channel_id][:sample] = raw_forward
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
groups = groups.values.sort_by { |group| - group[:last_at] }
|
100
|
-
.sort_by { |group| - group[:analysis][:count] }
|
101
|
-
|
102
|
-
groups = groups[0..limit - 1] unless limit.nil?
|
103
|
-
|
104
|
-
groups.map { |raw_group| ChannelForwardsGroup.new(direction, raw_group) }
|
105
|
-
end
|
106
|
-
|
107
|
-
def initialize(raw, respond_info: true)
|
108
|
-
@respond_info = respond_info
|
109
|
-
@data = { forwarding_history: { forwarding_events: [raw] } }
|
110
|
-
end
|
111
|
-
|
112
|
-
def id
|
113
|
-
@id ||= Digest::SHA256.hexdigest(
|
114
|
-
@data[:forwarding_history][:forwarding_events].first.timestamp_ns.to_s
|
115
|
-
)
|
116
|
-
end
|
117
|
-
|
118
|
-
def at
|
119
|
-
DateTime.parse(Time.at(
|
120
|
-
@data[:forwarding_history][:forwarding_events].first.timestamp_ns / 1e+9
|
121
|
-
).to_s)
|
18
|
+
@_key = data[:_key]
|
19
|
+
@at = data[:at]
|
122
20
|
end
|
123
21
|
|
124
22
|
def fee
|
125
|
-
Satoshis.new(milisatoshis: @data[:
|
23
|
+
@fee ||= Satoshis.new(milisatoshis: @data[:fee][:milisatoshis])
|
126
24
|
end
|
127
25
|
|
128
26
|
def in
|
129
|
-
@in ||= ForwardChannel.new(:in
|
27
|
+
@in ||= ForwardChannel.new(@data[:in])
|
130
28
|
end
|
131
29
|
|
132
30
|
def out
|
133
|
-
@out ||= ForwardChannel.new(:out
|
31
|
+
@out ||= ForwardChannel.new(@data[:out])
|
134
32
|
end
|
135
33
|
|
136
34
|
def to_h
|
137
35
|
{
|
138
|
-
|
36
|
+
_key: _key,
|
139
37
|
at: at,
|
140
38
|
fee: {
|
141
39
|
milisatoshis: fee.milisatoshis,
|
@@ -145,14 +43,6 @@ module Lighstorm
|
|
145
43
|
out: out.to_h
|
146
44
|
}
|
147
45
|
end
|
148
|
-
|
149
|
-
def raw
|
150
|
-
{
|
151
|
-
forwarding_history: {
|
152
|
-
forwarding_events: [@data[:forwarding_history][:forwarding_events].first.to_h]
|
153
|
-
}
|
154
|
-
}
|
155
|
-
end
|
156
46
|
end
|
157
47
|
end
|
158
48
|
end
|
@@ -3,19 +3,19 @@
|
|
3
3
|
module Lighstorm
|
4
4
|
module Models
|
5
5
|
class ChannelForwardsGroup
|
6
|
-
Analysis = Struct.new(:
|
6
|
+
Analysis = Struct.new(:data) do
|
7
7
|
def count
|
8
|
-
|
8
|
+
data[:count]
|
9
9
|
end
|
10
10
|
|
11
11
|
def sums
|
12
12
|
Struct.new(:sums) do
|
13
13
|
def amount
|
14
|
-
Satoshis.new(milisatoshis: sums[:amount])
|
14
|
+
Satoshis.new(milisatoshis: sums[:amount][:milisatoshis])
|
15
15
|
end
|
16
16
|
|
17
17
|
def fee
|
18
|
-
Satoshis.new(milisatoshis: sums[:fee])
|
18
|
+
Satoshis.new(milisatoshis: sums[:fee][:milisatoshis])
|
19
19
|
end
|
20
20
|
|
21
21
|
def to_h
|
@@ -27,20 +27,20 @@ module Lighstorm
|
|
27
27
|
}
|
28
28
|
}
|
29
29
|
end
|
30
|
-
end.new(
|
30
|
+
end.new(data[:sums])
|
31
31
|
end
|
32
32
|
|
33
33
|
def averages
|
34
|
-
Struct.new(:
|
34
|
+
Struct.new(:data) do
|
35
35
|
def amount
|
36
36
|
Satoshis.new(
|
37
|
-
milisatoshis:
|
37
|
+
milisatoshis: data[:sums][:amount][:milisatoshis].to_f / data[:count]
|
38
38
|
)
|
39
39
|
end
|
40
40
|
|
41
41
|
def fee
|
42
42
|
Satoshis.new(
|
43
|
-
milisatoshis:
|
43
|
+
milisatoshis: data[:sums][:fee][:milisatoshis].to_f / data[:count]
|
44
44
|
)
|
45
45
|
end
|
46
46
|
|
@@ -53,7 +53,7 @@ module Lighstorm
|
|
53
53
|
}
|
54
54
|
}
|
55
55
|
end
|
56
|
-
end.new(
|
56
|
+
end.new(data)
|
57
57
|
end
|
58
58
|
|
59
59
|
def to_h
|
@@ -1,66 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../satoshis'
|
4
|
-
require_relative 'analysis'
|
4
|
+
require_relative 'channel_forwards/analysis'
|
5
5
|
|
6
6
|
module Lighstorm
|
7
7
|
module Models
|
8
8
|
class ChannelForwardsGroup
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :_key, :last_at
|
10
|
+
|
11
|
+
def initialize(data)
|
11
12
|
@data = data
|
12
|
-
end
|
13
13
|
|
14
|
-
|
15
|
-
@last_at
|
14
|
+
@_key = data[:_key]
|
15
|
+
@last_at = data[:last_at]
|
16
16
|
end
|
17
17
|
|
18
18
|
def analysis
|
19
19
|
Analysis.new(@data[:analysis])
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
raise raise ArgumentError, "Method `in` doesn't exist." unless @direction == :in
|
26
|
-
|
27
|
-
@in = Channel.new({ id: @data[:in][:id] })
|
28
|
-
end
|
29
|
-
|
30
|
-
def out
|
31
|
-
return @out if @out
|
32
|
-
|
33
|
-
raise raise ArgumentError, "Method `out` doesn't exist." unless @direction == :out
|
34
|
-
|
35
|
-
@out = Channel.new({ id: @data[:out][:id] })
|
22
|
+
def channel
|
23
|
+
@channel ||= Channel.new(@data[:channel])
|
36
24
|
end
|
37
25
|
|
38
|
-
# def capacity
|
39
|
-
# @capacity ||= Satoshis.new(milisatoshis: @channel.data[:get_chan_info].capacity * 1000)
|
40
|
-
# end
|
41
|
-
|
42
26
|
def to_h
|
43
27
|
{
|
28
|
+
_key: _key,
|
44
29
|
last_at: last_at,
|
45
30
|
analysis: analysis.to_h,
|
46
|
-
|
47
|
-
id: channel.id,
|
48
|
-
partner: {
|
49
|
-
node: {
|
50
|
-
alias: channel&.partner&.node&.alias,
|
51
|
-
public_key: channel&.partner&.node&.public_key,
|
52
|
-
color: channel&.partner&.node&.color
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
31
|
+
channel: channel.to_h
|
56
32
|
}
|
57
33
|
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def channel
|
62
|
-
@channel ||= @direction == :in ? self.in : out
|
63
|
-
end
|
64
34
|
end
|
65
35
|
end
|
66
36
|
end
|