steem_api 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Rakefile +244 -67
- data/lib/steem_api.rb +4 -0
- data/lib/steem_api/models/comment.rb +5 -1
- data/lib/steem_api/models/dynamic_global_properties.rb +11 -0
- data/lib/steem_api/models/transaction.rb +21 -1
- data/lib/steem_api/models/tx/custom/community.rb +32 -0
- data/lib/steem_api/models/tx/update_proposal_vote.rb +31 -0
- data/lib/steem_api/models/vo/proposal_pay.rb +20 -0
- data/lib/steem_api/models/vo/sps_fund.rb +18 -0
- data/lib/steem_api/version.rb +1 -1
- data/steem_api.gemspec +1 -0
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d808e15bb5bd8b10b70af26c21af568880d3d8e25d892fe98ad777e1b9da1464
|
4
|
+
data.tar.gz: 1e7813932ab8c9568b8885260409aa1731ea0a31acefec85c2e01529c3b6d558
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a61f2735cf47ccecf244af806d5cccb72779c3ccfc8bcd524cf4c0e2385f6ec1f9d0d1af1426c33824b562a856b9647d402fb8ab94304308642c6e6ca31022e4
|
7
|
+
data.tar.gz: e40ea12b512db4aab6d7b2a33651445442b6020633f106dae9ce8acbaeabcee10d87968ca8c75da926cdf91eedf3e171f268799e17a9b7b459cc78cab2badb43
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@ require "bundler/gem_tasks"
|
|
2
2
|
require "rake/testtask"
|
3
3
|
require 'steem_api'
|
4
4
|
require 'awesome_print'
|
5
|
+
require 'pry'
|
5
6
|
|
6
7
|
Rake::TestTask.new(:test) do |t|
|
7
8
|
t.libs << 'test'
|
@@ -76,6 +77,39 @@ namespace :created do
|
|
76
77
|
ap customs
|
77
78
|
puts "# Total custom_json_operation: #{customs.values.sum}"
|
78
79
|
end
|
80
|
+
|
81
|
+
desc 'Lists comment_operations count grouped by author and date.'
|
82
|
+
task :comments, [:author, :days_ago, :min_count] do |t, args|
|
83
|
+
now = Time.now.utc
|
84
|
+
author = args[:author]
|
85
|
+
after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
|
86
|
+
min_count = (args[:min_count] || 1000).to_i
|
87
|
+
|
88
|
+
comments = SteemApi::Tx::Comment.all
|
89
|
+
|
90
|
+
if !!author || author == '%'
|
91
|
+
unless author == '%'
|
92
|
+
comments = comments.where(author: author)
|
93
|
+
end
|
94
|
+
elsif author =~ /.*%.*/
|
95
|
+
comments = comments.where('author LIKE ?', author)
|
96
|
+
end
|
97
|
+
|
98
|
+
comments = comments.where('timestamp > ?', after_timestamp)
|
99
|
+
comments = comments.group('CAST(timestamp AS DATE)', :author)
|
100
|
+
comments = comments.order('cast_timestamp_as_date ASC')
|
101
|
+
|
102
|
+
comments = comments.count
|
103
|
+
|
104
|
+
comments = comments.map do |k, v|
|
105
|
+
[k, v] if v >= min_count
|
106
|
+
end.compact.to_h
|
107
|
+
|
108
|
+
puts "# Daily creation count by #{author.nil? ? 'all authors' : author} since #{after_timestamp} ..."
|
109
|
+
ap comments
|
110
|
+
puts "# Total authors: #{comments.keys.uniq.size}"
|
111
|
+
puts "# Total comments: #{comments.values.sum}"
|
112
|
+
end
|
79
113
|
end
|
80
114
|
|
81
115
|
desc 'Lists sum of transfers grouped by date, from, and to.'
|
@@ -97,6 +131,22 @@ task :transfers, [:minimum_amount, :symbol, :days_ago] do |t, args|
|
|
97
131
|
ap transfers.sum(:amount)
|
98
132
|
end
|
99
133
|
|
134
|
+
desc 'Lists sum of delegations grouped by year and from.'
|
135
|
+
task :delegations, [:minimum_amount, :days_ago] do |t, args|
|
136
|
+
now = Time.now.utc
|
137
|
+
minimum_amount = (args[:minimum_amount] || '1000000').to_f
|
138
|
+
after_timestamp = now - ((args[:days_ago] || '30').to_i * 86400)
|
139
|
+
|
140
|
+
delegations = SteemApi::Tx::DelegateVestingShare.where('vesting_shares > ?', minimum_amount)
|
141
|
+
delegations = delegations.where('timestamp > ?', after_timestamp)
|
142
|
+
delegations = delegations.group("FORMAT(timestamp, 'yyyy')", :delegator)
|
143
|
+
delegations = delegations.order('format_timestamp_yyyy ASC')
|
144
|
+
|
145
|
+
puts "Daily delegation sum over #{'%.3f' % minimum_amount} since #{after_timestamp} ..."
|
146
|
+
ap delegations.count(:vesting_shares).map{|k, v| [k[1], v] if v > 50}.compact.to_h
|
147
|
+
# ap delegations.sum(:vesting_shares)
|
148
|
+
end
|
149
|
+
|
100
150
|
desc 'Lists sum of powered up grouped by date, from, and to.'
|
101
151
|
task :powerup, [:minimum_amount, :symbol, :days_ago, :not_to_self] do |t, args|
|
102
152
|
now = Time.now.utc
|
@@ -216,38 +266,55 @@ task :app_names, [:app, :days_ago] do |t, args|
|
|
216
266
|
end
|
217
267
|
|
218
268
|
desc 'Do all crosschecks of given account.'
|
219
|
-
task :crosscheck, [:account] do |t, args|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
269
|
+
task :crosscheck, [:account, :after_timestamp] do |t, args|
|
270
|
+
account_name = args[:account]
|
271
|
+
after_timestamp = args[:after_timestamp]
|
272
|
+
|
273
|
+
abort 'Account name required.' if account_name.nil? || account_name == ''
|
274
|
+
|
275
|
+
if after_timestamp.nil? || after_timestamp == ''
|
276
|
+
account = SteemApi::Account.find_by(name: account_name)
|
277
|
+
|
278
|
+
abort "No account found: #{account_name}" if account.nil?
|
279
|
+
end
|
280
|
+
|
281
|
+
Rake::Task["crosscheck:powerdowns"].invoke(account_name, after_timestamp)
|
282
|
+
Rake::Task["crosscheck:powerups"].invoke(account_name, after_timestamp)
|
283
|
+
Rake::Task["crosscheck:transfers"].invoke(account_name, after_timestamp)
|
284
|
+
Rake::Task["crosscheck:vesting_from"].invoke(account_name, after_timestamp)
|
285
|
+
Rake::Task["crosscheck:vesting_to"].invoke(account_name, after_timestamp)
|
227
286
|
end
|
228
287
|
|
229
288
|
namespace :crosscheck do
|
230
289
|
desc 'List of accounts grouped by transfer count crosschecked by memo of given account.'
|
231
|
-
task :transfers, [:account] do |t, args|
|
290
|
+
task :transfers, [:account, :after_timestamp] do |t, args|
|
232
291
|
exchanges = %w(bittrex poloniex openledger blocktrades deepcrypto8 gopax
|
233
292
|
binanceexchange teambitwala changelly hitbtc-exchange korbit roomofsatoshi
|
234
293
|
shapeshiftio)
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
elsif exchanges.include?
|
241
|
-
|
242
|
-
|
294
|
+
account_name = args[:account]
|
295
|
+
after_timestamp = args[:after_timestamp]
|
296
|
+
|
297
|
+
if account_name.nil? || account_name == ''
|
298
|
+
abort 'Account name required.'
|
299
|
+
elsif exchanges.include? account_name
|
300
|
+
abort 'That procedure is not recommended.'
|
301
|
+
end
|
302
|
+
|
303
|
+
if after_timestamp.nil? || after_timestamp == ''
|
304
|
+
account = SteemApi::Account.find_by(name: account_name)
|
305
|
+
|
306
|
+
abort "No account found: #{account_name}" if account.nil?
|
307
|
+
|
308
|
+
after_timestamp = account.created
|
243
309
|
end
|
244
310
|
|
245
311
|
all = SteemApi::Tx::Transfer.where(type: 'transfer')
|
246
312
|
transfers = all.where.not(memo: '')
|
313
|
+
transfers = transfers.where('timestamp >= ?', after_timestamp)
|
247
314
|
transfers = transfers.where(to: exchanges)
|
248
315
|
transfers = if account =~ /%/
|
249
316
|
table = SteemApi::Tx::Transfer.arel_table
|
250
|
-
transfers.where(table[:from].matches(
|
317
|
+
transfers.where(table[:from].matches(account_name))
|
251
318
|
else
|
252
319
|
transfers.where(from: account)
|
253
320
|
end
|
@@ -263,23 +330,30 @@ namespace :crosscheck do
|
|
263
330
|
end
|
264
331
|
|
265
332
|
desc 'List of accounts grouped by vesting transfers from a given account'
|
266
|
-
task :vesting_from, [:account] do |t, args|
|
267
|
-
|
333
|
+
task :vesting_from, [:account, :after_timestamp] do |t, args|
|
334
|
+
account_name = args[:account]
|
335
|
+
after_timestamp = args[:after_timestamp]
|
336
|
+
|
337
|
+
abort 'Account name required.' if account_name.nil? || account_name == ''
|
268
338
|
|
269
|
-
if
|
270
|
-
|
271
|
-
|
339
|
+
if after_timestamp.nil? || after_timestamp == ''
|
340
|
+
account = SteemApi::Account.find_by(name: account_name)
|
341
|
+
|
342
|
+
abort "No account found: #{account_name}" if account.nil?
|
343
|
+
|
344
|
+
after_timestamp = account.created
|
272
345
|
end
|
273
346
|
|
274
347
|
table = SteemApi::Tx::Transfer.arel_table
|
275
348
|
all = SteemApi::Tx::Transfer.where(type: 'transfer_to_vesting')
|
276
349
|
transfers = all.where(table[:from].not_eq(:to))
|
350
|
+
transfers = transfers.where('timestamp >= ?', after_timestamp)
|
277
351
|
transfers = transfers.where.not(to: '')
|
278
352
|
transfers = if account =~ /%/
|
279
353
|
table = SteemApi::Tx::Transfer.arel_table
|
280
|
-
transfers.where(table[:from].matches(
|
354
|
+
transfers.where(table[:from].matches(account_name))
|
281
355
|
else
|
282
|
-
transfers.where(from:
|
356
|
+
transfers.where(from: account_name)
|
283
357
|
end
|
284
358
|
|
285
359
|
if transfers.none?
|
@@ -292,23 +366,30 @@ namespace :crosscheck do
|
|
292
366
|
end
|
293
367
|
|
294
368
|
desc 'List of accounts grouped by vesting transfers to a given account'
|
295
|
-
task :vesting_to, [:account] do |t, args|
|
296
|
-
|
369
|
+
task :vesting_to, [:account, :after_timestamp] do |t, args|
|
370
|
+
account_name = args[:account]
|
371
|
+
after_timestamp = args[:after_timestamp]
|
372
|
+
|
373
|
+
abort 'Account name required.' if account_name.nil? || account_name == ''
|
297
374
|
|
298
|
-
if
|
299
|
-
|
300
|
-
|
375
|
+
if after_timestamp.nil? || after_timestamp == ''
|
376
|
+
account = SteemApi::Account.find_by(name: account_name)
|
377
|
+
|
378
|
+
abort "No account found: #{account_name}" if account.nil?
|
379
|
+
|
380
|
+
after_timestamp = account.created
|
301
381
|
end
|
302
382
|
|
303
383
|
table = SteemApi::Tx::Transfer.arel_table
|
304
384
|
all = SteemApi::Tx::Transfer.where(type: 'transfer_to_vesting')
|
305
385
|
transfers = all.where(table[:from].not_eq(table[:to]))
|
386
|
+
transfers = transfers.where('timestamp >= ?', after_timestamp)
|
306
387
|
transfers = transfers.where.not(to: '')
|
307
388
|
transfers = if account =~ /%/
|
308
389
|
table = SteemApi::Tx::Transfer.arel_table
|
309
|
-
transfers.where(table[:to].matches(
|
390
|
+
transfers.where(table[:to].matches(account_name))
|
310
391
|
else
|
311
|
-
transfers.where(to:
|
392
|
+
transfers.where(to: account_name)
|
312
393
|
end
|
313
394
|
|
314
395
|
if transfers.none?
|
@@ -321,22 +402,30 @@ namespace :crosscheck do
|
|
321
402
|
end
|
322
403
|
|
323
404
|
desc 'List of accounts grouped by powerdown sums crosschecked by given account.'
|
324
|
-
task :powerdowns, [:account] do |t, args|
|
325
|
-
|
405
|
+
task :powerdowns, [:account, :after_timestamp] do |t, args|
|
406
|
+
account_name = args[:account]
|
407
|
+
after_timestamp = args[:after_timestamp]
|
408
|
+
|
409
|
+
abort 'Account name required.' if account_name.nil? || account_name == ''
|
326
410
|
|
327
|
-
if
|
328
|
-
|
329
|
-
|
411
|
+
if after_timestamp.nil? || after_timestamp == ''
|
412
|
+
account = SteemApi::Account.find_by(name: account_name)
|
413
|
+
|
414
|
+
abort "No account found: #{account_name}" if account.nil?
|
415
|
+
|
416
|
+
after_timestamp = account.created
|
330
417
|
end
|
331
418
|
|
332
419
|
table = SteemApi::Vo::FillVestingWithdraw.arel_table
|
333
420
|
all = SteemApi::Vo::FillVestingWithdraw.where(table[:from_account].not_eq(table[:to_account]))
|
334
421
|
powerdowns = if account =~ /%/
|
335
|
-
all.where(table[:from_account].matches(
|
422
|
+
all.where(table[:from_account].matches(account_name))
|
336
423
|
else
|
337
|
-
all.where(from_account:
|
424
|
+
all.where(from_account: account_name)
|
338
425
|
end
|
339
426
|
|
427
|
+
powerdowns = powerdowns.where('timestamp >= ?', after_timestamp)
|
428
|
+
|
340
429
|
if powerdowns.none?
|
341
430
|
puts "No match."
|
342
431
|
else
|
@@ -349,22 +438,30 @@ namespace :crosscheck do
|
|
349
438
|
end
|
350
439
|
|
351
440
|
desc 'List of accounts grouped by powerup sums crosschecked by given account.'
|
352
|
-
task :powerups, [:account] do |t, args|
|
353
|
-
|
441
|
+
task :powerups, [:account, :after_timestamp] do |t, args|
|
442
|
+
account_name = args[:account]
|
443
|
+
after_timestamp = args[:after_timestamp]
|
444
|
+
|
445
|
+
abort 'Account name required.' if account_name.nil? || account_name == ''
|
354
446
|
|
355
|
-
if
|
356
|
-
|
357
|
-
|
447
|
+
if after_timestamp.nil? || after_timestamp == ''
|
448
|
+
account = SteemApi::Account.find_by(name: account_name)
|
449
|
+
|
450
|
+
abort "No account found: #{account_name}" if account.nil?
|
451
|
+
|
452
|
+
after_timestamp = account.created
|
358
453
|
end
|
359
454
|
|
360
455
|
table = SteemApi::Vo::FillVestingWithdraw.arel_table
|
361
456
|
all = SteemApi::Vo::FillVestingWithdraw.where(table[:from_account].not_eq(table[:to_account]))
|
362
457
|
powerups = if account =~ /%/
|
363
|
-
all.where(table[:to_account].matches(
|
458
|
+
all.where(table[:to_account].matches(account_name))
|
364
459
|
else
|
365
|
-
all.where(to_account:
|
460
|
+
all.where(to_account: account_name)
|
366
461
|
end
|
367
462
|
|
463
|
+
powerups = powerups.where('timestamp >= ?', after_timestamp)
|
464
|
+
|
368
465
|
if powerups.none?
|
369
466
|
puts "No match."
|
370
467
|
else
|
@@ -377,6 +474,23 @@ namespace :crosscheck do
|
|
377
474
|
end
|
378
475
|
end
|
379
476
|
|
477
|
+
namespace :count do
|
478
|
+
desc 'Count transactions of type (default comment) grouped by date.'
|
479
|
+
task :transactions, [:type, :days_ago] do |t, args|
|
480
|
+
now = Time.now.utc
|
481
|
+
type = args[:type] || 'comment'
|
482
|
+
after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
|
483
|
+
|
484
|
+
trxs = SteemApi::Transaction.where('expiration > ?', after_timestamp)
|
485
|
+
trxs = trxs.where("[Transactions].[type] = ?", type)
|
486
|
+
trxs = trxs.group('CAST([Transactions].[expiration] AS DATE)')
|
487
|
+
trxs = trxs.order('cast_transactions_expiration_as_date ASC')
|
488
|
+
trxs = trxs.count
|
489
|
+
|
490
|
+
ap trxs
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
380
494
|
namespace :rewards do
|
381
495
|
desc 'Lists author rewards grouped by date.'
|
382
496
|
task :author, [:symbol, :days_ago, :author] do |t, args|
|
@@ -408,7 +522,11 @@ namespace :rewards do
|
|
408
522
|
when 'VESTS' then rewards.sum(:vesting_payout)
|
409
523
|
when 'MVESTS'
|
410
524
|
rewards.sum('vesting_payout / 1000000')
|
411
|
-
|
525
|
+
when 'SP'
|
526
|
+
rewards.sum("vesting_payout / 1000000 * #{SteemApi::DynamicGlobalProperties.steem_per_mvest.to_f}")
|
527
|
+
when 'USD'
|
528
|
+
rewards.sum("vesting_payout / 1000000 * #{SteemApi::DynamicGlobalProperties.usd_per_mvest.to_f}")
|
529
|
+
else; puts "Unknown symbol: #{symbol}. Symbols supported: SBD, STEEM, VESTS, MVESTS, SP, USD"
|
412
530
|
end
|
413
531
|
|
414
532
|
ap rewards
|
@@ -417,16 +535,25 @@ namespace :rewards do
|
|
417
535
|
end
|
418
536
|
|
419
537
|
desc 'Lists curation rewards grouped by date.'
|
420
|
-
task :curation, [:symbol, :days_ago] do |t, args|
|
538
|
+
task :curation, [:symbol, :days_ago, :curator] do |t, args|
|
421
539
|
now = Time.now.utc
|
422
540
|
symbol = (args[:symbol] || 'MVESTS').upcase
|
423
541
|
after_timestamp = now - ((args[:days_ago] || '7').to_i * 86400)
|
424
|
-
|
542
|
+
curator = args[:curator]
|
543
|
+
|
425
544
|
rewards = SteemApi::Vo::CurationReward
|
426
545
|
rewards = rewards.where('timestamp > ?', after_timestamp)
|
427
546
|
rewards = rewards.group('CAST(timestamp AS DATE)')
|
428
547
|
rewards = rewards.order('cast_timestamp_as_date ASC')
|
429
548
|
|
549
|
+
if !!curator
|
550
|
+
if curator =~ /%/
|
551
|
+
rewards = rewards.where("curator LIKE ?", curator)
|
552
|
+
else
|
553
|
+
rewards = rewards.where(curator: curator)
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
430
557
|
puts "Daily curation reward #{symbol} sum grouped by date since #{after_timestamp} ..."
|
431
558
|
|
432
559
|
case symbol
|
@@ -434,7 +561,12 @@ namespace :rewards do
|
|
434
561
|
ap rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float)")
|
435
562
|
when 'MVESTS'
|
436
563
|
ap rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float) / 1000000")
|
437
|
-
|
564
|
+
when 'SP'
|
565
|
+
steem_per_mvest = dgpo.total_vesting_fund_steem / (dgpo.total_vesting_shares / 1e6)
|
566
|
+
ap rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float) / 1000000 * #{SteemApi::DynamicGlobalProperties.steem_per_mvest.to_f}")
|
567
|
+
when 'USD'
|
568
|
+
ap rewards.sum("TRY_PARSE(REPLACE(reward, ' VESTS', '') AS float) / 1000000 * #{SteemApi::DynamicGlobalProperties.usd_per_mvest.to_f}")
|
569
|
+
else; puts "Unknown symbol: #{symbol}. Symbols supported: VESTS, MVESTS, SP, USD"
|
438
570
|
end
|
439
571
|
end
|
440
572
|
end
|
@@ -492,32 +624,77 @@ task :claimed, [:account_name, :days_ago, :symbol] do |t, args|
|
|
492
624
|
puts "# Total claimed #{symbol}: #{claims.values.sum}"
|
493
625
|
end
|
494
626
|
|
495
|
-
|
627
|
+
desc "Total balance of transfers from party a to party b."
|
628
|
+
task :balance, [:party_a, :party_b, :symbol, :days_ago] do |t, args|
|
496
629
|
party_a = args[:party_a]
|
497
630
|
party_b = args[:party_b]
|
498
631
|
symbol = args[:symbol].upcase
|
632
|
+
days_ago = args[:days_ago]
|
499
633
|
|
500
|
-
balance_a = SteemApi::Tx::Transfer.where(to: party_a, from: party_b, amount_symbol: symbol)
|
501
|
-
|
634
|
+
balance_a = SteemApi::Tx::Transfer.where(to: party_a, from: party_b, amount_symbol: symbol)
|
635
|
+
balance_a = balance_a.after(days_ago.to_f.days.ago) if !!days_ago
|
636
|
+
balance_a = balance_a.sum(:amount).to_f
|
637
|
+
|
638
|
+
balance_b = SteemApi::Tx::Transfer.where(to: party_b, from: party_a, amount_symbol: symbol)
|
639
|
+
balance_b = balance_b.after(days_ago.to_f.days.ago) if !!days_ago
|
640
|
+
balance_b = balance_b.sum(:amount).to_f
|
502
641
|
|
503
642
|
puts "#{party_a}: %.3f #{symbol}, difference: %.3f #{symbol}" % [balance_a, (balance_a - balance_b)]
|
504
643
|
puts "#{party_b}: %.3f #{symbol}, difference: %.3f #{symbol}" % [balance_b, (balance_b - balance_a)]
|
505
644
|
end
|
506
645
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
646
|
+
desc 'Lists downvotes cast by follower aginst following.'
|
647
|
+
task :follow_downvote, [:follower] do |t, args|
|
648
|
+
follower = args[:follower]
|
649
|
+
follows = SteemApi::Follower.where(follower: follower)
|
650
|
+
downvotes = SteemApi::Tx::Vote.where(voter: follower, author: follows.select(:following)).
|
651
|
+
where('weight < 0').
|
652
|
+
order(:timestamp)
|
653
|
+
|
654
|
+
puts downvotes.pluck("CONCAT(weight / 100.0, ' %: ', 'https://steemit.com/@', author, '/', permlink)")
|
655
|
+
end
|
656
|
+
|
657
|
+
desc 'List conversion SBD conversion request sums grouped by day.'
|
658
|
+
task :convert, [:direction, :days_ago, :segment] do |t, args|
|
659
|
+
now = Time.now.utc
|
660
|
+
direction = (args[:direction] || 'in').downcase.to_sym
|
661
|
+
after_timestamp = now - ((args[:days_ago] || '90').to_f * 86400)
|
662
|
+
segment = (args[:segment] || 'daily').downcase.to_sym
|
663
|
+
|
664
|
+
converts = SteemApi::Vo::FillConvertRequest
|
665
|
+
converts = converts.where('timestamp > ?', after_timestamp)
|
666
|
+
converts = converts.where("TRY_PARSE(REPLACE(amount_in, ' SBD', '') AS float) > 0")
|
667
|
+
converts = converts.where("TRY_PARSE(REPLACE(amount_out, ' STEEM', '') AS float) > 0")
|
668
|
+
|
669
|
+
case segment
|
670
|
+
when :daily
|
671
|
+
converts = converts.group('CAST(timestamp AS DATE)')
|
672
|
+
converts = converts.order('cast_timestamp_as_date ASC')
|
673
|
+
when :monthly
|
674
|
+
converts = converts.group("FORMAT(timestamp, 'yyyy-MM')")
|
675
|
+
converts = converts.order('format_timestamp_yyyy_mm ASC')
|
676
|
+
else
|
677
|
+
raise "Unknown segment: #{direction}"
|
678
|
+
end
|
679
|
+
|
680
|
+
|
681
|
+
case direction
|
682
|
+
when :in
|
683
|
+
puts "#{segment.capitalize} conversion requests filled (in) sum grouped by date since #{after_timestamp} ..."
|
684
|
+
ap converts.sum("TRY_PARSE(REPLACE(amount_in, ' SBD', '') AS float)")
|
685
|
+
when :out
|
686
|
+
puts "#{segment.capitalize} conversion requests filled (out) sum grouped by date since #{after_timestamp} ..."
|
687
|
+
ap converts.sum("TRY_PARSE(REPLACE(amount_out, ' STEEM', '') AS float)")
|
688
|
+
when :ratio
|
689
|
+
puts "#{segment.capitalize} conversion requests filled (STEEM ratio) sum grouped by date since #{after_timestamp} ..."
|
690
|
+
ap converts.average("TRY_PARSE(REPLACE(amount_out, ' STEEM', '') AS float) / TRY_PARSE(REPLACE(amount_in, ' SBD', '') AS float)")
|
691
|
+
when :inverted_ratio
|
692
|
+
puts "#{segment.capitalize} conversion requests filled (SBD ratio) sum grouped by date since #{after_timestamp} ..."
|
693
|
+
ap converts.average("TRY_PARSE(REPLACE(amount_in, ' SBD', '') AS float) / TRY_PARSE(REPLACE(amount_out, ' STEEM', '') AS float)")
|
694
|
+
else
|
695
|
+
raise "Unknown direction: #{direction}"
|
696
|
+
end
|
697
|
+
end
|
521
698
|
|
522
699
|
desc 'Build a new version of the steem_api gem.'
|
523
700
|
task :build do
|
data/lib/steem_api.rb
CHANGED
@@ -36,6 +36,7 @@ require "steem_api/models/tx/feed"
|
|
36
36
|
require "steem_api/models/tx/limit_order"
|
37
37
|
require "steem_api/models/tx/pow"
|
38
38
|
require "steem_api/models/tx/transfer"
|
39
|
+
require "steem_api/models/tx/update_proposal_vote"
|
39
40
|
require "steem_api/models/tx/vote"
|
40
41
|
require "steem_api/models/tx/withdraw"
|
41
42
|
require "steem_api/models/tx/withdraw_vesting_route"
|
@@ -44,6 +45,7 @@ require "steem_api/models/tx/witness_update"
|
|
44
45
|
require "steem_api/models/tx/custom/follow"
|
45
46
|
require "steem_api/models/tx/custom/witness"
|
46
47
|
require "steem_api/models/tx/custom/reblog"
|
48
|
+
require "steem_api/models/tx/custom/community"
|
47
49
|
|
48
50
|
require "steem_api/models/vo/author_reward"
|
49
51
|
require "steem_api/models/vo/comment_benefactor_reward"
|
@@ -57,6 +59,8 @@ require "steem_api/models/vo/liquidity_reward"
|
|
57
59
|
require "steem_api/models/vo/producer_reward"
|
58
60
|
require "steem_api/models/vo/return_vesting_delegation"
|
59
61
|
require "steem_api/models/vo/shutdown_witness"
|
62
|
+
require "steem_api/models/vo/sps_fund"
|
63
|
+
require "steem_api/models/vo/proposal_pay"
|
60
64
|
|
61
65
|
module SteemApi
|
62
66
|
end
|
@@ -8,7 +8,7 @@ module SteemApi
|
|
8
8
|
scope :today, -> { after(1.day.ago) }
|
9
9
|
scope :yesterday, -> { before(1.day.ago).after(2.days.ago) }
|
10
10
|
|
11
|
-
scope :normalized_json, -> { where("json_metadata LIKE '{%}'") }
|
11
|
+
scope :normalized_json, -> { where("json_metadata LIKE '{%}' AND ISJSON(json_metadata) > 0") }
|
12
12
|
|
13
13
|
scope :app, lambda { |app|
|
14
14
|
normalized_json.where("JSON_VALUE(json_metadata, '$.app') LIKE ?", "#{app}/%")
|
@@ -18,6 +18,10 @@ module SteemApi
|
|
18
18
|
normalized_json.where("JSON_VALUE(json_metadata, '$.app') LIKE ?", "%/#{version}")
|
19
19
|
}
|
20
20
|
|
21
|
+
scope :tagged, lambda { |tag|
|
22
|
+
normalized_json.where("? IN (SELECT value FROM OPENJSON(json_metadata,'$.tags'))", tag)
|
23
|
+
}
|
24
|
+
|
21
25
|
scope :decorate_metadata, -> {
|
22
26
|
previous_select = if all.select_values.none?
|
23
27
|
Arel.star
|
@@ -1,8 +1,19 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
1
3
|
module SteemApi
|
2
4
|
class DynamicGlobalProperties < SteemApi::SqlBase
|
3
5
|
|
4
6
|
self.table_name = :DynamicGlobalProperties
|
5
7
|
|
8
|
+
def self.steem_per_mvest
|
9
|
+
dgpo = first
|
10
|
+
dgpo.total_vesting_fund_steem / (dgpo.total_vesting_shares / 1e6)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.usd_per_mvest
|
14
|
+
prices = JSON[open('https://postpromoter.net/api/prices').read]
|
15
|
+
(SteemApi::DynamicGlobalProperties.steem_per_mvest * prices.fetch('steem_price'))
|
16
|
+
end
|
6
17
|
end
|
7
18
|
end
|
8
19
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'steem'
|
2
|
+
|
1
3
|
module SteemApi
|
2
4
|
class Transaction < SteemApi::SqlBase
|
3
5
|
|
@@ -13,13 +15,31 @@ module SteemApi
|
|
13
15
|
scope :yesterday, -> { before(1.day.ago).after(2.days.ago) }
|
14
16
|
|
15
17
|
scope :type, lambda { |type| where(type: type) }
|
18
|
+
scope :trx_id, lambda { |trx_id|
|
19
|
+
url = "https://anyx.io/v1/account_history_api/get_transaction?id=#{trx_id}"
|
20
|
+
trx = JSON[open(url).read]
|
21
|
+
expiration = Time.parse(trx.fetch('expiration') + 'Z')
|
22
|
+
block_num = trx.fetch('block_num')
|
23
|
+
transaction_num = trx.fetch('transaction_num') + 1
|
24
|
+
|
25
|
+
where(expiration: expiration, block_num: block_num, transaction_num: transaction_num)
|
26
|
+
}
|
27
|
+
|
28
|
+
def trx_id
|
29
|
+
@block_api ||= Steem::BlockApi.new
|
30
|
+
@trx_id ||= @block_api.get_block(block_num: block_num) do |result|
|
31
|
+
return nil if result.nil? || result.block.nil?
|
32
|
+
|
33
|
+
result.block.transaction_ids[transaction_num - 1]
|
34
|
+
end
|
35
|
+
end
|
16
36
|
|
17
37
|
# So you have a Transaction#tx_id and you want to know what the operation was
|
18
38
|
# that lead to it. Well, that's tricky because all of the ops are in their
|
19
39
|
# own tables. This method will (slowly) try to find the appropriate table.
|
20
40
|
def op
|
21
41
|
retries = 0
|
22
|
-
|
42
|
+
|
23
43
|
# Here, we map the type to class name, if supported. Most of them can be
|
24
44
|
# mapped automatically, e.g. "vote" => "Vote" but some types share tables
|
25
45
|
# with one another. We also use timestamps to narrow the search
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module SteemApi
|
2
|
+
module Tx
|
3
|
+
class Custom::Community < SteemApi::Tx::Custom
|
4
|
+
default_scope { where(tid: :community) }
|
5
|
+
|
6
|
+
scope :normalized_json, -> { where("ISJSON(json_metadata) > 0") }
|
7
|
+
scope :op, lambda { |op| normalized_json.where("JSON_VALUE(json_metadata, '$[0]') = ?", op) }
|
8
|
+
scope :community, lambda { |community| normalized_json.where("JSON_VALUE(json_metadata, '$[1].community') = ?", community) }
|
9
|
+
scope :role, lambda { |role| normalized_json.where("JSON_VALUE(json_metadata, '$[1].role') = ?", role) }
|
10
|
+
scope :language, lambda { |language| normalized_json.where("JSON_VALUE(json_metadata, '$[1].language') = ?", language) }
|
11
|
+
scope :nsfw, lambda { |nsfw = true| normalized_json.where("JSON_VALUE(json_metadata, '$[1].is_nsfw') = ?", nsfw) }
|
12
|
+
scope :account, lambda { |account|
|
13
|
+
account = [account].flatten
|
14
|
+
normalized_json.where("required_auths IN(?) OR required_posting_auths IN(?) OR JSON_VALUE(json_metadata, '$[1].account') IN(?)", account, account, account)
|
15
|
+
}
|
16
|
+
scope :permlink, lambda { |permlink|
|
17
|
+
normalized_json.where("JSON_VALUE(json_metadata, '$[1].permlink') = ?", permlink)
|
18
|
+
}
|
19
|
+
scope :slug, lambda { |slug|
|
20
|
+
normalized_json.where("JSON_VALUE(json_metadata, '$[1].account') = ? AND JSON_VALUE(json_metadata, '$[1].permlink') = ?", *slug.split('/'))
|
21
|
+
}
|
22
|
+
|
23
|
+
def self.ops
|
24
|
+
distinct.normalized_json.pluck(Arel.sql "JSON_VALUE(json_metadata, '$[0]') AS ops")
|
25
|
+
end
|
26
|
+
|
27
|
+
def payload
|
28
|
+
JSON[json_metadata][1] rescue nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SteemApi
|
2
|
+
module Tx
|
3
|
+
class UpdateProposalVote < SteemApi::SqlBase
|
4
|
+
belongs_to :voter_record, foreign_key: :account, primary_key: :voter, class_name: 'SteemApi::Account'
|
5
|
+
|
6
|
+
self.table_name = :TxUpdateProposalVotes
|
7
|
+
|
8
|
+
scope :proposal, lambda { |id, invert = false|
|
9
|
+
if !!invert
|
10
|
+
where("? NOT IN (SELECT value FROM OPENJSON(proposal_ids,'$'))", id)
|
11
|
+
else
|
12
|
+
where("? IN (SELECT value FROM OPENJSON(proposal_ids,'$'))", id)
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
scope :approve, lambda {|approve = true| where(approve: approve)}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Structure
|
22
|
+
#
|
23
|
+
# SteemApi::Tx::Vote(
|
24
|
+
# ID: integer,
|
25
|
+
# tx_id: integer,
|
26
|
+
# voter: varchar,
|
27
|
+
# proposal_ids: varchar,
|
28
|
+
# approve: boolean,
|
29
|
+
# extensions: varchar,
|
30
|
+
# timestamp: datetime
|
31
|
+
# )
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SteemApi
|
2
|
+
module Vo
|
3
|
+
class ProposalPay < SteemApi::SqlBase
|
4
|
+
|
5
|
+
self.table_name = :VOProposalPay
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Structure
|
12
|
+
#
|
13
|
+
# SteemApi::Vo::ProposalPay(
|
14
|
+
# ID: integer,
|
15
|
+
# block_num: integer,
|
16
|
+
# timestamp: datetime,
|
17
|
+
# payment: money,
|
18
|
+
# trx_id: varchar,
|
19
|
+
# op_in_trx: integer
|
20
|
+
# )
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SteemApi
|
2
|
+
module Vo
|
3
|
+
class SpsFund < SteemApi::SqlBase
|
4
|
+
|
5
|
+
self.table_name = :VOSpsFund
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Structure
|
12
|
+
#
|
13
|
+
# SteemApi::Vo::SpsFund(
|
14
|
+
# ID: integer,
|
15
|
+
# block_num: integer,
|
16
|
+
# timestamp: datetime,
|
17
|
+
# additional_funds: money
|
18
|
+
# )
|
data/lib/steem_api/version.rb
CHANGED
data/steem_api.gemspec
CHANGED
@@ -38,4 +38,5 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_runtime_dependency "activerecord-sqlserver-adapter", [">= 4", "< 6"]
|
39
39
|
spec.add_runtime_dependency "activesupport", [">= 4", "< 6"]
|
40
40
|
spec.add_runtime_dependency 'awesome_print', '~> 1.7', '>= 1.7.0'
|
41
|
+
spec.add_runtime_dependency 'steem-ruby', '~> 0.9', '>= 0.9.4'
|
41
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steem_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Chaney (netuoso)
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-11-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -313,6 +313,26 @@ dependencies:
|
|
313
313
|
- - ">="
|
314
314
|
- !ruby/object:Gem::Version
|
315
315
|
version: 1.7.0
|
316
|
+
- !ruby/object:Gem::Dependency
|
317
|
+
name: steem-ruby
|
318
|
+
requirement: !ruby/object:Gem::Requirement
|
319
|
+
requirements:
|
320
|
+
- - "~>"
|
321
|
+
- !ruby/object:Gem::Version
|
322
|
+
version: '0.9'
|
323
|
+
- - ">="
|
324
|
+
- !ruby/object:Gem::Version
|
325
|
+
version: 0.9.4
|
326
|
+
type: :runtime
|
327
|
+
prerelease: false
|
328
|
+
version_requirements: !ruby/object:Gem::Requirement
|
329
|
+
requirements:
|
330
|
+
- - "~>"
|
331
|
+
- !ruby/object:Gem::Version
|
332
|
+
version: '0.9'
|
333
|
+
- - ">="
|
334
|
+
- !ruby/object:Gem::Version
|
335
|
+
version: 0.9.4
|
316
336
|
description: Rails compatible gem that provides full DB connection and models to SteemSQL.com
|
317
337
|
email:
|
318
338
|
- andrewc@pobox.com
|
@@ -350,6 +370,7 @@ files:
|
|
350
370
|
- lib/steem_api/models/tx/comments_option.rb
|
351
371
|
- lib/steem_api/models/tx/convert.rb
|
352
372
|
- lib/steem_api/models/tx/custom.rb
|
373
|
+
- lib/steem_api/models/tx/custom/community.rb
|
353
374
|
- lib/steem_api/models/tx/custom/follow.rb
|
354
375
|
- lib/steem_api/models/tx/custom/reblog.rb
|
355
376
|
- lib/steem_api/models/tx/custom/witness.rb
|
@@ -363,6 +384,7 @@ files:
|
|
363
384
|
- lib/steem_api/models/tx/limit_order.rb
|
364
385
|
- lib/steem_api/models/tx/pow.rb
|
365
386
|
- lib/steem_api/models/tx/transfer.rb
|
387
|
+
- lib/steem_api/models/tx/update_proposal_vote.rb
|
366
388
|
- lib/steem_api/models/tx/vote.rb
|
367
389
|
- lib/steem_api/models/tx/withdraw.rb
|
368
390
|
- lib/steem_api/models/tx/withdraw_vesting_route.rb
|
@@ -377,8 +399,10 @@ files:
|
|
377
399
|
- lib/steem_api/models/vo/interest.rb
|
378
400
|
- lib/steem_api/models/vo/liquidity_reward.rb
|
379
401
|
- lib/steem_api/models/vo/producer_reward.rb
|
402
|
+
- lib/steem_api/models/vo/proposal_pay.rb
|
380
403
|
- lib/steem_api/models/vo/return_vesting_delegation.rb
|
381
404
|
- lib/steem_api/models/vo/shutdown_witness.rb
|
405
|
+
- lib/steem_api/models/vo/sps_fund.rb
|
382
406
|
- lib/steem_api/models/witness.rb
|
383
407
|
- lib/steem_api/version.rb
|
384
408
|
- steem_api.gemspec
|