1+
2+
3+ module BlockCypher
4+
5+ V1 = 'v1'
6+
7+ BTC = 'btc'
8+ LTC = 'ltc'
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+ def initialize ( version : V1 , currency : BTC , network : MAIN_NET )
19+ @version = version
20+ @currency = currency
21+ @network = network
22+ end
23+
24+ ##################
25+ # Blockchain API
26+ ##################
27+
28+ def blockchain_transaction ( transaction_hash )
29+ api_http_get ( '/txs/' + transaction_hash )
30+ end
31+
32+ def blockchain_block ( block_index )
33+ api_http_get ( '/blocks/' + block_index )
34+ end
35+
36+ ##################
37+ # Transaction API
38+ ##################
39+
40+ def send_money ( from_address , to_address , satoshi_amount , private_key )
41+
42+ unless to_address . kind_of? Array
43+ to_address = [ to_address ]
44+ end
45+
46+ tx_new = transaction_new ( [ from_address ] , to_address , satoshi_amount )
47+
48+ transaction_sign_and_send ( tx_new , private_key )
49+ end
50+
51+ def transaction_new ( input_addreses , output_addresses , satoshi_amount )
52+ payload = {
53+ 'inputs' => [
54+ {
55+ addresses : input_addreses
56+ }
57+ ] ,
58+ 'outputs' => [
59+ {
60+ addresses : output_addresses ,
61+ value : satoshi_amount
62+ }
63+ ]
64+ }
65+ api_http_post ( '/txs/new' , json_payload : payload . to_json )
66+ end
67+
68+ def transaction_sign_and_send ( new_tx , private_key )
69+ key = Bitcoin ::Key . new ( private_key , nil , compressed = true )
70+ public_key = key . pub
71+ signatures = [ ]
72+ public_keys = [ ]
73+
74+ new_tx [ 'tosign' ] . each do |to_sign_hex |
75+ public_keys << public_key
76+ to_sign_binary = [ to_sign_hex ] . pack ( "H*" )
77+ sig_binary = key . sign ( to_sign_binary )
78+ sig_hex = sig_binary . unpack ( "H*" ) . first
79+ signatures << sig_hex
80+ end
81+ new_tx [ 'signatures' ] = signatures
82+ new_tx [ 'pubkeys' ] = public_keys
83+
84+ res = api_http_post ( '/txs/send' , json_payload : new_tx . to_json )
85+
86+ res
87+ end
88+
89+ ##################
90+ # Address APIs
91+ ##################
92+
93+ def address_generate
94+ api_http_post ( '/addrs' )
95+ end
96+
97+ def address_details ( address )
98+ api_http_get ( '/addrs/' + address )
99+ end
100+
101+ def address_final_balance ( address )
102+ details = address_details ( address )
103+ details [ 'final_balance' ]
104+
105+ end
106+
107+ ##################
108+ # Events API
109+ ##################
110+
111+ def event_webhook_subscribe ( url , filter , token = nil )
112+ payload = {
113+ url : url ,
114+ filter : filter ,
115+ token : token
116+ } . to_json
117+ api_http_post ( '/hooks' , json_payload : payload )
118+ end
119+
120+ private
121+
122+ def api_http_call ( http_method , api_path , json_payload : nil )
123+ uri = endpoint_uri ( api_path )
124+
125+ # Build the connection
126+ http = Net ::HTTP . new ( uri . host , uri . port )
127+ http . use_ssl = true
128+
129+ # Build the Request
130+ if http_method == :post
131+ request = Net ::HTTP ::Post . new ( uri . request_uri )
132+ elsif http_method == :get
133+ request = Net ::HTTP ::Get . new ( uri . request_uri )
134+ else
135+ raise 'Invalid HTTP method'
136+ end
137+
138+ unless json_payload . nil?
139+ request . content_type = 'application/json'
140+ request . body = json_payload
141+ end
142+
143+ response = http . request ( request )
144+
145+ # Detect errors
146+ if response . code == '400'
147+ raise Error . new ( uri . to_s + ' Response:' + response . body )
148+ end
149+
150+ # Process the response
151+ begin
152+ json_response = JSON . parse ( response . body )
153+ return json_response
154+ rescue => e
155+ raise "Unable to parse JSON response #{ e . inspect } , #{ response . body } "
156+ end
157+ end
158+
159+ def api_http_get ( api_path )
160+ api_http_call :get , api_path
161+ end
162+
163+ def api_http_post ( api_path , json_payload : nil )
164+ api_http_call :post , api_path , json_payload : json_payload
165+ end
166+
167+ def endpoint_uri ( api_path )
168+ if api_path [ 0 ] != '/'
169+ api_path += '/' + api_path
170+ end
171+ URI ( 'https://api.blockcypher.com/' + @version + '/' + @currency + '/' + @network + api_path )
172+ end
173+
174+ end
175+ end
0 commit comments