blzrb 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +105 -0
- data/LICENSE.txt +21 -0
- data/README.md +56 -0
- data/Rakefile +6 -0
- data/bluzelle.gemspec +36 -0
- data/examples/main.rb +153 -0
- data/lib/bluzelle.rb +8 -0
- data/lib/bluzelle/constants.rb +12 -0
- data/lib/bluzelle/error.rb +14 -0
- data/lib/bluzelle/swarm/client.rb +442 -0
- data/lib/bluzelle/swarm/cosmos.rb +209 -0
- data/lib/bluzelle/swarm/request.rb +50 -0
- data/lib/bluzelle/swarm/transaction.rb +32 -0
- data/lib/bluzelle/utils.rb +185 -0
- data/lib/bluzelle/version.rb +3 -0
- metadata +151 -0
data/lib/bluzelle.rb
ADDED
@@ -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
|