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
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'time'
4
- require 'date'
5
4
 
6
5
  require_relative '../../ports/grpc'
7
6
  require_relative '../../adapters/edges/channel'
@@ -12,6 +11,7 @@ require_relative '../../components/cache'
12
11
  require_relative '../nodes/node'
13
12
  require_relative 'channel/accounting'
14
13
 
14
+ require_relative '../../controllers/channel/actions/apply_gossip'
15
15
  require_relative '../connections/channel_node'
16
16
  require_relative '../satoshis'
17
17
 
@@ -20,7 +20,7 @@ require_relative '../errors'
20
20
  module Lighstorm
21
21
  module Models
22
22
  class Channel
23
- attr_reader :data, :_key, :id, :opened_at, :up_at, :active, :exposure
23
+ attr_reader :data, :_key, :id
24
24
 
25
25
  def initialize(data)
26
26
  @data = data
@@ -57,10 +57,16 @@ module Lighstorm
57
57
  @data[:up_at]
58
58
  end
59
59
 
60
- def active
60
+ def active?
61
61
  ensure_mine!
62
62
 
63
- @data[:active]
63
+ @data[:state] == 'active'
64
+ end
65
+
66
+ def state
67
+ ensure_mine!
68
+
69
+ @data[:state]
64
70
  end
65
71
 
66
72
  def accounting
@@ -126,7 +132,7 @@ module Lighstorm
126
132
  id: id,
127
133
  opened_at: opened_at,
128
134
  up_at: up_at,
129
- active: active,
135
+ state: state,
130
136
  exposure: exposure,
131
137
  accounting: accounting.to_h,
132
138
  partner: partner.to_h,
@@ -148,6 +154,34 @@ module Lighstorm
148
154
  end
149
155
  end
150
156
 
157
+ def dump
158
+ result = Marshal.load(Marshal.dump(@data)).merge(
159
+ { partners: partners.map(&:dump) }
160
+ )
161
+
162
+ result[:accounting] = accounting.dump if known?
163
+
164
+ result
165
+ end
166
+
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?
169
+
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)
176
+ end
177
+ end
178
+
179
+ def apply!(gossip:)
180
+ Controllers::Channel::ApplyGossip.perform(
181
+ self, gossip
182
+ )
183
+ end
184
+
151
185
  private
152
186
 
153
187
  def ensure_known!
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'time'
4
- require 'date'
5
4
 
6
5
  require_relative '../satoshis'
7
6
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'time'
4
- require 'date'
5
4
 
6
5
  require_relative '../satoshis'
7
6
 
data/models/errors.rb CHANGED
@@ -6,6 +6,9 @@ module Lighstorm
6
6
 
7
7
  class ToDoError < LighstormError; end
8
8
 
9
+ class TooManyArgumentsError < LighstormError; end
10
+ class IncoherentGossipError < LighstormError; end
11
+ class MissingGossipHandlerError < LighstormError; end
9
12
  class MissingCredentialsError < LighstormError; end
10
13
  class MissingMilisatoshisError < LighstormError; end
11
14
  class MissingPartsPerMillionError < LighstormError; end
@@ -20,6 +20,12 @@ module Lighstorm
20
20
  version: version
21
21
  }
22
22
  end
23
+
24
+ def dump
25
+ Marshal.load(
26
+ Marshal.dump({ implementation: implementation, version: version })
27
+ )
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -37,6 +37,12 @@ module Lighstorm
37
37
 
38
38
  response
39
39
  end
40
+
41
+ def dump
42
+ data = Marshal.load(Marshal.dump(@data))
43
+ data.merge(lightning: lightning.dump) if @node.myself?
44
+ data
45
+ end
40
46
  end
41
47
  end
42
48
  end
data/models/nodes/node.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../controllers/node/actions/apply_gossip'
3
4
  require_relative '../../controllers/channel'
5
+ require_relative '../../adapters/nodes/node'
6
+ require_relative '../concerns/protectable'
4
7
  require_relative '../errors'
5
8
 
6
9
  require_relative 'node/platform'
@@ -8,6 +11,8 @@ require_relative 'node/platform'
8
11
  module Lighstorm
9
12
  module Models
10
13
  class Node
14
+ include Protectable
15
+
11
16
  attr_reader :data, :_key, :alias, :public_key, :color
12
17
 
13
18
  def initialize(data)
@@ -46,6 +51,52 @@ module Lighstorm
46
51
 
47
52
  result
48
53
  end
54
+
55
+ def dump
56
+ result = Marshal.load(Marshal.dump(@data))
57
+
58
+ result[:platform] = platform.dump if @data[:platform]
59
+
60
+ result
61
+ end
62
+
63
+ def alias=(value)
64
+ protect!(value)
65
+
66
+ @alias = value[:value]
67
+
68
+ @data[:alias] = @alias
69
+
70
+ self.alias
71
+ end
72
+
73
+ def color=(value)
74
+ protect!(value)
75
+
76
+ @color = value[:value]
77
+
78
+ @data[:color] = @color
79
+
80
+ color
81
+ end
82
+
83
+ def self.adapt(gossip: nil, dump: nil)
84
+ raise TooManyArgumentsError, 'you need to pass gossip: or dump:, not both' if !gossip.nil? && !dump.nil?
85
+
86
+ raise ArgumentError, 'missing gossip: or dump:' if gossip.nil? && dump.nil?
87
+
88
+ if !gossip.nil?
89
+ new(Adapter::Node.subscribe_channel_graph(gossip))
90
+ elsif !dump.nil?
91
+ new(dump)
92
+ end
93
+ end
94
+
95
+ def apply!(gossip:)
96
+ Controllers::Node::ApplyGossip.perform(
97
+ self, gossip
98
+ )
99
+ end
49
100
  end
50
101
  end
51
102
  end
@@ -11,7 +11,10 @@ module Lighstorm
11
11
  def initialize(data)
12
12
  @data = data
13
13
 
14
- @_key = Digest::SHA256.hexdigest(data[:code])
14
+ @_key = data[:_key] || Digest::SHA256.hexdigest(
15
+ data[:code] || "#{data[:code][:amount][:milisatoshis]}#{Time.now}"
16
+ )
17
+
15
18
  @code = data[:code]
16
19
 
17
20
  @address = data[:address]
@@ -34,7 +37,7 @@ module Lighstorm
34
37
  def to_h
35
38
  { memo: memo, hash: hash }
36
39
  end
37
- end.new(@data[:description])
40
+ end.new(@data[:description] || {})
38
41
  end
39
42
 
40
43
  def secret
@@ -51,7 +54,7 @@ module Lighstorm
51
54
  # Don't expose 'secret' by default: Security
52
55
  { hash: hash }
53
56
  end
54
- end.new(@data[:secret])
57
+ end.new(@data[:secret] || {})
55
58
  end
56
59
 
57
60
  def to_h
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lighstorm
4
+ module Ports
5
+ class GRPCSession
6
+ attr_reader :calls
7
+
8
+ def initialize(grpc)
9
+ @grpc = grpc
10
+ @calls = {}
11
+ end
12
+
13
+ def handler(key, &block)
14
+ @calls[key] = 0 unless @calls.key?(key)
15
+ @calls[key] += 1
16
+ block.call
17
+ end
18
+
19
+ def method_missing(method_name, *args)
20
+ @grpc.send(method_name, *args) do |key, &block|
21
+ handler(key, &block)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
data/ports/grpc.rb CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  require_relative '../components/cache'
4
4
  require_relative '../components/lnd'
5
+ require_relative 'grpc/session'
5
6
 
6
7
  module Lighstorm
7
8
  module Ports
8
9
  class GRPC
9
- def initialize(service, service_key)
10
+ def initialize(service, service_key, &handler)
10
11
  @service = service
11
12
  @service_key = service_key
13
+ @handler = handler
12
14
  end
13
15
 
14
16
  def call!(call_key, *args, &block)
@@ -17,12 +19,24 @@ module Lighstorm
17
19
  if block.nil?
18
20
  response = Cache.for(key, params: args&.first) do
19
21
  LND.instance.middleware(key) do
20
- @service.send(call_key, *args, &block)
22
+ if @handler
23
+ @handler.call(call_key) do
24
+ @service.send(call_key, *args, &block)
25
+ end
26
+ else
27
+ @service.send(call_key, *args, &block)
28
+ end
21
29
  end
22
30
  end
23
31
  else
24
32
  LND.instance.middleware(key) do
25
- @service.send(call_key, *args, &block)
33
+ if @handler
34
+ @handler.call(call_key) do
35
+ @service.send(call_key, *args, &block)
36
+ end
37
+ else
38
+ @service.send(call_key, *args, &block)
39
+ end
26
40
  end
27
41
  end
28
42
  end
@@ -41,7 +55,11 @@ module Lighstorm
41
55
  @service.respond_to?(call_key) || super
42
56
  end
43
57
 
44
- def self.method_missing(method_name, *_args)
58
+ def self.session
59
+ GRPCSession.new(self)
60
+ end
61
+
62
+ def self.method_missing(method_name, *_args, &block)
45
63
  service_key = method_name.to_sym
46
64
 
47
65
  unless LND.instance.client.respond_to?(service_key)
@@ -49,7 +67,7 @@ module Lighstorm
49
67
  "Method `#{method_name}` doesn't exist."
50
68
  end
51
69
 
52
- new(LND.instance.client.send(service_key), service_key)
70
+ new(LND.instance.client.send(service_key), service_key, &block)
53
71
  end
54
72
 
55
73
  def self.respond_to_missing?(method_name, include_private = false)
data/static/spec.rb CHANGED
@@ -4,7 +4,7 @@ module Lighstorm
4
4
  module Static
5
5
  SPEC = {
6
6
  name: 'lighstorm',
7
- version: '0.0.4',
7
+ version: '0.0.6',
8
8
  author: 'icebaker',
9
9
  summary: 'API for interacting with a Lightning Node.',
10
10
  description: 'Lighstorm is an opinionated abstraction layer on top of the lnd-client for interacting with a Lightning Node.',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lighstorm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - icebaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-22 00:00:00.000000000 Z
11
+ date: 2023-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -66,6 +66,7 @@ extensions: []
66
66
  extra_rdoc_files: []
67
67
  files:
68
68
  - ".env.example"
69
+ - ".github/workflows/ruby-rspec-tests.yml"
69
70
  - ".gitignore"
70
71
  - ".rspec"
71
72
  - ".rubocop.yml"
@@ -75,6 +76,7 @@ files:
75
76
  - README.md
76
77
  - adapters/connections/channel_node.rb
77
78
  - adapters/connections/channel_node/fee.rb
79
+ - adapters/connections/channel_node/policy.rb
78
80
  - adapters/connections/payment_channel.rb
79
81
  - adapters/edges/channel.rb
80
82
  - adapters/edges/forward.rb
@@ -86,6 +88,7 @@ files:
86
88
  - components/cache.rb
87
89
  - components/lnd.rb
88
90
  - controllers/channel.rb
91
+ - controllers/channel/actions/apply_gossip.rb
89
92
  - controllers/channel/actions/update_fee.rb
90
93
  - controllers/channel/all.rb
91
94
  - controllers/channel/find_by_id.rb
@@ -100,6 +103,7 @@ files:
100
103
  - controllers/invoice/all.rb
101
104
  - controllers/invoice/find_by_secret_hash.rb
102
105
  - controllers/node.rb
106
+ - controllers/node/actions/apply_gossip.rb
103
107
  - controllers/node/all.rb
104
108
  - controllers/node/find_by_public_key.rb
105
109
  - controllers/node/myself.rb
@@ -116,10 +120,12 @@ files:
116
120
  - docs/vendor/prismjs/prism-ruby.min.js
117
121
  - docs/vendor/prismjs/prism-tomorrow.min.css
118
122
  - lighstorm.gemspec
123
+ - models/concerns/protectable.rb
119
124
  - models/connections/channel_node.rb
120
125
  - models/connections/channel_node/accounting.rb
121
126
  - models/connections/channel_node/fee.rb
122
127
  - models/connections/channel_node/htlc.rb
128
+ - models/connections/channel_node/htlc/blocks/delta.rb
123
129
  - models/connections/channel_node/policy.rb
124
130
  - models/connections/forward_channel.rb
125
131
  - models/connections/payment_channel.rb
@@ -141,6 +147,7 @@ files:
141
147
  - ports/dsl/lighstorm.rb
142
148
  - ports/dsl/lighstorm/errors.rb
143
149
  - ports/grpc.rb
150
+ - ports/grpc/session.rb
144
151
  - static/cache.rb
145
152
  - static/spec.rb
146
153
  homepage: https://icebaker.github.io/lighstorm