lnd-client 0.0.5 → 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.
- 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 [](https://badge.fury.io/rb/lnd-client) 
|
|
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
|