hive_sql 1.0.1 → 1.0.3

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.
data/Rakefile ADDED
@@ -0,0 +1,807 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require 'hive_sql'
4
+ require 'awesome_print'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ t.ruby_opts << if ENV['HELL_ENABLED']
11
+ '-W2'
12
+ else
13
+ '-W1'
14
+ end
15
+ end
16
+
17
+ task :default => :test
18
+
19
+ task :console do
20
+ exec "irb -r hive_sql -I ./lib"
21
+ end
22
+
23
+ namespace :created do
24
+ desc 'Lists accounts created grouped by creator and date.'
25
+ task :accounts, [:creator, :days_ago] do |t, args|
26
+ now = Time.now.utc
27
+ creator = args[:creator]
28
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
29
+
30
+ accounts = HiveSQL::Tx::AccountCreate.all
31
+
32
+ if !!creator || creator == '%'
33
+ unless creator == '%'
34
+ accounts = accounts.where(creator: creator)
35
+ end
36
+ elsif creator =~ /.*%.*/
37
+ accounts = accounts.where('creator LIKE ?', creator)
38
+ end
39
+
40
+ accounts = accounts.where('timestamp > ?', after_timestamp)
41
+ accounts = accounts.group('CAST(timestamp AS DATE)', :creator)
42
+ accounts = accounts.order('cast_timestamp_as_date ASC')
43
+
44
+ accounts = accounts.count
45
+ puts "# Daily creation count by #{creator.nil? ? 'all account creators' : creator} since #{after_timestamp} ..."
46
+ ap accounts
47
+ puts "# Total accounts: #{accounts.values.sum}"
48
+ end
49
+
50
+ desc 'Lists custom_json_operations grouped by id and date.'
51
+ task :custom_json, [:id, :days_ago, :min_count] do |t, args|
52
+ now = Time.now.utc
53
+ tid = args[:id]
54
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
55
+ min_count = (args[:min_count] || 1).to_i
56
+
57
+ customs = HiveSQL::Tx::Custom.all
58
+
59
+ if !!tid && tid != '%' && tid =~ /.*%.*/
60
+ customs = customs.where("tid LIKE ?", tid)
61
+ elsif !!tid && tid != '%'
62
+ customs = customs.where(tid: tid)
63
+ end
64
+
65
+ customs = customs.where('timestamp > ?', after_timestamp)
66
+ customs = customs.group('CAST(timestamp AS DATE)', :tid)
67
+ customs = customs.order('cast_timestamp_as_date ASC')
68
+
69
+ customs = customs.count
70
+
71
+ customs = customs.map do |k, v|
72
+ [k, v] if v >= min_count
73
+ end.compact.to_h
74
+
75
+ puts "# Daily creation count by #{tid.nil? ? 'all custom_json_operation' : tid} since #{after_timestamp} ..."
76
+ ap customs
77
+ puts "# Total custom_json_operation: #{customs.values.sum}"
78
+ end
79
+ end
80
+
81
+ namespace :deleted do
82
+ desc 'Lists comments deleted grouped by author and date.'
83
+ task :comments, [:author, :days_ago, :minimum_deletes] do |t, args|
84
+ now = Time.now.utc
85
+ author = args[:author]
86
+ after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
87
+ minimum_deletes = (args[:minimum_deletes] || '1').to_i
88
+
89
+ delete_comments = HiveSQL::Tx::DeleteComment.all
90
+
91
+ if !!author || author == '%'
92
+ unless author == '%'
93
+ delete_comments = delete_comments.where(author: author)
94
+ end
95
+ elsif author =~ /.*%.*/
96
+ delete_comments = delete_comments.where('author LIKE ?', author)
97
+ end
98
+
99
+ delete_comments = delete_comments.where('timestamp > ?', after_timestamp)
100
+ rewards = HiveSQL::Vo::AuthorReward.where(author: delete_comments.select(:author), permlink: delete_comments.select(:permlink))
101
+ delete_comments = delete_comments.group('CAST(timestamp AS DATE)', :author)
102
+ delete_comments = delete_comments.order('cast_timestamp_as_date ASC')
103
+
104
+ delete_comments = delete_comments.count
105
+
106
+ if minimum_deletes > 1
107
+ delete_comments = delete_comments.select{|k, v| v >= minimum_deletes}
108
+ end
109
+
110
+ puts "# Daily deleted comment count by #{author.nil? ? 'all account authors' : author} since #{after_timestamp} ..."
111
+ ap delete_comments
112
+ puts "# Total deleted comments: #{delete_comments.values.sum}"
113
+
114
+ puts "# Author reward impact:"
115
+ puts "# HBD: #{rewards.sum(:hbd_payout)}"
116
+ puts "# HIVE: #{rewards.sum(:hive_payout)}"
117
+ puts "# VESTS: #{rewards.sum(:vesting_payout)}"
118
+ end
119
+ end
120
+
121
+ desc 'Lists sum of transfers grouped by date, from, and to.'
122
+ task :transfers, [:minimum_amount, :symbol, :days_ago] do |t, args|
123
+ now = Time.now.utc
124
+ minimum_amount = (args[:minimum_amount] || '1000000').to_f
125
+ symbol = (args[:symbol] || 'HIVE').upcase
126
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
127
+
128
+ # Only type: transfer; ignore savings, vestings
129
+ transfers = HiveSQL::Tx::Transfer.where(type: 'transfer')
130
+ transfers = transfers.where('amount > ?', minimum_amount)
131
+ transfers = transfers.where('amount_symbol = ?', symbol)
132
+ transfers = transfers.where('timestamp > ?', after_timestamp)
133
+ transfers = transfers.group('CAST(timestamp AS DATE)', :from, :to)
134
+ transfers = transfers.order('cast_timestamp_as_date ASC')
135
+
136
+ puts "Daily transfer sum over #{'%.3f' % minimum_amount} #{symbol} since #{after_timestamp} ..."
137
+ ap transfers.sum(:amount)
138
+ end
139
+
140
+ desc 'Lists sum of powered up grouped by date, from, and to.'
141
+ task :powerup, [:minimum_amount, :symbol, :days_ago, :not_to_self] do |t, args|
142
+ now = Time.now.utc
143
+ minimum_amount = (args[:minimum_amount] || '500').to_f
144
+ symbol = (args[:symbol] || 'HIVE').upcase
145
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
146
+ not_to_self = (args[:not_to_self] || 'false') == 'true'
147
+
148
+ minimum_amount = case symbol
149
+ when 'MVESTS' then minimum_amount * 1e6 #TODO
150
+ when 'VESTS' then minimum_amount # TODO
151
+ when 'HIVE' then minimum_amount
152
+ else; raise "Unknown symbol: #{symbol}"
153
+ end
154
+
155
+ # Only type: transfer; ignore savings, vestings
156
+ transfers = HiveSQL::Tx::Transfer.where(type: 'transfer_to_vesting')
157
+ transfers = transfers.where('amount > ?', minimum_amount)
158
+ transfers = transfers.where('amount_symbol = ?', 'HIVE')
159
+ transfers = transfers.where('timestamp > ?', after_timestamp)
160
+ transfers = transfers.group('CAST(timestamp AS DATE)', :from, :to)
161
+ transfers = transfers.order('cast_timestamp_as_date ASC')
162
+
163
+ transfers = transfers.sum(:amount)
164
+
165
+ if not_to_self
166
+ transfers = transfers.map do |k, v|
167
+ [k, v] if k[1] != k[2]
168
+ end.compact.to_h
169
+ end
170
+
171
+ puts "# Daily transfer sum over #{'%.3f' % minimum_amount} #{symbol} #{not_to_self ? '' : 'not to self '}since #{after_timestamp} ..."
172
+ ap transfers
173
+ puts "# Total #{symbol}: #{transfers.values.sum}"
174
+ end
175
+
176
+ desc 'Lists sum of powered down grouped by date, from, and to.'
177
+ task :powerdown, [:minimum_amount, :symbol, :days_ago, :not_to_self] do |t, args|
178
+ now = Time.now.utc
179
+ minimum_amount = (args[:minimum_amount] || '500').to_f
180
+ symbol = (args[:symbol] || 'HIVE').upcase
181
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
182
+ not_to_self = (args[:not_to_self] || 'false') == 'true'
183
+
184
+ minimum_amount = case symbol
185
+ when 'MVESTS' then minimum_amount * 1e6 #TODO
186
+ when 'VESTS' then minimum_amount # TODO
187
+ when 'HIVE' then minimum_amount
188
+ else; raise "Unknown symbol: #{symbol}"
189
+ end
190
+
191
+ # Only type: transfer; ignore savings, vestings
192
+ transfers = HiveSQL::Tx::Transfer.where(type: 'transfer_to_vesting')
193
+ transfers = transfers.where('amount > ?', minimum_amount)
194
+ transfers = transfers.where('amount_symbol = ?', 'HIVE')
195
+ transfers = transfers.where('timestamp > ?', after_timestamp)
196
+ transfers = transfers.group('CAST(timestamp AS DATE)', :from, :to)
197
+ transfers = transfers.order('cast_timestamp_as_date ASC')
198
+
199
+ transfers = transfers.sum(:amount)
200
+
201
+ if not_to_self
202
+ transfers = transfers.map do |k, v|
203
+ [k, v] if k[1] != k[2]
204
+ end.compact.to_h
205
+ end
206
+
207
+ puts "# Daily transfer sum over #{'%.3f' % minimum_amount} #{symbol} #{not_to_self ? '' : 'not to self '}since #{after_timestamp} ..."
208
+ ap transfers
209
+ puts "# Total #{symbol}: #{transfers.values.sum}"
210
+ end
211
+
212
+ desc 'Lists apps grouped by date, app/version.'
213
+ task :apps, [:app, :days_ago] do |t, args|
214
+ now = Time.now.utc
215
+ app = args[:app]
216
+ after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
217
+
218
+ comments = HiveSQL::Comment.normalized_json
219
+ comments = comments.app(app) if !!app
220
+ comments = comments.where('created > ?', after_timestamp)
221
+ comments = comments.group('CAST(created AS DATE)', "JSON_VALUE(json_metadata, '$.app')")
222
+ comments = comments.order('cast_created_as_date ASC')
223
+
224
+ matching = " matching \"#{app}\"" if !!app
225
+ puts "Daily app#{matching} count since #{after_timestamp} ..."
226
+ ap comments.count(:all)
227
+ end
228
+
229
+ desc 'Lists app names grouped by date, app/version.'
230
+ task :app_names, [:app, :days_ago] do |t, args|
231
+ now = Time.now.utc
232
+ app = args[:app]
233
+ after_timestamp = now - ((args[:days_ago] || '7').to_f * 86400)
234
+
235
+ comments = HiveSQL::Comment.normalized_json
236
+ comments = comments.app(app) if !!app
237
+ comments = comments.where('created > ?', after_timestamp)
238
+ comments = comments.group('CAST(created AS DATE)', "JSON_VALUE(json_metadata, '$.app')")
239
+ comments = comments.order('cast_created_as_date ASC')
240
+
241
+ matching = " matching \"#{app}\"" if !!app
242
+ puts "# Daily app#{matching} count since #{after_timestamp} ..."
243
+
244
+ app_names = {}
245
+
246
+ comments.count(:all).each do |k, v|
247
+ date, app = k
248
+ if !!app && app.include?('/')
249
+ name, version = app.split('/')
250
+ app_names[[date, name]] ||= 0.0
251
+ app_names[[date, name]] += v
252
+ end
253
+ end
254
+
255
+ ap app_names
256
+ end
257
+
258
+ desc 'Do all crosschecks of given account.'
259
+ task :crosscheck, [:account] do |t, args|
260
+ account = args[:account]
261
+
262
+ Rake::Task["crosscheck:powerdowns"].invoke(account)
263
+ Rake::Task["crosscheck:powerups"].invoke(account)
264
+ Rake::Task["crosscheck:transfers"].invoke(account)
265
+ Rake::Task["crosscheck:vesting_from"].invoke(account)
266
+ Rake::Task["crosscheck:vesting_to"].invoke(account)
267
+ end
268
+
269
+ namespace :crosscheck do
270
+ desc 'List of accounts grouped by transfer count crosschecked by memo of given account.'
271
+ task :transfers, [:account] do |t, args|
272
+ exchanges = %w(bittrex poloniex openledger blocktrades deepcrypto8 gopax
273
+ binanceexchange teambitwala changelly hitbtc-exchange korbit roomofsatoshi
274
+ shapeshiftio huobi-withdrawal bithumbrecv2 user.dunamu hot.dunamu)
275
+ account = args[:account]
276
+
277
+ if account.nil? || account == ''
278
+ puts 'Account name required.'
279
+ exit
280
+ elsif exchanges.include? account
281
+ puts 'That procedure is not recommended.'
282
+ exit
283
+ end
284
+
285
+ all = HiveSQL::Tx::Transfer.where(type: 'transfer')
286
+ transfers = all.where.not(memo: '')
287
+ transfers = transfers.where(to: exchanges)
288
+ transfers = if account =~ /%/
289
+ table = HiveSQL::Tx::Transfer.arel_table
290
+ transfers.where(table[:from].matches(account))
291
+ else
292
+ transfers.where(from: account)
293
+ end
294
+ crosscheck_transfers = all.where(memo: transfers.select(:memo))
295
+
296
+ if transfers.none?
297
+ puts "No match."
298
+ else
299
+ from = transfers.pluck(:from).uniq.join(', ')
300
+ puts "Accounts grouped by transfer count using common memos as #{from} on common exchanges ..."
301
+ ap crosscheck_transfers.group(:from).order('count_all').count(:all)
302
+ end
303
+ end
304
+
305
+ desc 'List of accounts grouped by vesting transfers from a given account'
306
+ task :vesting_from, [:account] do |t, args|
307
+ account = args[:account]
308
+
309
+ if account.nil? || account == ''
310
+ puts 'Account name required.'
311
+ exit
312
+ end
313
+
314
+ table = HiveSQL::Tx::Transfer.arel_table
315
+ all = HiveSQL::Tx::Transfer.where(type: 'transfer_to_vesting')
316
+ transfers = all.where(table[:from].not_eq(:to))
317
+ transfers = transfers.where.not(to: '')
318
+ transfers = if account =~ /%/
319
+ table = HiveSQL::Tx::Transfer.arel_table
320
+ transfers.where(table[:from].matches(account))
321
+ else
322
+ transfers.where(from: account)
323
+ end
324
+
325
+ if transfers.none?
326
+ puts "No match."
327
+ else
328
+ from = transfers.pluck(:from).uniq.join(', ')
329
+ puts "Accounts grouped by vesting transfer count from #{from} ..."
330
+ ap transfers.group(:to).order('count_all').count(:all)
331
+ end
332
+ end
333
+
334
+ desc 'List of accounts grouped by vesting transfers to a given account'
335
+ task :vesting_to, [:account] do |t, args|
336
+ account = args[:account]
337
+
338
+ if account.nil? || account == ''
339
+ puts 'Account name required.'
340
+ exit
341
+ end
342
+
343
+ table = HiveSQL::Tx::Transfer.arel_table
344
+ all = HiveSQL::Tx::Transfer.where(type: 'transfer_to_vesting')
345
+ transfers = all.where(table[:from].not_eq(table[:to]))
346
+ transfers = transfers.where.not(to: '')
347
+ transfers = if account =~ /%/
348
+ table = HiveSQL::Tx::Transfer.arel_table
349
+ transfers.where(table[:to].matches(account))
350
+ else
351
+ transfers.where(to: account)
352
+ end
353
+
354
+ if transfers.none?
355
+ puts "No match."
356
+ else
357
+ from = transfers.pluck(:to).uniq.join(', ')
358
+ puts "Accounts grouped by vesting transfer count to #{from} ..."
359
+ ap transfers.group(:from).order('count_all').count(:all)
360
+ end
361
+ end
362
+
363
+ desc 'List of accounts grouped by powerdown sums crosschecked by given account.'
364
+ task :powerdowns, [:account] do |t, args|
365
+ account = args[:account]
366
+
367
+ if account.nil? || account == ''
368
+ puts 'Account name required.'
369
+ exit
370
+ end
371
+
372
+ table = HiveSQL::Vo::FillVestingWithdraw.arel_table
373
+ all = HiveSQL::Vo::FillVestingWithdraw.where(table[:from_account].not_eq(table[:to_account]))
374
+ powerdowns = if account =~ /%/
375
+ all.where(table[:from_account].matches(account))
376
+ else
377
+ all.where(from_account: account)
378
+ end
379
+
380
+ if powerdowns.none?
381
+ puts "No match."
382
+ else
383
+ from = powerdowns.pluck(:from_account).uniq.join(', ')
384
+ puts "Powerdowns grouped by sum from #{from} ..."
385
+ ap powerdowns.group(:to_account).
386
+ order('sum_try_parse_replace_withdrawn_vests_as_float').
387
+ sum("TRY_PARSE(REPLACE(withdrawn, ' VESTS', '') AS float)")
388
+ end
389
+ end
390
+
391
+ desc 'List of accounts grouped by powerup sums crosschecked by given account.'
392
+ task :powerups, [:account] do |t, args|
393
+ account = args[:account]
394
+
395
+ if account.nil? || account == ''
396
+ puts 'Account name required.'
397
+ exit
398
+ end
399
+
400
+ table = HiveSQL::Vo::FillVestingWithdraw.arel_table
401
+ all = HiveSQL::Vo::FillVestingWithdraw.where(table[:from_account].not_eq(table[:to_account]))
402
+ powerups = if account =~ /%/
403
+ all.where(table[:to_account].matches(account))
404
+ else
405
+ all.where(to_account: account)
406
+ end
407
+
408
+ if powerups.none?
409
+ puts "No match."
410
+ else
411
+ to = powerups.pluck(:to_account).uniq.join(', ')
412
+ puts "Powerups grouped by sum to #{to} ..."
413
+ ap powerups.group(:from_account).
414
+ order('sum_try_parse_replace_withdrawn_vests_as_float').
415
+ sum("TRY_PARSE(REPLACE(withdrawn, ' VESTS', '') AS float)")
416
+ end
417
+ end
418
+ end
419
+
420
+ namespace :rewards do
421
+ desc 'Lists author rewards grouped by date.'
422
+ task :author, [:symbol, :days_ago, :author] do |t, args|
423
+ now = Time.now.utc
424
+ symbol = (args[:symbol] || 'HBD').upcase
425
+ after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
426
+ author = args[:author]
427
+
428
+ rewards = HiveSQL::Vo::AuthorReward
429
+ rewards = rewards.where('timestamp > ?', after_timestamp)
430
+ rewards = rewards.group('CAST(timestamp AS DATE)')
431
+ rewards = rewards.order('cast_timestamp_as_date ASC')
432
+
433
+ if !!author
434
+ if author =~ /%/
435
+ rewards = rewards.where("author LIKE ?", author)
436
+ else
437
+ rewards = rewards.where(author: author)
438
+ end
439
+
440
+ puts "Daily #{author} reward #{symbol} sum grouped by date since #{after_timestamp} ..."
441
+ else
442
+ puts "Daily reward #{symbol} sum grouped by date since #{after_timestamp} ..."
443
+ end
444
+
445
+ rewards = case symbol
446
+ when 'HBD' then rewards.sum(:hbd_payout)
447
+ when 'HIVE' then rewards.sum(:hive_payout)
448
+ when 'VESTS' then rewards.sum(:vesting_payout)
449
+ when 'MVESTS'
450
+ rewards.sum('vesting_payout / 1000000')
451
+ when 'HP'
452
+ properties = HiveSQL::DynamicGlobalProperties.first
453
+ total_vesting_fund_hive = properties.total_vesting_fund_hive.to_f
454
+ total_vesting_shares_mvest = properties.total_vesting_shares.to_f / 1e6
455
+ base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest
456
+
457
+ rewards.sum("(vesting_payout / 1000000) * #{base_per_mvest}")
458
+ else; puts "Unknown symbol: #{symbol}. Symbols supported: HBD, HIVE, VESTS, MVESTS, HP"
459
+ end
460
+
461
+ ap rewards
462
+ sum = rewards.values.sum
463
+ puts "# Total rewards: %.3f %s (average: %.3f per day)" % [sum, symbol, (sum / rewards.size)]
464
+ end
465
+
466
+ desc 'Lists curation rewards grouped by date.'
467
+ task :curation, [:symbol, :days_ago, :curator] do |t, args|
468
+ now = Time.now.utc
469
+ symbol = (args[:symbol] || 'MVESTS').upcase
470
+ after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
471
+ curator = args[:curator]
472
+
473
+ rewards = HiveSQL::Vo::CurationReward
474
+ rewards = rewards.where('timestamp > ?', after_timestamp)
475
+ rewards = rewards.group('CAST(timestamp AS DATE)')
476
+ rewards = rewards.order('cast_timestamp_as_date ASC')
477
+
478
+ if !!curator
479
+ if curator =~ /%/
480
+ rewards = rewards.where("curator LIKE ?", curator)
481
+ else
482
+ rewards = rewards.where(curator: curator)
483
+ end
484
+
485
+ puts "Daily #{curator} reward #{symbol} sum grouped by date since #{after_timestamp} ..."
486
+ else
487
+ puts "Daily curation reward #{symbol} sum grouped by date since #{after_timestamp} ..."
488
+ end
489
+
490
+ rewards = case symbol
491
+ when 'VESTS'
492
+ rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float)")
493
+ when 'MVESTS'
494
+ rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float) / 1000000")
495
+ when 'HP'
496
+ properties = HiveSQL::DynamicGlobalProperties.first
497
+ total_vesting_fund_hive = properties.total_vesting_fund_hive.to_f
498
+ total_vesting_shares_mvest = properties.total_vesting_shares.to_f / 1e6
499
+ base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest
500
+
501
+ rewards.sum("(TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float) / 1000000) * #{base_per_mvest}")
502
+ else; puts "Unknown symbol: #{symbol}. Symbols supported: VESTS, MVESTS, HP"
503
+ end
504
+
505
+ ap rewards
506
+ sum = rewards.values.sum
507
+ puts "# Total rewards: %.3f %s (average: %.3f per day)" % [sum, symbol, (sum / rewards.size)]
508
+ end
509
+ end
510
+
511
+ desc 'Lists proxied grouped by month.'
512
+ task :proxied, [:days_ago] do |t, args|
513
+ now = Time.now.utc
514
+ after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
515
+
516
+ proxied = HiveSQL::Tx::AccountWitnessProxy
517
+ proxied = proxied.where('timestamp > ?', after_timestamp)
518
+ proxied = proxied.group("FORMAT(timestamp, 'yyyy-MM')", :proxy)
519
+ proxied = proxied.order('format_timestamp_yyyy_mm ASC')
520
+
521
+ puts "Daily proxied grouped by month since #{after_timestamp} ..."
522
+
523
+ ap proxied.count(:all)
524
+ end
525
+
526
+ desc <<~EOF
527
+ Claimed Rewards.
528
+ Use the "account_name" of a user or '%' to match on any user.
529
+ EOF
530
+ task :claimed, [:account_name, :days_ago, :symbol] do |t, args|
531
+ now = Time.now.utc
532
+ account_name = args[:account_name] || '%'
533
+ after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
534
+ symbol = (args[:symbol] || 'vests').downcase.to_sym
535
+ claims = HiveSQL::Tx::ClaimRewardBalance.where('timestamp > ?', after_timestamp)
536
+
537
+ claims = if account_name =~ /%/
538
+ claims.where('account LIKE ?', account_name)
539
+ else
540
+ claims.where(account: account_name)
541
+ end
542
+
543
+ claims = case symbol
544
+ when :vests then claims.where("reward_vests > 0")
545
+ when :mvests then claims.where("reward_vests > 0")
546
+ when :hive then claims.where("reward_hive > 0")
547
+ when :hbd then claims.where("reward_hbd > 0")
548
+ else; raise "Unknown symbol: #{symbol.to_s.upcase} (allowed: VESTS, MVESTS, HIVE, HBD)"
549
+ end
550
+
551
+ claims = claims.group("FORMAT(timestamp, 'yyyy-MM')")
552
+ claims = claims.order('format_timestamp_yyyy_mm ASC')
553
+
554
+ claims = case symbol
555
+ when :vests then claims.sum(:reward_vests)
556
+ when :mvests then claims.sum('reward_vests / 1000000')
557
+ when :hive then claims.sum(:reward_hive)
558
+ when :hbd then claims.sum(:reward_hbd)
559
+ end
560
+
561
+ puts "# Claimed rewards in #{symbol.to_s.upcase} sum grouped by month ..."
562
+
563
+ ap claims
564
+ puts "# Total claimed #{symbol}: #{claims.values.sum}"
565
+ end
566
+
567
+ desc <<~EOF
568
+ Balance for given parties.
569
+ Where "party_a" is the first account, "party_b" is the second account and "symbol" is a valid native symbol.
570
+ EOF
571
+ task :balance, [:party_a, :party_b, :symbol] do |t, args|
572
+ party_a = args[:party_a]
573
+ party_b = args[:party_b]
574
+ symbol = args[:symbol].upcase
575
+
576
+ balance_a = HiveSQL::Tx::Transfer.where(to: party_a, from: party_b, amount_symbol: symbol).sum(:amount).to_f
577
+ balance_b = HiveSQL::Tx::Transfer.where(to: party_b, from: party_a, amount_symbol: symbol).sum(:amount).to_f
578
+
579
+ puts "#{party_a}: %.3f #{symbol}, difference: %.3f #{symbol}" % [balance_a, (balance_a - balance_b)]
580
+ puts "#{party_b}: %.3f #{symbol}, difference: %.3f #{symbol}" % [balance_b, (balance_b - balance_a)]
581
+ end
582
+
583
+ desc <<~EOF
584
+ Top comments by what ...
585
+ Allowed \"what\" options: voter upvoted downvoted
586
+ EOF
587
+ task :top, [:what, :limit] do |t, args|
588
+ what = args[:what].to_s.downcase.to_sym
589
+ limit = (args[:limit] || '10').to_i
590
+ since = 1.week.ago
591
+
592
+ case what
593
+ when :voter
594
+ votes = HiveSQL::Tx::Vote.after(since)
595
+ votes = votes.group(:voter)
596
+ votes = votes.order('count_all DESC')
597
+ votes = votes.limit(limit)
598
+
599
+ ap votes.count
600
+ when :upvoted, :downvoted
601
+ comments = HiveSQL::Comment.after(since)
602
+ comments = if what == :upvoted
603
+ comments.where('net_rshares > 0')
604
+ comments = comments.order('sum_net_rshares DESC')
605
+ elsif what == :downvoted
606
+ comments.where('net_rshares < 0')
607
+ comments = comments.order('sum_net_rshares ASC')
608
+ end
609
+
610
+ comments = comments.group(:author, :permlink, :created)
611
+ comments = comments.limit(limit)
612
+
613
+ comments = comments.sum(:net_rshares)
614
+
615
+ comments.each do |k, v|
616
+ url = "https://hive.blog/@#{k[0]}/#{k[1]}"
617
+ created = (Time.now - k[2]) / 60 / 60 / 24
618
+
619
+ puts "#{v}; #{created.round(2)} days ago: #{url}"
620
+ end
621
+ else
622
+ exec 'rake -D top | head -3'
623
+ end
624
+ end
625
+
626
+ desc <<~EOF
627
+ Top tags by pending_payout_value.
628
+ EOF
629
+ task :top_tags, [:limit] do |t, args|
630
+ limit = (args[:limit] || '100').to_i
631
+ since = 1.week.ago
632
+
633
+ comments = HiveSQL::Comment.after(since)
634
+ comments = comments.joins(:tags)
635
+ comments = comments.where('pending_payout_value > 0')
636
+ comments = comments.order('sum_pending_payout_value DESC')
637
+
638
+ comments = comments.group('LOWER(tags.tag)')
639
+ comments = comments.limit(limit)
640
+
641
+ comments = comments.sum(:pending_payout_value)
642
+
643
+ comments.each do |k, v|
644
+ url = "https://hive.blog/#{k}"
645
+
646
+ puts "#{v}; #{url}"
647
+ end
648
+ end
649
+
650
+ desc 'Lists sum of proposal pay grouped by date, from, and to.'
651
+ task :proposal_pay, [:minimum_payment, :days_ago] do |t, args|
652
+ now = Time.now.utc
653
+ minimum_payment = (args[:minimum_payment] || '0.001').to_f
654
+ symbol = (args[:symbol] || 'HBD').upcase
655
+ days_ago = (args[:days_ago] || '30').to_i
656
+ after_timestamp = now - days_ago * 86400
657
+
658
+ payments = HiveSQL::Vo::ProposalPay.where.not(receiver: ['steem.dao', 'hive.fund'])
659
+ payments = payments.where('payment > ?', minimum_payment)
660
+ payments = payments.where('payment_symbol = ?', symbol)
661
+ payments = payments.where('timestamp > ?', after_timestamp)
662
+ payments = payments.group('CAST(timestamp AS DATE)', :receiver)
663
+ payments = payments.order('cast_timestamp_as_date ASC')
664
+
665
+ puts "Daily payment sum over #{'%.3f' % minimum_payment} #{symbol} since #{after_timestamp} ..."
666
+ ap payments.sum(:payment)
667
+
668
+ average_daily_payments = payments.sum(:payment).values.sum / days_ago
669
+ puts "Average daily payments: #{'%.3f' % average_daily_payments} #{symbol}"
670
+ end
671
+
672
+ desc 'Lists sum of HBD interest grouped by date, from, and to.'
673
+ task :interest, [:minimum_payment, :days_ago] do |t, args|
674
+ now = Time.now.utc
675
+ minimum_payment = (args[:minimum_payment] || '0.001').to_f
676
+ days_ago = (args[:days_ago] || '30').to_i
677
+ after_timestamp = now - days_ago * 86400
678
+
679
+ payments = HiveSQL::Vo::Interest.all
680
+ payments = payments.where('Interest > ?', minimum_payment)
681
+ payments = payments.where('timestamp > ?', after_timestamp)
682
+ duration = payments.minimum(:timestamp)
683
+
684
+ payments = payments.group('CAST(timestamp AS DATE)')
685
+ payments = payments.order('cast_timestamp_as_date ASC')
686
+
687
+ puts "# Daily interest payment sum #{'%.3f HBD' % minimum_payment} and over, since #{after_timestamp} ..."
688
+ ap payments.sum(:Interest)
689
+
690
+ actual_days = ((((Time.now - duration)) / 60) / 60) / 24
691
+ interst_sum = payments.sum(:Interest).values.sum
692
+ average_daily_payments = interst_sum / actual_days
693
+ puts "Total interest paid for period #{'%.3f HBD' % interst_sum}; average daily payments: #{'%.3f HBD' % average_daily_payments} (days: #{actual_days})"
694
+ end
695
+
696
+ # Doesn't look like this table exists.
697
+ desc 'List conversion HBD conversion request sums grouped by day.'
698
+ task :convert, [:days_ago] do |t, args|
699
+ now = Time.now.utc
700
+ after_timestamp = now - ((args[:days_ago] || '3.5').to_f * 86400)
701
+
702
+ converts = HiveSQL::Vo::FillConvertRequest
703
+ converts = converts.where('timestamp > ?', after_timestamp)
704
+ converts = converts.group('CAST(timestamp AS DATE)')
705
+ converts = converts.order('cast_timestamp_as_date ASC')
706
+
707
+ puts "# Daily HBD conversion requests sum grouped by date since #{after_timestamp} ..."
708
+ ap converts.sum(:amount_in)
709
+ end
710
+
711
+ # Doesn't look like this table exists.
712
+ desc 'List daily activity of account, for specified days (default 90)'
713
+ task :activity, [:account_name, :days_ago] do |t, args|
714
+ now = Time.now.utc
715
+ after_timestamp = now - ((args[:days_ago] || '90').to_f * 86400)
716
+ account_name = args[:account_name]
717
+
718
+ trx = HiveSQL::Transaction.by(account_name)
719
+ trx = trx.joins(:block).where('timestamp > ?', after_timestamp)
720
+ trx = trx.group('type')
721
+ trx = trx.order('count_type ASC')
722
+
723
+ puts "# Daily transactions by #{account_name} for type count grouped by type since #{after_timestamp} ..."
724
+ ap trx.count(:type)
725
+ end
726
+
727
+ namespace :witnesses do
728
+ desc 'Count witnesses that have signed blocks, group by day.'
729
+ task :count, [:days_ago] do |t, args|
730
+ now = Time.now.utc
731
+ days_ago = (args[:days_ago] || '3.5').to_f
732
+ after_timestamp = now - (days_ago * 86400)
733
+
734
+ blocks = HiveSQL::Block
735
+ blocks = blocks.where('timestamp > ?', after_timestamp)
736
+ duration = blocks.minimum(:timestamp)
737
+ total_witness_count = blocks.distinct.count(:witness)
738
+ blocks = blocks.group('CAST(timestamp AS DATE)')
739
+ blocks = blocks.order('cast_timestamp_as_date ASC')
740
+
741
+ actual_days = ((((Time.now - duration)) / 60) / 60) / 24
742
+
743
+ puts "Witness count that signed blocks grouped by date since #{after_timestamp} ..."
744
+ ap blocks.distinct.count(:witness)
745
+ puts "# Total unique witnesses: %d (average: %.1f per day)" % [total_witness_count, (blocks.distinct.count(:witness).values.sum) / actual_days]
746
+ end
747
+
748
+ desc 'Witness accounts that have signed blocks, group by day.'
749
+ task :accounts, [:days_ago] do |t, args|
750
+ now = Time.now.utc
751
+ days_ago = (args[:days_ago] || '3.5').to_f
752
+ after_timestamp = now - (days_ago * 86400)
753
+
754
+ blocks = HiveSQL::Block
755
+ blocks = blocks.where('timestamp > ?', after_timestamp)
756
+ duration = blocks.minimum(:timestamp)
757
+ total_witness_count = blocks.distinct.count(:witness)
758
+ blocks = blocks.group(:witness)
759
+ blocks = blocks.order('1 ASC')
760
+
761
+ actual_days = ((((Time.now - duration)) / 60) / 60) / 24
762
+
763
+ puts "Witness count that signed blocks grouped by date since #{after_timestamp} ..."
764
+ ap blocks.distinct.count(:all)
765
+ puts "# Total unique witnesses: %d" % [total_witness_count]
766
+ end
767
+
768
+ desc 'New witness accounts that have signed blocks, group by day.'
769
+ task :new_accounts, [:days_ago] do |t, args|
770
+ now = Time.now.utc
771
+ days_ago = (args[:days_ago] || '3.5').to_f
772
+ after_timestamp = now - (days_ago * 86400)
773
+
774
+ blocks = HiveSQL::Block
775
+ previous_blocks = blocks.where('timestamp <= ?', after_timestamp).limit(9600) # about one day of blocks
776
+ previous_blocks = previous_blocks.order(block_num: :desc)
777
+ blocks = blocks.where('timestamp > ?', after_timestamp).where.not(witness: previous_blocks.select(:witness))
778
+ duration = blocks.minimum(:timestamp)
779
+ total_witness_count = blocks.distinct.count(:witness)
780
+ blocks = blocks.group(:witness)
781
+ blocks = blocks.order('1 ASC')
782
+
783
+ actual_days = ((((Time.now - duration)) / 60) / 60) / 24
784
+
785
+ puts "New witness count that signed blocks grouped by date since #{after_timestamp} ..."
786
+ ap blocks.distinct.count(:all)
787
+ puts "# Total unique witnesses: %d" % [total_witness_count]
788
+ end
789
+ end
790
+
791
+ desc 'Build a new version of the hive_sql gem.'
792
+ task :build do
793
+ exec 'gem build hive_sql.gemspec'
794
+ end
795
+
796
+ desc 'Publish the current version of the hive_sql gem.'
797
+ task :push do
798
+ exec "gem push hive_sql-#{HiveSQL::VERSION}.gem"
799
+ end
800
+
801
+ # We're not going to yank on a regular basis, but this is how it's done if you
802
+ # really want a task for that for some reason.
803
+
804
+ # desc 'Yank the current version of the hive_sql gem.'
805
+ # task :yank do
806
+ # exec "gem yank hive_sql -v #{HiveSQL::VERSION}"
807
+ # end