lnd-client 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.example +1 -0
- data/.github/workflows/ruby-rspec-tests.yml +39 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -1
- data/Gemfile +8 -1
- data/Gemfile.lock +37 -8
- data/README.md +31 -81
- data/Rakefile +7 -0
- data/controllers/client.rb +6 -4
- data/controllers/connection.rb +116 -0
- data/controllers/documentation.rb +82 -3
- data/controllers/multiclient.rb +37 -0
- data/controllers/service.rb +4 -4
- data/lnd-client.gemspec +4 -2
- data/models/errors.rb +10 -0
- data/ports/dsl/lnd-client/errors.rb +5 -0
- data/ports/dsl/lnd-client.rb +22 -2
- data/static/spec.rb +3 -1
- metadata +13 -5
- data/controllers/config.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 390eda187c9b089d9231353dde80b2ce4ac24c06623ffde24000bdd8c8581d2d
|
4
|
+
data.tar.gz: 6f6aef6e66df47d1b174a7ff2b2d5f18ee2a0a062501b7c4eda1b4b006be27df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b0fe7dd402b9f180758df35897603a08a88042d7f024b66204508e3d09166f9a539d64a3919b1cde41696f5ebab4001a80c7278c159f7e60b09c4520a973905
|
7
|
+
data.tar.gz: 169d3a0f322e22bec0e955d8ad66d4e3139e99a2677688adac2c7854cd62cec942c868d95f6eec5ecdfb48b5e441ebf561dece46fbafd7eabbcca3d115765b58
|
data/.env.example
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
LND_CLIENT_DELETE_UNUSED_TEST_DATA=false
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
|
6
|
+
# GitHub recommends pinning actions to a commit SHA.
|
7
|
+
# To get a newer version, you will need to update the SHA.
|
8
|
+
# You can also reference a tag or branch, but the action may change without warning.
|
9
|
+
|
10
|
+
name: RSpec Tests
|
11
|
+
|
12
|
+
on:
|
13
|
+
push:
|
14
|
+
branches: [ main ]
|
15
|
+
pull_request:
|
16
|
+
branches: [ main ]
|
17
|
+
|
18
|
+
jobs:
|
19
|
+
rspec:
|
20
|
+
|
21
|
+
runs-on: ubuntu-latest
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v3
|
25
|
+
- uses: actions/cache@v3
|
26
|
+
with:
|
27
|
+
path: vendor/bundle
|
28
|
+
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
29
|
+
restore-keys: |
|
30
|
+
${{ runner.os }}-gems-
|
31
|
+
- name: Set up Ruby
|
32
|
+
uses: ruby/setup-ruby@359bebbc29cbe6c87da6bc9ea3bc930432750108
|
33
|
+
with:
|
34
|
+
ruby-version: '3.0.0'
|
35
|
+
bundler-cache: true
|
36
|
+
- name: Install Dependencies
|
37
|
+
run: bundle install
|
38
|
+
- name: Run RSpec Tests
|
39
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -5,7 +5,14 @@ source 'https://rubygems.org'
|
|
5
5
|
gemspec
|
6
6
|
|
7
7
|
group :test, :development do
|
8
|
+
gem 'babosa', '~> 2.0'
|
9
|
+
gem 'dotenv', '~> 2.8', '>= 2.8.1'
|
8
10
|
gem 'pry-byebug', '~> 3.10', '>= 3.10.1'
|
9
|
-
gem '
|
11
|
+
gem 'rainbow', '~> 3.1', '>= 3.1.1'
|
12
|
+
gem 'rake', '~> 13.0', '>= 13.0.6'
|
13
|
+
gem 'rspec', '~> 3.12'
|
14
|
+
gem 'rubocop', '~> 1.48'
|
10
15
|
gem 'rubocop-rake', '~> 0.6.0'
|
16
|
+
gem 'rubocop-rspec', '~> 2.19'
|
17
|
+
gem 'ruby-progressbar', '~> 1.8', '>= 1.8.1'
|
11
18
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lnd-client (0.0.
|
4
|
+
lnd-client (0.0.6)
|
5
5
|
grpc (~> 1.52)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.4.2)
|
11
|
+
babosa (2.0.0)
|
11
12
|
byebug (11.1.3)
|
12
13
|
coderay (1.1.3)
|
13
|
-
|
14
|
+
diff-lcs (1.5.0)
|
15
|
+
dotenv (2.8.1)
|
16
|
+
google-protobuf (3.22.2-x86_64-linux)
|
14
17
|
googleapis-common-protos-types (1.5.0)
|
15
18
|
google-protobuf (~> 3.14)
|
16
19
|
grpc (1.52.0-x86_64-linux)
|
@@ -19,7 +22,7 @@ GEM
|
|
19
22
|
json (2.6.3)
|
20
23
|
method_source (1.0.0)
|
21
24
|
parallel (1.22.1)
|
22
|
-
parser (3.2.1.
|
25
|
+
parser (3.2.1.1)
|
23
26
|
ast (~> 2.4.1)
|
24
27
|
pry (0.14.2)
|
25
28
|
coderay (~> 1.1)
|
@@ -28,33 +31,59 @@ GEM
|
|
28
31
|
byebug (~> 11.0)
|
29
32
|
pry (>= 0.13, < 0.15)
|
30
33
|
rainbow (3.1.1)
|
34
|
+
rake (13.0.6)
|
31
35
|
regexp_parser (2.7.0)
|
32
36
|
rexml (3.2.5)
|
33
|
-
|
37
|
+
rspec (3.12.0)
|
38
|
+
rspec-core (~> 3.12.0)
|
39
|
+
rspec-expectations (~> 3.12.0)
|
40
|
+
rspec-mocks (~> 3.12.0)
|
41
|
+
rspec-core (3.12.1)
|
42
|
+
rspec-support (~> 3.12.0)
|
43
|
+
rspec-expectations (3.12.2)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.12.0)
|
46
|
+
rspec-mocks (3.12.4)
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
+
rspec-support (~> 3.12.0)
|
49
|
+
rspec-support (3.12.0)
|
50
|
+
rubocop (1.48.1)
|
34
51
|
json (~> 2.3)
|
35
52
|
parallel (~> 1.10)
|
36
53
|
parser (>= 3.2.0.0)
|
37
54
|
rainbow (>= 2.2.2, < 4.0)
|
38
55
|
regexp_parser (>= 1.8, < 3.0)
|
39
56
|
rexml (>= 3.2.5, < 4.0)
|
40
|
-
rubocop-ast (>= 1.
|
57
|
+
rubocop-ast (>= 1.26.0, < 2.0)
|
41
58
|
ruby-progressbar (~> 1.7)
|
42
59
|
unicode-display_width (>= 2.4.0, < 3.0)
|
43
|
-
rubocop-ast (1.
|
60
|
+
rubocop-ast (1.27.0)
|
44
61
|
parser (>= 3.2.1.0)
|
62
|
+
rubocop-capybara (2.17.1)
|
63
|
+
rubocop (~> 1.41)
|
45
64
|
rubocop-rake (0.6.0)
|
46
65
|
rubocop (~> 1.0)
|
47
|
-
|
66
|
+
rubocop-rspec (2.19.0)
|
67
|
+
rubocop (~> 1.33)
|
68
|
+
rubocop-capybara (~> 2.17)
|
69
|
+
ruby-progressbar (1.13.0)
|
48
70
|
unicode-display_width (2.4.2)
|
49
71
|
|
50
72
|
PLATFORMS
|
51
73
|
x86_64-linux
|
52
74
|
|
53
75
|
DEPENDENCIES
|
76
|
+
babosa (~> 2.0)
|
77
|
+
dotenv (~> 2.8, >= 2.8.1)
|
54
78
|
lnd-client!
|
55
79
|
pry-byebug (~> 3.10, >= 3.10.1)
|
56
|
-
|
80
|
+
rainbow (~> 3.1, >= 3.1.1)
|
81
|
+
rake (~> 13.0, >= 13.0.6)
|
82
|
+
rspec (~> 3.12)
|
83
|
+
rubocop (~> 1.48)
|
57
84
|
rubocop-rake (~> 0.6.0)
|
85
|
+
rubocop-rspec (~> 2.19)
|
86
|
+
ruby-progressbar (~> 1.8, >= 1.8.1)
|
58
87
|
|
59
88
|
BUNDLED WITH
|
60
89
|
2.4.4
|
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# lnd-client [![Gem Version](https://badge.fury.io/rb/lnd-client.svg)](https://badge.fury.io/rb/lnd-client) ![RSpec Tests Status](https://github.com/icebaker/lnd-client/actions/workflows/ruby-rspec-tests.yml/badge.svg)
|
2
2
|
|
3
|
-
|
3
|
+
Ruby Lightning Network Daemon Client: Straightforward access to [lnd](https://github.com/lightningnetwork/lnd) [gRPC API](https://lightning.engineering/api-docs/api/lnd/#grpc)
|
4
4
|
|
5
5
|
This is a low-level client library. For a better experience, you may want to check out the [Lighstorm](https://github.com/icebaker/lighstorm) abstraction.
|
6
6
|
|
7
7
|
- [Usage](#usage)
|
8
|
-
- [
|
9
|
-
- [Documentation](#documentation)
|
8
|
+
- [Documentation](https://icebaker.github.io/lnd-client)
|
10
9
|
- [Development](#development)
|
11
10
|
- [Upgrading gRPC Proto Files](#upgrading-grpc-proto-files)
|
11
|
+
- [Generating Documentation](#generating-documentation)
|
12
12
|
- [Publish to RubyGems](#publish-to-rubygems)
|
13
13
|
|
14
14
|
## Usage
|
@@ -16,29 +16,30 @@ This is a low-level client library. For a better experience, you may want to che
|
|
16
16
|
Add to your `Gemfile`:
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
gem 'lnd-client', '~> 0.0.
|
19
|
+
gem 'lnd-client', '~> 0.0.6'
|
20
20
|
```
|
21
21
|
|
22
22
|
```ruby
|
23
23
|
require 'lnd-client'
|
24
24
|
|
25
|
-
puts LNDClient.version # => 0.0.
|
25
|
+
puts LNDClient.version # => 0.0.6
|
26
26
|
|
27
27
|
client = LNDClient.new(
|
28
|
-
|
29
|
-
macaroon_path: '/lnd/data/chain/bitcoin/mainnet/admin.macaroon',
|
30
|
-
socket_address: '127.0.0.1:10009'
|
28
|
+
'lndconnect://127.0.0.1:10009?cert=MIICJz...JBEERQ&macaroon=AgEDbG...45ukJ4'
|
31
29
|
)
|
32
30
|
|
33
31
|
client.lightning.wallet_balance.total_balance # => 101527
|
34
32
|
|
35
33
|
client.lightning.wallet_balance.to_h # =>
|
36
|
-
# {:
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
34
|
+
# { total_balance: 101_527,
|
35
|
+
# confirmed_balance: 101_527,
|
36
|
+
# unconfirmed_balance: 0,
|
37
|
+
# locked_balance: 0,
|
38
|
+
# reserved_balance_anchor_chan: 20_000,
|
39
|
+
# account_balance: {
|
40
|
+
# 'default' => {
|
41
|
+
# confirmed_balance: 101_527,
|
42
|
+
# unconfirmed_balance: 0 } } }
|
42
43
|
|
43
44
|
client.lightning.get_node_info(
|
44
45
|
pub_key: '02d3c80335a8ccb2ed364c06875f32240f36f7edb37d80f8dbe321b4c364b6e997'
|
@@ -53,74 +54,12 @@ client.router.subscribe_htlc_events do |data|
|
|
53
54
|
end
|
54
55
|
```
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
require 'lnd-client'
|
60
|
-
|
61
|
-
puts LNDClient.version # => 0.0.5
|
62
|
-
|
63
|
-
client = LNDClient.new(
|
64
|
-
certificate_path: '/lnd/tls.cert',
|
65
|
-
macaroon_path: '/lnd/data/chain/bitcoin/mainnet/admin.macaroon',
|
66
|
-
socket_address: '127.0.0.1:10009'
|
67
|
-
)
|
68
|
-
|
69
|
-
client.lightning(
|
70
|
-
channel_args: { 'grpc.max_receive_message_length' => 1024 * 1024 * 50 }
|
71
|
-
)
|
72
|
-
|
73
|
-
graph = client.lightning.describe_graph
|
74
|
-
|
75
|
-
graph.nodes # => [...]
|
76
|
-
graph.edges # => [...]
|
77
|
-
```
|
78
|
-
|
79
|
-
### Documentation
|
80
|
-
|
81
|
-
```ruby
|
82
|
-
require 'lnd-client'
|
83
|
-
|
84
|
-
puts LNDClient.version # => 0.0.5
|
85
|
-
|
86
|
-
client = LNDClient.new(
|
87
|
-
certificate_path: '/lnd/tls.cert',
|
88
|
-
macaroon_path: '/lnd/data/chain/bitcoin/mainnet/admin.macaroon',
|
89
|
-
socket_address: '127.0.0.1:10009'
|
90
|
-
)
|
91
|
-
|
92
|
-
client.doc.services # => ['lightning', 'router']
|
93
|
-
|
94
|
-
client.lightning.doc.available_methods # =>
|
95
|
-
# ['abandon_channel',
|
96
|
-
# 'add_invoice',
|
97
|
-
# 'bake_macaroon',
|
98
|
-
# 'batch_open_channel',
|
99
|
-
# 'channel_acceptor',
|
100
|
-
# 'channel_balance',
|
101
|
-
# 'check_macaroon_permissions',
|
102
|
-
# 'close_channel',
|
103
|
-
# 'closed_channels',
|
104
|
-
# # ...
|
105
|
-
# 'get_node_info'
|
106
|
-
# ]
|
107
|
-
|
108
|
-
client.lightning.doc.describe(:get_node_info) # =>
|
109
|
-
# { method: 'get_node_info',
|
110
|
-
# input: { pub_key: '', include_channels: false},
|
111
|
-
# output: { node: nil, num_channels: 0, total_capacity: 0, channels: []}}
|
112
|
-
|
113
|
-
client.lightning.doc.grpc(:get_node_info)
|
114
|
-
# #<struct GRPC::RpcDesc
|
115
|
-
# name=:GetNodeInfo,
|
116
|
-
# input=Lnrpc::NodeInfoRequest,
|
117
|
-
# output=Lnrpc::NodeInfo,
|
118
|
-
# marshal_method=:encode,
|
119
|
-
# unmarshal_method=:decode>
|
120
|
-
```
|
57
|
+
Check the [full documentation](https://icebaker.github.io/lnd-client).
|
121
58
|
|
122
59
|
## Development
|
123
60
|
|
61
|
+
Copy the `.env.example` file to `.env` and provide the required data.
|
62
|
+
|
124
63
|
```ruby
|
125
64
|
# Gemfile
|
126
65
|
gem 'lnd-client', path: '/home/user/lnd-client'
|
@@ -141,6 +80,17 @@ rubocop -A
|
|
141
80
|
```sh
|
142
81
|
bundle exec rake grpc:upgrade
|
143
82
|
```
|
83
|
+
|
84
|
+
### Generating Documentation
|
85
|
+
|
86
|
+
```sh
|
87
|
+
bundle exec rake grpc:docs
|
88
|
+
|
89
|
+
npm i docsify-cli -g
|
90
|
+
|
91
|
+
docsify serve ./docs
|
92
|
+
```
|
93
|
+
|
144
94
|
### Publish to RubyGems
|
145
95
|
|
146
96
|
```sh
|
@@ -148,5 +98,5 @@ gem build lnd-client.gemspec
|
|
148
98
|
|
149
99
|
gem signin
|
150
100
|
|
151
|
-
gem push lnd-client-0.0.
|
101
|
+
gem push lnd-client-0.0.6.gem
|
152
102
|
```
|
data/Rakefile
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './controllers/documentation'
|
3
4
|
require_relative './controllers/grpc_generator'
|
4
5
|
|
5
6
|
namespace :grpc do
|
7
|
+
desc 'Generate gRPC Documentation'
|
8
|
+
task :docs do
|
9
|
+
require 'ruby-progressbar'
|
10
|
+
LNDClientInternal::DocumentationController.generate!
|
11
|
+
end
|
12
|
+
|
6
13
|
desc 'Upgrade lnd Protocol Buffers for gGRPC'
|
7
14
|
task :upgrade do
|
8
15
|
LNDClientInternal::GrpcGeneratorController.upgrade!
|
data/controllers/client.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../components/grpc'
|
4
|
-
|
4
|
+
|
5
5
|
require_relative 'service'
|
6
6
|
|
7
7
|
module LNDClientInternal
|
8
8
|
class ClientController
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :connection, :doc
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@
|
11
|
+
def initialize(connection)
|
12
|
+
@connection = connection
|
13
13
|
@services = {}
|
14
14
|
|
15
15
|
doc = Struct.new(:services)
|
16
16
|
@doc = doc.new(LNDClientInternal::GRPC::SERVICES.keys.map(&:to_s))
|
17
|
+
|
18
|
+
lightning(**connection[:lightning]) if connection[:lightning]
|
17
19
|
end
|
18
20
|
|
19
21
|
def respond_to_missing?(method_name, include_private = false)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'base64'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
require 'grpc'
|
8
|
+
|
9
|
+
require_relative '../models/errors'
|
10
|
+
|
11
|
+
module LNDClientInternal
|
12
|
+
class Connection
|
13
|
+
def self.validate_params!(connection)
|
14
|
+
raise LNDClient::Errors::TooManyArgumentsError if connection.key?(:address) && connection.key?(:host)
|
15
|
+
raise LNDClient::Errors::TooManyArgumentsError if connection.key?(:address) && connection.key?(:port)
|
16
|
+
if connection.key?(:certificate_path) && connection.key?(:certificate)
|
17
|
+
raise LNDClient::Errors::TooManyArgumentsError
|
18
|
+
end
|
19
|
+
raise LNDClient::Errors::TooManyArgumentsError if connection.key?(:macaroon_path) && connection.key?(:macaroon)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.expand(*params, &vcr)
|
23
|
+
connection = if is_lndconnect?(*params)
|
24
|
+
exapand_lndconnect(*params)
|
25
|
+
else
|
26
|
+
params.first
|
27
|
+
end
|
28
|
+
|
29
|
+
validate_params!(connection)
|
30
|
+
|
31
|
+
connection[:certificate] = load_file(connection[:certificate_path], &vcr) if connection[:certificate_path]
|
32
|
+
|
33
|
+
connection[:macaroon] = load_file(connection[:macaroon_path], &vcr) if connection[:macaroon_path]
|
34
|
+
|
35
|
+
if !connection.key?(:address) && connection.key?(:host) && connection.key?(:port)
|
36
|
+
connection[:address] = "#{connection[:host]}:#{connection[:port]}"
|
37
|
+
elsif !connection.key?(:address)
|
38
|
+
raise LNDClient::Errors::ArgumentError, 'missing :address or :host + :port'
|
39
|
+
end
|
40
|
+
|
41
|
+
connection[:certificate] = decode_certificate(connection[:certificate])
|
42
|
+
connection[:macaroon] = decode_macaroon(connection[:macaroon])
|
43
|
+
|
44
|
+
if params.is_a?(Array)
|
45
|
+
params.each do |param|
|
46
|
+
connection[:lightning] = param[:lightning] if param.is_a?(Hash) && param.key?(:lightning)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
connection
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.decode_macaroon(macaroon)
|
54
|
+
if !macaroon.dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
55
|
+
macaroon.unpack1('H*')
|
56
|
+
elsif hex?(macaroon)
|
57
|
+
macaroon
|
58
|
+
elsif base64?(macaroon)
|
59
|
+
Base64.decode64(macaroon).unpack1('H*')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.decode_certificate(certificate)
|
64
|
+
if hex?(certificate)
|
65
|
+
[certificate].pack('H*')
|
66
|
+
elsif base64?(certificate)
|
67
|
+
Base64.decode64(certificate)
|
68
|
+
else
|
69
|
+
certificate
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.base64?(value)
|
74
|
+
(value.length % 4).zero? && value.match(%r{\A[A-Za-z0-9+/]+={0,3}\z})
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.hex?(value)
|
78
|
+
value.match(/\A[\da-fA-F]+\z/)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.exapand_lndconnect(*params)
|
82
|
+
parsed_uri = URI.parse(params.first)
|
83
|
+
host = parsed_uri.host
|
84
|
+
port = parsed_uri.port || 10_009
|
85
|
+
|
86
|
+
params = URI.decode_www_form(parsed_uri.query).to_h
|
87
|
+
certificate = params['cert'].tr('-_', '+/')
|
88
|
+
macaroon = Base64.urlsafe_decode64(params['macaroon'])
|
89
|
+
|
90
|
+
certificate = "-----BEGIN CERTIFICATE-----\n#{certificate.gsub(/(.{64})/, "\\1\n")}\n-----END CERTIFICATE-----\n"
|
91
|
+
|
92
|
+
{
|
93
|
+
host: host,
|
94
|
+
port: port,
|
95
|
+
certificate: certificate,
|
96
|
+
macaroon: macaroon
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.is_lndconnect?(*params)
|
101
|
+
params.is_a?(Array) &&
|
102
|
+
params.first.is_a?(String) &&
|
103
|
+
params.first.start_with?('lndconnect://')
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.standalone(*params, &vcr)
|
107
|
+
connection = Connection.expand(*params, &vcr)
|
108
|
+
connection[:credentials] = ::GRPC::Core::ChannelCredentials.new(connection[:certificate])
|
109
|
+
connection
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.load_file(path, &vcr)
|
113
|
+
vcr.nil? ? File.read(path) : vcr.call(-> { File.read(path) }, path)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -1,13 +1,92 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'securerandom'
|
4
|
+
|
3
5
|
require_relative '../logic/string'
|
6
|
+
require_relative '../components/grpc'
|
4
7
|
|
5
8
|
module LNDClientInternal
|
6
9
|
class DocumentationController
|
10
|
+
PROGRESS = true
|
11
|
+
PATH = 'docs/README.md'
|
12
|
+
KEY = '<!-- [INJECT:GRP:DOCS] -->'
|
13
|
+
|
7
14
|
attr_reader :available_methods
|
8
15
|
|
9
|
-
def
|
10
|
-
|
16
|
+
def self.format(code)
|
17
|
+
id = SecureRandom.hex(32)
|
18
|
+
path = "temp/#{id}.rb"
|
19
|
+
File.write("temp/#{id}.rb", code.gsub(', ', ",\n"))
|
20
|
+
`rubocop -A -c docs/.rubocop.yml #{path}`
|
21
|
+
output = File.read("temp/#{id}.rb")
|
22
|
+
File.delete("temp/#{id}.rb")
|
23
|
+
output.strip
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.generate!
|
27
|
+
services = LNDClientInternal::GRPC::SERVICES.keys.map(&:to_sym)
|
28
|
+
|
29
|
+
if PROGRESS
|
30
|
+
total = services.sum do |service|
|
31
|
+
new(
|
32
|
+
LNDClientInternal::GRPC::SERVICES[service].const_get(:Service)
|
33
|
+
).available_methods.size * 2
|
34
|
+
end
|
35
|
+
progressbar = ProgressBar.create(total: total, format: '%a %e |%b>>%i| %P% | %c of %C')
|
36
|
+
end
|
37
|
+
|
38
|
+
content = ''
|
39
|
+
|
40
|
+
services.each do |service|
|
41
|
+
content += "## #{service}\n"
|
42
|
+
doc = new(LNDClientInternal::GRPC::SERVICES[service].const_get(:Service))
|
43
|
+
|
44
|
+
doc.available_methods.each do |method_name|
|
45
|
+
content += "\n### #{method_name}\n"
|
46
|
+
|
47
|
+
url = "https://lightning.engineering/api-docs/api/lnd/#{service}/#{method_name.gsub('_', '-')}/index.html"
|
48
|
+
|
49
|
+
content += "\n[lightning.engineering/#{service}/#{method_name.gsub('_', '-')}](#{url})\n"
|
50
|
+
|
51
|
+
description = doc.describe(method_name)
|
52
|
+
content += "\n```ruby\n"
|
53
|
+
|
54
|
+
code = "client.#{service}.#{method_name}"
|
55
|
+
|
56
|
+
code += "(\n#{description[:input].inspect}\n)" if !description[:input].nil? && !description[:input].empty?
|
57
|
+
|
58
|
+
code += " do |data|\n puts data.inspect # => { ... }\nend" if method_name =~ /^subscribe/
|
59
|
+
|
60
|
+
content += if !description[:input].nil? && !description[:input].empty?
|
61
|
+
"#{self.format(code)}\n```\n"
|
62
|
+
else
|
63
|
+
"#{code}\n```\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
progressbar.increment if PROGRESS
|
67
|
+
|
68
|
+
if !description[:output].nil? && !description[:output].empty?
|
69
|
+
code = self.format(description[:output].inspect)
|
70
|
+
content += "\nOutput:\n```ruby\n#{code}\n```\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
progressbar.increment if PROGRESS
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
document = File.read(PATH)
|
78
|
+
|
79
|
+
parts = document.split(KEY)
|
80
|
+
|
81
|
+
File.write(PATH, "#{parts[0]}#{KEY}\n\n#{content}\n#{KEY}#{parts[2]}")
|
82
|
+
|
83
|
+
progressbar.finish
|
84
|
+
|
85
|
+
puts "\nDocumentation updated: #{PATH}\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(grpc_service)
|
89
|
+
@grpc_service = grpc_service
|
11
90
|
@descriptions = {}
|
12
91
|
@grpc = {}
|
13
92
|
|
@@ -15,7 +94,7 @@ module LNDClientInternal
|
|
15
94
|
end
|
16
95
|
|
17
96
|
def build!
|
18
|
-
@available_methods = @
|
97
|
+
@available_methods = @grpc_service.rpc_descs.values.map do |desc|
|
19
98
|
method_name = LNDClientInternal::StringLogic.underscore(desc.name.to_s)
|
20
99
|
|
21
100
|
build_description!(method_name, desc)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
require_relative 'connection'
|
6
|
+
|
7
|
+
require_relative 'client'
|
8
|
+
|
9
|
+
module LNDClientInternal
|
10
|
+
class Multiclient
|
11
|
+
include Singleton
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@clients = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_connection!(id, *params)
|
18
|
+
@clients[id] = ClientController.new(Connection.standalone(*params))
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove_connection!(id)
|
22
|
+
@clients.delete(id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def as(id)
|
26
|
+
@clients[id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear!
|
30
|
+
@clients = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def connections
|
34
|
+
@clients.keys
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/controllers/service.rb
CHANGED
@@ -11,17 +11,17 @@ module LNDClientInternal
|
|
11
11
|
@rpc = rpc
|
12
12
|
@service = rpc.const_get(:Service)
|
13
13
|
@stub = rpc.const_get(:Stub).new(
|
14
|
-
client.
|
15
|
-
client.
|
14
|
+
client.connection[:address],
|
15
|
+
client.connection[:credentials],
|
16
16
|
**params
|
17
17
|
)
|
18
|
-
@doc = LNDClientInternal::DocumentationController.new(
|
18
|
+
@doc = LNDClientInternal::DocumentationController.new(@service)
|
19
19
|
end
|
20
20
|
|
21
21
|
def call!(method_key, desc, *args, &block)
|
22
22
|
@stub.method(method_key).call(
|
23
23
|
desc.input.new(*args),
|
24
|
-
{ metadata: { macaroon: @client.
|
24
|
+
{ metadata: { macaroon: @client.connection[:macaroon] } },
|
25
25
|
&block
|
26
26
|
)
|
27
27
|
end
|
data/lnd-client.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.summary = LNDClientInternal::Static::SPEC[:summary]
|
11
11
|
spec.description = LNDClientInternal::Static::SPEC[:description]
|
12
12
|
|
13
|
-
spec.homepage = LNDClientInternal::Static::SPEC[:
|
13
|
+
spec.homepage = LNDClientInternal::Static::SPEC[:documentation]
|
14
14
|
|
15
15
|
spec.license = LNDClientInternal::Static::SPEC[:license]
|
16
16
|
|
@@ -20,10 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.metadata['homepage_uri'] = spec.homepage
|
22
22
|
spec.metadata['source_code_uri'] = LNDClientInternal::Static::SPEC[:github]
|
23
|
+
spec.metadata['documentation_uri'] = LNDClientInternal::Static::SPEC[:documentation]
|
24
|
+
spec.metadata['bug_tracker_uri'] = LNDClientInternal::Static::SPEC[:issues]
|
23
25
|
|
24
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
27
|
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
-
f.match(%r{\A(?:test|spec|features)/})
|
28
|
+
f.match(%r{\A(?:test|spec|docs|features)/})
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
data/models/errors.rb
ADDED
data/ports/dsl/lnd-client.rb
CHANGED
@@ -1,11 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../controllers/connection'
|
3
4
|
require_relative '../../controllers/client'
|
5
|
+
require_relative '../../controllers/multiclient'
|
4
6
|
require_relative '../../static/spec'
|
5
7
|
|
6
8
|
module LNDClient
|
7
|
-
def self.new(
|
8
|
-
LNDClientInternal::ClientController.new(
|
9
|
+
def self.new(...)
|
10
|
+
LNDClientInternal::ClientController.new(
|
11
|
+
LNDClientInternal::Connection.standalone(...)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.add_connection!(...)
|
16
|
+
LNDClientInternal::Multiclient.instance.add_connection!(...)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.connections(...)
|
20
|
+
LNDClientInternal::Multiclient.instance.connections(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.as(...)
|
24
|
+
LNDClientInternal::Multiclient.instance.as(...)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.remove_connection!(...)
|
28
|
+
LNDClientInternal::Multiclient.instance.remove_connection!(...)
|
9
29
|
end
|
10
30
|
|
11
31
|
def self.version
|
data/static/spec.rb
CHANGED
@@ -4,11 +4,13 @@ module LNDClientInternal
|
|
4
4
|
module Static
|
5
5
|
SPEC = {
|
6
6
|
name: 'lnd-client',
|
7
|
-
version: '0.0.
|
7
|
+
version: '0.0.6',
|
8
8
|
author: 'icebaker',
|
9
9
|
summary: 'Ruby Lightning Network Daemon (lnd) Client',
|
10
10
|
description: 'Ruby Lightning Network Daemon (lnd) Client',
|
11
11
|
github: 'https://github.com/icebaker/lnd-client',
|
12
|
+
documentation: 'https://icebaker.github.io/lnd-client',
|
13
|
+
issues: 'https://github.com/icebaker/lnd-client/issues',
|
12
14
|
license: 'MIT'
|
13
15
|
}.freeze
|
14
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lnd-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
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-
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grpc
|
@@ -30,7 +30,10 @@ executables: []
|
|
30
30
|
extensions: []
|
31
31
|
extra_rdoc_files: []
|
32
32
|
files:
|
33
|
+
- ".env.example"
|
34
|
+
- ".github/workflows/ruby-rspec-tests.yml"
|
33
35
|
- ".gitignore"
|
36
|
+
- ".rspec"
|
34
37
|
- ".rubocop.yml"
|
35
38
|
- Gemfile
|
36
39
|
- Gemfile.lock
|
@@ -72,21 +75,26 @@ files:
|
|
72
75
|
- components/grpc/wtclientrpc/wtclient_pb.rb
|
73
76
|
- components/grpc/wtclientrpc/wtclient_services_pb.rb
|
74
77
|
- controllers/client.rb
|
75
|
-
- controllers/
|
78
|
+
- controllers/connection.rb
|
76
79
|
- controllers/documentation.rb
|
77
80
|
- controllers/grpc_generator.rb
|
81
|
+
- controllers/multiclient.rb
|
78
82
|
- controllers/service.rb
|
79
83
|
- lnd-client.gemspec
|
80
84
|
- logic/string.rb
|
85
|
+
- models/errors.rb
|
81
86
|
- ports/dsl/lnd-client.rb
|
87
|
+
- ports/dsl/lnd-client/errors.rb
|
82
88
|
- static/spec.rb
|
83
|
-
homepage: https://github.
|
89
|
+
homepage: https://icebaker.github.io/lnd-client
|
84
90
|
licenses:
|
85
91
|
- MIT
|
86
92
|
metadata:
|
87
93
|
allowed_push_host: https://rubygems.org
|
88
|
-
homepage_uri: https://github.
|
94
|
+
homepage_uri: https://icebaker.github.io/lnd-client
|
89
95
|
source_code_uri: https://github.com/icebaker/lnd-client
|
96
|
+
documentation_uri: https://icebaker.github.io/lnd-client
|
97
|
+
bug_tracker_uri: https://github.com/icebaker/lnd-client/issues
|
90
98
|
rubygems_mfa_required: 'true'
|
91
99
|
post_install_message:
|
92
100
|
rdoc_options: []
|
data/controllers/config.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'grpc'
|
4
|
-
|
5
|
-
module LNDClientInternal
|
6
|
-
class ConfigController
|
7
|
-
attr_reader :socket_address, :credentials, :certificate, :macaroon
|
8
|
-
|
9
|
-
def initialize(client, options)
|
10
|
-
@client = client
|
11
|
-
|
12
|
-
@certificate_path = options[:certificate_path]
|
13
|
-
@certificate = options[:certificate]
|
14
|
-
|
15
|
-
@macaroon_path = options[:macaroon_path]
|
16
|
-
@macaroon = options[:macaroon]
|
17
|
-
|
18
|
-
@socket_address = options[:socket_address] || '127.0.0.1:10009'
|
19
|
-
|
20
|
-
setup_certificate!
|
21
|
-
setup_macaroon!
|
22
|
-
end
|
23
|
-
|
24
|
-
def setup_certificate!
|
25
|
-
raise 'conflicting options for certificate' if @certificate && @certificate_path
|
26
|
-
|
27
|
-
@certificate = File.read(@certificate_path) if @certificate_path
|
28
|
-
@credentials = ::GRPC::Core::ChannelCredentials.new(@certificate)
|
29
|
-
end
|
30
|
-
|
31
|
-
def setup_macaroon!
|
32
|
-
raise 'conflicting options for macaroon' if @macaroon && @macaroon_path
|
33
|
-
|
34
|
-
@macaroon = File.read(@macaroon_path).unpack('H*') if @macaroon_path
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|