waffle_api 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 +7 -0
- data/CONTRIBUTING.md +7 -0
- data/LICENSE.md +21 -0
- data/README.md +119 -0
- data/lib/waffle_api/address_validator.rb +56 -0
- data/lib/waffle_api/client.rb +38 -0
- data/lib/waffle_api/errors.rb +80 -0
- data/lib/waffle_api/helpers.rb +56 -0
- data/lib/waffle_api/version.rb +3 -0
- data/lib/waffle_api.rb +6 -0
- data/waffle_api.gemspec +14 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dc3f850365ea0b87271e5c6ff17619781fe21834
|
4
|
+
data.tar.gz: 66d0b71214fbb07192d370848347d56a21d54d44
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d13db65aa6dbb6aa3672c0fbf79e8c20ef49c5b3989e95d0f6e5cfa054ee3e67356da7c277dc784f5e5e4f0c8bada3620303d801e80cf7eb8da694239832002
|
7
|
+
data.tar.gz: 0e076e76958040a268e72766e6ea1a8af8fb571ca30da634fbc1254415de8d99bfc0562b64d948e227a0475989861b688eebe42a36e5a14a9dc35c5ddcda8b5b
|
data/CONTRIBUTING.md
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Charley D.
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# WaffleAPI
|
2
|
+
|
3
|
+
[![Build Status][travis_img]][travis_url]
|
4
|
+
[![Gem Version][fury_img]][fury_url]
|
5
|
+
[![Code Climate][code_climate_img]][code_climate_url]
|
6
|
+
[![Coverage Status][coveralls_img]][coveralls_url]
|
7
|
+
|
8
|
+
_Waffle pool API gem_
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
### Ruby 1.9.3+, 2+
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem install waffle_api
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'waffle_pool'
|
22
|
+
client = WaffleAPI::Client.new address: '1Ju8U9Ukfc5kiMqzQrRgQBP1JvRkeSv94V'
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
### Get current total hashrate
|
27
|
+
```ruby
|
28
|
+
client.hashrate
|
29
|
+
```
|
30
|
+
|
31
|
+
|
32
|
+
### Get workers infos
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
client.worker_hashrates
|
36
|
+
```
|
37
|
+
|
38
|
+
Will return a JSON array
|
39
|
+
|
40
|
+
```json
|
41
|
+
[
|
42
|
+
{
|
43
|
+
"username": "1Ju8U9Ukfc5kiMqzQrRgQBP1JvRkeSv94V_calyhrerig1",
|
44
|
+
"hashrate": 2529705,
|
45
|
+
"stalerate": 3.33,
|
46
|
+
"last_seen": 1398022030,
|
47
|
+
"str": "2.53 MH/s"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"username": "1Ju8U9Ukfc5kiMqzQrRgQBP1JvRkeSv94V_dqmsrig1",
|
51
|
+
"hashrate": 1773702,
|
52
|
+
"stalerate": 1.61,
|
53
|
+
"last_seen": 1398022030,
|
54
|
+
"str": "1.77 MH/s"
|
55
|
+
}
|
56
|
+
]
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
### Get balances
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
client.balances
|
64
|
+
```
|
65
|
+
|
66
|
+
Will return a JSON array
|
67
|
+
|
68
|
+
```json
|
69
|
+
{
|
70
|
+
"sent": 1.61039009,
|
71
|
+
"confirmed": 0.00383488,
|
72
|
+
"unconverted": 0.011964213459441
|
73
|
+
}
|
74
|
+
```
|
75
|
+
|
76
|
+
|
77
|
+
### Get payments
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
client.recent_payments
|
81
|
+
```
|
82
|
+
|
83
|
+
Will return a JSON array containing the last 10 payments
|
84
|
+
|
85
|
+
```json
|
86
|
+
[
|
87
|
+
{
|
88
|
+
"amount": "0.01715311",
|
89
|
+
"time": "2014-04-20 16:03:24",
|
90
|
+
"txn": "8706e0a..."
|
91
|
+
},
|
92
|
+
{
|
93
|
+
"amount": "0.01600557",
|
94
|
+
"time": "2014-04-20 04:36:01",
|
95
|
+
"txn": "258dda8..."
|
96
|
+
},
|
97
|
+
{
|
98
|
+
"..."
|
99
|
+
}
|
100
|
+
]
|
101
|
+
```
|
102
|
+
|
103
|
+
|
104
|
+
## Contributing
|
105
|
+
|
106
|
+
[Contributors](https://github.com/Calyhre/waffle_api/graphs/contributors) and [CONTRIBUTING](https://github.com/Calyhre/waffle_api/blob/master/CONTRIBUTING.md)
|
107
|
+
|
108
|
+
## Licence
|
109
|
+
|
110
|
+
Released under the MIT License. See the [LICENSE](https://github.com/Calyhre/waffle_api/blob/master/LICENSE.md) file for further details.
|
111
|
+
|
112
|
+
[travis_img]: https://travis-ci.org/Calyhre/waffle_api.png?branch=master
|
113
|
+
[travis_url]: https://travis-ci.org/Calyhre/waffle_api
|
114
|
+
[fury_img]: https://badge.fury.io/rb/waffle_api.png
|
115
|
+
[fury_url]: http://badge.fury.io/rb/waffle_api
|
116
|
+
[code_climate_img]: https://codeclimate.com/github/Calyhre/waffle_api.png
|
117
|
+
[code_climate_url]: https://codeclimate.com/github/Calyhre/waffle_api
|
118
|
+
[coveralls_img]: https://coveralls.io/repos/Calyhre/waffle_api/badge.png?branch=master
|
119
|
+
[coveralls_url]: https://coveralls.io/r/Calyhre/waffle_api?branch=master
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module WaffleAPI
|
4
|
+
# Module use to deeply validate BTC address
|
5
|
+
# From https://gist.github.com/alexandrz/4491729
|
6
|
+
module AddressValidator
|
7
|
+
private
|
8
|
+
|
9
|
+
B58_CHARS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
10
|
+
B58_BASE = B58_CHARS.length
|
11
|
+
|
12
|
+
def valid_address?
|
13
|
+
(@address =~ /^[a-zA-Z1-9]{33,35}$/) && DigestUtilities.version(@address)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Utilities are in a class to make them private
|
17
|
+
class DigestUtilities
|
18
|
+
def self.version(address)
|
19
|
+
decoded = b58_decode(address, 25)
|
20
|
+
|
21
|
+
version = decoded[0, 1]
|
22
|
+
checksum = decoded[-4, decoded.length]
|
23
|
+
vh160 = decoded[0, decoded.length - 4]
|
24
|
+
|
25
|
+
hashed = (Digest::SHA2.new << (Digest::SHA2.new << vh160).digest).digest
|
26
|
+
|
27
|
+
hashed[0, 4] == checksum ? version[0] : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.b58_decode(value, length)
|
31
|
+
long_value = 0
|
32
|
+
index = 0
|
33
|
+
result = ""
|
34
|
+
|
35
|
+
value.reverse.each_char do |c|
|
36
|
+
long_value += B58_CHARS.index(c) * (B58_BASE ** index)
|
37
|
+
index += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
while long_value >= 256 do
|
41
|
+
div, mod = long_value.divmod 256
|
42
|
+
result = mod.chr + result
|
43
|
+
long_value = div
|
44
|
+
end
|
45
|
+
|
46
|
+
result = long_value.chr + result
|
47
|
+
|
48
|
+
if result.length < length
|
49
|
+
result = 0.chr * (length - result.length) + result
|
50
|
+
end
|
51
|
+
|
52
|
+
result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'waffle_api/helpers'
|
2
|
+
require 'waffle_api/address_validator'
|
3
|
+
|
4
|
+
module WaffleAPI
|
5
|
+
# A Ruby class to call the Waffle stat API. You might use this if you want to
|
6
|
+
# retrieve your waffle pool stats from within a Ruby program.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# require 'waffle_api'
|
11
|
+
# stats = WaffleAPI::Client.new address: '<BTC_ADDRESS_HERE>'
|
12
|
+
# stats.create()
|
13
|
+
#
|
14
|
+
class Client
|
15
|
+
include WaffleAPI::Helpers
|
16
|
+
include WaffleAPI::AddressValidator
|
17
|
+
|
18
|
+
attr_accessor :address, :https_only
|
19
|
+
|
20
|
+
def initialize(address: nil, https_only: false, ignore_bad_address: false)
|
21
|
+
@address = address || ENV['BTC_ADDRESS']
|
22
|
+
@https_only = https_only
|
23
|
+
|
24
|
+
fail Error::EmptyAddress if @address.nil? || @address.empty?
|
25
|
+
fail Error::BadAddress, @address unless valid_address? || ignore_bad_address
|
26
|
+
end
|
27
|
+
|
28
|
+
def hashrate
|
29
|
+
stats 'hash_rate'
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method, *args, &block)
|
33
|
+
stats method.to_s
|
34
|
+
rescue Error::UnknownKey
|
35
|
+
super method, *args, &block
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module WaffleAPI
|
2
|
+
# WaffleAPI raised errors with explanations
|
3
|
+
module Error
|
4
|
+
ISSUES_URL = 'https://github.com/Calyhre/waffle_api/issues/new'
|
5
|
+
|
6
|
+
# Standard error we will inherit
|
7
|
+
class Standard < StandardError
|
8
|
+
def initialize(message = nil)
|
9
|
+
super(message || self.message)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Error raised when address is missing
|
14
|
+
class EmptyAddress < Standard
|
15
|
+
def message
|
16
|
+
"You must provide an address to use this API. Please check the " \
|
17
|
+
"documentation."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Error raised when address isn't valid
|
22
|
+
class BadAddress < Standard
|
23
|
+
def initialize(address = '')
|
24
|
+
super message address
|
25
|
+
end
|
26
|
+
|
27
|
+
def message(address = '')
|
28
|
+
"Address '#{address}' doesn't seem to be valid. You must provide a " \
|
29
|
+
"valid address to use this API. Use ignore_bad_address to skip this " \
|
30
|
+
"error."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Error raised when https call Waffle returned a bad call
|
35
|
+
# It meens Waffle isn't supporting https right now.
|
36
|
+
class HttpsNotSupportedYet < Standard
|
37
|
+
def message
|
38
|
+
"Waffle pool isn\'t supporting https yet. Please use WaffleAPI " \
|
39
|
+
"without https_only argument."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Error raised when Waffle change his API endpoint. Nothing to do but
|
44
|
+
# report an issue on this gem repo
|
45
|
+
class EndPointMoved < Standard
|
46
|
+
def message
|
47
|
+
"Waffle pool seems to have change his API endpoint. Please report " \
|
48
|
+
"an issue on #{ISSUES_URL}."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Error raised when Waffle change his API endpoint. Nothing to do but
|
53
|
+
# report an issue on this gem repo
|
54
|
+
class AddressNotFound < Standard
|
55
|
+
def initialize(address = '')
|
56
|
+
super message address
|
57
|
+
end
|
58
|
+
|
59
|
+
def message(address = '')
|
60
|
+
"The address #{address} was not found on Wafflepool. Please check it."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# If you raise this exception, please report it as an issue with the
|
65
|
+
# message on this gem repo
|
66
|
+
class UnknownError < Standard; end
|
67
|
+
|
68
|
+
# If you raise this exception, please report it as an issue with it's
|
69
|
+
# message on this gem repo
|
70
|
+
class UnknownKey < Standard
|
71
|
+
def initialize(key = '')
|
72
|
+
super message key
|
73
|
+
end
|
74
|
+
|
75
|
+
def message(key = '')
|
76
|
+
"The key '#{key}' does not exist on Wafflepool api."
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'waffle_api/errors'
|
2
|
+
require 'net/http'
|
3
|
+
require 'openssl'
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module WaffleAPI
|
8
|
+
# List of helpers used in WaffleAPI
|
9
|
+
module Helpers
|
10
|
+
WAFFLE_POOL_HOST = 'wafflepool.com'
|
11
|
+
NOT_FOUND_ERROR = 'Invalid BTC Address!'
|
12
|
+
INVALIDATION_TIME = 30 # Seconds
|
13
|
+
|
14
|
+
def call_uri
|
15
|
+
URI(
|
16
|
+
"#{@https_only ? 'https' : 'http'}://#{WAFFLE_POOL_HOST}" \
|
17
|
+
"/tmp_api?address=#{@address}"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def request_json
|
22
|
+
response = Net::HTTP.get_response call_uri
|
23
|
+
fail Error::EndPointMoved if response.is_a? Net::HTTPNotFound
|
24
|
+
|
25
|
+
json = JSON.parse response.body
|
26
|
+
fail Error::AddressNotFound, @address if json['error'] == NOT_FOUND_ERROR
|
27
|
+
fail Error::UnknownError, json['error'] unless json['error'].empty?
|
28
|
+
json.delete 'error'
|
29
|
+
|
30
|
+
return json
|
31
|
+
rescue OpenSSL::SSL::SSLError
|
32
|
+
raise Error::HttpsNotSupportedYet
|
33
|
+
end
|
34
|
+
|
35
|
+
def data_recent?
|
36
|
+
@retrieved_at && @retrieved_at > Time.now - INVALIDATION_TIME
|
37
|
+
end
|
38
|
+
|
39
|
+
def data_recent!
|
40
|
+
@retrieved_at = Time.now
|
41
|
+
end
|
42
|
+
|
43
|
+
def stats(key, force_update = false)
|
44
|
+
@datas ||= []
|
45
|
+
|
46
|
+
if !data_recent? || force_update
|
47
|
+
@datas = request_json
|
48
|
+
data_recent!
|
49
|
+
end
|
50
|
+
|
51
|
+
fail Error::UnknownKey, key if @datas[key].nil?
|
52
|
+
|
53
|
+
@datas[key]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/waffle_api.rb
ADDED
data/waffle_api.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path('../lib/waffle_api/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'waffle_api'
|
5
|
+
s.version = WaffleAPI::VERSION
|
6
|
+
s.summary = 'Waffle pool API gem'
|
7
|
+
s.description = s.summary
|
8
|
+
s.authors = ['Calyhre']
|
9
|
+
s.email = ['contact@calyh.re']
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.homepage = 'http://rubygems.org/gems/waffle_api'
|
13
|
+
s.license = 'MIT'
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: waffle_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Calyhre
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-20 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Waffle pool API gem
|
14
|
+
email:
|
15
|
+
- contact@calyh.re
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- CONTRIBUTING.md
|
21
|
+
- LICENSE.md
|
22
|
+
- README.md
|
23
|
+
- lib/waffle_api.rb
|
24
|
+
- lib/waffle_api/address_validator.rb
|
25
|
+
- lib/waffle_api/client.rb
|
26
|
+
- lib/waffle_api/errors.rb
|
27
|
+
- lib/waffle_api/helpers.rb
|
28
|
+
- lib/waffle_api/version.rb
|
29
|
+
- waffle_api.gemspec
|
30
|
+
homepage: http://rubygems.org/gems/waffle_api
|
31
|
+
licenses:
|
32
|
+
- MIT
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 2.2.0
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Waffle pool API gem
|
54
|
+
test_files: []
|