blockchain 2.0.0 → 3.0.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 +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
data/lib/blockchain.rb
CHANGED
@@ -1,80 +1,169 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
response = Blockchain::call_api(resource, method: 'get', data: params)
|
10
|
-
return Block.new(JSON.parse(response))
|
11
|
-
end
|
6
|
+
MAX_TRANSACTIONS_PER_REQUEST = 50
|
7
|
+
MAX_TRANSACTIONS_PER_MULTI_REQUEST = 100
|
8
|
+
DEFAULT_UNSPENT_TRANSACTIONS_PER_REQUEST = 250
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
class BlockExplorer
|
11
|
+
|
12
|
+
attr_reader :client
|
13
|
+
|
14
|
+
def initialize(base_url = nil, api_code = nil)
|
15
|
+
@client = Client.new(base_url, api_code)
|
16
|
+
end
|
17
|
+
|
18
|
+
def proxy(method_name, *args)
|
19
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of BlockExplorer class instead."
|
20
|
+
send(method_name, *args)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Deprecated. Please use get_block_by_hash whenever possible.
|
24
|
+
def get_block_by_index(index)
|
25
|
+
warn "[DEPRECATED] `get_block_by_index` is deprecated. Please use `get_block_by_hash` whenever possible."
|
26
|
+
return get_block(index.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_block_by_hash(block_hash)
|
30
|
+
return get_block(block_hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Deprecated. Please use get_tx_by_hash whenever possible.
|
34
|
+
def get_tx_by_index(tx_index)
|
35
|
+
warn "[DEPRECATED] `get_tx_by_index` is deprecated. Please use `get_tx_by_hash` whenever possible."
|
36
|
+
return get_tx(tx_index.to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_tx_by_hash(tx_hash)
|
40
|
+
return get_tx(tx_hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_block_height(height)
|
44
|
+
params = { 'format' => 'json' }
|
45
|
+
resource = "block-height/#{height}"
|
46
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
47
|
+
return JSON.parse(response)['blocks'].map{ |b| Block.new(b) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_address_by_hash160(address, limit = MAX_TRANSACTIONS_PER_REQUEST,
|
51
|
+
offset = 0, filter = FilterType::REMOVE_UNSPENDABLE)
|
52
|
+
return get_address(address, limit, offset, filter)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_address_by_base58(address, limit = MAX_TRANSACTIONS_PER_REQUEST,
|
56
|
+
offset = 0, filter = FilterType::REMOVE_UNSPENDABLE)
|
57
|
+
return get_address(address, limit, offset, filter)
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_xpub(xpub, limit = MAX_TRANSACTIONS_PER_MULTI_REQUEST,
|
61
|
+
offset = 0, filter = FilterType::REMOVE_UNSPENDABLE)
|
62
|
+
params = { 'active' => xpub, 'format' => 'json', 'limit' => limit, 'offset' => offset, 'filter' => filter }
|
63
|
+
resource = 'multiaddr'
|
64
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
65
|
+
return Xpub.new(JSON.parse(response))
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_multi_address(address_array, limit = MAX_TRANSACTIONS_PER_MULTI_REQUEST,
|
69
|
+
offset = 0, filter = FilterType::REMOVE_UNSPENDABLE)
|
70
|
+
params = { 'active' => address_array.join("|"), 'format' => 'json', 'limit' => limit, 'offset' => offset, 'filter' => filter }
|
71
|
+
resource = 'multiaddr'
|
72
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
73
|
+
return MultiAddress.new(JSON.parse(response))
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_unspent_outputs(address_array,
|
77
|
+
limit = DEFAULT_UNSPENT_TRANSACTIONS_PER_REQUEST,
|
78
|
+
confirmations = 0)
|
79
|
+
params = { 'active' => address_array.join("|"), 'limit' => limit, 'confirmations' => confirmations }
|
80
|
+
resource = 'unspent'
|
81
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
82
|
+
return JSON.parse(response)['unspent_outputs'].map{ |o| UnspentOutput.new(o) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_latest_block()
|
86
|
+
resource = 'latestblock'
|
87
|
+
response = @client.call_api(resource, method: 'get')
|
88
|
+
return LatestBlock.new(JSON.parse(response))
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_unconfirmed_tx()
|
92
|
+
params = { 'format' => 'json' }
|
93
|
+
resource = 'unconfirmed-transactions'
|
94
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
95
|
+
return JSON.parse(response)['txs'].map{ |t| Transaction.new(t) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_blocks(time = nil, pool_name = nil)
|
99
|
+
params = { 'format' => 'json' }
|
100
|
+
resource = "blocks/"
|
101
|
+
if !time.nil?
|
102
|
+
resource += time.to_s
|
103
|
+
elsif !pool_name.nil?
|
104
|
+
resource += pool_name
|
105
|
+
end
|
106
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
107
|
+
return JSON.parse(response)['blocks'].map{ |b| SimpleBlock.new(b) }
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def get_block(hash_or_index)
|
112
|
+
resource = 'rawblock/' + hash_or_index
|
113
|
+
response = @client.call_api(resource, method: 'get')
|
114
|
+
return Block.new(JSON.parse(response))
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def get_tx(hash_or_index)
|
119
|
+
resource = 'rawtx/' + hash_or_index
|
120
|
+
response = @client.call_api(resource, method: 'get')
|
121
|
+
return Transaction.new(JSON.parse(response))
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def get_address(address, limit = MAX_TRANSACTIONS_PER_REQUEST,
|
126
|
+
offset = 0, filter = FilterType::REMOVE_UNSPENDABLE)
|
127
|
+
params = { 'format' => 'json', 'limit' => limit, 'offset' => offset, 'filter' => filter }
|
128
|
+
resource = 'rawaddr/' + address
|
129
|
+
response = @client.call_api(resource, method: 'get', data: params)
|
130
|
+
return Address.new(JSON.parse(response))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.get_block(hash_or_index, api_code = nil)
|
135
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, hash_or_index)
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.get_tx(hash_or_index, api_code = nil)
|
139
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, hash_or_index)
|
140
|
+
end
|
19
141
|
|
20
142
|
def self.get_block_height(height, api_code = nil)
|
21
|
-
|
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) }
|
143
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, height)
|
26
144
|
end
|
27
145
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
146
|
+
def self.get_address(address, api_code = nil,
|
147
|
+
limit = MAX_TRANSACTIONS_PER_REQUEST, offset = 0,
|
148
|
+
filter = FilterType::REMOVE_UNSPENDABLE)
|
149
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, address, limit, offset, filter)
|
150
|
+
end
|
34
151
|
|
35
|
-
def self.get_unspent_outputs(
|
36
|
-
|
37
|
-
|
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) }
|
152
|
+
def self.get_unspent_outputs(address_array, api_code = nil,
|
153
|
+
limit = DEFAULT_UNSPENT_TRANSACTIONS_PER_REQUEST, confirmations = 0)
|
154
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, limit, confirmations)
|
41
155
|
end
|
42
156
|
|
43
157
|
def self.get_unconfirmed_tx(api_code = nil)
|
44
|
-
|
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) }
|
158
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__)
|
49
159
|
end
|
50
160
|
|
51
161
|
def self.get_blocks(api_code = nil, time: nil, pool_name: nil)
|
52
|
-
|
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) }
|
162
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__, time, pool_name)
|
62
163
|
end
|
63
|
-
|
164
|
+
|
64
165
|
def self.get_latest_block(api_code = nil)
|
65
|
-
|
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))
|
166
|
+
Blockchain::BlockExplorer.new(nil, api_code).proxy(__method__)
|
78
167
|
end
|
79
168
|
|
80
169
|
class SimpleBlock
|
@@ -82,7 +171,7 @@ module Blockchain
|
|
82
171
|
attr_reader :hash
|
83
172
|
attr_reader :time
|
84
173
|
attr_reader :main_chain
|
85
|
-
|
174
|
+
|
86
175
|
def initialize(b)
|
87
176
|
@height = b['height']
|
88
177
|
@hash = b['hash']
|
@@ -97,7 +186,7 @@ module Blockchain
|
|
97
186
|
attr_reader :block_index
|
98
187
|
attr_reader :height
|
99
188
|
attr_reader :tx_indexes
|
100
|
-
|
189
|
+
|
101
190
|
def initialize(b)
|
102
191
|
@hash = b['hash']
|
103
192
|
@time = b['time']
|
@@ -115,7 +204,7 @@ module Blockchain
|
|
115
204
|
attr_reader :value
|
116
205
|
attr_reader :value_hex
|
117
206
|
attr_reader :confirmations
|
118
|
-
|
207
|
+
|
119
208
|
def initialize(o)
|
120
209
|
@tx_hash = o['tx_hash']
|
121
210
|
@tx_index = o['tx_index']
|
@@ -135,18 +224,48 @@ module Blockchain
|
|
135
224
|
attr_reader :total_sent
|
136
225
|
attr_reader :final_balance
|
137
226
|
attr_reader :transactions
|
138
|
-
|
227
|
+
|
139
228
|
def initialize(a)
|
140
|
-
@hash160 = a['hash160']
|
229
|
+
@hash160 = a['hash160'] == nil ? nil : a['hash160']
|
141
230
|
@address = a['address']
|
142
231
|
@n_tx = a['n_tx']
|
143
232
|
@total_received = a['total_received']
|
144
233
|
@total_sent = a['total_sent']
|
145
234
|
@final_balance = a['final_balance']
|
146
|
-
@transactions = a['txs'].map{ |tx| Transaction.new(tx) }
|
235
|
+
@transactions = a['txs'] == nil ? nil : a['txs'].map{ |tx| Transaction.new(tx) }
|
147
236
|
end
|
148
237
|
end
|
149
238
|
|
239
|
+
class MultiAddress
|
240
|
+
attr_reader :addresses
|
241
|
+
attr_reader :transactions
|
242
|
+
|
243
|
+
def initialize(ma)
|
244
|
+
@addresses = ma['addresses'].map{ |a| Address.new(a) }
|
245
|
+
@transactions = ma['txs'].map{ |tx| Transaction.new(tx) }
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
class Xpub < Address
|
250
|
+
attr_reader :change_index
|
251
|
+
attr_reader :account_index
|
252
|
+
attr_reader :gap_limit
|
253
|
+
|
254
|
+
def initialize(x)
|
255
|
+
addr = x['addresses'][0]
|
256
|
+
@change_index = addr['change_index']
|
257
|
+
@account_index = addr['account_index']
|
258
|
+
@gap_limit = addr['gap_limit']
|
259
|
+
@hash160 = addr['hash160'] == nil ? nil : addr['hash160']
|
260
|
+
@address = addr['address']
|
261
|
+
@n_tx = addr['n_tx']
|
262
|
+
@total_received = addr['total_received']
|
263
|
+
@total_sent = addr['total_sent']
|
264
|
+
@final_balance = addr['final_balance']
|
265
|
+
@transactions = addr['txs'] == nil ? nil : addr['txs'].map{ |tx| Transaction.new(tx) }
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
150
269
|
class Input
|
151
270
|
attr_reader :n
|
152
271
|
attr_reader :value
|
@@ -206,7 +325,7 @@ module Blockchain
|
|
206
325
|
attr_reader :size
|
207
326
|
attr_reader :inputs
|
208
327
|
attr_reader :outputs
|
209
|
-
|
328
|
+
|
210
329
|
def initialize(t)
|
211
330
|
@double_spend = t.fetch('double_spend', false)
|
212
331
|
@block_height = t.fetch('block_height', false)
|
@@ -218,18 +337,18 @@ module Blockchain
|
|
218
337
|
@size = t['size']
|
219
338
|
@inputs = t['inputs'].map{ |i| Input.new(i) }
|
220
339
|
@outputs = t['out'].map{ |o| Output.new(o) }
|
221
|
-
|
340
|
+
|
222
341
|
if @block_height.nil?
|
223
342
|
@block_height = -1
|
224
343
|
end
|
225
344
|
end
|
226
|
-
|
345
|
+
|
227
346
|
def adjust_block_height(h)
|
228
347
|
@block_height = h
|
229
348
|
end
|
230
349
|
end
|
231
350
|
|
232
|
-
|
351
|
+
|
233
352
|
class Block
|
234
353
|
attr_reader :hash
|
235
354
|
attr_reader :version
|
@@ -247,7 +366,7 @@ module Blockchain
|
|
247
366
|
attr_reader :received_time
|
248
367
|
attr_reader :relayed_by
|
249
368
|
attr_reader :transactions
|
250
|
-
|
369
|
+
|
251
370
|
def initialize(b)
|
252
371
|
@hash = b['hash']
|
253
372
|
@version = b['ver']
|
@@ -268,31 +387,16 @@ module Blockchain
|
|
268
387
|
@transactions.each do |tx|
|
269
388
|
tx.adjust_block_height(@height)
|
270
389
|
end
|
271
|
-
|
390
|
+
|
272
391
|
if @received_time.nil?
|
273
392
|
@received_time = @time
|
274
393
|
end
|
275
394
|
end
|
276
395
|
end
|
277
396
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
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
|
-
|
397
|
+
module FilterType
|
398
|
+
ALL = 4
|
399
|
+
CONFIRMED_ONLY = 5
|
400
|
+
REMOVE_UNSPENDABLE = 6
|
401
|
+
end
|
298
402
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Blockchain
|
4
|
+
|
5
|
+
DEFAULT_BASE_URL = 'https://blockchain.info/'
|
6
|
+
TIMEOUT_SECONDS = 10
|
7
|
+
|
8
|
+
class Client
|
9
|
+
|
10
|
+
attr_reader :base_url
|
11
|
+
attr_reader :api_code
|
12
|
+
|
13
|
+
def initialize(base_url = nil, api_code = nil)
|
14
|
+
@base_url = base_url.nil? ? DEFAULT_BASE_URL : base_url
|
15
|
+
@api_code = api_code
|
16
|
+
end
|
17
|
+
|
18
|
+
class APIException < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
def call_api(resource, method: 'get', data: nil)
|
22
|
+
url = URI.parse(@base_url + resource)
|
23
|
+
http = Net::HTTP.new(url.host, url.port)
|
24
|
+
http.use_ssl = @base_url.start_with? 'https://'
|
25
|
+
http.read_timeout = TIMEOUT_SECONDS
|
26
|
+
|
27
|
+
request = nil
|
28
|
+
if method == 'get'
|
29
|
+
url.query = data.nil? ? nil : URI.encode_www_form(data)
|
30
|
+
request = Net::HTTP::Get.new(url.request_uri)
|
31
|
+
elsif method == 'post'
|
32
|
+
request = Net::HTTP::Post.new(url.request_uri)
|
33
|
+
request.content_type = 'application/x-www-form-urlencoded'
|
34
|
+
if data != nil
|
35
|
+
then
|
36
|
+
if !@api_code.nil? then data['api_code'] = @api_code
|
37
|
+
end
|
38
|
+
request.set_form_data(data)
|
39
|
+
else
|
40
|
+
if
|
41
|
+
!@api_code.nil? then data = { 'api_code' => @api_code }
|
42
|
+
request.set_form_data(data)
|
43
|
+
else {}
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
response = http.request(request)
|
49
|
+
if response.code != '200'
|
50
|
+
raise APIException, response.body
|
51
|
+
end
|
52
|
+
return response.body
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -1,27 +1,42 @@
|
|
1
1
|
require 'json'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'client'
|
3
3
|
|
4
4
|
module Blockchain
|
5
5
|
|
6
|
-
|
6
|
+
DEFAULT_WALLET_URL = 'http://127.0.0.1:3000/'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
8
|
+
class WalletCreator
|
9
|
+
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
def initialize(base_url = DEFAULT_WALLET_URL, api_code)
|
13
|
+
@client = Client.new(base_url, api_code)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_wallet(password, priv: nil, label: nil, email: nil)
|
17
|
+
params = { 'password' => password }
|
18
|
+
|
19
|
+
if !priv.nil?
|
20
|
+
params['priv'] = priv
|
21
|
+
end
|
22
|
+
if !label.nil?
|
23
|
+
params['label'] = label
|
24
|
+
end
|
25
|
+
if !email.nil?
|
26
|
+
params['email'] = email
|
27
|
+
end
|
28
|
+
|
29
|
+
response = @client.call_api('api/v2/create', method: 'post', data: params)
|
30
|
+
json_response = JSON.parse(response)
|
31
|
+
return CreateWalletResponse.new(json_response['guid'],
|
32
|
+
json_response['address'],
|
33
|
+
json_response['label'])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.create_wallet(password, api_code, url, priv: nil, label: nil, email: nil)
|
38
|
+
warn "[DEPRECATED] avoid use of static methods, use an instance of WalletCreator class instead."
|
39
|
+
Blockchain::WalletCreator.new(url, api_code).create_wallet(password, priv, label, email)
|
25
40
|
end
|
26
41
|
|
27
42
|
class CreateWalletResponse
|