blockchain 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 018e78fa4e59f75c5e786819ca080b696ef6dd33
4
+ data.tar.gz: 02d086845dd8c96c335e4cbb358c7ba9648b3149
5
+ SHA512:
6
+ metadata.gz: 51da40ee452dd3107775d4fad95c76983bf29976e25e0abd420ae3dbf0740f3e9d7e958e57681e178903cd950812dff5b2efc311f593f1c2c28fb94894726ebf
7
+ data.tar.gz: 7a6ff5c6980ece9c49d1b1165ec830e02b37b56f559f7e70ea15bdc69d4da15dec3a303e3f6873cb391cec3314497203f70ade6679b105c74669eb0deaf3f968
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in blockchain.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Blockchain
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,46 @@
1
+ #Blockchain API library (Ruby, v1)
2
+
3
+ An official Ruby gem for interacting with the Blockchain.info API.
4
+
5
+ ###Getting started
6
+
7
+ Installation via RubyGems:
8
+
9
+ ```
10
+ $ gem install blockchain
11
+ ```
12
+
13
+ Manual installation:
14
+ ```
15
+ $ git clone https://github.com/blockchain/api-v1-client-ruby
16
+ $ cd api-v1-client-ruby
17
+ $ rake install
18
+ ```
19
+
20
+ The gem consists of the following functionality:
21
+
22
+ * `blockexplorer` ([docs](docs/blockexplorer.md)) ([api/blockchain_api][api1])
23
+ * `createwallet` ([docs](docs/createwallet.md)) ([api/create_wallet][api2])
24
+ * `exchangerates` ([docs](docs/exchangerates.md)) ([api/exchange\_rates\_api][api3])
25
+ * `receive` ([docs](docs/receive.md)) ([api/api_receive][api4])
26
+ * `statistics` ([docs](docs/statistics.md)) ([api/charts_api][api5])
27
+ * `wallet` ([docs](docs/wallet.md)) ([api/blockchain\_wallet\_api][api6])
28
+
29
+ The main module is called `Blockchain`
30
+
31
+ ###Error handling
32
+
33
+ All functions may raise exceptions caused by incorrectly passed parameters or other problems. If a call is rejected server-side, the `APIException` exception will be raised.
34
+
35
+ ###Request limits and API keys
36
+
37
+ In order to prevent abuse some API methods require an API key approved with some basic contact information and a description of its intended use. Please request an API key [here](https://blockchain.info/api/api_create_code).
38
+
39
+ The same API key can be used to bypass the request limiter.
40
+
41
+ [api1]: https://blockchain.info/api/blockchain_api
42
+ [api2]: https://blockchain.info/api/create_wallet
43
+ [api3]: https://blockchain.info/api/exchange_rates_api
44
+ [api4]: https://blockchain.info/api/api_receive
45
+ [api5]: https://blockchain.info/api/charts_api
46
+ [api6]: https://blockchain.info/api/blockchain_wallet_api
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'blockchain/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "blockchain"
8
+ spec.version = Blockchain::VERSION
9
+ spec.authors = ["Blockchain"]
10
+ spec.email = ["support@blockchain.zendesk.com"]
11
+ spec.summary = %q{Blockchain API library (Ruby, v1)}
12
+ spec.description = %q{Blockchain API library (Ruby, v1)}
13
+ spec.homepage = "https://github.com/blockchain/api-v1-client-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,117 @@
1
+ ##Block explorer functionality
2
+
3
+ All functions support an optional parameter called `api_code`. It won't be listed with every function description.
4
+
5
+ ####`get_block`
6
+ Get a single block based on a block index or hash. Returns a `Block` object.
7
+
8
+ Params:
9
+ ```
10
+ block_id : str - block index or hash
11
+ ```
12
+
13
+ Usage:
14
+ ```ruby
15
+ require 'blockchain'
16
+
17
+ block = Blockchain::get_block('000000000000000016f9a2c3e0f4c1245ff24856a79c34806969f5084f410680')
18
+ ```
19
+
20
+ ####`get_tx`
21
+ Get a single transaction based on a transaction index or hash. Returns a `Transaction` object.
22
+
23
+ Params:
24
+ ```
25
+ tx_id : str - transaction index or hash
26
+ ```
27
+
28
+ Usage:
29
+ ```ruby
30
+ tx = Blockchain::get_tx('d4af240386cdacab4ca666d178afc88280b620ae308ae8d2585e9ab8fc664a94')
31
+ ```
32
+
33
+ ####`get_block_height`
34
+ Get an array of blocks at the specified height. Returns an array of `Block` objects.
35
+
36
+ Params:
37
+ ```
38
+ height : int - block height
39
+ ```
40
+
41
+ Usage:
42
+ ```ruby
43
+ blocks = Blockchain::get_block_height(2570)
44
+ ```
45
+
46
+ ####`get_address`
47
+ Get a single address and its transactions. Returns an `Address` object.
48
+
49
+ Params:
50
+ ```
51
+ address : str - address in the base58 or hash160 format
52
+ ```
53
+
54
+ Usage:
55
+ ```ruby
56
+ address = Blockchain::get_address('1HS9RLmKvJ7D1ZYgfPExJZQZA1DMU3DEVd')
57
+ ```
58
+
59
+ ####`get_unspent_outputs`
60
+ Get an array of unspent outputs for an address. Returns an array of `UnspentOutput` objects.
61
+
62
+ Params:
63
+ ```
64
+ address : str - address in the base58 or hash160 format
65
+ ```
66
+
67
+ Usage:
68
+ ```ruby
69
+ outs = Blockchain::get_unspent_outputs('1HS9RLmKvJ7D1ZYgfPExJZQZA1DMU3DEVd')
70
+ ```
71
+
72
+ ####`get_latest_block`
73
+ Get the latest block on the main chain. Returns a `LatestBlock` object.
74
+
75
+ Usage:
76
+ ```ruby
77
+ latest_block = Blockchain::get_latest_block()
78
+ ```
79
+
80
+ ####`get_unconfirmed_tx`
81
+ Get a list of currently unconfirmed transactions. Returns an array of `Transaction` objects.
82
+
83
+ Usage:
84
+ ```ruby
85
+ txs = Blockchain::get_unconfirmed_tx()
86
+ ```
87
+
88
+ ####`get_blocks`
89
+ Get a list of blocks for a specific day or mining pool. Returns an array of `SimpleBlock` objects.
90
+
91
+ Params:
92
+ ```
93
+ time : int - unix time in ms (optional)
94
+ pool_name : str - pool name (optional)
95
+ ```
96
+ At least one parameter is required.
97
+
98
+ Usage:
99
+ ```ruby
100
+ blocks = Blockchain::get_blocks(pool_name = 'Discus Fish')
101
+ ```
102
+
103
+ ####`get_inventory_data`
104
+ Get inventory data for recent blocks and addresses (up to 1 hour old). Returns an `InventoryData` object.
105
+
106
+ Params:
107
+ ```
108
+ hash : str - tx or block hash
109
+ ```
110
+
111
+ Usage:
112
+ ```ruby
113
+ inv = Blockchain::get_inventory_data('d4af240386cdacab4ca666d178afc88280b620ae308ae8d2585e9ab8fc664a94')
114
+ ```
115
+
116
+ Note regarding `Input` objects: if coinbase transaction, only `script` and `script_siq` will be populated.
117
+
@@ -0,0 +1,20 @@
1
+ ##Create Wallet functionality
2
+
3
+ ####`create_wallet`
4
+ Create a new Blockchain.info wallet. It can be created containing a pre-generated private key or will otherwise generate a new private key. Returns a `CreateWalletResponse` instance.
5
+
6
+ Params:
7
+ ```
8
+ password : str - password for the new wallet. At least 10 characters.
9
+ api_code : str - API code with the create wallets permission
10
+ priv : str - private key to add to the wallet (optional, keyword)
11
+ label : str - label for the first address in the wallet (optional, keyword)
12
+ email : str - email to associate with the new wallet (optional, keyword)
13
+ ```
14
+
15
+ Usage:
16
+ ```ruby
17
+ require 'blockchain'
18
+
19
+ wallet = Blockchain::create_wallet('1234password', '58ck39ajuiw', label: 'Test wallet')
20
+ ```
@@ -0,0 +1,32 @@
1
+ ##Exchange rates functionality
2
+
3
+ All functions support an optional parameter called `api_code`. It won't be listed with every function description.
4
+
5
+ ####`get_ticker`
6
+ Call the 'ticker' method and return a dictionary of `Currency` objects. Keys are currency symbols (str) and values are `Currency` objects.
7
+
8
+
9
+ Usage:
10
+ ```ruby
11
+ require 'blockchain'
12
+
13
+ ticker = Blockchain::get_ticker()
14
+ #print the 15 min price for every currency
15
+ ticker.keys.each do |key|
16
+ puts ticker[key].p15min
17
+ end
18
+ ```
19
+
20
+ ####`to_btc`
21
+ Call the 'tobtc' method and convert x value in the provided currency to BTC. Returns a `float`.
22
+
23
+ Params:
24
+ ```
25
+ ccy : str - currency code
26
+ value : float
27
+ ```
28
+
29
+ Usage:
30
+ ```ruby
31
+ btc_amount = Blockchain::to_btc('USD', 4342.11)
32
+ ```
data/docs/receive.md ADDED
@@ -0,0 +1,19 @@
1
+ ##Receive functionality
2
+
3
+ ####`receive`
4
+ Call the 'api/receive' endpoint and create a forwarding address. Returns a `ReceiveResponse` object.
5
+
6
+ Params:
7
+ ```
8
+ dest_addr : str
9
+ callback : str
10
+ api_code : str (optional)
11
+ ```
12
+
13
+ Usage:
14
+ ```ruby
15
+ require 'blockchain'
16
+
17
+ resp = Blockchain::receive('1hNapz1CuH4DhnV1DFHH7hafwDE8FJRheA', 'http://your.url.com')
18
+
19
+ ```
@@ -0,0 +1,16 @@
1
+ ## Statistics functionality
2
+
3
+ ####`get`
4
+ Get network statistics. Returns a `StatisticsResponse` object.
5
+
6
+ Params:
7
+ ```
8
+ api_code : str (optional)
9
+ ```
10
+
11
+ Usage:
12
+ ```ruby
13
+ require 'blockchain'
14
+
15
+ stats = Blockchain::get_statistics()
16
+ ```
data/docs/wallet.md ADDED
@@ -0,0 +1,148 @@
1
+ ##`wallet` module
2
+
3
+ An instance of the `Wallet` class needs to be initialized before it can be used.
4
+
5
+ Constructor params:
6
+ ```
7
+ identifier : str
8
+ password : str
9
+ second_password : str (optional)
10
+ api_code : str (optional)
11
+ ```
12
+
13
+ Usage:
14
+ ```ruby
15
+ require 'blockchain'
16
+
17
+ wallet = Blockchain::Wallet.new('ada4e4b6-3c9f-11e4-baad-164230d1df67', 'password123')
18
+ ```
19
+
20
+ ####`send`
21
+ Send bitcoin from your wallet to a single address. Returns a `PaymentResponse` object.
22
+
23
+ Params:
24
+ ```
25
+ to : str - receiving address
26
+ amount : int - amount to send (in satoshi)
27
+ from_address : str - specific address to send from (optional, keyword)
28
+ fee : int - transaction fee in satoshi. Must be greater than default (optional, keyword)
29
+ note : str - public note to include with the transaction (optional, keyword)
30
+ ```
31
+
32
+ Usage:
33
+ ```ruby
34
+ payment = wallet.send('1NAF7GbdyRg3miHNrw2bGxrd63tfMEmJob', 1000000, from_address: '1A8JiWcwvpY7tAopUkSnGuEYHmzGYfZPiq')
35
+
36
+ puts payment.tx_hash
37
+ ```
38
+
39
+ ####`send_many`
40
+ Send bitcoin from your wallet to multiple addresses. Returns a `PaymentResponse` object.
41
+
42
+ Params:
43
+ ```
44
+ recipients : dictionary - dictionary with the structure of 'address':amount
45
+ from_address : str - specific address to send from (optional, keyword)
46
+ fee : int - transaction fee in satoshi. Must be greater than default (optional, keyword)
47
+ note : str - public note to include with the transaction (optional, keyword)
48
+ ```
49
+
50
+ Usage:
51
+ ```ruby
52
+ recipients = { '1NAF7GbdyRg3miHNrw2bGxrd63tfMEmJob' => 1428300,
53
+ '1A8JiWcwvpY7tAopUkSnGuEYHmzGYfZPiq' => 234522117 }
54
+ payment = wallet.send_many(recipients)
55
+
56
+ puts payment.tx_hash
57
+ ```
58
+
59
+ ####`get_balance`
60
+ Fetch the wallet balance. Includes unconfirmed transactions and possibly double spends. Returns the wallet balance in satoshi.
61
+
62
+ Usage:
63
+ ```ruby
64
+ puts wallet.get_balance()
65
+ ```
66
+
67
+ ####`list_addresses`
68
+ List all active addresses in the wallet. Returns an array of `Address` objects.
69
+
70
+ Params:
71
+ ```
72
+ confirmations : int - minimum number of confirmations transactions must have before being included in balance of addresses (optional)
73
+ ```
74
+
75
+ Usage:
76
+ ```ruby
77
+ addresses = wallet.list_addresses()
78
+ addresses.each do |a|
79
+ puts a.balance
80
+ end
81
+
82
+ ```
83
+
84
+ ####`get_address`
85
+ Retrieve an address from the wallet. Returns an `Address` object.
86
+
87
+ Params:
88
+ ```
89
+ confirmations : int - minimum number of confirmations transactions must have before being included in the balance (optional)
90
+ ```
91
+
92
+ Usage:
93
+ ```ruby
94
+ addr = wallet.get_address('1NAF7GbdyRg3miHNrw2bGxrd63tfMEmJob', confirmations = 2)
95
+ puts addr.balance
96
+ ```
97
+
98
+ ####`new_address`
99
+ Generate a new address and add it to the wallet. Returns an `Address` object.
100
+
101
+ Params:
102
+ ```
103
+ label : str - label to attach to the address (optional, keyword)
104
+ ```
105
+
106
+ Usage:
107
+ ```ruby
108
+ newaddr = wallet.new_address('test_label')
109
+ ```
110
+
111
+ ####`archive_address`
112
+ Archive an address. Returns a string representation of the archived address.
113
+
114
+ Params:
115
+ ```
116
+ address : str - address to archive
117
+ ```
118
+
119
+ Usage:
120
+ ```ruby
121
+ wallet.archive_address('1NAF7GbdyRg3miHNrw2bGxrd63tfMEmJob')
122
+ ```
123
+
124
+ ####`unarchive_address`
125
+ Unarchive an address. Returns a string representation of the unarchived address.
126
+
127
+ Params:
128
+ ```
129
+ address : str - address to unarchive
130
+ ```
131
+
132
+ Usage:
133
+ ```ruby
134
+ wallet.unarchive_address('1NAF7GbdyRg3miHNrw2bGxrd63tfMEmJob')
135
+ ```
136
+
137
+ ####`consolidate`
138
+ Consolidate the wallet addresses. Returns a string array of consolidated addresses.
139
+
140
+ Params:
141
+ ```
142
+ days : int - addresses which have not received any transactions in at least this many days will be consolidated.
143
+ ```
144
+
145
+ Usage:
146
+ ```ruby
147
+ wallet.consolidate(50)
148
+ ```
data/lib/blockchain.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "blockchain/version"
2
+ require "blockchain/blockexplorer"
3
+ require "blockchain/createwallet"
4
+ require "blockchain/exchangerates"
5
+ require "blockchain/receive"
6
+ require "blockchain/statistics"
7
+ require "blockchain/wallet"
8
+
9
+ module Blockchain
10
+
11
+ end
@@ -0,0 +1,298 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ def self.get_block(block_id, api_code = nil)
7
+ params = api_code.nil? ? { } : { 'api_code' => api_code }
8
+ resource = 'rawblock/' + block_id
9
+ response = Blockchain::call_api(resource, method: 'get', data: params)
10
+ return Block.new(JSON.parse(response))
11
+ end
12
+
13
+ def self.get_tx(tx_id, api_code = nil)
14
+ params = api_code.nil? ? { } : { 'api_code' => api_code }
15
+ resource = 'rawtx/' + tx_id
16
+ response = Blockchain::call_api(resource, method: 'get', data: params)
17
+ return Transaction.new(JSON.parse(response))
18
+ end
19
+
20
+ def self.get_block_height(height, api_code = nil)
21
+ params = { 'format' => 'json' }
22
+ if !api_code.nil? then params['api_code'] = api_code end
23
+ resource = "block-height/#{height}"
24
+ response = Blockchain::call_api(resource, method: 'get', data: params)
25
+ return JSON.parse(response)['blocks'].map{ |b| Block.new(b) }
26
+ end
27
+
28
+ def self.get_address(address, api_code = nil)
29
+ params = api_code.nil? ? { } : { 'api_code' => api_code }
30
+ resource = 'rawaddr/' + address
31
+ response = Blockchain::call_api(resource, method: 'get', data: params)
32
+ return Address.new(JSON.parse(response))
33
+ end
34
+
35
+ def self.get_unspent_outputs(address, api_code = nil)
36
+ params = { 'active' => address }
37
+ if !api_code.nil? then params['api_code'] = api_code end
38
+ resource = 'unspent'
39
+ response = Blockchain::call_api(resource, method: 'get', data: params)
40
+ return JSON.parse(response)['unspent_outputs'].map{ |o| UnspentOutput.new(o) }
41
+ end
42
+
43
+ def self.get_unconfirmed_tx(api_code = nil)
44
+ params = { 'format' => 'json' }
45
+ if !api_code.nil? then params['api_code'] = api_code end
46
+ resource = 'unconfirmed-transactions'
47
+ response = Blockchain::call_api(resource, method: 'get', data: params)
48
+ return JSON.parse(response)['txs'].map{ |t| Transaction.new(t) }
49
+ end
50
+
51
+ def self.get_blocks(api_code = nil, time: nil, pool_name: nil)
52
+ params = { 'format' => 'json' }
53
+ if !api_code.nil? then params['api_code'] = api_code end
54
+ resource = "blocks/"
55
+ if !time.nil?
56
+ resource += time.to_s
57
+ elsif !pool_name.nil?
58
+ resource += pool_name
59
+ end
60
+ response = Blockchain::call_api(resource, method: 'get', data: params)
61
+ return JSON.parse(response)['blocks'].map{ |b| SimpleBlock.new(b) }
62
+ end
63
+
64
+ def self.get_latest_block(api_code = nil)
65
+ params = {}
66
+ if !api_code.nil? then params['api_code'] = api_code end
67
+ resource = 'latestblock'
68
+ response = Blockchain::call_api(resource, method: 'get', data: params)
69
+ return LatestBlock.new(JSON.parse(response))
70
+ end
71
+
72
+ def self.get_inventory_data(hash, api_code = nil)
73
+ params = { 'format' => 'json' }
74
+ if !api_code.nil? then params['api_code'] = api_code end
75
+ resource = "inv/#{hash}"
76
+ response = Blockchain::call_api(resource, method: 'get', data: params)
77
+ return InventoryData.new(JSON.parse(response))
78
+ end
79
+
80
+ class SimpleBlock
81
+ attr_reader :height
82
+ attr_reader :hash
83
+ attr_reader :time
84
+ attr_reader :main_chain
85
+
86
+ def initialize(b)
87
+ @height = b['height']
88
+ @hash = b['hash']
89
+ @time = b['time']
90
+ @main_chain = b['main_chain']
91
+ end
92
+ end
93
+
94
+ class LatestBlock
95
+ attr_reader :hash
96
+ attr_reader :time
97
+ attr_reader :block_index
98
+ attr_reader :height
99
+ attr_reader :tx_indexes
100
+
101
+ def initialize(b)
102
+ @hash = b['hash']
103
+ @time = b['time']
104
+ @block_index = b['block_index']
105
+ @height = b['height']
106
+ @tx_indexes = b['txIndexes']
107
+ end
108
+ end
109
+
110
+ class UnspentOutput
111
+ attr_reader :tx_hash
112
+ attr_reader :tx_index
113
+ attr_reader :tx_output_n
114
+ attr_reader :script
115
+ attr_reader :value
116
+ attr_reader :value_hex
117
+ attr_reader :confirmations
118
+
119
+ def initialize(o)
120
+ @tx_hash = o['tx_hash']
121
+ @tx_index = o['tx_index']
122
+ @tx_output_n = o['tx_output_n']
123
+ @script = o['script']
124
+ @value = o['value']
125
+ @value_hex = o['value_hex']
126
+ @confirmations = o['confirmations']
127
+ end
128
+ end
129
+
130
+ class Address
131
+ attr_reader :hash160
132
+ attr_reader :address
133
+ attr_reader :n_tx
134
+ attr_reader :total_received
135
+ attr_reader :total_sent
136
+ attr_reader :final_balance
137
+ attr_reader :transactions
138
+
139
+ def initialize(a)
140
+ @hash160 = a['hash160']
141
+ @address = a['address']
142
+ @n_tx = a['n_tx']
143
+ @total_received = a['total_received']
144
+ @total_sent = a['total_sent']
145
+ @final_balance = a['final_balance']
146
+ @transactions = a['txs'].map{ |tx| Transaction.new(tx) }
147
+ end
148
+ end
149
+
150
+ class Input
151
+ attr_reader :n
152
+ attr_reader :value
153
+ attr_reader :address
154
+ attr_reader :tx_index
155
+ attr_reader :type
156
+ attr_reader :script
157
+ attr_reader :script_sig
158
+ attr_reader :sequence
159
+
160
+ def initialize(i)
161
+ obj = i['prev_out']
162
+ if !obj.nil?
163
+ # regular TX
164
+ @n = obj['n']
165
+ @value = obj['value']
166
+ @address = obj['addr']
167
+ @tx_index = obj['tx_index']
168
+ @type = obj['type']
169
+ @script = obj['script']
170
+ @script_sig = i['script']
171
+ @sequence = i['sequence']
172
+ else
173
+ # coinbase TX
174
+ @script_sig = i['script']
175
+ @sequence = i['sequence']
176
+ end
177
+ end
178
+ end
179
+
180
+ class Output
181
+ attr_reader :n
182
+ attr_reader :value
183
+ attr_reader :address
184
+ attr_reader :tx_index
185
+ attr_reader :script
186
+ attr_reader :spent
187
+
188
+ def initialize(o)
189
+ @n = o['n']
190
+ @value = o['value']
191
+ @address = o['addr']
192
+ @tx_index = o['tx_index']
193
+ @script = o['script']
194
+ @spent = o['spent']
195
+ end
196
+ end
197
+
198
+ class Transaction
199
+ attr_reader :double_spend
200
+ attr_reader :block_height
201
+ attr_reader :time
202
+ attr_reader :relayed_by
203
+ attr_reader :hash
204
+ attr_reader :tx_index
205
+ attr_reader :version
206
+ attr_reader :size
207
+ attr_reader :inputs
208
+ attr_reader :outputs
209
+
210
+ def initialize(t)
211
+ @double_spend = t.fetch('double_spend', false)
212
+ @block_height = t.fetch('block_height', false)
213
+ @time = t['time']
214
+ @relayed_by = t['relayed_by']
215
+ @hash = t['hash']
216
+ @tx_index = t['tx_index']
217
+ @version = t['ver']
218
+ @size = t['size']
219
+ @inputs = t['inputs'].map{ |i| Input.new(i) }
220
+ @outputs = t['out'].map{ |o| Output.new(o) }
221
+
222
+ if @block_height.nil?
223
+ @block_height = -1
224
+ end
225
+ end
226
+
227
+ def adjust_block_height(h)
228
+ @block_height = h
229
+ end
230
+ end
231
+
232
+
233
+ class Block
234
+ attr_reader :hash
235
+ attr_reader :version
236
+ attr_reader :previous_block
237
+ attr_reader :merkle_root
238
+ attr_reader :time
239
+ attr_reader :bits
240
+ attr_reader :fee
241
+ attr_reader :nonce
242
+ attr_reader :n_tx
243
+ attr_reader :size
244
+ attr_reader :block_index
245
+ attr_reader :main_chain
246
+ attr_reader :height
247
+ attr_reader :received_time
248
+ attr_reader :relayed_by
249
+ attr_reader :transactions
250
+
251
+ def initialize(b)
252
+ @hash = b['hash']
253
+ @version = b['ver']
254
+ @previous_block = b['prev_block']
255
+ @merkle_root = b['mrkl_root']
256
+ @time = b['time']
257
+ @bits = b['bits']
258
+ @fee = b['fee']
259
+ @nonce = b['nonce']
260
+ @n_tx = b['n_tx']
261
+ @size = b['size']
262
+ @block_index = b['block_index']
263
+ @main_chain = b['main_chain']
264
+ @height = b['height']
265
+ @received_time = b['received_time']
266
+ @relayed_by = b['relayed_by']
267
+ @transactions = b['tx'].map{ |tx| Transaction.new(tx) }
268
+ @transactions.each do |tx|
269
+ tx.adjust_block_height(@height)
270
+ end
271
+
272
+ if @received_time.nil?
273
+ @received_time = @time
274
+ end
275
+ end
276
+ end
277
+
278
+ class InventoryData
279
+ attr_reader :hash
280
+ attr_reader :type
281
+ attr_reader :initial_time
282
+ attr_reader :initial_ip
283
+ attr_reader :nconnected
284
+ attr_reader :relayed_count
285
+ attr_reader :relayed_percent
286
+
287
+ def initialize(i)
288
+ @hash = i['hash']
289
+ @type = i['type']
290
+ @initial_time = i['initial_time'].to_i
291
+ @initial_ip = i['initial_ip']
292
+ @nconnected = i['nconnected'].to_i
293
+ @relayed_count = i['relayed_count'].to_i
294
+ @relayed_percent = i['relayed_percent'].to_i
295
+ end
296
+ end
297
+
298
+ end
@@ -0,0 +1,39 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ def self.create_wallet(password, api_code, priv: nil, label: nil, email: nil)
7
+
8
+ params = { 'password' => password, 'api_code' => api_code }
9
+
10
+ if !priv.nil?
11
+ params['priv'] = priv
12
+ end
13
+ if !label.nil?
14
+ params['label'] = label
15
+ end
16
+ if !email.nil?
17
+ params['email'] = email
18
+ end
19
+
20
+ response = Blockchain::call_api('api/v2/create_wallet', method: 'post', data: params)
21
+ json_response = JSON.parse(response)
22
+ return CreateWalletResponse.new(json_response['guid'],
23
+ json_response['address'],
24
+ json_response['link'])
25
+ end
26
+
27
+ class CreateWalletResponse
28
+ attr_reader :identifier
29
+ attr_reader :address
30
+ attr_reader :link
31
+
32
+ def initialize(identifier, address, link)
33
+ @identifier = identifier
34
+ @address = address
35
+ @link = link
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,47 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ class Currency
7
+ attr_reader :last
8
+ attr_reader :buy
9
+ attr_reader :sell
10
+ attr_reader :symbol
11
+ attr_reader :p15min
12
+
13
+ def initialize(last, buy, sell, symbol, p15min)
14
+ @last = last
15
+ @buy = buy
16
+ @sell = sell
17
+ @symbol = symbol
18
+ @p15min = p15min
19
+ end
20
+ end
21
+
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
+ end
@@ -0,0 +1,32 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ class ReceiveResponse
7
+ attr_reader :fee_percent
8
+ attr_reader :destination
9
+ attr_reader :input_address
10
+ attr_reader :callback_url
11
+
12
+ def initialize(fee_percent, dest, input, callback)
13
+ @fee_percent = fee_percent
14
+ @destination = dest
15
+ @input_address = input
16
+ @callback_url = callback
17
+ end
18
+ end
19
+
20
+ def self.receive(dest_addr, callback, api_code = nil)
21
+ params = { 'method' => 'create', 'address' => dest_addr, 'callback' => callback }
22
+ if !api_code.nil? then params['api_code'] = api_code end
23
+ resp = Blockchain::call_api('api/receive', method: 'post', data: params)
24
+ json_resp = JSON.parse(resp)
25
+ receive_response = ReceiveResponse.new(json_resp['fee_percent'],
26
+ json_resp['destination'],
27
+ json_resp['input_address'],
28
+ json_resp['callback_url'])
29
+ return receive_response
30
+ end
31
+
32
+ end
@@ -0,0 +1,62 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ def self.get_statistics(api_code = nil)
7
+ params = { 'format' => 'json' }
8
+ if !api_code.nil? then params['api_code'] = api_code end
9
+ response = Blockchain::call_api('stats', method: 'get', data: params)
10
+ json_response = JSON.parse(response)
11
+ return StatisticsResponse.new(json_response)
12
+ end
13
+
14
+ class StatisticsResponse
15
+ attr_reader :trade_volume_btc
16
+ attr_reader :miners_revenue_usd
17
+ attr_reader :btc_mined
18
+ attr_reader :trade_volume_usd
19
+ attr_reader :difficulty
20
+ attr_reader :minutes_between_blocks
21
+ attr_reader :days_destroyed
22
+ attr_reader :number_of_transactions
23
+ attr_reader :hash_rate
24
+ attr_reader :timestamp
25
+ attr_reader :mined_blocks
26
+ attr_reader :blocks_size
27
+ attr_reader :total_fees_btc
28
+ attr_reader :total_btc_sent
29
+ attr_reader :estimated_btc_sent
30
+ attr_reader :total_btc
31
+ attr_reader :total_blocks
32
+ attr_reader :next_retarget
33
+ attr_reader :estimated_transaction_volume_usd
34
+ attr_reader :miners_revenue_btc
35
+ attr_reader :market_price_usd
36
+
37
+ def initialize(s)
38
+ @trade_volume_btc = s['trade_volume_btc']
39
+ @miners_revenue_usd = s['miners_revenue_usd']
40
+ @btc_mined = s['n_btc_mined']
41
+ @trade_volume_usd = s['trade_volume_usd']
42
+ @difficulty = s['difficulty']
43
+ @minutes_between_blocks = s['minutes_between_blocks']
44
+ @days_destroyed = s['days_destroyed']
45
+ @number_of_transactions = s['n_tx']
46
+ @hash_rate = s['hash_rate']
47
+ @timestamp = s['timestamp']
48
+ @mined_blocks = s['n_blocks_mined']
49
+ @blocks_size = s['blocks_size']
50
+ @total_fees_btc = s['total_fees_btc']
51
+ @total_btc_sent = s['total_btc_sent']
52
+ @estimated_btc_sent = s['estimated_btc_sent']
53
+ @total_btc = s['totalbc']
54
+ @total_blocks = s['n_blocks_total']
55
+ @next_retarget = s['nextretarget']
56
+ @estimated_transaction_volume_usd = s['estimated_transaction_volume_usd']
57
+ @miners_revenue_btc = s['miners_revenue_btc']
58
+ @market_price_usd = s['market_price_usd']
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,32 @@
1
+ require 'net/http'
2
+
3
+ module Blockchain
4
+
5
+ class APIException < StandardError
6
+ end
7
+
8
+ BASE_URL = "https://blockchain.info/"
9
+
10
+ def self.call_api(resource, method: 'get', data: nil)
11
+ url = URI.parse(BASE_URL + resource)
12
+ http = Net::HTTP.new(url.host, url.port)
13
+ http.use_ssl = true
14
+
15
+ request = nil
16
+ if method == 'get'
17
+ url.query = data.nil? ? nil : URI.encode_www_form(data)
18
+ request = Net::HTTP::Get.new(url.request_uri)
19
+ elsif method == 'post'
20
+ request = Net::HTTP::Post.new(url.request_uri)
21
+ request.content_type = 'application/x-www-form-urlencoded'
22
+ if data != nil then request.set_form_data(data) else {} end
23
+ end
24
+
25
+ response = http.request(request)
26
+ if response.code != '200'
27
+ raise APIException, response.body
28
+ end
29
+ return response.body
30
+ end
31
+
32
+ end
@@ -0,0 +1,3 @@
1
+ module Blockchain
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,167 @@
1
+ require 'json'
2
+ require_relative 'util'
3
+
4
+ module Blockchain
5
+
6
+ class Wallet
7
+
8
+ def initialize(identifier, password, second_password = nil, api_code = nil)
9
+ @identifier = identifier
10
+ @password = password
11
+ @second_password = second_password
12
+ @api_code = api_code
13
+ end
14
+
15
+ def send(to, amount, from_address: nil, fee: nil, note: nil)
16
+ recipient = { to => amount }
17
+ return send_many(recipient, from_address: from_address, fee: fee, note: note)
18
+ end
19
+
20
+ def send_many(recipients, from_address: nil, fee: nil, note: nil)
21
+ params = build_basic_request()
22
+ method = ''
23
+
24
+ if recipients.size == 1
25
+ params['to'] = recipients.keys[0]
26
+ params['amount'] = recipients.values[0]
27
+ method = 'payment'
28
+ else
29
+ params['recipients'] = JSON.dump(recipients)
30
+ method = 'sendmany'
31
+ end
32
+
33
+ if !from_address.nil?
34
+ params['from'] = from_address
35
+ end
36
+ if !fee.nil?
37
+ params['fee'] = fee
38
+ end
39
+ if !note.nil?
40
+ params['note'] = note
41
+ end
42
+
43
+ response = Blockchain::call_api("merchant/#{@identifier}/#{method}", method: 'post', data: params)
44
+ json_response = parse_json(response)
45
+ return PaymentResponse.new(
46
+ json_response['message'],
47
+ json_response['tx_hash'],
48
+ json_response['notice'])
49
+ end
50
+
51
+ def get_balance()
52
+ response = resp = Blockchain::call_api("merchant/#{@identifier}/balance", method: 'get', data: build_basic_request())
53
+ json_response = parse_json(response)
54
+ return json_response['balance']
55
+ end
56
+
57
+ def list_addresses(confirmations = 0)
58
+ params = build_basic_request()
59
+ params['confirmations'] = confirmations
60
+ response = Blockchain::call_api("merchant/#{@identifier}/list", method: 'get', data: params)
61
+ json_response = parse_json(response)
62
+
63
+ addresses = []
64
+ json_response['addresses'].each do |a|
65
+ addr = WalletAddress.new(a['balance'],
66
+ a['address'],
67
+ a['label'],
68
+ a['total_received'])
69
+ addresses.push(addr)
70
+ end
71
+ return addresses
72
+ end
73
+
74
+ def get_address(address, confirmations = 0)
75
+ params = build_basic_request()
76
+ params['address'] = address
77
+ params['confirmations'] = confirmations
78
+ response = Blockchain::call_api("merchant/#{@identifier}/address_balance", method: 'get', data: params)
79
+ json_response = parse_json(response)
80
+ return WalletAddress.new(json_response['balance'],
81
+ json_response['address'],
82
+ nil,
83
+ json_response['total_received'])
84
+ end
85
+
86
+ def new_address(label = nil)
87
+ params = build_basic_request()
88
+ if !label.nil? then params['label'] = label end
89
+ response = Blockchain::call_api("merchant/#{@identifier}/new_address", method: 'post', data: params)
90
+ json_response = parse_json(response)
91
+ return WalletAddress.new(0,
92
+ json_response['address'],
93
+ json_response['label'],
94
+ 0)
95
+ end
96
+
97
+ def archive_address(address)
98
+ params = build_basic_request()
99
+ params['address'] = address
100
+ response = Blockchain::call_api("merchant/#{@identifier}/archive_address", method: 'post', data: params)
101
+ json_response = parse_json(response)
102
+ return json_response['archived']
103
+ end
104
+
105
+ def unarchive_address(address)
106
+ params = build_basic_request()
107
+ params['address'] = address
108
+ response = Blockchain::call_api("merchant/#{@identifier}/unarchive_address", method: 'post', data: params)
109
+ json_response = parse_json(response)
110
+ return json_response['active']
111
+ end
112
+
113
+ def consolidate(days)
114
+ params = build_basic_request()
115
+ params['days'] = days
116
+ response = Blockchain::call_api("merchant/#{@identifier}/auto_consolidate", method: 'post', data: params)
117
+ json_response = parse_json(response)
118
+ return json_response['consolidated']
119
+ end
120
+
121
+ def build_basic_request()
122
+ params = { 'password' => @password }
123
+ if !@second_password.nil?
124
+ params['second_password'] = @second_password
125
+ end
126
+ if !@api_code.nil?
127
+ params['api_code'] = @api_code
128
+ end
129
+ return params
130
+ end
131
+
132
+ # convenience method that parses a response into json AND makes sure there are no errors
133
+ def parse_json(response)
134
+ json_response = JSON.parse(response)
135
+ error = json_response['error']
136
+ if !error.nil? then raise APIException.new(error) end
137
+ return json_response
138
+ end
139
+ end
140
+
141
+ class WalletAddress
142
+ attr_reader :balance
143
+ attr_reader :address
144
+ attr_reader :label
145
+ attr_reader :total_received
146
+
147
+ def initialize(balance, address, label, total_received)
148
+ @balance = balance
149
+ @address = address
150
+ @label = label
151
+ @total_received = total_received
152
+ end
153
+ end
154
+
155
+ class PaymentResponse
156
+ attr_reader :message
157
+ attr_reader :tx_hash
158
+ attr_reader :notice
159
+
160
+ def initialize(message, tx_hash, notice)
161
+ @message = message
162
+ @tx_hash = tx_hash
163
+ @notice = notice
164
+ end
165
+ end
166
+
167
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blockchain
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Blockchain
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Blockchain API library (Ruby, v1)
42
+ email:
43
+ - support@blockchain.zendesk.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - blockchain.gemspec
54
+ - docs/blockexplorer.md
55
+ - docs/createwallet.md
56
+ - docs/exchangerates.md
57
+ - docs/receive.md
58
+ - docs/statistics.md
59
+ - docs/wallet.md
60
+ - lib/blockchain.rb
61
+ - lib/blockchain/blockexplorer.rb
62
+ - lib/blockchain/createwallet.rb
63
+ - lib/blockchain/exchangerates.rb
64
+ - lib/blockchain/receive.rb
65
+ - lib/blockchain/statistics.rb
66
+ - lib/blockchain/util.rb
67
+ - lib/blockchain/version.rb
68
+ - lib/blockchain/wallet.rb
69
+ homepage: https://github.com/blockchain/api-v1-client-ruby
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.2.2
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Blockchain API library (Ruby, v1)
93
+ test_files: []