lighstorm 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +5 -0
  3. data/.gitignore +1 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +10 -0
  6. data/Gemfile +5 -1
  7. data/Gemfile.lock +32 -8
  8. data/README.md +30 -341
  9. data/adapters/connections/channel_node/fee.rb +26 -0
  10. data/adapters/connections/channel_node.rb +52 -0
  11. data/adapters/connections/payment_channel.rb +28 -0
  12. data/adapters/edges/channel.rb +80 -0
  13. data/adapters/edges/forward.rb +41 -0
  14. data/adapters/edges/payment/purpose.rb +34 -0
  15. data/adapters/edges/payment.rb +53 -0
  16. data/adapters/invoice.rb +50 -0
  17. data/adapters/nodes/node.rb +77 -0
  18. data/adapters/payment_request.rb +77 -0
  19. data/components/cache.rb +3 -2
  20. data/components/lnd.rb +5 -1
  21. data/controllers/channel/actions/update_fee.rb +76 -0
  22. data/controllers/channel/all.rb +79 -0
  23. data/controllers/channel/find_by_id.rb +153 -0
  24. data/controllers/channel/mine.rb +114 -0
  25. data/controllers/channel.rb +23 -0
  26. data/controllers/forward/all.rb +244 -0
  27. data/controllers/forward/group_by_channel.rb +89 -0
  28. data/controllers/forward.rb +28 -0
  29. data/controllers/invoice/actions/create.rb +36 -0
  30. data/controllers/invoice/actions/pay.rb +28 -0
  31. data/controllers/invoice/actions/pay_through_route.rb +71 -0
  32. data/controllers/invoice/all.rb +70 -0
  33. data/controllers/invoice/find_by_secret_hash.rb +42 -0
  34. data/controllers/invoice.rb +36 -0
  35. data/controllers/node/all.rb +63 -0
  36. data/controllers/node/find_by_public_key.rb +49 -0
  37. data/controllers/node/myself.rb +34 -0
  38. data/controllers/node.rb +23 -0
  39. data/controllers/payment/all.rb +352 -0
  40. data/controllers/payment.rb +21 -0
  41. data/docs/.nojekyll +0 -0
  42. data/docs/README.md +655 -0
  43. data/docs/_coverpage.md +12 -0
  44. data/docs/index.html +26 -0
  45. data/docs/vendor/docsify/docsify@4.js +1 -0
  46. data/docs/vendor/docsify-themeable/theme-simple-dark.css +3 -0
  47. data/docs/vendor/docsify-themeable/theme-simple-dark.css.map +1 -0
  48. data/docs/vendor/prismjs/prism-bash.min.js +1 -0
  49. data/docs/vendor/prismjs/prism-ruby.min.js +1 -0
  50. data/docs/vendor/prismjs/prism-tomorrow.min.css +1 -0
  51. data/lighstorm.gemspec +4 -2
  52. data/models/connections/channel_node/accounting.rb +3 -12
  53. data/models/connections/channel_node/fee.rb +44 -56
  54. data/models/connections/channel_node/htlc.rb +52 -0
  55. data/models/connections/channel_node/policy.rb +11 -12
  56. data/models/connections/channel_node.rb +20 -19
  57. data/models/connections/forward_channel.rb +8 -43
  58. data/models/connections/payment_channel.rb +18 -39
  59. data/models/edges/channel/accounting.rb +42 -18
  60. data/models/edges/channel/hop.rb +65 -0
  61. data/models/edges/channel.rb +98 -120
  62. data/models/edges/forward.rb +9 -118
  63. data/models/edges/groups/{analysis.rb → channel_forwards/analysis.rb} +9 -9
  64. data/models/edges/groups/channel_forwards.rb +10 -40
  65. data/models/edges/payment.rb +29 -214
  66. data/models/errors.rb +29 -0
  67. data/models/invoice.rb +49 -0
  68. data/models/nodes/node/lightning.rb +5 -16
  69. data/models/nodes/node/platform.rb +7 -13
  70. data/models/nodes/node.rb +19 -56
  71. data/models/payment_request.rb +69 -0
  72. data/models/rate.rb +11 -1
  73. data/models/satoshis.rb +5 -6
  74. data/ports/dsl/lighstorm/errors.rb +5 -0
  75. data/ports/dsl/lighstorm.rb +12 -8
  76. data/ports/grpc.rb +62 -0
  77. data/static/cache.rb +12 -0
  78. data/static/spec.rb +3 -1
  79. metadata +58 -8
  80. data/models/connections/channel_node/constraints.rb +0 -24
@@ -1,71 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../edges/channel'
3
+ require_relative '../edges/channel/hop'
4
4
  require_relative '../nodes/node'
5
5
 
6
6
  module Lighstorm
7
7
  module Models
8
8
  class PaymentChannel
9
- KIND = :connection
9
+ attr_reader :hop
10
+
11
+ def initialize(data, payment)
12
+ @data = data
10
13
 
11
- def initialize(raw_hop, hop_index, respond_info: true)
12
- @respond_info = respond_info
13
- @raw_hop = raw_hop
14
- @hop = hop_index
14
+ @hop = data[:hop]
15
+ @payment = payment
15
16
  end
16
17
 
17
- attr_reader :hop
18
+ def first?
19
+ @hop == 1
20
+ end
18
21
 
19
- def channel
20
- Channel.find_by_id(@raw_hop.chan_id)
22
+ def last?
23
+ @data[:is_last] == true
21
24
  end
22
25
 
23
26
  def amount
24
- @amount ||= Satoshis.new(milisatoshis: @raw_hop.amt_to_forward_msat)
27
+ @amount ||= Satoshis.new(milisatoshis: @data[:amount][:milisatoshis])
25
28
  end
26
29
 
27
30
  def fee
28
- @fee ||= Satoshis.new(milisatoshis: @raw_hop.fee_msat)
29
- end
30
-
31
- def raw
32
- @raw_hop
31
+ @fee ||= Satoshis.new(milisatoshis: @data[:fee][:milisatoshis])
33
32
  end
34
33
 
35
- def partner_node
36
- Node.find_by_public_key(@raw_hop.pub_key)
34
+ def channel
35
+ @channel ||= HopChannel.new(@data, @payment)
37
36
  end
38
37
 
39
38
  def to_h
40
- response = {
39
+ {
41
40
  hop: hop,
42
41
  amount: amount.to_h,
43
42
  fee: {
44
43
  milisatoshis: fee.milisatoshis,
45
44
  parts_per_million: fee.parts_per_million(amount.milisatoshis)
46
45
  },
47
- channel: {
48
- id: @raw_hop.chan_id.to_s,
49
- node: {
50
- public_key: @raw_hop.pub_key
51
- }
52
- }
53
- }
54
-
55
- return response unless @respond_info
56
-
57
- response[:channel] = {
58
- id: channel.id,
59
- partner: {
60
- node: {
61
- alias: partner_node&.alias,
62
- public_key: partner_node&.public_key,
63
- color: partner_node&.color
64
- }
65
- }
46
+ channel: channel.to_h
66
47
  }
67
-
68
- response
69
48
  end
70
49
  end
71
50
  end
@@ -1,43 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../satoshis'
4
+ require_relative '../../errors'
4
5
 
5
6
  module Lighstorm
6
7
  module Models
7
8
  class ChannelAccounting
8
- def initialize(channel)
9
- @channel = channel
9
+ def initialize(data, is_mine)
10
+ @data = data
11
+ @is_mine = is_mine
10
12
  end
11
13
 
12
14
  def capacity
13
- @capacity ||= Satoshis.new(milisatoshis: @channel.data[:get_chan_info].capacity * 1000)
15
+ @capacity ||= if @data[:capacity]
16
+ Satoshis.new(
17
+ milisatoshis: @data[:capacity][:milisatoshis]
18
+ )
19
+ end
14
20
  end
15
21
 
16
22
  def sent
17
- @sent ||= Satoshis.new(milisatoshis: (
18
- @channel.data[:list_channels][:channels].first.total_satoshis_sent.to_f * 1000.0
19
- ))
23
+ raise Errors::NotYourChannelError unless @is_mine
24
+
25
+ @sent ||= if @data[:sent]
26
+ Satoshis.new(
27
+ milisatoshis: @data[:sent][:milisatoshis]
28
+ )
29
+ end
20
30
  end
21
31
 
22
32
  def received
23
- @received ||= Satoshis.new(milisatoshis: (
24
- @channel.data[:list_channels][:channels].first.total_satoshis_received.to_f * 1000.0
25
- ))
33
+ raise Errors::NotYourChannelError unless @is_mine
34
+
35
+ @received ||= if @data[:received]
36
+ Satoshis.new(
37
+ milisatoshis: @data[:received][:milisatoshis]
38
+ )
39
+ end
26
40
  end
27
41
 
28
42
  def unsettled
29
- @unsettled ||= Satoshis.new(milisatoshis: (
30
- @channel.data[:list_channels][:channels].first.unsettled_balance.to_f * 1000.0
31
- ))
43
+ raise Errors::NotYourChannelError unless @is_mine
44
+
45
+ @unsettled ||= if @data[:unsettled]
46
+ Satoshis.new(
47
+ milisatoshis: @data[:unsettled][:milisatoshis]
48
+ )
49
+ end
32
50
  end
33
51
 
34
52
  def to_h
35
- {
36
- capacity: capacity.to_h,
37
- sent: sent.to_h,
38
- received: received.to_h,
39
- unsettled: unsettled.to_h
40
- }
53
+ if @is_mine
54
+ {
55
+ capacity: capacity.to_h,
56
+ sent: sent.to_h,
57
+ received: received.to_h,
58
+ unsettled: unsettled.to_h
59
+ }
60
+ else
61
+ {
62
+ capacity: capacity.to_h
63
+ }
64
+ end
41
65
  end
42
66
  end
43
67
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../channel'
4
+
5
+ module Lighstorm
6
+ module Models
7
+ class HopChannel < Channel
8
+ def initialize(data, payment)
9
+ @hop_data = data
10
+ @payment = payment
11
+ super(data[:channel])
12
+ end
13
+
14
+ def target
15
+ partners.find do |partner|
16
+ partner.node.public_key == @hop_data[:channel][:target][:public_key]
17
+ end.node
18
+ end
19
+
20
+ def exit
21
+ @exit ||= if include_myself? && @hop_data[:hop] == 1
22
+ partners.reverse.find do |partner|
23
+ !partner.node.myself?
24
+ end.node
25
+ elsif @hop_data[:hop] == 1
26
+ target
27
+ end
28
+ end
29
+
30
+ def entry
31
+ return nil if @hop_data[:is_last] && @hop_data[:hop] == 1
32
+
33
+ @entry ||= if include_myself? && @hop_data[:is_last]
34
+ if partners.size > 1
35
+ partners.reverse.find do |partner|
36
+ !partner.node.myself?
37
+ end.node
38
+ else
39
+ @payment.hops[@payment.hops.size - 2].channel.target
40
+ end
41
+ end
42
+ end
43
+
44
+ def include_myself?
45
+ !partners.find { |partner| partner.node.myself? }.nil?
46
+ end
47
+
48
+ def to_h
49
+ if !known? && !partners.size.positive?
50
+ { _key: _key, id: id }
51
+ else
52
+ target_hash = target.to_h
53
+ target_hash.delete(:platform)
54
+
55
+ result = { _key: _key, id: id, target: target_hash }
56
+
57
+ result[:entry] = entry.to_h if entry
58
+ result[:exit] = self.exit.to_h if self.exit
59
+
60
+ result
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -3,6 +3,9 @@
3
3
  require 'time'
4
4
  require 'date'
5
5
 
6
+ require_relative '../../ports/grpc'
7
+ require_relative '../../adapters/edges/channel'
8
+
6
9
  require_relative '../../components/lnd'
7
10
  require_relative '../../components/cache'
8
11
 
@@ -12,173 +15,148 @@ require_relative 'channel/accounting'
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
- KIND = :edge
19
-
20
- attr_reader :data
21
-
22
- def self.all
23
- response = Cache.for('lightning.list_channels') do
24
- LND.instance.middleware('lightning.list_channels') do
25
- LND.instance.client.lightning.list_channels
26
- end
27
- end
23
+ attr_reader :data, :_key, :id, :opened_at, :up_at, :active, :exposure
28
24
 
29
- response.channels.map do |channel|
30
- Channel.find_by_id(channel.chan_id.to_s)
31
- end
32
- end
25
+ def initialize(data)
26
+ @data = data
33
27
 
34
- def self.first
35
- all.first
28
+ @_key = data[:_key]
29
+ @id = data[:id]
36
30
  end
37
31
 
38
- def self.last
39
- all.last
32
+ def known?
33
+ @data[:known] == true
40
34
  end
41
35
 
42
- def self.find_by_id(id)
43
- Channel.new({ id: id })
44
- end
36
+ def mine?
37
+ ensure_known!
45
38
 
46
- def id
47
- # Standard JSON don't support BigInt, so, a String is safer.
48
- @id.to_s
39
+ @data[:mine]
49
40
  end
50
41
 
51
- def initialize(params)
52
- begin
53
- response = Cache.for('lightning.get_chan_info', params: { chan_id: params[:id].to_i }) do
54
- LND.instance.middleware('lightning.get_chan_info') do
55
- LND.instance.client.lightning.get_chan_info(chan_id: params[:id].to_i)
56
- end
57
- end
58
-
59
- @data = { get_chan_info: response }
60
- @id = @data[:get_chan_info].channel_id
61
- rescue StandardError => e
62
- @data = { get_chan_info: nil, error: e }
63
- @id = params[:id]
64
- end
65
-
66
- fetch_from_fee_report!
42
+ def exposure
43
+ ensure_known!
67
44
 
68
- fetch_from_list_channels!
69
- calculate_times_after_list_channels!
45
+ @data[:exposure]
70
46
  end
71
47
 
72
- def error
73
- @data[:error]
74
- end
48
+ def opened_at
49
+ ensure_mine!
75
50
 
76
- def active
77
- @data[:list_channels] ? @data[:list_channels][:channels].first.active : nil
51
+ @data[:opened_at]
78
52
  end
79
53
 
80
- def exposure
81
- return unless @data[:list_channels]
54
+ def up_at
55
+ ensure_mine!
82
56
 
83
- @data[:list_channels][:channels].first.private ? 'private' : 'public'
57
+ @data[:up_at]
84
58
  end
85
59
 
86
- def opened_at
87
- @opened_at ||= if @data[:list_channels]
88
- DateTime.parse(
89
- (Time.now - @data[:list_channels][:channels].first.lifetime).to_s
90
- )
91
- end
92
- end
60
+ def active
61
+ ensure_mine!
93
62
 
94
- def up_at
95
- @up_at ||= if @data[:list_channels]
96
- DateTime.parse(
97
- (Time.now - @data[:list_channels][:channels].first.uptime).to_s
98
- )
99
- end
63
+ @data[:active]
100
64
  end
101
65
 
102
66
  def accounting
103
- return nil unless @data[:get_chan_info]
67
+ ensure_known!
68
+
69
+ @accounting ||= @data[:accounting] ? ChannelAccounting.new(@data[:accounting], mine?) : nil
70
+ end
104
71
 
105
- @accounting ||= ChannelAccounting.new(self)
72
+ def partners
73
+ @partners ||= if @data[:partners]
74
+ @data[:partners].map do |data|
75
+ ChannelNode.new(data, known? ? mine? : nil, transaction)
76
+ end
77
+ else
78
+ []
79
+ end
106
80
  end
107
81
 
108
82
  def myself
109
- return nil unless @data[:get_chan_info]
83
+ ensure_mine!
110
84
 
111
- @myself ||= ChannelNode.new(self, Node.myself)
85
+ @myself ||= partners.find { |partner| partner.node.myself? }
112
86
  end
113
87
 
114
88
  def partner
115
- return nil unless @data[:get_chan_info]
89
+ ensure_mine!
116
90
 
117
- public_key = if @data[:get_chan_info].node1_pub == myself.node.public_key
118
- @data[:get_chan_info].node2_pub
119
- else
120
- @data[:get_chan_info].node1_pub
121
- end
122
-
123
- @partner ||= ChannelNode.new(self, Node.find_by_public_key(public_key))
124
- end
125
-
126
- def raw
127
- {
128
- get_chan_info: @data[:get_chan_info].to_h,
129
- list_channels: { channels: @data[:list_channels][:channels].map(&:to_h) }
130
- }
91
+ @partner ||= partners.find { |partner| !partner.node.myself? }
131
92
  end
132
93
 
133
- def to_h
134
- {
135
- id: id,
136
- opened_at: opened_at,
137
- up_at: up_at,
138
- active: active,
139
- exposure: exposure,
140
- accounting: accounting.to_h,
141
- partner: partner.to_h,
142
- myself: myself.to_h
143
- }
144
- end
94
+ def transaction
95
+ Struct.new(:data) do
96
+ def funding
97
+ Struct.new(:data) do
98
+ def id
99
+ data[:id]
100
+ end
145
101
 
146
- private
102
+ def index
103
+ data[:index]
104
+ end
147
105
 
148
- # Ensure that we are getting fresh up-date data about our own fees.
149
- def fetch_from_fee_report!
150
- response = Cache.for('lightning.fee_report') do
151
- LND.instance.middleware('lightning.fee_report') do
152
- LND.instance.client.lightning.fee_report
106
+ def to_h
107
+ { id: id, index: index }
108
+ end
109
+ end.new(data[:funding])
153
110
  end
154
- end
155
111
 
156
- response.channel_fees.map do |channel|
157
- if channel.chan_id == @id
158
- @data[:fee_report] = { channel_fees: [channel] }
159
- break
112
+ def to_h
113
+ { funding: funding.to_h }
160
114
  end
161
- end
115
+ end.new(@data[:transaction])
162
116
  end
163
117
 
164
- def fetch_from_list_channels!
165
- response = Cache.for('lightning.list_channels') do
166
- LND.instance.middleware('lightning.list_channels') do
167
- LND.instance.client.lightning.list_channels
168
- end
118
+ def to_h
119
+ if !known? && partners.size.positive?
120
+ { _key: _key, id: id, partners: partners.map(&:to_h) }
121
+ elsif !known?
122
+ { _key: _key, id: id }
123
+ elsif mine?
124
+ {
125
+ _key: _key,
126
+ id: id,
127
+ opened_at: opened_at,
128
+ up_at: up_at,
129
+ active: active,
130
+ exposure: exposure,
131
+ accounting: accounting.to_h,
132
+ partner: partner.to_h,
133
+ myself: myself.to_h
134
+ }
135
+ elsif @data[:accounting]
136
+ {
137
+ _key: _key,
138
+ id: id,
139
+ accounting: accounting.to_h,
140
+ partners: partners.map(&:to_h)
141
+ }
142
+ else
143
+ {
144
+ _key: _key,
145
+ id: id,
146
+ partners: partners.map(&:to_h)
147
+ }
169
148
  end
149
+ end
170
150
 
171
- response.channels.map do |channel|
172
- if channel.chan_id == @id
173
- @data[:list_channels] = { channels: [channel] }
174
- break
175
- end
176
- end
151
+ private
152
+
153
+ def ensure_known!
154
+ raise Errors::UnknownChannelError unless known?
177
155
  end
178
156
 
179
- def calculate_times_after_list_channels!
180
- opened_at
181
- up_at
157
+ def ensure_mine!
158
+ ensure_known!
159
+ raise Errors::NotYourChannelError if @data[:mine] == false
182
160
  end
183
161
  end
184
162
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
4
3
  require 'time'
5
4
  require 'date'
6
5
 
@@ -12,130 +11,30 @@ require_relative 'groups/channel_forwards'
12
11
  module Lighstorm
13
12
  module Models
14
13
  class Forward
15
- KIND = :edge
14
+ attr_reader :_key, :at
16
15
 
17
- attr_reader :data
16
+ def initialize(data)
17
+ @data = data
18
18
 
19
- def self.all(limit: nil, raw: false, info: true)
20
- last_offset = 0
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)
19
+ @_key = data[:_key]
20
+ @at = data[:at]
122
21
  end
123
22
 
124
23
  def fee
125
- Satoshis.new(milisatoshis: @data[:forwarding_history][:forwarding_events].first.fee_msat)
24
+ @fee ||= Satoshis.new(milisatoshis: @data[:fee][:milisatoshis])
126
25
  end
127
26
 
128
27
  def in
129
- @in ||= ForwardChannel.new(:in, self, respond_info: @respond_info)
28
+ @in ||= ForwardChannel.new(@data[:in])
130
29
  end
131
30
 
132
31
  def out
133
- @out ||= ForwardChannel.new(:out, self, respond_info: @respond_info)
32
+ @out ||= ForwardChannel.new(@data[:out])
134
33
  end
135
34
 
136
35
  def to_h
137
36
  {
138
- id: id,
37
+ _key: _key,
139
38
  at: at,
140
39
  fee: {
141
40
  milisatoshis: fee.milisatoshis,
@@ -145,14 +44,6 @@ module Lighstorm
145
44
  out: out.to_h
146
45
  }
147
46
  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
47
  end
157
48
  end
158
49
  end