skynet_ruby 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: f090c4c97ad8488468ba123da7dca5c76a1d58f0cac3b8a0b4c87a11d4bcde9f
4
+ data.tar.gz: 0e6e21eb7d267053fe89620c4357ea627e93d77c2864421f0eedb0bdb6a94538
5
+ SHA512:
6
+ metadata.gz: 0cad41376522ac2e360d83a054e82bed619c8e07b201d0099837caf752d11c757be897fb991986341fdb1d962640f63467c25757a975db72283b122805ce8de2
7
+ data.tar.gz: 8461824f5cdfeb5d6bc78043a615a179619d659e25e2523a59a5452b75d683ef9e9946af4f4e7f5d8c2fbd439461a52b6f6ec367fa8a52759e121c3195b29f33
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .solargraph.yml
2
+ .rvmrc
3
+ .yardoc
4
+ .rspec_status
5
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ # This is the configuration used to check the rubocop source code.
2
+ require:
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+ Exclude:
8
+ - 'vendor/**/*'
9
+ - 'spec/fixtures/**/*'
10
+ - 'tmp/**/*'
11
+ - '.git/**/*'
12
+ - 'bin/*'
13
+ TargetRubyVersion: 2.7
14
+ SuggestExtensions: false
15
+
16
+ Metrics/AbcSize:
17
+ Enabled: False
18
+ Metrics/MethodLength:
19
+ Max: 15
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.3
6
+ before_install: gem install bundler -v 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in sia_skynet.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 12.0'
9
+ gem 'typhoeus', '~> 1.4.0'
10
+ gem 'mimemagic', '~> 0.4.3'
11
+ gem 'multipart_body', '~> 0.2.1'
12
+ gem 'thor', '~> 1.1.0'
13
+
14
+ group :test, :development do
15
+ gem 'rspec', '~> 3.0'
16
+ gem 'rubocop', '~> 1.13.0'
17
+ gem 'rubocop-rspec', '~> 2.2.0'
18
+ gem 'byebug', require: 'byebug'
19
+ end
20
+
21
+ group :test do
22
+ gem "webmock", '~> 3.12.0'
23
+ gem 'rspec-json_expectations'
24
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,93 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sia_skynet (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.7.0)
10
+ public_suffix (>= 2.0.2, < 5.0)
11
+ ast (2.4.2)
12
+ byebug (11.1.3)
13
+ crack (0.4.5)
14
+ rexml
15
+ diff-lcs (1.4.4)
16
+ ethon (0.14.0)
17
+ ffi (>= 1.15.0)
18
+ ffi (1.15.0)
19
+ hashdiff (1.0.1)
20
+ mimemagic (0.4.3)
21
+ nokogiri (~> 1)
22
+ rake
23
+ mini_portile2 (2.5.1)
24
+ multipart_body (0.2.1)
25
+ nokogiri (1.11.3)
26
+ mini_portile2 (~> 2.5.0)
27
+ racc (~> 1.4)
28
+ parallel (1.20.1)
29
+ parser (3.0.1.0)
30
+ ast (~> 2.4.1)
31
+ public_suffix (4.0.6)
32
+ racc (1.5.2)
33
+ rainbow (3.0.0)
34
+ rake (12.3.3)
35
+ regexp_parser (2.1.1)
36
+ rexml (3.2.5)
37
+ rspec (3.10.0)
38
+ rspec-core (~> 3.10.0)
39
+ rspec-expectations (~> 3.10.0)
40
+ rspec-mocks (~> 3.10.0)
41
+ rspec-core (3.10.1)
42
+ rspec-support (~> 3.10.0)
43
+ rspec-expectations (3.10.1)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.10.0)
46
+ rspec-json_expectations (2.2.0)
47
+ rspec-mocks (3.10.2)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.10.0)
50
+ rspec-support (3.10.2)
51
+ rubocop (1.13.0)
52
+ parallel (~> 1.10)
53
+ parser (>= 3.0.0.0)
54
+ rainbow (>= 2.2.2, < 4.0)
55
+ regexp_parser (>= 1.8, < 3.0)
56
+ rexml
57
+ rubocop-ast (>= 1.2.0, < 2.0)
58
+ ruby-progressbar (~> 1.7)
59
+ unicode-display_width (>= 1.4.0, < 3.0)
60
+ rubocop-ast (1.4.1)
61
+ parser (>= 2.7.1.5)
62
+ rubocop-rspec (2.2.0)
63
+ rubocop (~> 1.0)
64
+ rubocop-ast (>= 1.1.0)
65
+ ruby-progressbar (1.11.0)
66
+ thor (1.1.0)
67
+ typhoeus (1.4.0)
68
+ ethon (>= 0.9.0)
69
+ unicode-display_width (2.0.0)
70
+ webmock (3.12.2)
71
+ addressable (>= 2.3.6)
72
+ crack (>= 0.3.2)
73
+ hashdiff (>= 0.4.0, < 2.0.0)
74
+
75
+ PLATFORMS
76
+ ruby
77
+
78
+ DEPENDENCIES
79
+ byebug
80
+ mimemagic (~> 0.4.3)
81
+ multipart_body (~> 0.2.1)
82
+ rake (~> 12.0)
83
+ rspec (~> 3.0)
84
+ rspec-json_expectations
85
+ rubocop (~> 1.13.0)
86
+ rubocop-rspec (~> 2.2.0)
87
+ sia_skynet!
88
+ thor (~> 1.1.0)
89
+ typhoeus (~> 1.4.0)
90
+ webmock (~> 3.12.0)
91
+
92
+ BUNDLED WITH
93
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Christoph Klocker
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,83 @@
1
+ # Skynet
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sia_skynet`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'sia_skynet'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sia_skynet
22
+
23
+ ## Usage
24
+
25
+ require 'skynet'
26
+
27
+ ### Uploading to a Skynet portal
28
+
29
+ #### Uploading a single file
30
+
31
+ client = Skynet::Client.new
32
+ client.upload_file '/path/to/file.pdf'
33
+ => "sia://ZAAZyxRQ7Ixzd3zujn1ly8RA..."
34
+
35
+ # if you want to get the full response
36
+ client.upload_file '/path/to/file.pdf', full_response: true
37
+ => {
38
+ "skylink"=>"ZAAZyxRQ7Ixzd3zujn1ly8RA...",
39
+ "merkleroot"=>"19cb1450ec8981fcc63c73777cee8e7d65cbc44",
40
+ "bitfield"=>100,
41
+ "sialink"=>"sia://ZAAZyxRQ7Ixzd3zujn1ly8RA"
42
+ }
43
+
44
+ #### Uploading a directory:
45
+
46
+ client.upload_directory '/path/to/directory'
47
+
48
+ #### Downloading a file or directory:
49
+
50
+ This function downloads a skylink using HTTP streaming. The call blocks until the data is received. There is a 30s default timeout applied to downloading a skylink. If the data can not be found within this 30s time constraint, a 404 error will be returned. This timeout is configurable.
51
+
52
+ A directory will be downloaded as zip file, otherwise as regular file.
53
+
54
+ client.download_file("/path/foo.zip", skylink)
55
+
56
+ #### Getting Metadata
57
+
58
+ Returns the metadata of an upload. Currently quite often no metadata is returned and a `Skynet::NoMetadataError` exception will be raised.
59
+
60
+ client.get_metadata "ZAAZyxRQ7ImB_...."
61
+
62
+ ## Progress
63
+
64
+ ☑ Uploading a file\
65
+ ☑ Uploading a directory\
66
+ ☑ Downloading a file\
67
+ ☑ Downloading a directory\
68
+ ☑ Getting Metadata\
69
+ ☐ SkyDB\
70
+ ☐ Registry\
71
+ ☐ MySky\
72
+
73
+ ## Contributing
74
+
75
+
76
+ Bug reports and pull requests are welcome on GitHub at https://github.com/corck/sia_skynet.
77
+
78
+
79
+ ## License
80
+
81
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
82
+
83
+ Copyright 2021, by Christoph Klocker.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
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 'skynet'
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/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
data/lib/skynet.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'skynet/version'
4
+ require 'skynet/client'
5
+
6
+ module Skynet
7
+ class Error < StandardError; end
8
+
9
+ class NoMetadataError < Skynet::Error; end
10
+ end
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'typhoeus'
5
+ require 'multipart_body'
6
+ require 'mimemagic'
7
+
8
+ module Skynet
9
+ # Client for interacting with Skynet
10
+ #
11
+ # Default portal is set to https://siasky.net
12
+ #
13
+ class Client
14
+ DEFAULT_SKYNET_PORTAL_URL = 'https://siasky.net'
15
+ DEFAULT_SKYNET_PORTAL_PATH = '/skynet/skyfile'
16
+ URI_SKYNET_PREFIX = 'sia://'
17
+ DEFAULT_USER_AGENT = 'Sia-Agent'
18
+
19
+ attr_reader :user_agent
20
+ attr_accessor :config
21
+
22
+ # Initializes the client, allows to set a custom portal or uses siasky.net as default
23
+ #
24
+ # @param [Hash] config the configuration options to initialize the client with
25
+ # @option config [String] :api_key The API password used for authentication.
26
+ # @option config [String] :user_agent Allows changing the User Agent, as some portals may reject user agents
27
+ # that are not `Sia-Agent` for security reasons.
28
+ # @option config [String] :on_upload_progress Optional callback to track upload progress. (Not implemented yet)
29
+ # @option config [String] :portal url to a custom portal, defaults to https://siasky.net
30
+ # @option config [String] :dirname Optional directory name on skynet
31
+ # @option config [Boolean] :verbose Set to true to log network requests
32
+
33
+ def initialize(custom_config = {})
34
+ @config = default_upload_options
35
+ @config.merge!(custom_config)
36
+ @api_key = config[:api_key] || nil
37
+ Typhoeus::Config.user_agent = config[:user_agent]
38
+ @on_upload_progress = config[:on_upload_progress]
39
+ Typhoeus::Config.verbose = true if custom_config[:verbose]
40
+ end
41
+
42
+ # Takes a file path and uploads it
43
+ #
44
+ # @param [String] file File or file path where the file is located
45
+ #
46
+ # @param [Hash] custom_opts additional upload options
47
+ # @option custom_opts [String] :portal_file_field_name The field name for files on the portal.
48
+ # Usually should not need to be changed.
49
+ # @option custom_opts [String] :portal_directory_file_field_name The field name for directories on the portal.
50
+ # Usually should not need to be changed.
51
+ # @option custom_opts [String] :filename Custom filename.
52
+ # This is the filename that will be returned when downloading the file in a browser
53
+ # @option custom_opts [String] :custom_dirname Custom dirname. If this is empty,
54
+ # the base name of the directory being uploaded will be used by default.
55
+ # @option custom_opts [String] :timeout_seconds Custom filename. The timeout in seconds.
56
+ # @option custom_opts [Boolean] :full_response Returns full hash with skylink, merkleroot and bitfield
57
+ #
58
+ # @return [String] Returns the sialink (sia://AABBCC) by default
59
+ # @return [Hash] Response Hash with full response from skynet including skylink, merkleroot
60
+ # bitfield and sialink if :full_response option is given
61
+ # @option response [String] :skylink
62
+ #
63
+ # @example Default response:
64
+ # sia://KAA54bKo-YqFRj345xGXdo9h15k.....
65
+ #
66
+ # @example Full response as hash
67
+ # {
68
+ # "skylink"=>"KAA54bKo-YqFRjDxRxGXdo9h15k8......",
69
+ # "merkleroot"=>"39e1b2a....",
70
+ # "bitfield"=>40,
71
+ # "sialink"=>"sia://KAA54bKo-YqFRjDxRxGXdo9h15k8...."
72
+ # }
73
+ #
74
+ #
75
+ def upload_file(file, custom_opts = {})
76
+ res = upload(file, config.merge(custom_opts)).run
77
+
78
+ format_response(res, custom_opts)
79
+ end
80
+
81
+ def upload_directory(directory, opts = {})
82
+ custom_options = filter_upload_options(config.merge(opts))
83
+
84
+ multipart = prepare_multipart_body(directory)
85
+ header = default_headers.merge({ 'Content-Type' => "multipart/form-data; boundary=#{multipart.boundary}" })
86
+
87
+ res = Typhoeus::Request.new(
88
+ "#{portal}#{portal_path}",
89
+ method: :post,
90
+ params: custom_options.merge(filename: File.basename(directory)),
91
+ headers: header,
92
+ body: multipart.to_s
93
+ ).run
94
+
95
+ format_response(res, custom_options)
96
+ end
97
+
98
+ # Download a file
99
+ # @param [String] path The local path where the file should be downloaded to.
100
+ # @param [String] skylink The skylink that should be downloaded. The skylink can contain an optional path.
101
+ #
102
+ # @return [String] path Path of the downloaded file
103
+ def download_file(path, skylink)
104
+ skylink = strip_uri_prefix(skylink)
105
+
106
+ f = File.open(path, 'wb')
107
+ begin
108
+ request = Typhoeus::Request.new("#{portal}/#{skylink}", headers: default_headers)
109
+ request.on_headers do |response|
110
+ raise 'Request failed' if response.code != 200
111
+ end
112
+ request.on_body do |chunk|
113
+ f.write(chunk)
114
+ end
115
+ request.on_complete do |_response|
116
+ f.close
117
+ end
118
+ request.run
119
+ ensure
120
+ f.close
121
+ end
122
+
123
+ path
124
+ end
125
+
126
+ # Downloads the metadata of a skylink
127
+ #
128
+ # @param [String] skylink Skylink of the file
129
+ #
130
+ # @return [Hash]
131
+ #
132
+ # @example Response
133
+ # {
134
+ # 'filename' => 'foo.pdf',
135
+ # 'length' => 21_977,
136
+ # 'subfiles' =>
137
+ # { 'foo.pdf' =>
138
+ # { 'filename' => 'foo.pdf',
139
+ # 'contenttype' => 'application/octet-stream',
140
+ # 'len' => 21_977 } }
141
+ # }
142
+ def get_metadata(skylink)
143
+ skylink = strip_uri_prefix(skylink)
144
+ res = Typhoeus::Request.head(
145
+ "#{portal}/#{skylink}", headers: default_headers
146
+ )
147
+
148
+ raise Skynet::NoMetadataError, 'No metadata returned' unless res.headers['skynet-file-metadata']
149
+
150
+ JSON.parse res.headers['skynet-file-metadata']
151
+ end
152
+
153
+ private
154
+
155
+ # Return all files recursively, exclude directories
156
+ #
157
+ def files_to_upload(path)
158
+ Dir.glob("#{path}/**/*")
159
+ .reject { |fn| File.directory?(fn) }
160
+ .map do |f|
161
+ { path: f, relative_path: f.gsub(%r{#{path}/}, '') }
162
+ end
163
+ end
164
+
165
+ # Returns default upload options
166
+ def default_upload_options
167
+ opts = {}
168
+ opts[:portal] = DEFAULT_SKYNET_PORTAL_URL
169
+ opts[:portal_path] = DEFAULT_SKYNET_PORTAL_PATH
170
+ opts[:user_agent] = DEFAULT_USER_AGENT
171
+ opts[:portal_file_fieldname] = 'file'
172
+ opts[:portal_directory_file_fieldname] = 'files[]'
173
+ opts[:filename] = 'file'
174
+ opts[:dirname] = ''
175
+ opts
176
+ end
177
+
178
+ def portal_path
179
+ File.join(config[:portal_path], config[:dirname])
180
+ end
181
+
182
+ def portal
183
+ config[:portal]
184
+ end
185
+
186
+ def upload(file, opts = {})
187
+ custom_opts = config.merge(opts)
188
+ params = custom_opts.filter { |k| default_upload_options.keys.include?(k) }
189
+
190
+ begin
191
+ f = File.open(file, 'rb')
192
+
193
+ Typhoeus::Request.new(
194
+ "#{portal}#{portal_path}",
195
+ method: :post,
196
+ params: params,
197
+ body: {
198
+ file: f
199
+ }
200
+ )
201
+ ensure
202
+ f&.close
203
+ end
204
+ end
205
+
206
+ # Filter by available upload options
207
+ def filter_upload_options(opts)
208
+ opts.filter { |k| default_upload_options.keys.include?(k) }
209
+ end
210
+
211
+ def default_headers
212
+ { "User-Agent": DEFAULT_USER_AGENT }
213
+ end
214
+
215
+ def format_response(res, custom_opts = {})
216
+ json = JSON.parse res.body
217
+ sialink = "#{URI_SKYNET_PREFIX}#{json['skylink']}"
218
+
219
+ custom_opts[:full_response] == true ? json.merge({ 'sialink' => sialink }) : sialink
220
+ end
221
+
222
+ def prepare_multipart_body(directory)
223
+ files = files_to_upload(directory)
224
+
225
+ file_parts = files.inject([]) do |parts, file|
226
+ ct = MimeMagic.by_path(file[:path])&.type
227
+ begin
228
+ f = File.open(file[:path], 'r')
229
+ parts << Part.new(name: config[:portal_directory_file_fieldname],
230
+ body: f.read,
231
+ filename: file[:relative_path],
232
+ content_type: ct)
233
+ ensure
234
+ f.close
235
+ end
236
+ end
237
+
238
+ MultipartBody.new(file_parts)
239
+ end
240
+
241
+ def strip_uri_prefix(skylink)
242
+ skylink.delete_prefix(URI_SKYNET_PREFIX)
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skynet
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/skynet/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'skynet_ruby'
7
+ spec.version = Skynet::VERSION
8
+ spec.authors = ['Christoph Klocker']
9
+ spec.email = ['christoph@vedanova.com']
10
+
11
+ spec.summary = 'Skynet client to interact with Sia Skynet'
12
+ spec.description = 'Skynet is a decentralized storage solution built on the Sia blockchain'
13
+ spec.homepage = 'https://siasky.net'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
16
+
17
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = 'https://github.com/corck/sia_skynet'
21
+ # spec.metadata["changelog_uri"] = "https://github.com/corck/sia_skynet"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skynet_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christoph Klocker
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-06-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Skynet is a decentralized storage solution built on the Sia blockchain
14
+ email:
15
+ - christoph@vedanova.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - ".rubocop.yml"
23
+ - ".travis.yml"
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/console
30
+ - bin/setup
31
+ - lib/skynet.rb
32
+ - lib/skynet/client.rb
33
+ - lib/skynet/version.rb
34
+ - sia_skynet.gemspec
35
+ homepage: https://siasky.net
36
+ licenses:
37
+ - MIT
38
+ metadata:
39
+ allowed_push_host: https://rubygems.org
40
+ homepage_uri: https://siasky.net
41
+ source_code_uri: https://github.com/corck/sia_skynet
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.7.0
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.2.20
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Skynet client to interact with Sia Skynet
61
+ test_files: []