1
0
mirror of https://github.com/bumi/blockstream_satellite synced 2024-12-03 16:48:58 +00:00

hello space

This commit is contained in:
bumi 2019-02-08 21:13:57 +01:00
commit db7a23d827
17 changed files with 476 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
# rspec failure tracking
.rspec_status
.ruby-version

3
.rspec Normal file
View File

@ -0,0 +1,3 @@
--format documentation
--color
--require spec_helper

6
Gemfile Normal file
View File

@ -0,0 +1,6 @@
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
# Specify your gem's dependencies in blockstream_satellite.gemspec
gemspec

64
Gemfile.lock Normal file
View File

@ -0,0 +1,64 @@
PATH
remote: .
specs:
blockstream_satellite (0.1.0)
activesupport (>= 5.0.1)
faraday (> 0.8)
faraday_middleware (> 0.12)
lnrpc (>= 0.1.0)
GEM
remote: https://rubygems.org/
specs:
activesupport (5.2.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
concurrent-ruby (1.1.4)
diff-lcs (1.3)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0)
google-protobuf (3.6.1)
googleapis-common-protos-types (1.0.3)
google-protobuf (~> 3.0)
grpc (1.18.0)
google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0)
i18n (1.5.3)
concurrent-ruby (~> 1.0)
lnrpc (0.1.0)
grpc (>= 1.16.0)
minitest (5.11.3)
multipart-post (2.0.0)
rake (10.5.0)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
PLATFORMS
ruby
DEPENDENCIES
blockstream_satellite!
bundler (~> 1.17)
rake (~> 10.0)
rspec (~> 3.0)
BUNDLED WITH
1.17.2

21
LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 Michael Bumann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

85
README.md Normal file
View File

@ -0,0 +1,85 @@
# BlockstreamSatellite
Ruby gem to interact with the [Blockstream Satellite](https://blockstream.com/satellite/) API.
To learn more about the Blockstream Satellite check their [website](https://blockstream.com/satellite/) and [API documentation](https://blockstream.com/satellite-api/).
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'blockstream_satellite'
```
Or install it yourself as:
$ gem install blockstream_satellite
## Usage
### Quick example
```ruby
order = BlockstreamSatellite::Order.create(path: '/path/to/file')
puts order.status # pending
order.pay # sends the lightning payment using the configured lnd client; request is synchronous
puts order.status # transmitting
order.refresh
puts order.status # sent
```
### Configuration
In order to be able to pay for the lightninig invoice you need to connect to you lightning node.
(By default the testnet cert and macaroon files are loaded from `~/.lnd` and `localhost:10009` is used)
```ruby
lnd_client = Lnrpc::Client.new({
credentials_path: '/path/to/tls.cert',
macaroon_path: '/path/to/admin.macaroon',
address: 'localhost:10009'
})
BlockstreamSatellite.lnd_client = lnd_client
```
### Creating an order
`BlockstreamSatellite::Order.create` accepts the following parameters:
* `path`: path to the file to transmit
* `data`: data to transmit; can be used as an alternative `path`
* `bid`: bid for the order. defaults to file size * 51
```ruby
order = BlockstreamSatellite::Order.create(path: '/path/to/file')
```
### Loading an order by UUID and auth_token
```ruby
order = BlockstreamSatellite::Order.get(uuid: 'uuid', auth_token: 'auth_token')
```
### Bump the bid for an order
```ruby
order = BlockstreamSatellite::Order.get(uuid: 'uuid', auth_token: 'auth_token')
order.bump(1000)
```
## Satus
Currently I consider this gem experimental and it is missing tests current.
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/blockstream_satellite.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

6
Rakefile Normal file
View File

@ -0,0 +1,6 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task :default => :spec

14
bin/console Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
require "bundler/setup"
require "blockstream_satellite"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require "irb"
IRB.start(__FILE__)

8
bin/setup Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here

View File

@ -0,0 +1,44 @@
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "blockstream_satellite/version"
Gem::Specification.new do |spec|
spec.name = "blockstream_satellite"
spec.version = BlockstreamSatellite::VERSION
spec.authors = ["Michael Bumann"]
spec.email = ["hello@michaelbumann.com"]
spec.summary = %q{API client for the Blockstream satellite}
spec.description = %q{API clent to interact with the Blockstream satellite}
spec.homepage = "http://github.com/bumi/blockstream_satellite"
spec.license = "MIT"
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["changelog_uri"] = "http://github.com/bumi/blockstream_satellite/"
else
raise "RubyGems 2.0 or newer is required to protect against " \
"public gem pushes."
end
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.17"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_dependency "faraday", "> 0.8"
spec.add_dependency "faraday_middleware", ">0.12"
spec.add_dependency "lnrpc", ">= 0.1.0"
spec.add_dependency "activesupport", ">= 5.0.1"
end

View File

@ -0,0 +1,45 @@
require "blockstream_satellite/version"
require 'lnrpc'
module BlockstreamSatellite
class Error < StandardError; end
autoload :Order, 'blockstream_satellite/order'
autoload :Client, 'blockstream_satellite/client'
autoload :Configuration, 'blockstream_satellite/configuration'
autoload :Response, 'blockstream_satellite/response'
API_HOST = 'https://satellite.blockstream.com'
def self.lnd_client=(value)
@lnd_client = value
end
def self.lnd_client
@lnd_client ||= Lnrpc::Client.new({})
end
def http_client=(value)
@http_client = value
end
def self.http_client
@http_client ||= Faraday.new(url: API_HOST) do |faraday|
faraday.request :multipart
faraday.request :url_encoded
faraday.response :json, :content_type => /\bjson$/
faraday.adapter Faraday.default_adapter
end
end
def self.client
@client ||= Client.new(lnd_client: self.lnd_client, http_client: self.http_client)
end
def self.info
self.client.get('/info')
end
end
BSat = BlockstreamSatellite

View File

@ -0,0 +1,40 @@
require "faraday"
require 'faraday_middleware'
module BlockstreamSatellite
class Client
attr_accessor :http_client, :lnd_client
def initialize(options)
self.lnd_client = options[:lnd_client]
self.http_client = options[:http_client]
end
def get(path, params = nil, &block)
request(:get, path, params, &block)
end
def post(path, body = nil, &block)
puts body.inspect
request(:post, path, nil, body, &block)
end
def pay(payreq)
self.lnd_client.send_payment_sync(Lnrpc::SendRequest.new(payment_request: payreq))
end
def request(http_method, path, params=nil, body=nil)
response = http_client.send(http_method) do |req|
req.url "/api/#{path}"
req.params = params if params
req.body = body if body
yield req if block_given?
end
Response.new(response)
rescue Faraday::ClientError => error
return Response.new(error)
end
end
end

View File

@ -0,0 +1,78 @@
require 'faraday'
require 'faraday_middleware'
require "active_support/core_ext/hash/indifferent_access"
require 'tempfile'
require 'securerandom'
module BlockstreamSatellite
class Order
attr_accessor :attributes
def initialize(attributes)
self.attributes = attributes.with_indifferent_access
end
# defining accessors
[:auth_token, :uuid, :lightning_invoice, :sha256_message_digest, :message_digest, :status, :bid, :unpaid_bid].each do |attr|
define_method(attr) do
self.attributes[attr]
end
end
def payreq
lightning_invoice['payreq']
end
def self.create(options)
if data = options.delete(:data)
file = Tempfile.new(SecureRandom.hex(5))
file.write(data)
file.rewind
options[:file] = file
elsif path = options.delete(:path)
options[:file] = File.open(path)
end
options[:bid] ||= options[:file].size * 51 # default price
options[:file] = UploadIO.new(options[:file], 'text/plain')
response = BlockstreamSatellite.client.post('order', options)
if response.success?
Order.new(response.body)
else
response
end
end
def self.get(order)
Order.new(order).tap do |o|
o.refresh
end
end
def refresh
response = BlockstreamSatellite.client.get("order/#{self.uuid}") do |req|
req.headers['X-Auth-Token'] = self.auth_token
end
if response.success?
self.attributes.merge!(response.body)
end
end
def pay
BlockstreamSatellite.client.pay(self.payreq)
self.refresh
end
def bump(bid_increase)
response = BlockstreamSatellite.client.post("order/#{self.uuid}/bump", bid_increase: bid_increase) do |req|
req.headers['X-Auth-Token'] = self.auth_token
end
if response.success?
self.attributes['lightning_invoice'] = response['lightning_invoice']
else
response
end
end
end
end

View File

@ -0,0 +1,23 @@
require "faraday"
module BlockstreamSatellite
class Response
attr_accessor :response, :body, :error
def initialize(response)
if response.is_a?(Faraday::ClientError)
@error = response
else
@response = response
@body = response.body
end
end
def success?
self.error.nil? && !self.response.nil? && self.response.success?
end
def [](key)
self.body[key.to_s]
end
end
end

View File

@ -0,0 +1,3 @@
module BlockstreamSatellite
VERSION = "0.1.0"
end

View File

@ -0,0 +1,9 @@
RSpec.describe BlockstreamSatellite do
it "has a version number" do
expect(BlockstreamSatellite::VERSION).not_to be nil
end
it "does something useful" do
expect(false).to eq(true)
end
end

14
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,14 @@
require "bundler/setup"
require "blockstream_satellite"
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
config.expect_with :rspec do |c|
c.syntax = :expect
end
end