cardano-up 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 630dda3bb909a92e0fa63562f5aff0f90afa817c8f5170f7567bcf059a962f2e
4
+ data.tar.gz: c37378163253bb7945188c3a8794d6e01d638a0a4a053e887347b9aef5046a48
5
+ SHA512:
6
+ metadata.gz: 7e84594cee7e1fe4716f78c58f1deb39676f0d3ff3d7a721af055d13b6e627e96085dbceabda516665036f0137393121a29176df07bef07c9120872d680013b5
7
+ data.tar.gz: 602b2379f4fd6a2dad86f2f4234ca4c3e7492cb194f73a95e60675f40d502e9dcaef2e3dc37532ae5ccd8b19a48eeddc96d1bd93f1197cceeda64451dd49f10d
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Piotr Stachyra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Cardano Up!
2
+ <a href="https://badge.fury.io/rb/cardano-up">
3
+ <img src="https://badge.fury.io/rb/cardano-up.svg" alt="Gem Version">
4
+ </a>
5
+ <a href="https://github.com/piotr-iohk/cardano-up/releases">
6
+ <img src="https://img.shields.io/github/release/piotr-iohk/cardano-up.svg" />
7
+ </a>
8
+ <a href="https://github.com/piotr-iohk/cardano-up/actions?query=workflow%3ATests">
9
+ <img src="https://github.com/piotr-iohk/cardano-up/workflows/Tests/badge.svg" />
10
+ </a>
11
+ <a href="https://github.com/piotr-iohk/cardano-up/actions?query=workflow%3ADocs">
12
+ <img src="https://github.com/piotr-iohk/cardano-up/workflows/Docs/badge.svg" />
13
+ </a>
14
+ <a href="https://github.com/piotr-iohk/cardano-up/actions?query=workflow%3ARubocop">
15
+ <img src="https://github.com/piotr-iohk/cardano-up/workflows/Rubocop/badge.svg" />
16
+ </a>
17
+
18
+ ## Overview
19
+
20
+ This Ruby gem provides easy way for:
21
+ - getting `cardano-node`, `cardano-cli`, `cardano-wallet`, `cardano-addresses` and `bech32` tools onto your system (Linux, MacOS or Windows).
22
+ - getting configuration for any Cardano public environment.
23
+ - starting, managing and monitoring cardano-node and cardano-wallet services.
24
+
25
+ <img src="cardano-up.gif" />
26
+
27
+ ## Installation
28
+
29
+ $ gem install cardano-up
30
+
31
+ ## Usage
32
+
33
+ It only takes a single command to start node and wallet on your system. Say, on `mainnet`?
34
+
35
+ $ cardano-up mainnet node-wallet up
36
+
37
+ That's it! 🎉
38
+
39
+ If any configs are missing cardano-up will download them. If any binaries are missing cardano-up will get ones from latest release.
40
+
41
+ Call `$ cardano-up --help` to explore more options.
42
+
43
+ ## Documentation
44
+
45
+ | Link | Description |
46
+ |--|--|
47
+ | [Ruby API (edge)](https://piotr-iohk.github.io/cardano-up/master/) | cardano-up API doc |
48
+
49
+ ## How it works
50
+
51
+ **Configurations** for the networks are downloaded from [Cardano Book](https://book.world.dev.cardano.org/environments.html).
52
+
53
+ **Binaries** come from [cardano-wallet](https://github.com/input-output-hk/cardano-wallet) which actually provides `cardano-node`, `cardano-cli`, `cardano-wallet`, `cardano-addresses` and `bech32` tools in each of its release bundles. This ensures that all components are compatible and work smoothly together. You can get any public release of the cardano-wallet bundle as well as `master` version and even any of the PRs that are currently being worked on.
54
+
55
+ **Starting** `cardano-node` and `cardano-wallet`, cardano-up attempts to launch separate [`screen`](https://www.gnu.org/software/screen/) sessions for wallet and node respectively. If screen is not present on your system you can install it using package manager, e.g.:
56
+
57
+ MacOS:
58
+
59
+ $ brew install screen
60
+
61
+ Linux:
62
+
63
+ $ sudo apt-get install screen
64
+
65
+ In case of Windows it will attempt to install cardano-node and cardano-wallet as Windows services using [`nssm`](https://nssm.cc/) tool. Nssm can be installed via choco package manager:
66
+
67
+ $ choco install nssm
68
+
69
+ > :warning: nssm requires administrator permissions to register Windows services, therefore you need to start your cmd as an administrator.
70
+
71
+ By default cardano-up keeps all files at `$HOME/.cardano-up/` however this can be configured by editing `$HOME/.cardano-up/.cardano-up.json` directly or via `config` sub-command. One can check the contents of this internal config file by calling `$ cardano-up config`.
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/cardano-up ADDED
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'cardano-up'
5
+ require 'docopt'
6
+
7
+ doc = <<~DOCOPT
8
+ Cardano Up!
9
+ Lightweight manager for Cardano binaries and configs.
10
+
11
+ Usage:
12
+ #{File.basename(__FILE__)} install [<release>]
13
+ #{File.basename(__FILE__)} get-configs <env>
14
+ #{File.basename(__FILE__)} <env> (node|wallet|node-wallet) up [--port <port>]
15
+ #{File.basename(__FILE__)} <env> (node|wallet|node-wallet) down
16
+ #{File.basename(__FILE__)} <env> (node|wallet) tail
17
+ #{File.basename(__FILE__)} config [--set-default] [--bindir <path>] [--configdir <path>] [--logdir <path>] [--statedir <path>]
18
+ #{File.basename(__FILE__)} -v | --version
19
+ #{File.basename(__FILE__)} -h | --help
20
+
21
+ Options:
22
+ install Install cardano-node, cardano-cli, cardano-wallet, cardano-addresses and bech32.
23
+ <release> latest | release tag | master | pr num [default: latest]
24
+ get-configs Get configs for particular Cardano environment.
25
+ <env> mainnet | preview | preprod etc.
26
+ up Start particular service. If any configs are missing #{File.basename(__FILE__)}
27
+ will download them. If any binaries are missing #{File.basename(__FILE__)} will get
28
+ ones from latest release.
29
+ down Stop particular service.
30
+ tail Follow logs for particular service.
31
+ --port <port> Specify wallet port. [default: 8090]
32
+
33
+ config Internal config for #{File.basename(__FILE__)}
34
+ --set-default Overwrite config with default values.
35
+ --bindir <path> Set bin dir.
36
+ --configdir <path> Set config dir.
37
+ --logdir <path> Set log dir.
38
+ --statedir <path> Set state dir.
39
+
40
+ -v --version Check #{File.basename(__FILE__)} version and versions of
41
+ installed binaries if available.
42
+ -h --help This help.
43
+ DOCOPT
44
+
45
+ def pretty_json(c)
46
+ puts JSON.pretty_generate(c)
47
+ end
48
+
49
+ def ok
50
+ warn 'Ok.'
51
+ end
52
+
53
+ begin
54
+ CardanoUp.configure_default unless CardanoUp.configured?
55
+ o = Docopt.docopt(doc)
56
+
57
+ # VERSION
58
+ if o['--version'] == true
59
+ warn "#{File.basename(__FILE__)}: #{CardanoUp::VERSION}"
60
+ $stderr.puts
61
+ begin
62
+ pretty_json CardanoUp::Install.return_versions
63
+ rescue StandardError => e
64
+ warn 'Nothing installed? To fix run:'
65
+ warn " $ #{File.basename(__FILE__)} install"
66
+ warn e
67
+ end
68
+ exit 1
69
+ end
70
+
71
+ # CONFIG
72
+ if o['config'] == true
73
+ c = CardanoUp.config
74
+ if o['--set-default'] == true
75
+ c = CardanoUp.configure_default
76
+ warn 'Configs set to default!'
77
+ end
78
+ if o['--bindir']
79
+ bindir = o['--bindir']
80
+ c = CardanoUp.configure(bindir, nil, nil, nil)
81
+ warn 'Installdir updated!'
82
+ end
83
+ if o['--statedir']
84
+ statedir = o['--statedir']
85
+ c = CardanoUp.configure(nil, statedir, nil, nil)
86
+ warn 'Statedir updated!'
87
+ end
88
+ if o['--logdir']
89
+ logdir = o['--logdir']
90
+ c = CardanoUp.configure(nil, nil, logdir, nil)
91
+ warn 'Logdir updated!'
92
+ end
93
+ if o['--configdir']
94
+ configdir = o['--configdir']
95
+ c = CardanoUp.configure(nil, nil, nil, configdir)
96
+ warn 'Configdir updated!'
97
+ end
98
+
99
+ warn "Your config file is #{CardanoUp.adrestia_bundler_config}:"
100
+ $stderr.puts
101
+ pretty_json(c)
102
+ exit
103
+ end
104
+
105
+ # INSTALL
106
+ if o['install'] == true
107
+ release = o['<release>']
108
+ begin
109
+ $stderr.print "Installing '#{release}'... "
110
+ versions = CardanoUp::Install.install_bins(release)
111
+ ok
112
+ rescue CardanoUp::VersionNotSupportedError => e
113
+ warn(e.message)
114
+ exit 1
115
+ end
116
+ warn "Install dir: #{CardanoUp.config['bin_dir']}"
117
+ $stderr.puts
118
+ pretty_json(versions)
119
+ exit
120
+ end
121
+
122
+ # INSTALL CONFIGS
123
+ if o['get-configs'] == true
124
+ env = o['<env>']
125
+ begin
126
+ configs = CardanoUp::Install.install_configs(env)
127
+ rescue CardanoUp::EnvNotSupportedError => e
128
+ warn(e.message)
129
+ exit 1
130
+ end
131
+ warn "Downloaded configs for '#{env}' environment."
132
+ warn "Config dir: #{File.join(CardanoUp.config['config_dir'], env)}"
133
+ $stderr.puts
134
+ pretty_json(configs)
135
+ exit
136
+ end
137
+
138
+ # UP
139
+ if o['up'] == true
140
+ env = o['<env>']
141
+ port = o['--port']
142
+
143
+ begin
144
+ $stderr.print 'Configs: '
145
+ unless CardanoUp::Install.configs_exist?(env)
146
+ $stderr.print "installing configs for #{env}... "
147
+ CardanoUp::Install.install_configs(env)
148
+ end
149
+ ok
150
+
151
+ $stderr.print 'Binaries: '
152
+ begin
153
+ CardanoUp::Install.return_versions
154
+ ok
155
+ rescue StandardError
156
+ $stderr.print 'installing latest release binaries... '
157
+ CardanoUp::Install.install_bins('latest')
158
+ ok
159
+ end
160
+
161
+ $stderr.puts
162
+ warn 'Starting...'
163
+ $stderr.puts
164
+ c = CardanoUp::Start.prepare_configuration({ env: env, wallet_port: port })
165
+ rescue CardanoUp::EnvNotSupportedError => e
166
+ warn(e.message)
167
+ exit 1
168
+ end
169
+ begin
170
+ if o['node']
171
+ pretty_json CardanoUp::Start.start_node(c)
172
+ $stderr.puts
173
+ warn "Congratulations! You've just started cardano-node!"
174
+ elsif o['wallet']
175
+ pretty_json CardanoUp::Start.start_wallet(c)
176
+ $stderr.puts
177
+ warn "Congratulations! You've just started cardano-wallet!"
178
+ elsif o['node-wallet']
179
+ pretty_json CardanoUp::Start.start_node_and_wallet(c)
180
+ $stderr.puts
181
+ warn "Congratulations! You've just started cardano-node and cardano-wallet!"
182
+ end
183
+ rescue StandardError => e
184
+ warn 'Either you miss configs or binaries... To fix that try running:'
185
+ warn " $ #{File.basename(__FILE__)} get-configs #{env}"
186
+ warn " $ #{File.basename(__FILE__)} install"
187
+ warn e
188
+ exit 1
189
+ end
190
+ end
191
+
192
+ # STOP
193
+ if o['down'] == true
194
+ env = o['<env>']
195
+
196
+ begin
197
+ if o['node']
198
+ CardanoUp::Start.stop_node(env)
199
+ elsif o['wallet']
200
+ CardanoUp::Start.stop_wallet(env)
201
+ elsif o['node-wallet']
202
+ CardanoUp::Start.stop_node_and_wallet(env)
203
+ end
204
+ warn 'Stopped.'
205
+ rescue CardanoUp::EnvNotSupportedError => e
206
+ warn(e.message)
207
+ exit 1
208
+ end
209
+ end
210
+
211
+ # TAIL
212
+ if o['tail'] == true
213
+ env = o['<env>']
214
+ begin
215
+ log_dir = File.join(CardanoUp.config['log_dir'], env)
216
+ if o['node']
217
+ log_file = File.join(log_dir, 'node.log')
218
+ CardanoUp::Tail.tail(log_file)
219
+ elsif o['wallet']
220
+ log_file = File.join(log_dir, 'wallet.log')
221
+ CardanoUp::Tail.tail(log_file)
222
+ end
223
+ rescue CardanoUp::EnvNotSupportedError => e
224
+ warn(e.message)
225
+ exit 1
226
+ rescue StandardError => e
227
+ warn "Log file does not seem to exist: #{log_file}"
228
+ warn(e.message)
229
+ exit 1
230
+ rescue Interrupt
231
+ exit
232
+ end
233
+ end
234
+ rescue Docopt::Exit => e
235
+ puts e.message
236
+ end
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'cardano-up'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/rebuild ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ gem build *.gemspec -o cardano-up.gem
3
+ gem install cardano-up.gem
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ # Thrown when env is not supported
5
+ class EnvNotSupportedError < StandardError
6
+ def initialize(env)
7
+ super("Environment '#{env}' not supported. Supported are: #{ENVS}")
8
+ end
9
+ end
10
+
11
+ # Thrown when cardano_up internal config does not exists
12
+ class ConfigNotSetError < StandardError
13
+ def initialize
14
+ super("Config not exists at '#{CardanoUp.cardano_up_config}'!")
15
+ end
16
+ end
17
+
18
+ # Thrown when wallet port is not set
19
+ class WalletPortError < StandardError
20
+ def initialize
21
+ super('Wallet port is not set!')
22
+ end
23
+ end
24
+
25
+ # Thrown when version of bundle to download is not supported
26
+ class VersionNotSupportedError < StandardError
27
+ def initialize(ver)
28
+ super(["Not supported version: #{ver}. Supported are: 'latest', 'master',",
29
+ "tag (e.g. 'v2022-08-16') or pr number ('3045')"].join(' '))
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ # Installing configs for Cardano environments and binaries
5
+ module Install
6
+ # Check all necessary config files for particular environment exist.
7
+ # @param env [String] - one of {ENVS}
8
+ # @raise CardanoUp::EnvNotSupportedError
9
+ def self.configs_exist?(env)
10
+ CardanoUp.configure_default unless CardanoUp.configured?
11
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include?(env)
12
+
13
+ configs = CardanoUp.config
14
+ config_dir_env = FileUtils.mkdir_p(File.join(configs['config_dir'], env))
15
+ config_files = CardanoUp::CONFIG_FILES
16
+ not_existing = []
17
+ config_files.each do |file|
18
+ conf_file_path = File.join(config_dir_env, file)
19
+ not_existing << conf_file_path unless File.exist?(conf_file_path)
20
+ end
21
+ not_existing.empty?
22
+ end
23
+
24
+ # Get all necessary config files for particular environment.
25
+ # @param env [String] - one of {ENVS}
26
+ # @raise CardanoUp::EnvNotSupportedError
27
+ def self.install_configs(env)
28
+ CardanoUp.configure_default unless CardanoUp.configured?
29
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include?(env)
30
+
31
+ configs = CardanoUp.config
32
+ config_urls = CardanoUp::Utils.config_urls(env)
33
+ config_dir_env = FileUtils.mkdir_p(File.join(configs['config_dir'], env))
34
+ config_urls.each do |url|
35
+ CardanoUp::Utils.wget(url, File.join(config_dir_env, File.basename(url)))
36
+ end
37
+ end
38
+
39
+ # Get cardano-wallet bundle binaries to your computer.
40
+ # @param release [String] - 'latest' | /^v20.{2}-.{2}-.{2}/ | 'master' | '3341'
41
+ # @raise CardanoUp::VersionNotSupportedError
42
+ def self.install_bins(release)
43
+ CardanoUp.configure_default unless CardanoUp.configured?
44
+ configs = CardanoUp.config
45
+ url = CardanoUp::Utils.get_binary_url(release)
46
+ bin_dir_env = FileUtils.mkdir_p(configs['bin_dir']).first
47
+ file_to_unpack = File.join(bin_dir_env, 'binary-dist')
48
+ CardanoUp::Utils.wget(url, file_to_unpack)
49
+
50
+ unpack_binary(file_to_unpack, bin_dir_env)
51
+ return_versions(bin_dir_env)
52
+ end
53
+
54
+ def unpack_binary(file_path, destination)
55
+ if CardanoUp::Utils.win?
56
+ CardanoUp::Tar.unzip(file_path, destination)
57
+ else
58
+ gio = CardanoUp::Tar.ungzip(File.open(file_path, 'rb'))
59
+ CardanoUp::Tar.untar(gio, destination)
60
+ cw_dir = Dir[File.join(destination, '/cardano-wallet-*')].first
61
+ FileUtils.cp_r(Dir[File.join(cw_dir, '/*')], destination)
62
+ FileUtils.rm_rf(file_path)
63
+ FileUtils.rm_rf(cw_dir)
64
+ executables = Dir[File.join(destination, '/cardano-*')] << File.join(destination, '/bech32')
65
+ executables.each { |e| FileUtils.chmod('u+x', e) }
66
+ executables
67
+ end
68
+ end
69
+ module_function :unpack_binary
70
+ private_class_method :unpack_binary
71
+
72
+ # Return versions of installed components
73
+ # @raise CardanoUp::ConfigNotSetError
74
+ def self.return_versions(bin_dir = nil)
75
+ bindir = bin_dir.nil? ? CardanoUp.config['bin_dir'] : bin_dir
76
+ exe = CardanoUp::Utils.win? ? '.exe' : ''
77
+ cn = CardanoUp::Utils.cmd "#{bindir}/cardano-node#{exe} version"
78
+ cli = CardanoUp::Utils.cmd "#{bindir}/cardano-cli#{exe} version"
79
+ cw = CardanoUp::Utils.cmd "#{bindir}/cardano-wallet#{exe} version"
80
+ ca = CardanoUp::Utils.cmd "#{bindir}/cardano-address#{exe} version"
81
+ b32 = CardanoUp::Utils.cmd "#{bindir}/bech32#{exe} --version"
82
+ { 'cardano-node' => cn,
83
+ 'cardano-cli' => cli,
84
+ 'cardano-wallet' => cw,
85
+ 'cardano-address' => ca,
86
+ 'bech32' => b32 }
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ ##
5
+ # Start cardano-node and cardano-wallet on your system.
6
+ #
7
+ # For Linux and MacOS it will attempt to start separate screen sessions for
8
+ # wallet and node respectively, therefore 'screen' tool is required on your system.
9
+ # @see https://www.gnu.org/software/screen/
10
+ # If screen is not present you can install it using your package manager for instance:
11
+ # # MacOS:
12
+ # brew install screen
13
+ # # Linux:
14
+ # sudo apt-get install screen
15
+ #
16
+ # For Windows it will attepmt to install cardano-node and cardano-wallet as Windows services
17
+ # using 'nssm' tool.
18
+ # @see https://nssm.cc/
19
+ # Nssm can be installed via choco package manager:
20
+ # choco install nssm
21
+ module Start
22
+ # Prepare configuration for wallet and node to be started
23
+ # @param env [Hash] provide env and wallet_port, e.g. { env: 'mainnet', wallet_port: '8090' }
24
+ # @raise CardanoUp::EnvNotSupportedError
25
+ # @raise CardanoUp::WalletPortError
26
+ def self.prepare_configuration(opt = { env: 'mainnet', wallet_port: '8090' })
27
+ env = opt[:env]
28
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include? env
29
+
30
+ wallet_port = opt[:wallet_port]
31
+ raise CardanoUp::WalletPortError if wallet_port.nil? || wallet_port.empty?
32
+
33
+ token_metadata_server = env == 'mainnet' ? CardanoUp::MAINNET_TOKEN_SERVER : CardanoUp::TESTNET_TOKEN_SERVER
34
+
35
+ CardanoUp.configure_default unless CardanoUp.configured?
36
+ configs = CardanoUp.config
37
+ bin_dir = configs['bin_dir']
38
+ config_dir = File.join(configs['config_dir'], env)
39
+ log_dir = File.join(configs['log_dir'], env)
40
+ state_dir = File.join(configs['state_dir'], env)
41
+ wallet_db_dir = File.join(state_dir, 'wallet-db')
42
+ node_db_dir = File.join(state_dir, 'node-db')
43
+ [bin_dir, config_dir, log_dir, state_dir, wallet_db_dir, node_db_dir].each do |dir|
44
+ FileUtils.mkdir_p(dir)
45
+ end
46
+
47
+ node_socket = if CardanoUp::Utils.win?
48
+ "\\\\.\\pipe\\cardano-node-#{env}"
49
+ else
50
+ File.join(state_dir, 'node.socket')
51
+ end
52
+ network = env == 'mainnet' ? '--mainnet' : "--testnet #{config_dir}/byron-genesis.json"
53
+
54
+ {
55
+ env: env,
56
+ wallet_port: wallet_port,
57
+ token_metadata_server: token_metadata_server,
58
+ bin_dir: bin_dir,
59
+ config_dir: config_dir,
60
+ log_dir: log_dir,
61
+ state_dir: state_dir,
62
+ wallet_db_dir: wallet_db_dir,
63
+ node_db_dir: node_db_dir,
64
+ node_socket: node_socket,
65
+ network: network
66
+ }
67
+ end
68
+
69
+ # @param configuration [Hash] output of prepare_configuration
70
+ def self.start_node(configuration)
71
+ env = configuration[:env]
72
+ bin_dir = configuration[:bin_dir]
73
+ config_dir = configuration[:config_dir]
74
+ log_dir = configuration[:log_dir]
75
+ node_db_dir = configuration[:node_db_dir]
76
+ node_socket = configuration[:node_socket]
77
+
78
+ exe = CardanoUp::Utils.win? ? '.exe' : ''
79
+ version = CardanoUp::Utils.cmd "#{bin_dir}/cardano-node#{exe} version"
80
+
81
+ if CardanoUp::Utils.win?
82
+ # Turn off p2p for Windows
83
+ # TODO: remove after https://github.com/input-output-hk/ouroboros-network/issues/3968 released
84
+ config_win = JSON.parse(File.read("#{config_dir}/config.json"))
85
+ config_win['EnableP2P'] = false
86
+ File.write("#{config_dir}/config.json", JSON.pretty_generate(config_win))
87
+ topology = %({
88
+ "Producers": [
89
+ {
90
+ "addr": "#{env}-node.world.dev.cardano.org",
91
+ "port": 30002,
92
+ "valency": 2
93
+ }
94
+ ]
95
+ })
96
+ File.write("#{config_dir}/topology.json", topology)
97
+
98
+ # create cardano-node.bat file
99
+ node_cmd = ["#{bin_dir}/cardano-node.exe run",
100
+ "--config #{config_dir}/config.json",
101
+ "--topology #{config_dir}/topology.json",
102
+ "--database-path #{node_db_dir}",
103
+ "--socket-path #{node_socket}"].join(' ')
104
+ File.write("#{bin_dir}/cardano-node.bat", node_cmd)
105
+ node_service = "cardano-node-#{env}"
106
+ install_node = "nssm install #{node_service} #{bin_dir}/cardano-node.bat"
107
+ log_stdout_node = "nssm set #{node_service} AppStdout #{log_dir}/node.log"
108
+ log_stderr_node = "nssm set #{node_service} AppStderr #{log_dir}/node.log"
109
+ start_node = "nssm start #{node_service}"
110
+
111
+ CardanoUp::Utils.cmd install_node
112
+ CardanoUp::Utils.cmd log_stdout_node
113
+ CardanoUp::Utils.cmd log_stderr_node
114
+ CardanoUp::Utils.cmd start_node
115
+ else
116
+ node_cmd = ["#{bin_dir}/cardano-node run",
117
+ "--config #{config_dir}/config.json",
118
+ "--topology #{config_dir}/topology.json",
119
+ "--database-path #{node_db_dir}",
120
+ "--socket-path #{node_socket}"].join(' ')
121
+ node_service = "NODE_#{env}"
122
+ CardanoUp::Utils.cmd "screen -dmS #{node_service} -L -Logfile #{log_dir}/node.log #{node_cmd}"
123
+ end
124
+
125
+ {
126
+ node: {
127
+ service: node_service,
128
+ network: env,
129
+ version: version,
130
+ log: "#{log_dir}/node.log",
131
+ db_dir: node_db_dir,
132
+ socket_path: node_socket,
133
+ protocol_magic: get_protocol_magic(config_dir),
134
+ bin: node_cmd.split.first,
135
+ cmd: node_cmd
136
+ }
137
+ }
138
+ end
139
+
140
+ # @param configuration [Hash] output of prepare_configuration
141
+ def self.start_wallet(configuration)
142
+ env = configuration[:env]
143
+ wallet_port = configuration[:wallet_port]
144
+ token_metadata_server = configuration[:token_metadata_server]
145
+ bin_dir = configuration[:bin_dir]
146
+ log_dir = configuration[:log_dir]
147
+ wallet_db_dir = configuration[:wallet_db_dir]
148
+ node_socket = configuration[:node_socket]
149
+ network = configuration[:network]
150
+
151
+ exe = CardanoUp::Utils.win? ? '.exe' : ''
152
+ version = CardanoUp::Utils.cmd "#{bin_dir}/cardano-wallet#{exe} version"
153
+
154
+ if CardanoUp::Utils.win?
155
+
156
+ # create cardano-wallet.bat file
157
+ wallet_cmd = ["#{bin_dir}/cardano-wallet.exe serve",
158
+ "--port #{wallet_port}",
159
+ "--node-socket #{node_socket}",
160
+ network.to_s,
161
+ "--database #{wallet_db_dir}",
162
+ "--token-metadata-server #{token_metadata_server}"].join(' ')
163
+ File.write("#{bin_dir}/cardano-wallet.bat", wallet_cmd)
164
+ wallet_service = "cardano-wallet-#{env}"
165
+ install_wallet = "nssm install #{wallet_service} #{bin_dir}/cardano-wallet.bat"
166
+ log_stdout_wallet = "nssm set #{wallet_service} AppStdout #{log_dir}/wallet.log"
167
+ log_stderr_wallet = "nssm set #{wallet_service} AppStderr #{log_dir}/wallet.log"
168
+ start_wallet = "nssm start #{wallet_service}"
169
+
170
+ CardanoUp::Utils.cmd install_wallet
171
+ CardanoUp::Utils.cmd log_stdout_wallet
172
+ CardanoUp::Utils.cmd log_stderr_wallet
173
+ CardanoUp::Utils.cmd start_wallet
174
+ else
175
+ wallet_cmd = ["#{bin_dir}/cardano-wallet serve",
176
+ "--port #{wallet_port}",
177
+ "--node-socket #{node_socket}",
178
+ network.to_s,
179
+ "--database #{wallet_db_dir}",
180
+ "--token-metadata-server #{token_metadata_server}"].join(' ')
181
+ wallet_service = "WALLET_#{env}"
182
+ CardanoUp::Utils.cmd "screen -dmS #{wallet_service} -L -Logfile #{log_dir}/wallet.log #{wallet_cmd}"
183
+ end
184
+
185
+ {
186
+ wallet: {
187
+ service: wallet_service,
188
+ network: env,
189
+ version: version,
190
+ log: "#{log_dir}/wallet.log",
191
+ db_dir: wallet_db_dir,
192
+ port: wallet_port.to_i,
193
+ host: "http://localhost:#{wallet_port}/v2",
194
+ bin: wallet_cmd.split.first,
195
+ cmd: wallet_cmd
196
+ }
197
+ }
198
+ end
199
+
200
+ # @param configuration [Hash] output of prepare_configuration
201
+ def self.start_node_and_wallet(configuration)
202
+ cn = start_node(configuration)
203
+ cw = start_wallet(configuration)
204
+ cn.merge(cw)
205
+ end
206
+
207
+ # @raise CardanoUp::EnvNotSupportedError
208
+ def self.stop_node(env)
209
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include? env
210
+
211
+ if CardanoUp::Utils.win?
212
+ CardanoUp::Utils.cmd "nssm stop cardano-node-#{env}"
213
+ CardanoUp::Utils.cmd "nssm remove cardano-node-#{env} confirm"
214
+ else
215
+ CardanoUp::Utils.cmd "screen -S NODE_#{env} -X at '0' stuff '^C'"
216
+ CardanoUp::Utils.cmd "screen -XS NODE_#{env} quit"
217
+ end
218
+ end
219
+
220
+ # @raise CardanoUp::EnvNotSupportedError
221
+ def self.stop_wallet(env)
222
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include? env
223
+
224
+ if CardanoUp::Utils.win?
225
+ CardanoUp::Utils.cmd "nssm stop cardano-wallet-#{env}"
226
+ CardanoUp::Utils.cmd "nssm remove cardano-wallet-#{env} confirm"
227
+ else
228
+ CardanoUp::Utils.cmd "screen -S WALLET_#{env} -X at '0' stuff '^C'"
229
+ CardanoUp::Utils.cmd "screen -XS WALLET_#{env} quit"
230
+ end
231
+ end
232
+
233
+ # @raise CardanoUp::EnvNotSupportedError
234
+ def self.stop_node_and_wallet(env)
235
+ stop_wallet(env)
236
+ stop_node(env)
237
+ end
238
+
239
+ ##
240
+ # Get protocol magic from config's byron-genesis.json
241
+ def get_protocol_magic(config)
242
+ byron_genesis = JSON.parse(File.read(File.join(config, 'byron-genesis.json')))
243
+ byron_genesis['protocolConsts']['protocolMagic'].to_i
244
+ end
245
+ module_function :get_protocol_magic
246
+ private_class_method :get_protocol_magic
247
+ end
248
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ # Tail log file
5
+ module Tail
6
+ def self.tail(file_path)
7
+ File.open(file_path) do |log|
8
+ log.extend(File::Tail)
9
+ log.interval
10
+ log.backward(10)
11
+ log.tail { |line| warn line }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ # unpacking archives
5
+ module Tar
6
+ # unzip file to destination directory
7
+ def self.unzip(file, destination)
8
+ FileUtils.mkdir_p(destination)
9
+ Zip::File.open(file) do |zip_file|
10
+ zip_file.each do |f|
11
+ fpath = File.join(destination, f.name)
12
+ zip_file.extract(f, fpath)
13
+ end
14
+ end
15
+ end
16
+
17
+ # un-gzips the given IO, returning the
18
+ # decompressed version as a StringIO
19
+ def self.ungzip(tarfile)
20
+ z = Zlib::GzipReader.new(tarfile)
21
+ unzipped = StringIO.new(z.read)
22
+ z.close
23
+ unzipped
24
+ end
25
+
26
+ # untars the given IO into the specified
27
+ # directory
28
+ def self.untar(io, destination)
29
+ Gem::Package::TarReader.new io do |tar|
30
+ tar.each do |tarfile|
31
+ destination_file = File.join destination, tarfile.full_name
32
+
33
+ if tarfile.directory?
34
+ FileUtils.mkdir_p destination_file
35
+ else
36
+ destination_directory = File.dirname(destination_file)
37
+ FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
38
+ File.open destination_file, 'wb' do |f|
39
+ f.print tarfile.read
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardanoUp
4
+ # Utility methods
5
+ module Utils
6
+ def self.cmd(cmd, display_result: false)
7
+ cmd.gsub(/\s+/, ' ')
8
+ res = `#{cmd}`
9
+ puts cmd if display_result
10
+ puts res if display_result
11
+ res.gsub("\n", '')
12
+ end
13
+
14
+ def self.wget(url, file = nil)
15
+ file ||= File.basename(url)
16
+ resp = HTTParty.get(url)
17
+ File.binwrite(file, resp.body)
18
+ end
19
+
20
+ def self.win?
21
+ RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/
22
+ end
23
+
24
+ def self.linux?
25
+ RUBY_PLATFORM =~ /linux/
26
+ end
27
+
28
+ def self.mac?
29
+ RUBY_PLATFORM =~ /darwin/
30
+ end
31
+
32
+ def self.latest_tag
33
+ HTTParty.get("#{CardanoUp::BINS_BASE_URL}/releases/latest",
34
+ headers: { 'Accept' => 'application/json' })['tag_name']
35
+ end
36
+
37
+ ##
38
+ # Latest binary url for latest release or particular tag, from master or pr num.
39
+ # @param release [String] - 'latest' | /^v20.{2}-.{2}-.{2}/ | 'master' | '3341'
40
+ # @raise CardanoUp::VersionNotSupportedError
41
+ def self.get_binary_url(release = 'latest')
42
+ unless release == 'master' || release == 'latest' || release =~ /^v20.{2}-.{2}-.{2}/ || release =~ /^\d+$/
43
+ raise CardanoUp::VersionNotSupportedError, release
44
+ end
45
+
46
+ url = ''
47
+ if release == 'latest' || release =~ /^v20.{2}-.{2}-.{2}/
48
+ tag = release == 'latest' ? latest_tag : release
49
+ if linux?
50
+ file = "cardano-wallet-#{tag}-linux64.tar.gz"
51
+ elsif mac?
52
+ file = "cardano-wallet-#{tag}-macos-intel.tar.gz"
53
+ elsif win?
54
+ file = "cardano-wallet-#{tag}-win64.zip"
55
+ end
56
+ url = "#{CardanoUp::BINS_BASE_URL}/releases/download/#{tag}/#{file}"
57
+ else
58
+ if linux?
59
+ os = 'linux.musl.cardano-wallet-linux64'
60
+ elsif mac?
61
+ os = 'macos.intel.cardano-wallet-macos-intel'
62
+ elsif win?
63
+ os = 'linux.windows.cardano-wallet-win64'
64
+ end
65
+
66
+ url = if release == 'master'
67
+ "#{CardanoUp::HYDRA_BASE_URL}/#{os}/latest/download-by-type/file/binary-dist"
68
+ else
69
+ "#{CardanoUp::HYDRA_BASE_URL}-pr-#{release}/#{os}/latest/download-by-type/file/binary-dist"
70
+ end
71
+ end
72
+ url
73
+ end
74
+
75
+ ##
76
+ # Latest Cardano configs
77
+ # @raise CardanoUp::EnvNotSupportedError
78
+ def self.configs_base_url(env)
79
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include?(env)
80
+
81
+ "#{CardanoUp::CONFIGS_BASE_URL}/#{env}/"
82
+ end
83
+
84
+ # @raise CardanoUp::EnvNotSupportedError
85
+ def self.config_urls(env)
86
+ raise CardanoUp::EnvNotSupportedError, env unless CardanoUp::ENVS.include?(env)
87
+
88
+ base_url = configs_base_url(env)
89
+ configs = []
90
+ CardanoUp::CONFIG_FILES.each do |file|
91
+ configs << "#{base_url}#{file}"
92
+ end
93
+ configs
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Version
4
+ module CardanoUp
5
+ VERSION ||= '0.1.0'
6
+ end
data/lib/cardano-up.rb ADDED
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'rubygems/package'
5
+ require 'httparty'
6
+ require 'fileutils'
7
+ require 'file-tail'
8
+ require 'json'
9
+ require 'zlib'
10
+ require 'zip'
11
+
12
+ require 'cardano-up/version'
13
+ require 'cardano-up/err'
14
+ require 'cardano-up/utils'
15
+ require 'cardano-up/tar'
16
+ require 'cardano-up/install'
17
+ require 'cardano-up/start'
18
+ require 'cardano-up/tail'
19
+
20
+ # Cardano Up!
21
+ # Lightweight manager for Cardano binaries and configs.
22
+ module CardanoUp
23
+ CONFIGS_BASE_URL = 'https://book.world.dev.cardano.org/environments'
24
+ BINS_BASE_URL = 'https://github.com/input-output-hk/cardano-wallet'
25
+ HYDRA_BASE_URL = 'https://hydra.iohk.io/job/Cardano/cardano-wallet'
26
+ ENVS = %w[mainnet preview preprod shelley-qa
27
+ staging vasil-qa vasil-dev mixed testnet].freeze
28
+ CONFIG_FILES = ['alonzo-genesis.json', 'byron-genesis.json', 'shelley-genesis.json',
29
+ 'config.json', 'topology.json'].freeze
30
+ MAINNET_TOKEN_SERVER = 'https://tokens.cardano.org'
31
+ TESTNET_TOKEN_SERVER = 'https://metadata.cardano-testnet.iohkdev.io'
32
+ # It is recommended to use default value for {base_dir},
33
+ # however it is possible to modify it with {base_dir=}.
34
+ @base_dir = File.join(Dir.home, '.cardano-up')
35
+
36
+ # It is recommended to use default value for {cardano_up_config},
37
+ # however it is possible to modify it with {cardano_up_config=}.
38
+ @cardano_up_config = File.join(@base_dir, '.cardano-up.json')
39
+
40
+ def self.base_dir
41
+ @base_dir
42
+ end
43
+
44
+ def self.base_dir=(value)
45
+ @base_dir = value
46
+ @cardano_up_config = File.join(@base_dir, 'config.json')
47
+ @base_dir
48
+ end
49
+
50
+ def self.cardano_up_config
51
+ @cardano_up_config
52
+ end
53
+
54
+ def self.cardano_up_config=(value)
55
+ @cardano_up_config = value
56
+ end
57
+
58
+ # Check if CardanoUp config exists
59
+ def self.configured?
60
+ File.exist?(@cardano_up_config)
61
+ end
62
+
63
+ # Set default config for CardanoUp
64
+ def self.configure_default
65
+ configure(File.join(@base_dir, 'bins'),
66
+ File.join(@base_dir, 'state'),
67
+ File.join(@base_dir, 'logs'),
68
+ File.join(@base_dir, 'configs'))
69
+ end
70
+
71
+ # Set custom config for CardanoUp
72
+ def self.configure(bin_dir, state_dir, logs_dir, config_dir)
73
+ FileUtils.mkdir_p(@base_dir)
74
+ c = if configured?
75
+ CardanoUp.config
76
+ else
77
+ { 'bin_dir' => File.join(@base_dir, 'bins'),
78
+ 'state_dir' => File.join(@base_dir, 'state'),
79
+ 'log_dir' => File.join(@base_dir, 'state'),
80
+ 'config_dir' => File.join(@base_dir, 'configs') }
81
+ end
82
+ c['bin_dir'] = bin_dir if bin_dir
83
+ c['state_dir'] = state_dir if state_dir
84
+ c['log_dir'] = logs_dir if logs_dir
85
+ c['config_dir'] = config_dir if config_dir
86
+ File.write(@cardano_up_config, JSON.pretty_generate(c))
87
+ JSON.parse(File.read(@cardano_up_config))
88
+ end
89
+
90
+ # Get config values
91
+ def self.config
92
+ raise CardanoUp::ConfigNotSetError unless configured?
93
+
94
+ JSON.parse(File.read(@cardano_up_config))
95
+ end
96
+
97
+ # Remove configuration file
98
+ def self.remove_cardano_up_config
99
+ FileUtils.rm_f(@cardano_up_config)
100
+ end
101
+
102
+ # dir [String] config dir
103
+ def self.clean_config_dir(dir)
104
+ FileUtils.rm_f(config[dir])
105
+ end
106
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cardano-up
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Piotr Stachyra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docopt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.6.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.6.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: file-tail
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: httparty
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.20.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.20.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubyzip
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.3.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '12.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '12.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.11'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.11'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.36'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.36'
111
+ description: |-
112
+ Cardano Up lets you get all essential Cardano
113
+ tools on your system: cardano-node, cardano-cli, cardano-wallet,
114
+ cardano-addresses and bech32. Then easily manage configuration
115
+ for different environments and launch node and wallet services.
116
+ email:
117
+ - piotr.stachyra@gmail.com
118
+ executables:
119
+ - cardano-up
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - LICENSE.txt
124
+ - README.md
125
+ - bin/cardano-up
126
+ - bin/console
127
+ - bin/rebuild
128
+ - bin/setup
129
+ - lib/cardano-up.rb
130
+ - lib/cardano-up/err.rb
131
+ - lib/cardano-up/install.rb
132
+ - lib/cardano-up/start.rb
133
+ - lib/cardano-up/tail.rb
134
+ - lib/cardano-up/tar.rb
135
+ - lib/cardano-up/utils.rb
136
+ - lib/cardano-up/version.rb
137
+ homepage: https://github.com/piotr-iohk/cardano-up
138
+ licenses:
139
+ - MIT
140
+ metadata:
141
+ allowed_push_host: https://rubygems.org/
142
+ homepage_uri: https://github.com/piotr-iohk/cardano-up
143
+ source_code_uri: https://github.com/piotr-iohk/cardano-up
144
+ changelog_uri: https://github.com/piotr-iohk/cardano-up
145
+ rubygems_mfa_required: 'true'
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ - bin
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: 2.7.0
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubygems_version: 3.0.3.1
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: Lightweight manager for Cardano binaries and configs.
166
+ test_files: []