steem_api 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|