cosgrove 0.0.2 → 0.0.3rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -120,7 +120,7 @@ module Cosgrove
120
120
  end
121
121
  private
122
122
  def chain
123
- @chain ||= yml[:chain]
123
+ @chain_hash ||= yml[:chain]
124
124
  end
125
125
 
126
126
  def yml
@@ -4,18 +4,19 @@ module Cosgrove
4
4
  include ActionView::Helpers::NumberHelper
5
5
 
6
6
  def price_feed(chain = :steem)
7
- feed_history = api(chain).get_feed_history.result
8
- base_per_mvest = api(chain).steem_per_mvest
9
-
10
- current_median_history = feed_history.current_median_history
11
- base = current_median_history.base
12
- base = base.split(' ').first.to_f
13
- quote = current_median_history.quote
14
- quote = quote.split(' ').first.to_f
15
-
16
- base_per_debt = (base / quote) * base_per_mvest
17
-
18
- [base_per_mvest, base_per_debt]
7
+ api(chain).get_feed_history do |feed_history|
8
+ base_per_mvest = api(chain).steem_per_mvest
9
+
10
+ current_median_history = feed_history.current_median_history
11
+ base = current_median_history.base
12
+ base = base.split(' ').first.to_f
13
+ quote = current_median_history.quote
14
+ quote = quote.split(' ').first.to_f
15
+
16
+ base_per_debt = (base / quote) * base_per_mvest
17
+
18
+ [base_per_mvest, base_per_debt]
19
+ end
19
20
  end
20
21
 
21
22
  # https://api.vaultoro.com/#api-Basic_API-getMarkets
@@ -113,13 +114,12 @@ module Cosgrove
113
114
  if a =~ /.*\*$/
114
115
  wildcards = true
115
116
  lower_bound_name = a.split('*').first
116
- response = api(chain).lookup_accounts(a, 1000)
117
- result = response.result
118
-
119
- if result.any?
120
- account_names -= [a]
121
- account_names += [lower_bound_name]
122
- account_names += result.map { |name| name if name =~ /#{lower_bound_name}.*/ }.compact
117
+ api(chain).lookup_accounts(a, 1000) do |names, error|
118
+ if names.any?
119
+ account_names -= [a]
120
+ account_names += [lower_bound_name]
121
+ account_names += names.map { |name| name if name =~ /#{lower_bound_name}.*/ }.compact
122
+ end
123
123
  end
124
124
  end
125
125
  end
@@ -128,10 +128,21 @@ module Cosgrove
128
128
  accounts = SteemData::Account.where(:name.in => account_names)
129
129
  account = accounts.last
130
130
 
131
+ if accounts.size == 0
132
+ accounts = SteemApi::Account.where(name: account_names)
133
+ account = accounts.limit(1).last
134
+ end
135
+
131
136
  if accounts.count == account_names.size
132
- vests = accounts.sum('vesting_shares.amount')
133
- delegated_vests = accounts.sum('delegated_vesting_shares.amount')
134
- received_vests = accounts.sum('received_vesting_shares.amount')
137
+ if accounts.kind_of? Mongoid::Criteria
138
+ vests = accounts.sum('vesting_shares.amount')
139
+ delegated_vests = accounts.sum('delegated_vesting_shares.amount')
140
+ received_vests = accounts.sum('received_vesting_shares.amount')
141
+ else
142
+ vests = accounts.pluck(:vesting_shares).map(&:to_f).sum
143
+ delegated_vests = accounts.pluck(:delegated_vesting_shares).map(&:to_f).sum
144
+ received_vests = accounts.pluck(:received_vesting_shares).map(&:to_f).sum
145
+ end
135
146
  elsif !wildcards
136
147
  valid_names = accounts.distinct(:name)
137
148
  unknown_names = account_names - valid_names
@@ -141,11 +152,12 @@ module Cosgrove
141
152
  if accounts.count == 1 && vests == 0.0
142
153
  # Falling back to RPC because balance is out of date and we only want
143
154
  # a single account.
144
- response = api(:steem).get_accounts([account.name])
145
- account = response.result.first
146
- vests = account.vesting_shares.split(' ').first.to_f
147
- delegated_vests = account.delegated_vesting_shares.split(' ').first.to_f
148
- received_vests = account.received_vesting_shares.split(' ').first.to_f
155
+ api(:steem).get_accounts([account.name]) do |accounts|
156
+ account = accounts.first
157
+ vests = account.vesting_shares.split(' ').first.to_f
158
+ delegated_vests = account.delegated_vesting_shares.split(' ').first.to_f
159
+ received_vests = account.received_vesting_shares.split(' ').first.to_f
160
+ end
149
161
  end
150
162
 
151
163
  mvests = vests / 1000000
@@ -177,9 +189,13 @@ module Cosgrove
177
189
  "**#{pluralize(accounts.count, 'account')}:** `#{balance.join(' ')}`"
178
190
  end
179
191
  when :golos
180
- response = api(:golos).get_accounts(account_names)
181
- account = response.result.first
182
- gests = account.vesting_shares.split(' ').first.to_f
192
+ account = nil
193
+ gests = nil
194
+
195
+ api(:golos).get_accounts(account_names) do |accounts, error|
196
+ account = accounts.first
197
+ gests = account.vesting_shares.split(' ').first.to_f
198
+ end
183
199
 
184
200
  mgests = gests / 1000000
185
201
  golos = base_per_mvest * mgests
@@ -203,10 +219,10 @@ module Cosgrove
203
219
 
204
220
  case chain
205
221
  when :steem
206
- response = api(chain).get_reward_fund 'post'
207
- reward_fund = response.result
208
- total = reward_fund.reward_balance
209
- total = total.split(' ').first.to_f
222
+ total = api(chain).get_reward_fund('post') do |reward_fund|
223
+ reward_fund.reward_balance.split(' ').first.to_f
224
+ end
225
+
210
226
  total_usd = (total / base_per_mvest) * base_per_debt
211
227
  btx_total_usd = total * btx_usdt_steem
212
228
 
@@ -216,10 +232,10 @@ module Cosgrove
216
232
 
217
233
  "Total Reward Fund: `#{total} STEEM (Worth: #{total_usd} internally; #{btx_total_usd} on Bittrex)`"
218
234
  when :golos
219
- response = api(chain).get_dynamic_global_properties
220
- properties = response.result
221
- total = properties.total_reward_fund_steem
222
- total = total.split(' ').first.to_f
235
+ total = api(chain).get_dynamic_global_properties do |properties|
236
+ properties.total_reward_fund_steem.split(' ').first.to_f
237
+ end
238
+
223
239
  total_gbg = (total / base_per_mvest) * base_per_debt
224
240
  btx_total_usd = total * btx_usdt_golos
225
241
 
@@ -258,10 +274,9 @@ module Cosgrove
258
274
  sum_promoted = promoted.sum('amount.amount')
259
275
 
260
276
  base_per_mvest, base_per_debt = price_feed(chain)
261
- response = api(chain).get_reward_fund 'post'
262
- reward_fund = response.result
263
- total = reward_fund.reward_balance
264
- total = total.split(' ').first.to_f
277
+ total = api(chain).get_reward_fund('post') do |reward_fund|
278
+ reward_fund.reward_balance.split(' ').first.to_f
279
+ end
265
280
 
266
281
  total_usd = (total / base_per_mvest) * base_per_debt
267
282
  ratio = (sum_promoted / total_usd) * 100
@@ -274,23 +289,22 @@ module Cosgrove
274
289
 
275
290
  def supply(chain)
276
291
  base_per_mvest, base_per_debt = price_feed(chain)
277
-
278
- response = api(chain).get_dynamic_global_properties
279
- properties = response.result
292
+ properties = api(chain).get_dynamic_global_properties do |_properties, error|
293
+ _properties
294
+ end
295
+
280
296
  current_supply = properties.current_supply.split(' ').first.to_f
281
297
  current_debt_supply = properties.current_sbd_supply.split(' ').first.to_f
282
298
  total_vesting_fund_steem = properties.total_vesting_fund_steem.split(' ').first.to_f
283
-
284
299
  total_base = (current_supply / base_per_mvest) * base_per_debt
285
300
  ratio = (current_debt_supply / total_base) * 100
286
301
 
287
302
  supply = []
288
303
  case chain
289
304
  when :steem
290
- response = api(chain).get_reward_fund 'post'
291
- reward_fund = response.result
292
- reward_balance = reward_fund.reward_balance
293
- reward_balance = reward_balance.split(' ').first.to_f
305
+ reward_balance = api(chain).get_reward_fund('post') do |reward_fund|
306
+ reward_fund.reward_balance.split(' ').first.to_f
307
+ end
294
308
 
295
309
  liquid_supply = current_supply - reward_balance - total_vesting_fund_steem
296
310
  ratio_liquid = (liquid_supply / current_supply) * 100
@@ -306,7 +320,6 @@ module Cosgrove
306
320
  supply << ["#{current_debt_supply} SBD (#{ratio} of supply)"]
307
321
  supply << ["#{liquid_supply} Liquid STEEM (#{ratio_liquid} of supply)"]
308
322
  when :golos
309
- properties = response.result
310
323
  reward_balance = properties.total_reward_fund_steem
311
324
  reward_balance = reward_balance.split(' ').first.to_f
312
325
 
@@ -324,7 +337,6 @@ module Cosgrove
324
337
  supply << ["#{current_debt_supply} GBG (#{ratio} of supply)"]
325
338
  supply << ["#{liquid_supply} Liquid GOLOS (#{ratio_liquid} of supply)"]
326
339
  when :test
327
- properties = response.result
328
340
  reward_balance = properties.total_reward_fund_steem
329
341
  reward_balance = reward_balance.split(' ').first.to_f
330
342
 
@@ -358,9 +370,9 @@ module Cosgrove
358
370
 
359
371
  def debt_exchange_rate(chain = :steem, limit = 19)
360
372
  chain = chain.to_sym
361
- response = api(chain).get_witnesses_by_vote('', limit)
362
- witnesses = response.result
363
- rates = witnesses.map(&:sbd_exchange_rate)
373
+ rates = api(chain).get_witnesses_by_vote('', limit) do |witnesses|
374
+ witnesses.map(&:sbd_exchange_rate)
375
+ end
364
376
 
365
377
  symbol = case chain
366
378
  when :steem then 'SBD'
@@ -382,9 +394,9 @@ module Cosgrove
382
394
 
383
395
  def apr(chain = :steem, limit = 19)
384
396
  chain = chain.to_sym
385
- response = api(chain).get_witnesses_by_vote('', limit)
386
- witnesses = response.result
387
- rates = witnesses.map(&:props).map { |p| p['sbd_interest_rate'] }
397
+ rates = api(chain).get_witnesses_by_vote('', limit) do |witnesses|
398
+ witnesses.map(&:props).map { |p| p['sbd_interest_rate'] }
399
+ end
388
400
 
389
401
  rate = rates.sum / rates.size
390
402
  rate = rate / 100.0
@@ -393,9 +405,9 @@ module Cosgrove
393
405
 
394
406
  def effective_apr(chain = :steem)
395
407
  chain = chain.to_sym
396
- response = api(chain).get_dynamic_global_properties
397
- properties = response.result
398
- rate = properties.sbd_interest_rate
408
+ rate = api(chain).get_dynamic_global_properties do |properties|
409
+ properties.sbd_interest_rate
410
+ end
399
411
 
400
412
  rate = rate / 100.0
401
413
  number_to_percentage(rate, precision: 3)
@@ -403,9 +415,9 @@ module Cosgrove
403
415
 
404
416
  def effective_price(chain = :steem)
405
417
  chain = chain.to_sym
406
- response = api(chain).get_feed_history
407
- feed_history = response.result
408
- current_median_history = feed_history.current_median_history
418
+ current_median_history = api(chain).get_feed_history do |feed_history|
419
+ feed_history.current_median_history
420
+ end
409
421
 
410
422
  b = current_median_history.base.split(' ').first.to_f
411
423
  q = current_median_history.quote.split(' ').first.to_f
@@ -29,12 +29,16 @@ module Cosgrove
29
29
  end
30
30
 
31
31
  def mongo_behind_warning(event)
32
+ elapse = -1
33
+
32
34
  begin
33
35
  message = []
34
36
 
35
37
  if (blocks = head_block_number(:steem) - steem_data_head_block_number) > 1200
36
38
  elapse = blocks * 3
37
39
  message << "Mongo is behind by #{time_ago_in_words(elapse.seconds.ago)}."
40
+ else
41
+ 0
38
42
  end
39
43
 
40
44
  if message.size > 0
@@ -45,6 +49,8 @@ module Cosgrove
45
49
  sleep 15
46
50
  event.respond Cosgrove::SnarkCommands::WITTY.sample
47
51
  end
52
+
53
+ elapse
48
54
  end
49
55
 
50
56
  def cannot_find_input(event, message_prefix = "Unable to find that.")
@@ -62,16 +68,31 @@ module Cosgrove
62
68
 
63
69
  def append_link_details(event, slug)
64
70
  author_name, permlink = parse_slug slug
71
+ created = nil
72
+ cashout_time = nil
73
+
74
+ if slug =~ /steemit.com/
75
+ chain = :steem
76
+ elsif slug =~ /golos.io/
77
+ chain = :golos
78
+ elsif slug =~ /golos.blog/
79
+ chain = :golos
80
+ else
81
+ return # silntlly ignore this slug
82
+ end
65
83
 
66
- post = SteemData::Post.where(author: author_name, permlink: permlink).last
84
+ post = case chain
85
+ when :steem then SteemData::Post.where(author: author_name, permlink: permlink).last
86
+ when :golos then GolosCloud::Comment.where(author: author_name, permlink: permlink).last
87
+ end
67
88
 
68
89
  if post.nil?
69
90
  # Fall back to RPC
70
- response = api(:steem).get_content(author_name, permlink)
71
- unless response.result.author.empty?
72
- post = response.result
73
- created = Time.parse(post.created + 'Z')
74
- cashout_time = Time.parse(post.cashout_time + 'Z')
91
+ api(chain).get_content(author_name, permlink) do |content, errors|
92
+ unless content.author.empty?
93
+ created = Time.parse(content.created + 'Z')
94
+ cashout_time = Time.parse(content.cashout_time + 'Z')
95
+ end
75
96
  end
76
97
  end
77
98
 
@@ -98,7 +119,10 @@ module Cosgrove
98
119
 
99
120
  # Only append this detail of the post less than an hour old.
100
121
  if created > 1.hour.ago
101
- votes = SteemData::AccountOperation.type('vote').starting(post.created)
122
+ votes = case chain
123
+ when :steem then SteemData::AccountOperation.type('vote').starting(post.created)
124
+ when :golos then GolosCloud::Vote.where('timestamp > ?', post.created)
125
+ end
102
126
  total_votes = votes.count
103
127
  total_voters = votes.distinct(:voter).size
104
128
 
@@ -115,7 +139,7 @@ module Cosgrove
115
139
 
116
140
  begin
117
141
  event.respond details.join('; ')
118
- rescue Discordrb::Errors::NoPermission => e
142
+ rescue Discordrb::Errors::NoPermission => _
119
143
  puts "Unable to append link details on #{event.channel.server.name} in #{event.channel.name}"
120
144
  end
121
145
 
@@ -124,19 +148,41 @@ module Cosgrove
124
148
 
125
149
  def find_account(key, event = nil, chain = :steem)
126
150
  key = key.to_s.downcase
151
+ chain = chain.to_sym
127
152
 
128
- if (accounts = SteemData::Account.where(name: key)).any?
129
- return accounts.first
130
- elsif !!(cb_account = Cosgrove::Account.find_by_discord_id(key, chain))
131
- return SteemData::Account.find_by(name: cb_account.account_name)
132
- else
133
- # Fall back to RPC
134
- if !!key
135
- response = api(chain).get_accounts([key])
136
- return account = response.result.first
153
+ raise "Required argument: chain" if chain.nil?
154
+
155
+ if chain == :steem
156
+ account = if (accounts = SteemData::Account.where(name: key)).any?
157
+ accounts.first
137
158
  end
159
+ end
160
+
161
+ if account.nil?
162
+ account = if !!(cb_account = Cosgrove::Account.find_by_discord_id(key, chain))
163
+ cb_account.chain_account
164
+ end
165
+ end
166
+
167
+ if account.nil?
168
+ account = if !!key
169
+ if chain == :steem && (accounts = SteemApi::Account.where(name: key)).any?
170
+ accounts.first
171
+ elsif chain == :golos && (accounts = GolosCloud::Account.where(name: key)).any?
172
+ accounts.first
173
+ else
174
+ # Fall back to RPC
175
+ api(chain).get_accounts([key]) do |_accounts, errors|
176
+ _accounts.first
177
+ end
178
+ end
179
+ end
180
+ end
138
181
 
139
- unknown_account(key, event) unless !!account
182
+ if account.nil?
183
+ unknown_account(key, event)
184
+ else
185
+ account
140
186
  end
141
187
  end
142
188
 
@@ -204,9 +250,12 @@ module Cosgrove
204
250
  count = -1
205
251
  until count == ignoring.size
206
252
  count = ignoring.size
207
- response = follow_api(chain).get_following(a, ignoring.last, 'ignore', 100)
208
- ignoring += response.result.map(&:following)
209
- ignoring = ignoring.uniq
253
+ follow_api(chain).get_following(a, ignoring.last, 'ignore', 100) do |ignores, errors|
254
+ next unless defined? ignores.following
255
+
256
+ ignoring += ignores.map(&:following)
257
+ ignoring = ignoring.uniq
258
+ end
210
259
  end
211
260
  muted += ignoring
212
261
  end
@@ -22,7 +22,13 @@ module Cosgrove
22
22
  muters << steem_account
23
23
  muted = muted by: muters, chain: :steem
24
24
 
25
- posts = SteemData::Post.root_posts.where(author: author_name, permlink: permlink)
25
+ post = find_comment(author: author_name, permlink: permlink)
26
+
27
+ if post.nil?
28
+ cannot_find_input(event)
29
+ return
30
+ end
31
+
26
32
  votes_today = SteemData::AccountOperation.type('vote').where(voter: steem_account).today
27
33
  today_count = votes_today.count
28
34
  author_count = votes_today.where(author: author_name).count
@@ -32,27 +38,15 @@ module Cosgrove
32
38
  author_count.to_f / today_count
33
39
  end
34
40
 
35
- post = posts.first
36
-
37
- if post.nil?
38
- # Fall back to RPC
39
- response = api(:steem).get_content(author_name, permlink)
40
- unless response.result.author.empty?
41
- post = response.result
42
- created = Time.parse(post.created + 'Z')
43
- cashout_time = Time.parse(post.cashout_time + 'Z')
44
- end
45
- end
46
-
47
- if post.nil?
48
- cannot_find_input(event)
49
- return
50
- end
51
-
52
41
  created ||= post.created
53
42
  cashout_time ||= post.cashout_time
54
43
  root_post = post.parent_author == ''
55
44
 
45
+ if created.class == String
46
+ created = Time.parse(created + 'Z')
47
+ cashout_time = Time.parse(cashout_time + 'Z')
48
+ end
49
+
56
50
  nope = if created > 1.minute.ago
57
51
  "Give it a second! It's going to SPACE! Can you give it a second to come back from space?"
58
52
  elsif created > 20.minutes.ago
@@ -103,19 +97,63 @@ module Cosgrove
103
97
  }
104
98
 
105
99
  tx = new_tx :steem
106
- op = Radiator::Operation.new(vote)
107
- tx.operations << op
108
- response = tx.process(true)
109
-
110
- ap response.to_json
100
+ tx.operations << vote
101
+ friendy_error = nil
102
+
103
+ loop do
104
+ begin
105
+ response = tx.process(true)
106
+ rescue => e
107
+ puts "Unable to vote: #{e}"
108
+ ap e
109
+ end
110
+
111
+ if !!response && !!response.error
112
+ message = response.error.message
113
+ if message.to_s =~ /missing required posting authority/
114
+ friendy_error = "Failed: Check posting key."
115
+ break
116
+ elsif message.to_s =~ /You have already voted in a similar way./
117
+ friendy_error = "Failed: duplicate vote."
118
+ break
119
+ elsif message.to_s =~ /Can only vote once every 3 seconds./
120
+ puts "Retrying: voting too quickly."
121
+ sleep 3
122
+ redo
123
+ elsif message.to_s =~ /Voting weight is too small, please accumulate more voting power or steem power./
124
+ friendy_error = "Failed: voting weight too small"
125
+ break
126
+ elsif message.to_s =~ /unknown key/
127
+ friendy_error = "Failed: unknown key (testing?)"
128
+ break
129
+ elsif message.to_s =~ /tapos_block_summary/
130
+ puts "Retrying vote/comment: tapos_block_summary (?)"
131
+ redo
132
+ elsif message.to_s =~ /now < trx.expiration/
133
+ puts "Retrying vote/comment: now < trx.expiration (?)"
134
+ redo
135
+ elsif message.to_s =~ /signature is not canonical/
136
+ puts "Retrying vote/comment: signature was not canonical (bug in Radiator?)"
137
+ redo
138
+ elsif message.to_s =~ /STEEMIT_UPVOTE_LOCKOUT_HF17/
139
+ friendy_error = "Failed: upvote lockout (last twelve hours before payout)"
140
+ break
141
+ else
142
+ friendy_error = 'Unable to vote right now. Maybe I already voted on that. Try again later.'
143
+ ap e
144
+ ap e.backtrace
145
+ break
146
+ end
147
+ end
148
+
149
+ break
150
+ end
111
151
 
112
- if !!response.error
113
- 'Unable to vote right now. Maybe I already voted on that. Try again later.'
152
+ if !!friendy_error
153
+ friendy_error
114
154
  elsif !!response.result.id
115
- # if created > 30.minutes.ago
116
- # event.respond "*#{SteemSlap.slap(event.author.display_name)}*"
117
- # end
118
-
155
+ ap response.to_json
156
+
119
157
  if !!@on_success
120
158
  begin
121
159
  @on_success.call(event, "@#{post.author}/#{post.permlink}")