blockcypher-ruby 0.2.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: 7745506061c201b5a82f943b2dadec2759f82a88
4
+ data.tar.gz: fb35dcbc2e31dbf1c3433f41d442413b9cb79a62
5
+ SHA512:
6
+ metadata.gz: 1ce6d7b7f4d59c3080e77d952e0bf5ff59c1674d9d3f833c749f6d20058f0dbe0e2080fbee7864e8a75a77f17d0fd1a8e1ea5747576a47fc4127216e6edc1da2
7
+ data.tar.gz: a3a07c71551edd6f81a4f94ad3017fb540b7cb14eefd2e182a33330ce530a92b2cec39b1346dce0b9fc2b53bc5b79ab6fdc1f9480a9d71cb83c7c5b4de12c714
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # BlockCypher Ruby Client
2
+
3
+ Simple Ruby client for the [BlockCypher](http://www.blockcypher.com) API.
4
+
5
+ ## Setup
6
+
7
+ Simply using rubygems:
8
+
9
+ gem install blockcypher-ruby
10
+
11
+ ## Initializing a client
12
+
13
+ If you want to use BTC on the main net, which is normally what you want to do, it's as simple as:
14
+
15
+ block_cypher = BlockCypher::Api.new
16
+
17
+ ## BlockCypher's documentation
18
+
19
+ For more information check the API docs at:
20
+
21
+ http://dev.blockcypher.com
22
+
23
+ ## Contributors
24
+
25
+ Contributions from [CoinHako](http://www.coinhako.com) and [meXBT](https://mexbt.com)
@@ -0,0 +1,5 @@
1
+ require 'blockcypher/api'
2
+ require 'bitcoin'
3
+ require 'json'
4
+ require 'uri'
5
+ require 'net/http'
@@ -0,0 +1,346 @@
1
+ module BlockCypher
2
+
3
+ V1 = 'v1'
4
+
5
+ BTC = 'btc'
6
+ LTC = 'ltc'
7
+ DOGE = 'doge'
8
+ BCY= 'bcy'
9
+
10
+ MAIN_NET = 'main'
11
+ TEST_NET = 'test'
12
+ TEST_NET_3 = 'test3'
13
+
14
+ class Api
15
+
16
+ class Error < RuntimeError ; end
17
+
18
+ attr_reader :api_token
19
+
20
+ def initialize(version: V1, currency: BTC, network: MAIN_NET, api_token: nil)
21
+ @version = version
22
+ @currency = currency
23
+ @network = network
24
+ @api_token = api_token
25
+ end
26
+
27
+ ##################
28
+ # Blockchain API
29
+ ##################
30
+
31
+ def blockchain_unconfirmed_tx
32
+ api_http_get('/txs')
33
+ end
34
+
35
+ def blockchain_transaction(transaction_hash)
36
+ api_http_get('/txs/' + transaction_hash)
37
+ end
38
+
39
+ def blockchain_block(block_index, params)
40
+ api_http_get('/blocks/' + block_index, query: params)
41
+ end
42
+
43
+ def blockchain
44
+ api_http_get('')
45
+ end
46
+
47
+ ##################
48
+ # Faucet API
49
+ ##################
50
+
51
+ def faucet(address, amount)
52
+ payload = { 'address' => address, 'amount' => amount }
53
+ api_http_post('/faucet', json_payload: payload)
54
+ end
55
+
56
+ ##################
57
+ # Transaction API
58
+ ##################
59
+
60
+ def decode_hex(hex)
61
+ payload = { 'tx' => hex}
62
+ api_http_post('/txs/decode', json_payload: payload)
63
+ end
64
+
65
+ def push_hex(hex)
66
+ payload = { 'tx' => hex }
67
+ api_http_post('/txs/push', json_payload: payload)
68
+ end
69
+
70
+ def send_money(from_address, to_address, satoshi_amount, private_key)
71
+
72
+ unless to_address.kind_of? Array
73
+ to_address = [to_address]
74
+ end
75
+
76
+ tx_new = transaction_new([from_address], to_address, satoshi_amount)
77
+
78
+ transaction_sign_and_send(tx_new, private_key)
79
+ end
80
+
81
+ def transaction_new(input_addreses, output_addresses, satoshi_amount)
82
+ payload = {
83
+ 'inputs' => [
84
+ {
85
+ addresses: input_addreses
86
+ }
87
+ ],
88
+ 'outputs' => [
89
+ {
90
+ addresses: output_addresses,
91
+ value: satoshi_amount
92
+ }
93
+ ]
94
+ }
95
+ api_http_post('/txs/new', json_payload: payload)
96
+ end
97
+
98
+ def transaction_sign_and_send(new_tx, private_key)
99
+ pubkey = pubkey_from_priv(private_key)
100
+ # Make array of pubkeys matching length of 'tosign'
101
+ new_tx['pubkeys'] = Array.new(new_tx['tosign'].length) { pubkey }
102
+ # Sign the 'tosign' array
103
+ new_tx['signatures'] = signer(private_key, new_tx['tosign'])
104
+ api_http_post('/txs/send', json_payload: new_tx)
105
+ end
106
+
107
+ def pubkey_from_priv(private_key)
108
+ key = Bitcoin::Key.new(private_key, nil, compressed = true)
109
+ key.pub
110
+ end
111
+
112
+ def signer(private_key, tosign)
113
+ key = Bitcoin::Key.new(private_key, nil, compressed = true)
114
+ signatures = []
115
+
116
+ tosign.each do |to_sign_hex|
117
+ to_sign_binary = [to_sign_hex].pack("H*")
118
+ sig_binary = key.sign(to_sign_binary)
119
+ sig_hex = sig_binary.unpack("H*").first
120
+ signatures << sig_hex
121
+ end
122
+
123
+ return signatures
124
+ end
125
+
126
+ def transaction_new_custom(payload)
127
+ # Build payload yourself, for custom transactions
128
+ api_http_post('/txs/new', json_payload: payload)
129
+ end
130
+
131
+ def transaction_send_custom(payload)
132
+ # Send TXSkeleton payload yourself, for custom transactions
133
+ # You may need to sign your data using another library, like Bitcoin
134
+ api_http_post('/txs/send', json_payload: payload)
135
+ end
136
+
137
+ def tx_confidence(tx_hash)
138
+ api_http_get('/txs/' + tx_hash + '/confidence')
139
+ end
140
+
141
+ ##################
142
+ # Microtx API
143
+ ##################
144
+
145
+ # This method sends private key to server
146
+ def microtx_from_priv(private_key, to_address, value_satoshis)
147
+ payload = {
148
+ from_private: private_key,
149
+ to_address: to_address,
150
+ value_satoshis: value_satoshis
151
+ }
152
+ api_http_post('/txs/micro', json_payload: payload)
153
+ end
154
+
155
+ # This method uses public key, signs with private key locally
156
+ def microtx_from_pub(private_key, to_address, value_satoshis)
157
+ pubkey = pubkey_from_priv(private_key)
158
+ payload = {
159
+ from_pubkey: pubkey,
160
+ to_address: to_address,
161
+ value_satoshis: value_satoshis
162
+ }
163
+ micro_skel = api_http_post('/txs/micro', json_payload: payload)
164
+ micro_skel['signatures'] = signer(private_key, micro_skel['tosign'])
165
+ api_http_post('/txs/micro', json_payload: micro_skel)
166
+ end
167
+
168
+ ##################
169
+ # Address APIs
170
+ ##################
171
+
172
+ def address_generate
173
+ api_http_post('/addrs')
174
+ end
175
+
176
+ def address_generate_multi(pubkeys, script_type)
177
+ payload = { 'pubkeys' => pubkeys, 'script_type' => script_type}
178
+ api_http_post('/addrs', json_payload: payload)
179
+ end
180
+
181
+ def address_details(address, unspent_only: false)
182
+ api_http_get('/addrs/' + address, query: { unspentOnly: unspent_only } )
183
+ end
184
+
185
+ def address_balance(address)
186
+ api_http_get('/addrs/' + address + '/balance')
187
+ end
188
+
189
+ def address_final_balance(address)
190
+ details = address_balance(address)
191
+ details['final_balance']
192
+ end
193
+
194
+ def address_full_txs(address, limit: 10)
195
+ api_http_get("/addrs/#{address}/full", query: { limit: limit })
196
+ end
197
+
198
+ ##################
199
+ # Wallet API
200
+ ##################
201
+
202
+ def wallet_create(name, addresses)
203
+ payload = { 'name' => name, 'addresses' => Array(addresses)}
204
+ api_http_post('/wallets', json_payload: payload)
205
+ end
206
+
207
+ def wallet_get(name)
208
+ api_http_get('/wallets/' + name)
209
+ end
210
+
211
+ def wallet_add_addr(name, addresses)
212
+ payload = { 'addresses' => Array(addresses)}
213
+ api_http_post('/wallets/' + name + '/addresses', json_payload: payload)
214
+ end
215
+
216
+ def wallet_get_addr(name)
217
+ api_http_get('/wallets/' + name + '/addresses')
218
+ end
219
+
220
+ def wallet_delete_addr(name, addresses)
221
+ addrjoin = addresses.join(";")
222
+ api_http_delete('/wallets/' + name + '/addresses', query: { address: addrjoin})
223
+ end
224
+
225
+ def wallet_gen_addr(name)
226
+ api_http_post('/wallets/' + name + '/addresses/generate')
227
+ end
228
+
229
+ def wallet_delete(name)
230
+ api_http_delete('/wallets/' + name)
231
+ end
232
+
233
+ ##################
234
+ # Events API
235
+ ##################
236
+
237
+ def event_webhook_subscribe(url, event, confirmations: nil, hash:nil, address:nil, script:nil)
238
+ payload = {
239
+ url: url,
240
+ event: event,
241
+ }
242
+ payload[:address] = address if address
243
+ payload[:hash] = hash if hash
244
+ payload[:script] = script if script
245
+ payload[:confirmations] = confirmations if confirmations
246
+ api_http_post('/hooks', json_payload: payload)
247
+ end
248
+
249
+ def event_webhook_listall
250
+ api_http_get('/hooks')
251
+ end
252
+
253
+ def event_webhook_get(id)
254
+ api_http_get('/hooks/' + id)
255
+ end
256
+
257
+ def event_webhook_delete(id)
258
+ api_http_delete('/hooks/' + id)
259
+ end
260
+
261
+ ##################
262
+ # Payments and Forwarding API
263
+ ##################
264
+
265
+ def create_forwarding_address(destination, callback_url: nil, enable_confirmations: false)
266
+ payload = {
267
+ destination: destination,
268
+ callback_url: callback_url,
269
+ enable_confirmations: enable_confirmations
270
+ }
271
+ api_http_post('/payments', json_payload: payload)
272
+ end
273
+
274
+ alias :create_payments_forwarding :create_forwarding_address
275
+
276
+ def list_forwarding_addresses
277
+ api_http_get("/payments")
278
+ end
279
+
280
+ def delete_forwarding_address(id)
281
+ api_http_delete("/payments/" + id)
282
+ end
283
+
284
+ private
285
+
286
+ def api_http_call(http_method, api_path, query, json_payload: nil)
287
+ uri = endpoint_uri(api_path, query)
288
+
289
+ # Build the connection
290
+ http = Net::HTTP.new(uri.host, uri.port)
291
+ http.use_ssl = true
292
+
293
+ # Build the Request
294
+ if http_method == :post
295
+ request = Net::HTTP::Post.new(uri.request_uri)
296
+ elsif http_method == :get
297
+ request = Net::HTTP::Get.new(uri.request_uri)
298
+ elsif http_method == :delete
299
+ request = Net::HTTP::Delete.new(uri.request_uri)
300
+ else
301
+ raise 'Invalid HTTP method'
302
+ end
303
+
304
+ unless json_payload.nil?
305
+ request.content_type = 'application/json'
306
+ request.body = json_payload.to_json
307
+ end
308
+
309
+ response = http.request(request)
310
+
311
+ # Detect errors/return 204 empty body
312
+ if response.code == '400'
313
+ raise Error.new(uri.to_s + ' Response:' + response.body)
314
+ elsif response.code == '204'
315
+ return nil
316
+ end
317
+
318
+ # Process the response
319
+ begin
320
+ json_response = JSON.parse(response.body)
321
+ return json_response
322
+ rescue => e
323
+ raise "Unable to parse JSON response #{e.inspect}, #{response.body}"
324
+ end
325
+ end
326
+
327
+ def api_http_get(api_path, query: {})
328
+ api_http_call(:get, api_path, query)
329
+ end
330
+
331
+ def api_http_post(api_path, json_payload: nil, query: {})
332
+ api_http_call(:post, api_path, query, json_payload: json_payload)
333
+ end
334
+
335
+ def api_http_delete(api_path, query: {})
336
+ api_http_call(:delete, api_path, query)
337
+ end
338
+
339
+ def endpoint_uri(api_path, query)
340
+ uri = URI("https://api.blockcypher.com/#{@version}/#{@currency}/#{@network}#{api_path}")
341
+ query[:token] = api_token if api_token
342
+ uri.query = URI.encode_www_form(query) unless query.empty?
343
+ uri
344
+ end
345
+ end
346
+ end
@@ -0,0 +1,103 @@
1
+ require 'blockcypher'
2
+
3
+ module BlockCypher
4
+
5
+ describe Api do
6
+ let(:api) { BlockCypher::Api.new(currency: BlockCypher::BTC, network: BlockCypher::TEST_NET_3, version: BlockCypher::V1) }
7
+
8
+ let(:address_1) { 'miB9s4fcYCEBxPQm8vw6UrsYc2iSiEW3Yn' }
9
+ let(:address_1_private_key) { 'f2a73451a726e81aec76a2bfd5a4393a89822b30cc4cddb2b4317efb2266ad47' }
10
+
11
+ let(:address_2) { 'mnTBb2Fd13pKwNjFQz9LVoy2bqmDugLM5m' }
12
+ let(:address_2_private_key) { '76a32c1e5b6f9e174719e7c1b555d6a55674fdc2fd99cfeee96a5de632775645' }
13
+
14
+ context '#transaction_new' do
15
+
16
+ it 'should call the txs/new api' do
17
+ input_addresses = [address_1]
18
+ output_addresses = [address_2]
19
+ satoshi_value = 20000
20
+ res = api.transaction_new(input_addresses, output_addresses, satoshi_value)
21
+ expect(res["tx"]["hash"]).to be_a(String)
22
+ expect(res["tx"]["hash"].length).to be(64)
23
+ end
24
+ end
25
+
26
+ context '#transaction_sign_and_send' do
27
+
28
+ it 'should call txs/send api' do
29
+
30
+ input_addresses = [address_2]
31
+ output_addresses = [address_1]
32
+ satoshi_value = 10000
33
+
34
+ new_tx = api.transaction_new(input_addresses, output_addresses, satoshi_value)
35
+ res = api.transaction_sign_and_send(new_tx, address_2_private_key)
36
+ expect(res["tx"]["hash"]).to be_a(String)
37
+ expect(res["tx"]["hash"].length).to be(64)
38
+ end
39
+
40
+ end
41
+
42
+ context '#address_final_balance' do
43
+
44
+ it 'should get the balance of an address' do
45
+ balance = api.address_final_balance(address_1)
46
+ expect(balance).to be_kind_of Integer
47
+ expect(balance).to be > 0
48
+ end
49
+
50
+ end
51
+
52
+ context '#create_forwarding_address' do
53
+
54
+ it 'creates a payment forward' do
55
+ forward_details = api.create_forwarding_address(address_1, "foo")
56
+ expect(forward_details["input_address"]).to be_a(String)
57
+ expect(forward_details["input_address"].length).to be(34) # Ok this isn't strictly true but..
58
+ end
59
+
60
+ it 'allows creating a payment forward with a callback' do
61
+ forward_details = api.create_forwarding_address(address_1, "foo", callback_url: "http://test.com/foo")
62
+ expect(forward_details["callback_url"]).to eql("http://test.com/foo")
63
+ expect(forward_details["enable_confirmations"]).to be nil
64
+ end
65
+
66
+ it 'allows creating a payment forward with a callback and confirmation notifications enabled' do
67
+ forward_details = api.create_forwarding_address(address_1, "foo", callback_url: "http://test.com/foo", enable_confirmations: true)
68
+ expect(forward_details["callback_url"]).to eql("http://test.com/foo")
69
+ expect(forward_details["enable_confirmations"]).to be true
70
+ end
71
+
72
+ it 'is possible to use the alias create_payments_forwarding' do
73
+ forward_details = api.create_payments_forwarding(address_1, "foo")
74
+ expect(forward_details["input_address"]).to be_a(String)
75
+ end
76
+
77
+ end
78
+
79
+ context '#list_forwarding_addresses' do
80
+
81
+ it 'lists all forwading addresses created for a given token' do
82
+ forwarding_addresses = api.list_forwarding_addresses("foo")
83
+ expect(forwarding_addresses.first["destination"]).to eql(address_1)
84
+ end
85
+
86
+ end
87
+
88
+ describe '#endpoint_uri' do
89
+ it 'should encode query into URI' do
90
+ uri = api.send(:endpoint_uri, '/path', { test: 42 }).to_s
91
+ expect(uri).to match(/\?test=42/)
92
+ end
93
+
94
+ it 'should encode @api_token into URI if exists' do
95
+ allow(api).to receive(:api_token) { 'token' }
96
+ uri = api.send(:endpoint_uri, '/path', {}).to_s
97
+ expect(uri).to match(/\?token=token/)
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blockcypher-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - CoinHako
8
+ - BlockCypher
9
+ - meXBT
10
+ - Gem
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2015-06-23 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bitcoin-ruby
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 0.0.5
30
+ - !ruby/object:Gem::Dependency
31
+ name: ffi
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: bundler
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.6'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.6'
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: rspec
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ description: Ruby library to help you build your crypto application on BlockCypher
87
+ email: contact@blockcypher.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - LICENSE
93
+ - README.md
94
+ - lib/blockcypher.rb
95
+ - lib/blockcypher/api.rb
96
+ - spec/blockcypher/api_spec.rb
97
+ homepage: http://www.blockcypher.com
98
+ licenses:
99
+ - Apache 2.0
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.4.5
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Ruby library to help you build your crypto application on BlockCypher
121
+ test_files: []