hive_sql 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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