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.
- checksums.yaml +4 -4
- data/.env.example +5 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +32 -8
- data/README.md +30 -341
- data/adapters/connections/channel_node/fee.rb +26 -0
- data/adapters/connections/channel_node.rb +52 -0
- data/adapters/connections/payment_channel.rb +28 -0
- data/adapters/edges/channel.rb +80 -0
- data/adapters/edges/forward.rb +41 -0
- data/adapters/edges/payment/purpose.rb +34 -0
- data/adapters/edges/payment.rb +53 -0
- data/adapters/invoice.rb +50 -0
- data/adapters/nodes/node.rb +77 -0
- data/adapters/payment_request.rb +77 -0
- data/components/cache.rb +3 -2
- data/components/lnd.rb +5 -1
- 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 +23 -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/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 +23 -0
- data/controllers/payment/all.rb +352 -0
- data/controllers/payment.rb +21 -0
- data/docs/.nojekyll +0 -0
- data/docs/README.md +655 -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 +4 -2
- data/models/connections/channel_node/accounting.rb +3 -12
- data/models/connections/channel_node/fee.rb +44 -56
- data/models/connections/channel_node/htlc.rb +52 -0
- data/models/connections/channel_node/policy.rb +11 -12
- data/models/connections/channel_node.rb +20 -19
- data/models/connections/forward_channel.rb +8 -43
- data/models/connections/payment_channel.rb +18 -39
- data/models/edges/channel/accounting.rb +42 -18
- data/models/edges/channel/hop.rb +65 -0
- data/models/edges/channel.rb +98 -120
- data/models/edges/forward.rb +9 -118
- 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 -214
- data/models/errors.rb +29 -0
- data/models/invoice.rb +49 -0
- data/models/nodes/node/lightning.rb +5 -16
- data/models/nodes/node/platform.rb +7 -13
- data/models/nodes/node.rb +19 -56
- data/models/payment_request.rb +69 -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 +12 -8
- data/ports/grpc.rb +62 -0
- data/static/cache.rb +12 -0
- data/static/spec.rb +3 -1
- metadata +58 -8
- data/models/connections/channel_node/constraints.rb +0 -24
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
require_relative '../connections/channel_node'
|
7
|
+
|
8
|
+
module Lighstorm
|
9
|
+
module Adapter
|
10
|
+
class Channel
|
11
|
+
def self._key(id, active)
|
12
|
+
Digest::SHA256.hexdigest(
|
13
|
+
[id, active].join('/')
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.list_channels(grpc, at)
|
18
|
+
{
|
19
|
+
_source: :list_channels,
|
20
|
+
_key: _key(grpc[:chan_id], grpc[:active]),
|
21
|
+
# Standard JSON don't support BigInt, so, a String is safer.
|
22
|
+
id: grpc[:chan_id].to_s,
|
23
|
+
transaction: {
|
24
|
+
funding: {
|
25
|
+
id: grpc[:channel_point].split(':').first,
|
26
|
+
index: grpc[:channel_point].split(':').last.to_i
|
27
|
+
}
|
28
|
+
},
|
29
|
+
opened_at: DateTime.parse((at - grpc[:lifetime]).to_s),
|
30
|
+
up_at: DateTime.parse((at - grpc[:uptime]).to_s),
|
31
|
+
active: grpc[:active],
|
32
|
+
exposure: grpc[:private] ? 'private' : 'public',
|
33
|
+
accounting: {
|
34
|
+
capacity: { milisatoshis: grpc[:capacity] * 1000 },
|
35
|
+
sent: { milisatoshis: grpc[:total_satoshis_sent] * 1000 },
|
36
|
+
received: { milisatoshis: grpc[:total_satoshis_received] * 1000 },
|
37
|
+
unsettled: { milisatoshis: grpc[:unsettled_balance] * 1000 }
|
38
|
+
},
|
39
|
+
partners: [
|
40
|
+
ChannelNode.list_channels(grpc, :local),
|
41
|
+
ChannelNode.list_channels(grpc, :remote)
|
42
|
+
]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.get_chan_info(grpc)
|
47
|
+
{
|
48
|
+
_source: :get_chan_info,
|
49
|
+
_key: _key(grpc[:channel_id], nil),
|
50
|
+
# Standard JSON don't support BigInt, so, a String is safer.
|
51
|
+
id: grpc[:channel_id].to_s,
|
52
|
+
accounting: {
|
53
|
+
capacity: { milisatoshis: grpc[:capacity] * 1000 }
|
54
|
+
},
|
55
|
+
partners: [
|
56
|
+
ChannelNode.get_chan_info(grpc, 1),
|
57
|
+
ChannelNode.get_chan_info(grpc, 2)
|
58
|
+
]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.describe_graph(grpc)
|
63
|
+
{
|
64
|
+
_source: :describe_graph,
|
65
|
+
_key: _key(grpc[:channel_id], nil),
|
66
|
+
# Standard JSON don't support BigInt, so, a String is safer.
|
67
|
+
id: grpc[:channel_id].to_s,
|
68
|
+
exposure: 'public',
|
69
|
+
accounting: {
|
70
|
+
capacity: { milisatoshis: grpc[:capacity] * 1000 }
|
71
|
+
},
|
72
|
+
partners: [
|
73
|
+
ChannelNode.describe_graph(grpc, 1),
|
74
|
+
ChannelNode.describe_graph(grpc, 2)
|
75
|
+
]
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
module Lighstorm
|
7
|
+
module Adapter
|
8
|
+
class Forward
|
9
|
+
def self.forwarding_history(grpc)
|
10
|
+
{
|
11
|
+
_source: :forwarding_history,
|
12
|
+
_key: _key(grpc),
|
13
|
+
at: DateTime.parse(Time.at(grpc[:timestamp_ns] / 1e+9).to_s),
|
14
|
+
fee: { milisatoshis: grpc[:fee_msat] },
|
15
|
+
in: {
|
16
|
+
amount: { milisatoshis: grpc[:amt_in_msat] },
|
17
|
+
channel: {
|
18
|
+
id: grpc[:chan_id_in].to_s
|
19
|
+
}
|
20
|
+
},
|
21
|
+
out: {
|
22
|
+
amount: { milisatoshis: grpc[:amt_out_msat] },
|
23
|
+
channel: {
|
24
|
+
id: grpc[:chan_id_out].to_s
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self._key(grpc)
|
31
|
+
Digest::SHA256.hexdigest(
|
32
|
+
[
|
33
|
+
grpc[:timestamp_ns],
|
34
|
+
grpc[:chan_id_in], grpc[:chan_id_out],
|
35
|
+
grpc[:amt_in_msat], grpc[:fee_msat]
|
36
|
+
].join('/')
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module Lighstorm
|
6
|
+
module Adapter
|
7
|
+
class Purpose
|
8
|
+
def self.list_payments(grpc, node_get_info)
|
9
|
+
return 'self-payment' if self_payment?(grpc)
|
10
|
+
return 'peer-to-peer' if peer_to_peer?(grpc)
|
11
|
+
return 'rebalance' if rebalance?(grpc, node_get_info)
|
12
|
+
|
13
|
+
'payment'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.self_payment?(grpc)
|
17
|
+
grpc[:htlcs].first[:route][:hops].size == 2 &&
|
18
|
+
grpc[:htlcs].first[:route][:hops][0][:chan_id] == grpc[:htlcs].first[:route][:hops][1][:chan_id]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.peer_to_peer?(grpc)
|
22
|
+
grpc[:htlcs].first[:route][:hops].size == 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.rebalance?(grpc, node_get_info)
|
26
|
+
return false if grpc[:htlcs].first[:route][:hops].size <= 2
|
27
|
+
|
28
|
+
destination_public_key = grpc[:htlcs].first[:route][:hops].last[:pub_key]
|
29
|
+
|
30
|
+
node_get_info[:identity_pubkey] == destination_public_key
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
require_relative '../connections/payment_channel'
|
7
|
+
require_relative 'payment/purpose'
|
8
|
+
|
9
|
+
require_relative '../payment_request'
|
10
|
+
|
11
|
+
require_relative '../../ports/dsl/lighstorm/errors'
|
12
|
+
|
13
|
+
module Lighstorm
|
14
|
+
module Adapter
|
15
|
+
class Payment
|
16
|
+
def self._key(grpc)
|
17
|
+
Digest::SHA256.hexdigest(
|
18
|
+
[
|
19
|
+
grpc[:payment_request],
|
20
|
+
grpc[:creation_time_ns],
|
21
|
+
grpc[:resolve_time_ns],
|
22
|
+
grpc[:status]
|
23
|
+
].join('/')
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.list_payments(grpc, node_get_info)
|
28
|
+
raise UnexpectedNumberOfHTLCsError, "htlcs: #{grpc[:htlcs].size}" if grpc[:htlcs].size > 1
|
29
|
+
|
30
|
+
data = {
|
31
|
+
_source: :list_payments,
|
32
|
+
_key: _key(grpc),
|
33
|
+
created_at: DateTime.parse(Time.at(grpc[:creation_time_ns] / 1e+9).to_s),
|
34
|
+
status: grpc[:status].to_s.downcase,
|
35
|
+
fee: { milisatoshis: grpc[:fee_msat] },
|
36
|
+
purpose: Purpose.list_payments(grpc, node_get_info),
|
37
|
+
request: PaymentRequest.list_payments(grpc),
|
38
|
+
hops: grpc[:htlcs].first[:route][:hops].map.with_index do |raw_hop, i|
|
39
|
+
hop = PaymentChannel.list_payments(raw_hop, i)
|
40
|
+
hop[:channel][:target] = { public_key: raw_hop[:pub_key] }
|
41
|
+
hop
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
if grpc[:htlcs].first[:resolve_time_ns]
|
46
|
+
data[:settled_at] = DateTime.parse(Time.at(grpc[:htlcs].first[:resolve_time_ns] / 1e+9).to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
data
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/adapters/invoice.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
require_relative 'payment_request'
|
7
|
+
|
8
|
+
module Lighstorm
|
9
|
+
module Adapter
|
10
|
+
class Invoice
|
11
|
+
def self.lookup_invoice(grpc)
|
12
|
+
adapted = list_or_lookup(grpc)
|
13
|
+
|
14
|
+
adapted[:_source] = :lookup_invoice
|
15
|
+
adapted[:request] = PaymentRequest.lookup_invoice(grpc)
|
16
|
+
|
17
|
+
adapted
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.list_invoices(grpc)
|
21
|
+
adapted = list_or_lookup(grpc)
|
22
|
+
|
23
|
+
adapted[:_source] = :list_invoices
|
24
|
+
adapted[:request] = PaymentRequest.list_invoices(grpc)
|
25
|
+
|
26
|
+
adapted
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.list_or_lookup(grpc)
|
30
|
+
{
|
31
|
+
_key: _key(grpc),
|
32
|
+
created_at: DateTime.parse(Time.at(grpc[:creation_date]).to_s),
|
33
|
+
settle_at: DateTime.parse(Time.at(grpc[:settle_date]).to_s),
|
34
|
+
state: grpc[:state].to_s.downcase
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def self._key(grpc)
|
39
|
+
Digest::SHA256.hexdigest(
|
40
|
+
[
|
41
|
+
grpc[:creation_date],
|
42
|
+
grpc[:settle_date],
|
43
|
+
grpc[:payment_request],
|
44
|
+
grpc[:state]
|
45
|
+
].join('/')
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
module Lighstorm
|
6
|
+
module Adapter
|
7
|
+
class Node
|
8
|
+
def self._key(public_key)
|
9
|
+
Digest::SHA256.hexdigest(
|
10
|
+
[public_key].join('/')
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.get_chan_info(grpc, index)
|
15
|
+
{
|
16
|
+
_source: :get_chan_info,
|
17
|
+
_key: _key(grpc[:"node#{index}_pub"]),
|
18
|
+
public_key: grpc[:"node#{index}_pub"]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.list_channels(grpc, key)
|
23
|
+
{
|
24
|
+
_source: :list_channels,
|
25
|
+
_key: _key(key == :remote ? grpc[:remote_pubkey] : nil),
|
26
|
+
public_key: key == :remote ? grpc[:remote_pubkey] : nil
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.get_info(grpc)
|
31
|
+
{
|
32
|
+
_source: :get_info,
|
33
|
+
_key: _key(grpc[:identity_pubkey]),
|
34
|
+
public_key: grpc[:identity_pubkey],
|
35
|
+
alias: grpc[:alias],
|
36
|
+
color: grpc[:color],
|
37
|
+
platform: {
|
38
|
+
blockchain: grpc[:chains][0][:chain],
|
39
|
+
network: grpc[:chains][0][:network],
|
40
|
+
lightning: {
|
41
|
+
implementation: 'lnd',
|
42
|
+
version: grpc[:version]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.get_node_info(grpc)
|
49
|
+
{
|
50
|
+
_source: :get_node_info,
|
51
|
+
_key: _key(grpc[:node][:pub_key]),
|
52
|
+
public_key: grpc[:node][:pub_key],
|
53
|
+
alias: grpc[:node][:alias],
|
54
|
+
color: grpc[:node][:color]
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.describe_graph(grpc)
|
59
|
+
{
|
60
|
+
_source: :describe_graph,
|
61
|
+
_key: _key(grpc[:pub_key]),
|
62
|
+
public_key: grpc[:pub_key],
|
63
|
+
alias: grpc[:alias],
|
64
|
+
color: grpc[:color]
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.describe_graph_from_channel(grpc, index)
|
69
|
+
{
|
70
|
+
_source: :describe_graph,
|
71
|
+
_key: _key(grpc[:"node#{index}_pub"]),
|
72
|
+
public_key: grpc[:"node#{index}_pub"]
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
require_relative '../ports/dsl/lighstorm/errors'
|
7
|
+
|
8
|
+
module Lighstorm
|
9
|
+
module Adapter
|
10
|
+
class PaymentRequest
|
11
|
+
def self.decode_pay_req(grpc)
|
12
|
+
{
|
13
|
+
_source: :decode_pay_req,
|
14
|
+
amount: { milisatoshis: grpc[:num_msat] },
|
15
|
+
description: {
|
16
|
+
memo: grpc[:description],
|
17
|
+
hash: grpc[:description_hash] == '' ? nil : grpc[:description_hash]
|
18
|
+
},
|
19
|
+
address: grpc[:payment_addr].unpack1('H*'),
|
20
|
+
secret: {
|
21
|
+
hash: grpc[:payment_hash]
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.lookup_invoice(grpc)
|
27
|
+
adapted = list_or_lookup_invoice(grpc)
|
28
|
+
adapted[:_source] = :lookup_invoice
|
29
|
+
adapted
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.list_invoices(grpc)
|
33
|
+
adapted = list_or_lookup_invoice(grpc)
|
34
|
+
adapted[:_source] = :list_invoices
|
35
|
+
adapted
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.list_or_lookup_invoice(grpc)
|
39
|
+
{
|
40
|
+
code: grpc[:payment_request],
|
41
|
+
amount: { milisatoshis: grpc[:value_msat] },
|
42
|
+
description: {
|
43
|
+
memo: grpc[:memo],
|
44
|
+
hash: grpc[:description_hash] == '' ? nil : grpc[:description_hash]
|
45
|
+
},
|
46
|
+
address: grpc[:payment_addr].unpack1('H*'),
|
47
|
+
secret: {
|
48
|
+
preimage: grpc[:r_preimage].unpack1('H*'),
|
49
|
+
hash: grpc[:r_hash].unpack1('H*')
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.list_payments(grpc)
|
55
|
+
raise UnexpectedNumberOfHTLCsError, "htlcs: #{grpc[:htlcs].size}" if grpc[:htlcs].size > 1
|
56
|
+
|
57
|
+
data = {
|
58
|
+
_source: :list_payments,
|
59
|
+
code: grpc[:payment_request],
|
60
|
+
amount: { milisatoshis: grpc[:value_msat] },
|
61
|
+
secret: {
|
62
|
+
preimage: grpc[:payment_preimage],
|
63
|
+
hash: grpc[:payment_hash]
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
grpc[:htlcs].first[:route][:hops].map do |raw_hop|
|
68
|
+
if raw_hop[:mpp_record] && raw_hop[:mpp_record][:payment_addr]
|
69
|
+
data[:address] = raw_hop[:mpp_record][:payment_addr].unpack1('H*')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
data
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/components/cache.rb
CHANGED
@@ -5,6 +5,7 @@ require 'singleton'
|
|
5
5
|
require 'zache'
|
6
6
|
|
7
7
|
require_relative '../static/cache'
|
8
|
+
require_relative '../ports/dsl/lighstorm/errors'
|
8
9
|
|
9
10
|
module Lighstorm
|
10
11
|
class Cache
|
@@ -23,7 +24,7 @@ module Lighstorm
|
|
23
24
|
def for(key, ttl: nil, params: {}, &block)
|
24
25
|
if ttl.nil?
|
25
26
|
ttl = Lighstorm::Static::CACHE[key.sub('lightning.', '').to_sym]
|
26
|
-
raise "missing ttl for #{key}" if ttl.nil?
|
27
|
+
raise MissingTTLError, "missing ttl for #{key} static/cache.rb" if ttl.nil?
|
27
28
|
|
28
29
|
ttl = ttl[:ttl]
|
29
30
|
end
|
@@ -36,7 +37,7 @@ module Lighstorm
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def build_key_for(key, params)
|
39
|
-
return key unless params.size.positive?
|
40
|
+
return key unless !params.nil? && params.size.positive?
|
40
41
|
|
41
42
|
key_params = []
|
42
43
|
params.keys.sort.each do |param_key|
|
data/components/lnd.rb
CHANGED
@@ -4,6 +4,8 @@ require 'singleton'
|
|
4
4
|
|
5
5
|
require 'lnd-client'
|
6
6
|
|
7
|
+
require_relative '../ports/dsl/lighstorm/errors'
|
8
|
+
|
7
9
|
module Lighstorm
|
8
10
|
class LND
|
9
11
|
include Singleton
|
@@ -23,7 +25,9 @@ module Lighstorm
|
|
23
25
|
def client
|
24
26
|
return @client if @client
|
25
27
|
|
26
|
-
raise 'missing credentials' if @config.nil? && ENV.fetch(
|
28
|
+
raise MissingCredentialsError, 'missing credentials' if @config.nil? && ENV.fetch(
|
29
|
+
'LIGHSTORM_CERTIFICATE_PATH', nil
|
30
|
+
).nil?
|
27
31
|
|
28
32
|
@client = if @config
|
29
33
|
create_client_from_config
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../ports/grpc'
|
4
|
+
require_relative '../../../models/errors'
|
5
|
+
require_relative '../../../models/satoshis'
|
6
|
+
require_relative '../../../models/rate'
|
7
|
+
|
8
|
+
module Lighstorm
|
9
|
+
module Controllers
|
10
|
+
module Channel
|
11
|
+
module UpdateFee
|
12
|
+
def self.perform(policy, params, preview: false, fake: false)
|
13
|
+
grpc_request = {
|
14
|
+
service: :lightning,
|
15
|
+
method: :update_channel_policy,
|
16
|
+
params: {
|
17
|
+
chan_point: {
|
18
|
+
funding_txid_str: policy.transaction.funding.id,
|
19
|
+
output_index: policy.transaction.funding.index
|
20
|
+
},
|
21
|
+
base_fee_msat: policy.fee.base.milisatoshis,
|
22
|
+
fee_rate_ppm: policy.fee.rate.parts_per_million,
|
23
|
+
time_lock_delta: policy.htlc.blocks.delta.minimum,
|
24
|
+
max_htlc_msat: policy.htlc.maximum.milisatoshis,
|
25
|
+
min_htlc_msat: policy.htlc.minimum.milisatoshis
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
if params[:rate] && params[:rate][:parts_per_million]
|
30
|
+
if (params[:rate][:parts_per_million]).negative?
|
31
|
+
raise Errors::NegativeNotAllowedError, "fee rate can't be negative: #{params[:rate][:parts_per_million]}"
|
32
|
+
end
|
33
|
+
|
34
|
+
grpc_request[:params][:fee_rate_ppm] = params[:rate][:parts_per_million]
|
35
|
+
end
|
36
|
+
|
37
|
+
if params[:base] && params[:base][:milisatoshis]
|
38
|
+
if (params[:base][:milisatoshis]).negative?
|
39
|
+
raise Errors::NegativeNotAllowedError, "fee base can't be negative: #{params[:base][:milisatoshis]}"
|
40
|
+
end
|
41
|
+
|
42
|
+
grpc_request[:params][:base_fee_msat] = params[:base][:milisatoshis]
|
43
|
+
end
|
44
|
+
|
45
|
+
return grpc_request if preview
|
46
|
+
|
47
|
+
response = if fake
|
48
|
+
:fake
|
49
|
+
else
|
50
|
+
LND.instance.middleware("lightning.#{grpc_request[:method]}") do
|
51
|
+
LND.instance.client.lightning.send(grpc_request[:method], grpc_request[:params])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
raise UpdateChannelPolicyError.new(nil, response) unless fake || response.failed_updates.empty?
|
56
|
+
|
57
|
+
token = SecureRandom.hex
|
58
|
+
policy.fee.prepare_token!(token)
|
59
|
+
policy.fee.base = {
|
60
|
+
value: Models::Satoshis.new(milisatoshis: grpc_request[:params][:base_fee_msat]),
|
61
|
+
token: token
|
62
|
+
}
|
63
|
+
|
64
|
+
token = SecureRandom.hex
|
65
|
+
policy.fee.prepare_token!(token)
|
66
|
+
policy.fee.rate = {
|
67
|
+
value: Models::Rate.new(parts_per_million: grpc_request[:params][:fee_rate_ppm]),
|
68
|
+
token: token
|
69
|
+
}
|
70
|
+
|
71
|
+
response
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'mine'
|
4
|
+
|
5
|
+
require_relative '../../ports/grpc'
|
6
|
+
require_relative '../../adapters/edges/channel'
|
7
|
+
require_relative '../../adapters/nodes/node'
|
8
|
+
require_relative '../../adapters/connections/channel_node/fee'
|
9
|
+
|
10
|
+
module Lighstorm
|
11
|
+
module Controllers
|
12
|
+
module Channel
|
13
|
+
module All
|
14
|
+
def self.fetch(limit: nil)
|
15
|
+
data = {
|
16
|
+
at: Time.now,
|
17
|
+
mine: Mine.fetch,
|
18
|
+
describe_graph: Ports::GRPC.lightning.describe_graph.edges
|
19
|
+
}
|
20
|
+
|
21
|
+
data[:describe_graph] = data[:describe_graph][0..limit - 1] unless limit.nil?
|
22
|
+
|
23
|
+
data
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.adapt(raw)
|
27
|
+
mine_adapted = Mine.adapt(raw[:mine])
|
28
|
+
|
29
|
+
mine = mine_adapted[:list_channels].map do |data|
|
30
|
+
Mine.transform(data, mine_adapted)
|
31
|
+
end
|
32
|
+
|
33
|
+
adapted = {
|
34
|
+
mine: {},
|
35
|
+
describe_graph: raw[:describe_graph].map do |raw_channel|
|
36
|
+
Lighstorm::Adapter::Channel.describe_graph(raw_channel.to_h)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
mine.each do |channel|
|
41
|
+
adapted[:mine][channel[:id]] = channel
|
42
|
+
end
|
43
|
+
|
44
|
+
adapted
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.transform(data, adapted)
|
48
|
+
return adapted[:mine][data[:id]] if adapted[:mine][data[:id]]
|
49
|
+
|
50
|
+
data[:known] = true
|
51
|
+
data[:mine] = false
|
52
|
+
|
53
|
+
data[:partners].each do |partner|
|
54
|
+
partner[:node][:platform] = {
|
55
|
+
blockchain: adapted[:mine].first[1][:partners][0][:node][:platform][:blockchain],
|
56
|
+
network: adapted[:mine].first[1][:partners][0][:node][:platform][:network]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
data
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.data(limit: nil, &vcr)
|
64
|
+
raw = vcr.nil? ? fetch(limit: limit) : vcr.call(-> { fetch(limit: limit) })
|
65
|
+
|
66
|
+
adapted = adapt(raw)
|
67
|
+
|
68
|
+
adapted[:describe_graph].map { |data| transform(data, adapted) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.model(data)
|
72
|
+
data.map do |node_data|
|
73
|
+
Lighstorm::Models::Channel.new(node_data)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|