blzrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ require "bluzelle/constants"
2
+ require "bluzelle/error"
3
+ require "bluzelle/swarm/transaction"
4
+ require "bluzelle/swarm/request"
5
+ require "bluzelle/swarm/cosmos"
6
+ require "bluzelle/swarm/client"
7
+ require "bluzelle/utils"
8
+ require "bluzelle/version"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bluzelle
4
+ module Constants
5
+ PREFIX = 'bluzelle'
6
+ PATH = "m/44'/118'/0'/0/0"
7
+ TOKEN_NAME = 'ubnt'
8
+ TX_COMMAND = 'txs'
9
+ BROADCAST_RETRY_SECONDS = 1
10
+ BLOCK_TIME_IN_SECONDS = 5
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bluzelle
4
+ module Error
5
+ class Error < StandardError
6
+ def initialize(msg = 'Error occurred')
7
+ super(msg)
8
+ end
9
+ end
10
+
11
+ class ApiError < Error
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,442 @@
1
+ # frozen_string_literal: true
2
+ require 'bluzelle/utils'
3
+ require 'bluzelle/constants'
4
+
5
+ module Bluzelle
6
+ module Swarm
7
+ class Client
8
+ include Bluzelle::Constants
9
+ include Bluzelle::Utils
10
+
11
+ attr_reader :address, :mnemonic, :uuid, :chain_id, :endpoint, :app_service
12
+ attr_reader :cosmos
13
+
14
+ # Creates a new Bluzelle connection.
15
+
16
+ # @param options [Hash]
17
+ # @return [Bluzelle::Swarm::Client]
18
+ def initialize(options = {})
19
+ options = stringify_keys(options)
20
+
21
+ validate_string(options['mnemonic'], 'Mnemonic must be a string.')
22
+ validate_string(options['uuid'], 'UUID must be a string.')
23
+
24
+ @mnemonic = options['mnemonic']
25
+ @uuid = options['uuid']
26
+ @chain_id = options['chain_id'] || 'bluzelle'
27
+ @endpoint = options['endpoint'] || 'http://localhost:1317'
28
+ @app_service = 'crud'
29
+
30
+ @cosmos = Cosmos.new(
31
+ mnemonic: @mnemonic,
32
+ endpoint: @endpoint,
33
+ chain_id: @chain_id
34
+ )
35
+
36
+ @address = @cosmos.address
37
+ end
38
+
39
+ # Create a field in the database
40
+ #
41
+ # @param [String] key The name of the key to create
42
+ # @param [String] value The string value to set the key
43
+ # @param [Hash] gas_info Hash containing gas parameters
44
+ # @param [Hash] lease_info Minimum time for key to remain in database
45
+ #
46
+ # @return [void]
47
+ def create(key, value, gas_info, lease_info = nil)
48
+ validate_string(key, 'key must be a string')
49
+ validate_string(value, 'value must be a string')
50
+
51
+ lease = convert_lease(lease_info)
52
+
53
+ validate_lease(lease, 'invalid lease time')
54
+
55
+ @cosmos.send_transaction(
56
+ 'post',
57
+ "#{@app_service}/create",
58
+ build_params({ 'Key' => key, 'Value' => value, 'Lease' => lease }),
59
+ gas_info
60
+ )
61
+ end
62
+
63
+ # Update a field in the database
64
+ #
65
+ # @param [String] key The name of the key to update
66
+ # @param [String] value The string value to set the key
67
+ # @param [Hash] gas_info Hash containing gas parameters
68
+ # @param [Hash] lease_info Minimum time for key to remain in database
69
+ #
70
+ # @return [void]
71
+ def update(key, value, gas_info, lease_info = nil)
72
+ validate_string(key, 'Key must be a string')
73
+ validate_string(value, 'Value must be a string')
74
+
75
+ lease = convert_lease(lease_info)
76
+
77
+ validate_lease(lease, 'invalid lease time')
78
+
79
+ @cosmos.send_transaction(
80
+ 'post',
81
+ "#{@app_service}/update",
82
+ build_params({ Key: key, Value: value, Lease: lease }),
83
+ gas_info
84
+ )
85
+ end
86
+
87
+ # Retrieve the value of a key without consensus verification
88
+ #
89
+ # @param [String] key The key to retrieve
90
+ # @param [Boolean] prove
91
+ #
92
+ # @return [String] String value of the key
93
+ def read(key, prove = false)
94
+ validate_string(key, 'Key must be a string')
95
+
96
+ path = prove ? 'pread' : 'read'
97
+ url = "#{@app_service}/#{path}/#{@uuid}/#{key}"
98
+
99
+ @cosmos.query(url)
100
+ .dig('result', 'value')
101
+ end
102
+
103
+ # Retrieve the value of a key via a transaction (i.e uses consensus)
104
+ #
105
+ # @param [String] key The key to retrieve
106
+ # @param [Hash] gas_info Hash containing gas parameters
107
+ #
108
+ # @return [String] String value of the key
109
+ def tx_read(key, gas_info)
110
+ validate_string(key, 'Key must be a string')
111
+
112
+ @cosmos.send_transaction(
113
+ 'post',
114
+ "#{@app_service}/read",
115
+ build_params({ Key: key }),
116
+ gas_info
117
+ ).dig('value')
118
+ end
119
+
120
+ # Delete a field from the database
121
+ #
122
+ # @param [String] key The name of the key to delete
123
+ # @param [Hash] gas_info Hash containing gas parameters
124
+ #
125
+ # @return [void]
126
+ def delete(key, gas_info)
127
+ validate_string(key, 'Key must be a string')
128
+
129
+ @cosmos.send_transaction(
130
+ 'delete',
131
+ "#{@app_service}/delete",
132
+ build_params({ Key: key }),
133
+ gas_info
134
+ )
135
+ end
136
+
137
+ # Query to see if a key is in the database. This function bypasses
138
+ # the consensus and cryptography mechanisms in favour of speed.
139
+ #
140
+ # @param [String] key The name of the key to query
141
+ #
142
+ # @return [Boolean]
143
+ def has(key)
144
+ validate_string(key, 'Key must be a string')
145
+
146
+ @cosmos.query("#{@app_service}/has/#{@uuid}/#{key}")
147
+ .dig('result', 'has')
148
+ end
149
+
150
+ # Query to see if a key is in the database via a transaction (i.e uses consensus)
151
+ #
152
+ # @param [String] key The name of the key to query
153
+ # @param [Hash] gas_info Hash containing gas parameters
154
+ #
155
+ # @return [Boolean]
156
+ def tx_has(key, gas_info)
157
+ validate_string(key, 'Key must be a string')
158
+
159
+ @cosmos.send_transaction(
160
+ 'post',
161
+ "#{@app_service}/has",
162
+ build_params({ Key: key }),
163
+ gas_info
164
+ ).dig('has')
165
+ end
166
+
167
+ # Retrieve a list of all keys. This function bypasses the consensus
168
+ # and cryptography mechanisms in favour of speed.
169
+ #
170
+ # @return [Array]
171
+ def keys
172
+ @cosmos.query("#{@app_service}/keys/#{@uuid}")
173
+ .dig('result', 'keys') || []
174
+ end
175
+
176
+ # Retrieve a list of all keys via a transaction (i.e use consensus)
177
+ #
178
+ # @param [Hash] gas_info Hash containing gas parameters
179
+ #
180
+ # @return [Array]
181
+ def tx_keys(gas_info)
182
+ @cosmos.send_transaction(
183
+ 'post',
184
+ "#{@app_service}/keys",
185
+ build_params({}),
186
+ gas_info
187
+ ).dig('keys') || []
188
+ end
189
+
190
+ # Change the name of an existing key
191
+ #
192
+ # @param [String] key
193
+ # @param [String] new_key
194
+ # @param [Hash] gas_info Hash containing gas parameters
195
+ #
196
+ # @return [void]
197
+ def rename(key, new_key, gas_info)
198
+ validate_string(key, 'key must be a string')
199
+ validate_string(new_key, 'new_key must be a string')
200
+
201
+ @cosmos.send_transaction(
202
+ 'post',
203
+ "#{@app_service}/rename",
204
+ build_params({ Key: key, NewKey: new_key }),
205
+ gas_info
206
+ )
207
+ end
208
+
209
+ # Retrieve the number of keys in the current database/uuid.
210
+ # This function bypasses the consensus and cryptography
211
+ # mechanisms in favor of speed
212
+ #
213
+ # @return [Integer]
214
+ def count
215
+ @cosmos.query("#{app_service}/count/#{@uuid}")
216
+ .dig('result', 'count')
217
+ end
218
+
219
+ # Retrieve the number of keys in the current database/uuid via a transaction
220
+ #
221
+ # @param [Hash] gas_info Hash containing gas parameters
222
+ #
223
+ # @return [Integer]
224
+ def tx_count(gas_info)
225
+ @cosmos.send_transaction(
226
+ 'post',
227
+ "#{@app_service}/count",
228
+ build_params({}),
229
+ gas_info
230
+ ).dig('count')
231
+ end
232
+
233
+ # Remove all keys in the current database/uuid
234
+ #
235
+ # @param [Hash] gas_info Hash containing gas parameters
236
+ #
237
+ # @return [void]
238
+ def delete_all(gas_info)
239
+ @cosmos.send_transaction(
240
+ 'post',
241
+ "#{@app_service}/deleteall",
242
+ build_params({}),
243
+ gas_info
244
+ )
245
+ end
246
+
247
+ # Enumerate all keys and values in the current database/uuid.
248
+ # This function bypasses the consensus and cryptography mechanisms in favor of speed
249
+ #
250
+ # @return [Array]
251
+ def key_values
252
+ @cosmos.query("#{app_service}/keyvalues/#{@uuid}")
253
+ .dig('result', 'keyvalues') || []
254
+ end
255
+
256
+ # Enumerate all keys and values in the current database/uuid via a transaction
257
+ #
258
+ # @param [Hash] gas_info Hash containing gas parameters
259
+ #
260
+ # @return [Array]
261
+ def tx_key_values(gas_info)
262
+ @cosmos.send_transaction(
263
+ 'post',
264
+ "#{@app_service}/keyvalues",
265
+ build_params({}),
266
+ gas_info
267
+ ).dig('keyvalues') || []
268
+ end
269
+
270
+ # Update multiple fields in the database
271
+ #
272
+ # @param [Array]
273
+ # @param [Hash] gas_info Hash containing gas parameters
274
+ def multi_update(key_values, gas_info)
275
+ validate_array(key_values, 'key_values must be an array')
276
+
277
+ key_values.each do |key_value|
278
+ validate_string(key_value.dig('key'), 'All keys must be strings')
279
+ validate_string(key_value.dig('value'), 'All values must be string')
280
+ end
281
+
282
+ @cosmos.send_transaction(
283
+ 'post',
284
+ "#{@app_service}/multiupdate",
285
+ build_params({ KeyValues: key_values }),
286
+ gas_info
287
+ )
288
+ end
289
+
290
+ # Retrieve the minimum time remaining on the lease for a key.
291
+ # This function bypasses the consensus and cryptography mechanisms in favor of speed
292
+ #
293
+ # @param [String] key
294
+ #
295
+ # @return [String]
296
+ def get_lease(key)
297
+ validate_string(key, 'key must be a string')
298
+
299
+ @cosmos.query("#{@app_service}/getlease/#{@uuid}/#{key}")
300
+ .dig('result', 'lease').to_i * BLOCK_TIME_IN_SECONDS
301
+ end
302
+
303
+ # Retrieve the minimum time remaining on the lease for a key, using a transaction
304
+ #
305
+ # @param [String] key The key to retrieve the lease information for
306
+ # @param [Hash] gas_info Hash containing gas parameters
307
+ #
308
+ # @return [String]
309
+ def tx_get_lease(key, gas_info)
310
+ validate_string(key, 'key must be a string')
311
+
312
+ @cosmos.send_transaction(
313
+ 'post',
314
+ "#{@app_service}/getlease",
315
+ build_params({ Key: key }),
316
+ gas_info
317
+ ).dig('lease').to_i * BLOCK_TIME_IN_SECONDS
318
+ end
319
+
320
+ # Update the minimum time remaining on the lease for a key
321
+ #
322
+ # @param [String] key The key to retrieve the lease information for
323
+ # @param [Hash] gas_info Hash containing gas parameters
324
+ # @param [Hash] lease Minimum time for key to remain in database
325
+ def renew_lease(key, lease, gas_info)
326
+ validate_string(key, 'key must be a string')
327
+
328
+ lease = convert_lease(lease)
329
+
330
+ validate_lease(lease, 'invalid lease time')
331
+
332
+ @cosmos.send_transaction(
333
+ 'post',
334
+ "#{@app_service}/renewlease",
335
+ build_params({ Key: key, Lease: lease }),
336
+ gas_info
337
+ )
338
+ end
339
+
340
+ # Update the minimum time remaining on the lease for all keys
341
+ #
342
+ # @param [Hash] gas_info Hash containing gas parameters
343
+ # @param [Hash] lease Minimum time for key to remain in database
344
+ def renew_lease_all(lease, gas_info)
345
+ lease = convert_lease(lease)
346
+
347
+ validate_lease(lease, 'invalid lease time')
348
+
349
+ @cosmos.send_transaction(
350
+ 'post',
351
+ "#{@app_service}/renewleaseall",
352
+ build_params({ Lease: lease }),
353
+ gas_info
354
+ )
355
+ end
356
+
357
+ # Retrieve a list of the n keys in the database with the shortest leases.
358
+ # This function bypasses the consensus and cryptography mechanisms in favor of speed
359
+ #
360
+ # @param [Integer] n The number of keys to retrieve the lease information for
361
+ #
362
+ # @return [Array]
363
+ def get_n_shortest_leases(n)
364
+ validate_lease(n, 'invalid value specified')
365
+
366
+ @cosmos.query("#{@app_service}/getnshortestleases/#{@uuid}/#{n}")
367
+ .dig('result', 'keyleases')
368
+ .map do |key_lease|
369
+ {
370
+ 'key' => key_lease['key'],
371
+ 'lease' => key_lease['lease'].to_i * BLOCK_TIME_IN_SECONDS
372
+ }
373
+ end
374
+ end
375
+
376
+ # Retrieve a list of the N keys/values in the database with the shortest leases,
377
+ # using a transaction
378
+ #
379
+ # @param [Integer] n The number of keys to retrieve the lease information for
380
+ # @param [Hash] gas_info Hash containing lize(options = {})gas parameters
381
+ #
382
+ # @return [Array]
383
+ def tx_get_n_shortest_leases(n, gas_info)
384
+ validate_lease(n, 'invalid value specified')
385
+
386
+ @cosmos.send_transaction(
387
+ 'post',
388
+ "#{@app_service}/getnshortestleases",
389
+ build_params({ N: n.to_s }),
390
+ gas_info
391
+ ).dig('keyleases')
392
+ .map do |key_lease|
393
+ {
394
+ 'key' => key_lease['key'],
395
+ 'lease' => key_lease['lease'].to_i * BLOCK_TIME_IN_SECONDS
396
+ }
397
+ end
398
+ end
399
+
400
+ # Retrieve information about the currently active Bluzelle account
401
+ #
402
+ # @return [Hash]
403
+ def account
404
+ @cosmos.query("auth/accounts/#{@address}")
405
+ .dig('result', 'value')
406
+ end
407
+
408
+ # Retrieve the version of the Bluzelle service
409
+ #
410
+ # @return [String]
411
+ def version
412
+ @cosmos.query('node_info')
413
+ .dig('application_version', 'version')
414
+ end
415
+
416
+ private
417
+
418
+ def validate_array(arg, msg)
419
+ raise ArgumentError, msg unless arg.is_a?(Array)
420
+ end
421
+
422
+ def validate_string(arg, msg)
423
+ raise ArgumentError, msg unless arg.is_a?(String)
424
+ end
425
+
426
+ def validate_lease(arg, msg)
427
+ raise ArgumentError, msg if arg.is_a?(Integer) && arg.negative?
428
+ end
429
+
430
+ def build_params(params)
431
+ {
432
+ 'BaseReq' => {
433
+ 'chain_id' => @chain_id,
434
+ 'from' => @address
435
+ },
436
+ 'Owner' => @address,
437
+ 'UUID' => @uuid
438
+ }.merge(params)
439
+ end
440
+ end
441
+ end
442
+ end