blockchain 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -6
- data/Rakefile +6 -7
- data/blockchain.gemspec +1 -3
- data/docs/blockexplorer.md +235 -64
- data/docs/createwallet.md +32 -15
- data/docs/exchangerates.md +42 -17
- data/docs/pushtx.md +17 -11
- data/docs/receive.md +49 -22
- data/docs/statistics.md +71 -8
- data/docs/wallet.md +61 -79
- data/lib/blockchain.rb +1 -0
- data/lib/blockchain/blockexplorer.rb +195 -91
- data/lib/blockchain/client.rb +56 -0
- data/lib/blockchain/createwallet.rb +34 -19
- data/lib/blockchain/exchangerates.rb +55 -28
- data/lib/blockchain/pushtx.rb +21 -9
- data/lib/blockchain/receive.rb +52 -26
- data/lib/blockchain/statistics.rb +90 -29
- data/lib/blockchain/version.rb +1 -1
- data/lib/blockchain/wallet.rb +39 -42
- data/test/test_block.rb +97 -0
- data/test/test_exchangerates.rb +31 -0
- data/test/test_pushtx.rb +11 -0
- data/test/test_statistics.rb +35 -0
- data/test/test_wallet.rb +44 -0
- metadata +14 -18
- data/lib/blockchain/util.rb +0 -35
@@ -1,9 +1,61 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
class ExchangeRateExplorer
|
7
|
+
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
def initialize(base_url = nil, api_code = nil)
|
11
|
+
@client = Client.new(base_url, api_code)
|
12
|
+
end
|
13
|
+
|
14
|
+
def proxy(method_name, *args)
|
15
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of ExchangeRateExplorer class instead."
|
16
|
+
send(method_name, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_ticker()
|
20
|
+
params = {}
|
21
|
+
response = @client.call_api('ticker', data: params)
|
22
|
+
json_response = JSON.parse(response)
|
23
|
+
|
24
|
+
ticker = {}
|
25
|
+
json_response.each do |key,value|
|
26
|
+
json_ccy = json_response[key]
|
27
|
+
ccy = Currency.new(json_ccy['last'],
|
28
|
+
json_ccy['buy'],
|
29
|
+
json_ccy['sell'],
|
30
|
+
json_ccy['symbol'],
|
31
|
+
json_ccy['15m'])
|
32
|
+
ticker[key] = ccy
|
33
|
+
end
|
34
|
+
return ticker
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_btc(ccy, value)
|
38
|
+
params = { 'currency' => ccy, 'value' => value}
|
39
|
+
return @client.call_api('tobtc', data: params).to_f
|
40
|
+
end
|
41
|
+
|
42
|
+
def from_btc(ccy = nil, satoshi_value)
|
43
|
+
params = {'value' => satoshi_value}
|
44
|
+
if !ccy.nil? then params['currency'] = ccy end
|
45
|
+
return @client.call_api('frombtc', data: params).to_f
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.get_ticker(api_code = nil)
|
51
|
+
Blockchain::ExchangeRateExplorer.new(nil, api_code).proxy(__method__)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.to_btc(ccy, value, api_code = nil)
|
55
|
+
Blockchain::ExchangeRateExplorer.new(nil, api_code).proxy(__method__, ccy, value)
|
56
|
+
end
|
57
|
+
|
58
|
+
class Currency
|
7
59
|
attr_reader :last
|
8
60
|
attr_reader :buy
|
9
61
|
attr_reader :sell
|
@@ -19,29 +71,4 @@ module Blockchain
|
|
19
71
|
end
|
20
72
|
end
|
21
73
|
|
22
|
-
def self.get_ticker(api_code = nil)
|
23
|
-
params = {}
|
24
|
-
if !api_code.nil? then params['api_code'] = api_code end
|
25
|
-
response = Blockchain::call_api('ticker', data: params)
|
26
|
-
json_response = JSON.parse(response)
|
27
|
-
|
28
|
-
ticker = {}
|
29
|
-
json_response.each do |key,value|
|
30
|
-
json_ccy = json_response[key]
|
31
|
-
ccy = Currency.new(json_ccy['last'],
|
32
|
-
json_ccy['buy'],
|
33
|
-
json_ccy['sell'],
|
34
|
-
json_ccy['symbol'],
|
35
|
-
json_ccy['15m'])
|
36
|
-
ticker[key] = ccy
|
37
|
-
end
|
38
|
-
return ticker
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.to_btc(ccy, value, api_code = nil)
|
42
|
-
params = { 'currency' => ccy, 'value' => value}
|
43
|
-
if !api_code.nil? then params['api_code'] = api_code end
|
44
|
-
return Blockchain::call_api('tobtc', data: params).to_f
|
45
|
-
end
|
46
|
-
|
47
74
|
end
|
data/lib/blockchain/pushtx.rb
CHANGED
@@ -1,16 +1,28 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
5
|
|
6
|
+
class PushTx
|
7
|
+
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
def initialize(base_url = nil, api_code = nil)
|
11
|
+
@client = Client.new(base_url, api_code)
|
12
|
+
end
|
13
|
+
|
14
|
+
def proxy(method_name, tx)
|
15
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of PushTx class instead."
|
16
|
+
send(method_name, tx)
|
17
|
+
end
|
18
|
+
|
19
|
+
def pushtx(tx)
|
20
|
+
params = { 'tx' => tx }
|
21
|
+
@client.call_api('pushtx', method: 'post', data: params)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
6
25
|
def self.pushtx(tx, api_code = nil)
|
7
|
-
|
8
|
-
|
9
|
-
if !api_code.nil?
|
10
|
-
params['api_code'] = api_code
|
11
|
-
end
|
12
|
-
|
13
|
-
Blockchain::call_api('pushtx', method: 'post', data: params)
|
26
|
+
Blockchain::PushTx.new(nil, api_code).proxy(__method__, tx)
|
14
27
|
end
|
15
|
-
|
16
28
|
end
|
data/lib/blockchain/receive.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'client'
|
4
4
|
|
5
5
|
module Blockchain
|
6
6
|
|
@@ -19,7 +19,57 @@ module Blockchain
|
|
19
19
|
end
|
20
20
|
|
21
21
|
module V2
|
22
|
-
|
22
|
+
|
23
|
+
class Receive
|
24
|
+
|
25
|
+
attr_reader :client
|
26
|
+
|
27
|
+
def initialize(base_url = nil)
|
28
|
+
base_url = base_url.nil? ? 'https://api.blockchain.info/v2/' : base_url
|
29
|
+
@client = Client.new(base_url)
|
30
|
+
end
|
31
|
+
|
32
|
+
def proxy(method_name, *args)
|
33
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of Receive class instead."
|
34
|
+
send(method_name, *args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def receive(xpub, callback, api_key, gap_limit = nil)
|
38
|
+
params = { 'xpub' => xpub, 'callback' => callback, 'key' => api_key }
|
39
|
+
if !gap_limit.nil? then params['gap_limit'] = gap_limit end
|
40
|
+
response = @client.call_api('receive', method: 'get', data: params)
|
41
|
+
return ReceiveResponse.new(JSON.parse(response))
|
42
|
+
end
|
43
|
+
|
44
|
+
def callback_log(callback, api_key = nil)
|
45
|
+
params = {'callback' => callback }
|
46
|
+
params['key'] = api_key unless api_key.nil?
|
47
|
+
response = @client.call_api('receive/callback_log', method: 'get', data: params)
|
48
|
+
json_resp = JSON.parse(response)
|
49
|
+
log_entries = json_resp.map do |entry|
|
50
|
+
LogEntry.new(JSON.parse(entry))
|
51
|
+
end
|
52
|
+
return log_entries
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_gap(xpub, api_key = nil)
|
56
|
+
params = {'xpub' => xpub}
|
57
|
+
params['key'] = api_key unless api_key.nil?
|
58
|
+
response = @client.call_api('receive/checkgap', method: 'get', data: params)
|
59
|
+
return JSON.parse(response)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.receive(xpub, callback, api_key)
|
65
|
+
Blockchain::V2::Receive.new.proxy(__method__, xpub, callback, api_key)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.callback_log(callback, api_key = nil)
|
69
|
+
Blockchain::V2::Receive.new.proxy(__method__, callback, api_key)
|
70
|
+
end
|
71
|
+
|
72
|
+
class ReceiveResponse
|
23
73
|
attr_reader :address
|
24
74
|
attr_reader :index
|
25
75
|
attr_reader :callback_url
|
@@ -44,30 +94,6 @@ module Blockchain
|
|
44
94
|
@response_code = response_code
|
45
95
|
end
|
46
96
|
end
|
47
|
-
|
48
|
-
def self.receive(xpub, callback, api_key)
|
49
|
-
params = { 'xpub' => xpub, 'callback' => callback, 'key' => api_key }
|
50
|
-
resp = Blockchain::call_api('v2/receive', method: 'get', data: params, base_url: 'https://api.blockchain.info/')
|
51
|
-
json_resp = JSON.parse(resp)
|
52
|
-
receive_response = ReceiveResponse.new(json_resp['address'],
|
53
|
-
json_resp['index'],
|
54
|
-
json_resp['callback'])
|
55
|
-
receive_response
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.callback_log(callback, api_key = nil)
|
59
|
-
params = {'callback' => callback }
|
60
|
-
params['key'] = api_key unless api_key.nil?
|
61
|
-
resp = Blockchain::call_api('v2/receive/callback_log', method: 'get', data: params, base_url: 'https://api.blockchain.info/')
|
62
|
-
json_resp = JSON.parse(resp)
|
63
|
-
receive_response = json_resp.map do |entry|
|
64
|
-
LogEntry.new(entry['callback'],
|
65
|
-
entry['called_at'],
|
66
|
-
entry['raw_response'],
|
67
|
-
entry['response_code'])
|
68
|
-
end
|
69
|
-
receive_response
|
70
|
-
end
|
71
97
|
end
|
72
98
|
|
73
99
|
|
@@ -1,38 +1,74 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
class StatisticsExplorer
|
7
|
+
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
def initialize(base_url = nil, api_code = nil)
|
11
|
+
@client = Client.new(base_url, api_code)
|
12
|
+
end
|
13
|
+
|
14
|
+
def proxy(method_name, *args)
|
15
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of StatisticsExplorer class instead."
|
16
|
+
send(method_name, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_statistics()
|
20
|
+
params = { 'format' => 'json' }
|
21
|
+
resource = 'stats'
|
22
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
23
|
+
return StatisticsResponse.new(JSON.parse(response))
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_chart(chart_type, timespan = nil, rolling_average = nil)
|
27
|
+
params = { 'format' => 'json' }
|
28
|
+
if !timespan.nil? then params['timespan'] = timespan end
|
29
|
+
if !rolling_average.nil? then params['rollingAverage'] = rolling_average end
|
30
|
+
resource = 'charts/' + chart_type
|
31
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
32
|
+
return ChartResponse.new(JSON.parse(response))
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_pools(timespan = 4)
|
36
|
+
if timespan < 1 || timespan > 10
|
37
|
+
raise ArgumentError, 'timespan must be between 1 and 10'
|
38
|
+
end
|
39
|
+
params = { 'format' => 'json', 'timespan' => timespan.to_s + 'days' }
|
40
|
+
resource = 'pools'
|
41
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
42
|
+
return JSON.parse(response)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.get(api_code = nil)
|
47
|
+
Blockchain::StatisticsExplorer.new(nil, api_code).proxy('get_statistics')
|
12
48
|
end
|
13
49
|
|
14
50
|
class StatisticsResponse
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
51
|
+
attr_reader :trade_volume_btc
|
52
|
+
attr_reader :miners_revenue_usd
|
53
|
+
attr_reader :btc_mined
|
54
|
+
attr_reader :trade_volume_usd
|
55
|
+
attr_reader :difficulty
|
56
|
+
attr_reader :minutes_between_blocks
|
57
|
+
attr_reader :number_of_transactions
|
58
|
+
attr_reader :hash_rate
|
59
|
+
attr_reader :timestamp
|
60
|
+
attr_reader :mined_blocks
|
61
|
+
attr_reader :blocks_size
|
62
|
+
attr_reader :total_fees_btc
|
63
|
+
attr_reader :total_btc_sent
|
64
|
+
attr_reader :estimated_btc_sent
|
65
|
+
attr_reader :total_btc
|
66
|
+
attr_reader :total_blocks
|
67
|
+
attr_reader :next_retarget
|
68
|
+
attr_reader :estimated_transaction_volume_usd
|
69
|
+
attr_reader :miners_revenue_btc
|
70
|
+
attr_reader :market_price_usd
|
71
|
+
|
36
72
|
def initialize(s)
|
37
73
|
@trade_volume_btc = s['trade_volume_btc']
|
38
74
|
@miners_revenue_usd = s['miners_revenue_usd']
|
@@ -56,5 +92,30 @@ module Blockchain
|
|
56
92
|
@market_price_usd = s['market_price_usd']
|
57
93
|
end
|
58
94
|
end
|
59
|
-
|
95
|
+
|
96
|
+
class ChartResponse
|
97
|
+
attr_reader :chart_name
|
98
|
+
attr_reader :unit
|
99
|
+
attr_reader :timespan
|
100
|
+
attr_reader :description
|
101
|
+
attr_reader :values
|
102
|
+
|
103
|
+
def initialize(cr)
|
104
|
+
@chart_name = cr['name']
|
105
|
+
@unit = cr['unit']
|
106
|
+
@timespan = cr['period']
|
107
|
+
@description = cr['description']
|
108
|
+
@values = cr['values'].map{ |value| ChartValue.new(value) }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class ChartValue
|
113
|
+
attr_reader :x
|
114
|
+
attr_reader :y
|
115
|
+
|
116
|
+
def initialize(cv)
|
117
|
+
@x = cv['x']
|
118
|
+
@y = cv['y']
|
119
|
+
end
|
120
|
+
end
|
60
121
|
end
|
data/lib/blockchain/version.rb
CHANGED
data/lib/blockchain/wallet.rb
CHANGED
@@ -1,27 +1,32 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
5
|
|
6
6
|
class Wallet
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
def initialize(identifier, password, url = 'http://localhost:3000/', second_password = nil, api_code = nil)
|
11
|
+
@client = Client.new(url, api_code)
|
12
|
+
@identifier = identifier
|
10
13
|
@password = password
|
11
14
|
@second_password = second_password
|
12
|
-
@api_code = api_code
|
13
|
-
@url = url
|
14
15
|
end
|
15
|
-
|
16
|
-
def send(to, amount, from_address: nil, fee: nil
|
16
|
+
|
17
|
+
def send(to, amount, from_address: nil, fee: nil)
|
17
18
|
recipient = { to => amount }
|
18
|
-
return send_many(recipient, from_address: from_address, fee: fee
|
19
|
+
return send_many(recipient, from_address: from_address, fee: fee)
|
19
20
|
end
|
20
|
-
|
21
|
-
def send_many(recipients, from_address: nil, fee: nil
|
21
|
+
|
22
|
+
def send_many(recipients, from_address: nil, fee: nil)
|
22
23
|
params = build_basic_request()
|
23
24
|
method = ''
|
24
|
-
|
25
|
+
|
26
|
+
if recipients.nil? || recipients.size == 0
|
27
|
+
raise ArgumentError, 'Sending bitcoin from your wallet requires at least one receipient'
|
28
|
+
end
|
29
|
+
|
25
30
|
if recipients.size == 1
|
26
31
|
params['to'] = recipients.keys[0]
|
27
32
|
params['amount'] = recipients.values[0]
|
@@ -30,37 +35,33 @@ module Blockchain
|
|
30
35
|
params['recipients'] = JSON.dump(recipients)
|
31
36
|
method = 'sendmany'
|
32
37
|
end
|
33
|
-
|
38
|
+
|
34
39
|
if !from_address.nil?
|
35
40
|
params['from'] = from_address
|
36
41
|
end
|
37
42
|
if !fee.nil?
|
38
43
|
params['fee'] = fee
|
39
44
|
end
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
response = Blockchain::call_api("merchant/#{@identifier}/#{method}", method: 'post', data: params, base_url: @url)
|
45
|
+
|
46
|
+
response = @client.call_api("merchant/#{@identifier}/#{method}", method: 'post', data: params)
|
45
47
|
json_response = parse_json(response)
|
46
48
|
return PaymentResponse.new(
|
47
49
|
json_response['message'],
|
48
50
|
json_response['tx_hash'],
|
49
51
|
json_response['notice'])
|
50
52
|
end
|
51
|
-
|
53
|
+
|
52
54
|
def get_balance()
|
53
|
-
response =
|
55
|
+
response = @client.call_api("merchant/#{@identifier}/balance", method: 'get', data: build_basic_request())
|
54
56
|
json_response = parse_json(response)
|
55
57
|
return json_response['balance']
|
56
58
|
end
|
57
|
-
|
58
|
-
def list_addresses(
|
59
|
+
|
60
|
+
def list_addresses()
|
59
61
|
params = build_basic_request()
|
60
|
-
|
61
|
-
response = Blockchain::call_api("merchant/#{@identifier}/list", method: 'get', data: params)
|
62
|
+
response = @client.call_api("merchant/#{@identifier}/list", method: 'get', data: params)
|
62
63
|
json_response = parse_json(response)
|
63
|
-
|
64
|
+
|
64
65
|
addresses = []
|
65
66
|
json_response['addresses'].each do |a|
|
66
67
|
addr = WalletAddress.new(a['balance'],
|
@@ -71,57 +72,53 @@ module Blockchain
|
|
71
72
|
end
|
72
73
|
return addresses
|
73
74
|
end
|
74
|
-
|
75
|
-
def get_address(address
|
75
|
+
|
76
|
+
def get_address(address)
|
76
77
|
params = build_basic_request()
|
77
78
|
params['address'] = address
|
78
|
-
|
79
|
-
response = Blockchain::call_api("merchant/#{@identifier}/address_balance", method: 'get', data: params)
|
79
|
+
response = @client.call_api("merchant/#{@identifier}/address_balance", method: 'get', data: params)
|
80
80
|
json_response = parse_json(response)
|
81
81
|
return WalletAddress.new(json_response['balance'],
|
82
82
|
json_response['address'],
|
83
83
|
nil,
|
84
84
|
json_response['total_received'])
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
def new_address(label = nil)
|
88
88
|
params = build_basic_request()
|
89
89
|
if !label.nil? then params['label'] = label end
|
90
|
-
response =
|
90
|
+
response = @client.call_api("merchant/#{@identifier}/new_address", method: 'post', data: params)
|
91
91
|
json_response = parse_json(response)
|
92
92
|
return WalletAddress.new(0,
|
93
93
|
json_response['address'],
|
94
94
|
json_response['label'],
|
95
95
|
0)
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
def archive_address(address)
|
99
99
|
params = build_basic_request()
|
100
100
|
params['address'] = address
|
101
|
-
response =
|
101
|
+
response = @client.call_api("merchant/#{@identifier}/archive_address", method: 'post', data: params)
|
102
102
|
json_response = parse_json(response)
|
103
103
|
return json_response['archived']
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
def unarchive_address(address)
|
107
107
|
params = build_basic_request()
|
108
108
|
params['address'] = address
|
109
|
-
response =
|
109
|
+
response = @client.call_api("merchant/#{@identifier}/unarchive_address", method: 'post', data: params)
|
110
110
|
json_response = parse_json(response)
|
111
111
|
return json_response['active']
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
def build_basic_request()
|
115
115
|
params = { 'password' => @password }
|
116
116
|
if !@second_password.nil?
|
117
117
|
params['second_password'] = @second_password
|
118
118
|
end
|
119
|
-
if !@api_code.nil?
|
120
|
-
params['api_code'] = @api_code
|
121
|
-
end
|
122
119
|
return params
|
123
120
|
end
|
124
|
-
|
121
|
+
|
125
122
|
# convenience method that parses a response into json AND makes sure there are no errors
|
126
123
|
def parse_json(response)
|
127
124
|
json_response = JSON.parse(response)
|
@@ -136,7 +133,7 @@ module Blockchain
|
|
136
133
|
attr_reader :address
|
137
134
|
attr_reader :label
|
138
135
|
attr_reader :total_received
|
139
|
-
|
136
|
+
|
140
137
|
def initialize(balance, address, label, total_received)
|
141
138
|
@balance = balance
|
142
139
|
@address = address
|
@@ -149,12 +146,12 @@ module Blockchain
|
|
149
146
|
attr_reader :message
|
150
147
|
attr_reader :tx_hash
|
151
148
|
attr_reader :notice
|
152
|
-
|
149
|
+
|
153
150
|
def initialize(message, tx_hash, notice)
|
154
151
|
@message = message
|
155
152
|
@tx_hash = tx_hash
|
156
153
|
@notice = notice
|
157
154
|
end
|
158
155
|
end
|
159
|
-
|
156
|
+
|
160
157
|
end
|